// Copyright 2020 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. namespace internal { namespace runtime { extern runtime GetTemplateObject(implicit context: Context)( TemplateObjectDescription, SharedFunctionInfo, Smi): JSAny; extern runtime BytecodeBudgetInterruptFromCode(implicit context: Context)( FeedbackCell): JSAny; } builtin GetTemplateObject( context: Context, shared: SharedFunctionInfo, description: TemplateObjectDescription, slot: uintptr, maybeFeedbackVector: Undefined|FeedbackVector): JSArray { // TODO(jgruber): Consider merging with the GetTemplateObject bytecode // handler; the current advantage of the split implementation is that the // bytecode can skip most work if feedback exists. // TODO(v8:9891): Remove this assert once all callers are ported to Torque. // This assert ensures correctness of maybeFeedbackVector's type which can // be easily broken for calls from CSA. assert( IsUndefined(maybeFeedbackVector) || Is<FeedbackVector>(maybeFeedbackVector)); try { const vector = Cast<FeedbackVector>(maybeFeedbackVector) otherwise CallRuntime; return Cast<JSArray>(ic::LoadFeedbackVectorSlot(vector, slot)) otherwise CallRuntime; } label CallRuntime deferred { const result = UnsafeCast<JSArray>(runtime::GetTemplateObject( description, shared, Convert<Smi>(Signed(slot)))); const vector = Cast<FeedbackVector>(maybeFeedbackVector) otherwise return result; ic::StoreFeedbackVectorSlot(vector, slot, result); return result; } } builtin BytecodeBudgetInterruptFromCode(implicit context: Context)( feedbackCell: FeedbackCell): Object { // The runtime call is wrapped by a builtin since the calling sequence in // generated code is shorter for builtins than for runtime calls. tail runtime::BytecodeBudgetInterruptFromCode(feedbackCell); } extern transitioning builtin ForInFilter(implicit context: Context)( JSAny, HeapObject): JSAny; extern enum ForInFeedback extends uint31 { kAny, ...} extern macro UpdateFeedback( SmiTagged<ForInFeedback>, Undefined | FeedbackVector, uintptr, constexpr UpdateFeedbackMode); @export transitioning macro ForInNextSlow( context: Context, slot: uintptr, receiver: JSAnyNotSmi, key: JSAny, cacheType: Object, maybeFeedbackVector: Undefined|FeedbackVector, guaranteedFeedback: constexpr UpdateFeedbackMode): JSAny { assert(receiver.map != cacheType); // Handled on the fast path. UpdateFeedback( SmiTag<ForInFeedback>(ForInFeedback::kAny), maybeFeedbackVector, slot, guaranteedFeedback); return ForInFilter(key, receiver); } // Note: the untagged {slot} parameter must be in the first couple of args to // guarantee it's allocated in a register. transitioning builtin ForInNext( context: Context, slot: uintptr, receiver: JSAnyNotSmi, cacheArray: FixedArray, cacheType: Object, cacheIndex: Smi, feedbackVector: FeedbackVector): JSAny { // Load the next key from the enumeration array. const key = UnsafeCast<JSAny>(cacheArray.objects[cacheIndex]); if (receiver.map == cacheType) { // The enum cache is in use for {receiver}, the {key} is definitely valid. return key; } return ForInNextSlow( context, slot, receiver, key, cacheType, feedbackVector, UpdateFeedbackMode::kGuaranteedFeedback); } extern macro GetImportMetaObject(Context): Object; extern macro LoadContextFromBaseline(): Context; builtin GetImportMetaObjectBaseline(): Object { const context: Context = LoadContextFromBaseline(); return GetImportMetaObject(context); } } // namespace internal