| // 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 macro ForInPrepareForTorque( |
| Map | FixedArray, uintptr, Undefined | FeedbackVector): FixedArray; |
| |
| transitioning builtin ForInPrepare(implicit _context: Context)( |
| enumerator: Map|FixedArray, slot: uintptr, |
| maybeFeedbackVector: Undefined|FeedbackVector): FixedArray { |
| return ForInPrepareForTorque(enumerator, slot, maybeFeedbackVector); |
| } |
| |
| extern transitioning builtin ForInFilter(implicit context: Context)( |
| JSAny, HeapObject): JSAny; |
| extern enum ForInFeedback extends uint31 { kAny, ...} |
| extern macro UpdateFeedback( |
| SmiTagged<ForInFeedback>, Undefined | FeedbackVector, uintptr); |
| |
| @export |
| transitioning macro ForInNextSlow( |
| context: Context, slot: uintptr, receiver: JSAnyNotSmi, key: JSAny, |
| cacheType: Object, maybeFeedbackVector: Undefined|FeedbackVector): JSAny { |
| assert(receiver.map != cacheType); // Handled on the fast path. |
| UpdateFeedback( |
| SmiTag<ForInFeedback>(ForInFeedback::kAny), maybeFeedbackVector, slot); |
| 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, |
| maybeFeedbackVector: Undefined|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, maybeFeedbackVector); |
| } |
| |
| } // namespace internal |