1// Copyright 2020 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5namespace internal { 6 7namespace runtime { 8extern runtime GetTemplateObject(implicit context: Context)( 9 TemplateObjectDescription, SharedFunctionInfo, Smi): JSAny; 10extern runtime BytecodeBudgetInterruptFromCode(implicit context: Context)( 11 FeedbackCell): JSAny; 12} 13 14builtin GetTemplateObject( 15 context: Context, shared: SharedFunctionInfo, 16 description: TemplateObjectDescription, slot: uintptr, 17 maybeFeedbackVector: Undefined|FeedbackVector): JSArray { 18 // TODO(jgruber): Consider merging with the GetTemplateObject bytecode 19 // handler; the current advantage of the split implementation is that the 20 // bytecode can skip most work if feedback exists. 21 22 // TODO(v8:9891): Remove this assert once all callers are ported to Torque. 23 // This assert ensures correctness of maybeFeedbackVector's type which can 24 // be easily broken for calls from CSA. 25 assert( 26 IsUndefined(maybeFeedbackVector) || 27 Is<FeedbackVector>(maybeFeedbackVector)); 28 try { 29 const vector = 30 Cast<FeedbackVector>(maybeFeedbackVector) otherwise CallRuntime; 31 return Cast<JSArray>(ic::LoadFeedbackVectorSlot(vector, slot)) 32 otherwise CallRuntime; 33 } label CallRuntime deferred { 34 const result = UnsafeCast<JSArray>(runtime::GetTemplateObject( 35 description, shared, Convert<Smi>(Signed(slot)))); 36 const vector = 37 Cast<FeedbackVector>(maybeFeedbackVector) otherwise return result; 38 ic::StoreFeedbackVectorSlot(vector, slot, result); 39 return result; 40 } 41} 42 43builtin BytecodeBudgetInterruptFromCode(implicit context: Context)( 44 feedbackCell: FeedbackCell): Object { 45 // The runtime call is wrapped by a builtin since the calling sequence in 46 // generated code is shorter for builtins than for runtime calls. 47 tail runtime::BytecodeBudgetInterruptFromCode(feedbackCell); 48} 49 50extern transitioning macro ForInPrepareForTorque( 51 Map | FixedArray, uintptr, Undefined | FeedbackVector): FixedArray; 52 53transitioning builtin ForInPrepare(implicit _context: Context)( 54 enumerator: Map|FixedArray, slot: uintptr, 55 maybeFeedbackVector: Undefined|FeedbackVector): FixedArray { 56 return ForInPrepareForTorque(enumerator, slot, maybeFeedbackVector); 57} 58 59extern transitioning builtin ForInFilter(implicit context: Context)( 60 JSAny, HeapObject): JSAny; 61extern enum ForInFeedback extends uint31 { kAny, ...} 62extern macro UpdateFeedback( 63 SmiTagged<ForInFeedback>, Undefined | FeedbackVector, uintptr); 64 65@export 66transitioning macro ForInNextSlow( 67 context: Context, slot: uintptr, receiver: JSAnyNotSmi, key: JSAny, 68 cacheType: Object, maybeFeedbackVector: Undefined|FeedbackVector): JSAny { 69 assert(receiver.map != cacheType); // Handled on the fast path. 70 UpdateFeedback( 71 SmiTag<ForInFeedback>(ForInFeedback::kAny), maybeFeedbackVector, slot); 72 return ForInFilter(key, receiver); 73} 74 75// Note: the untagged {slot} parameter must be in the first couple of args to 76// guarantee it's allocated in a register. 77transitioning builtin ForInNext( 78 context: Context, slot: uintptr, receiver: JSAnyNotSmi, 79 cacheArray: FixedArray, cacheType: Object, cacheIndex: Smi, 80 maybeFeedbackVector: Undefined|FeedbackVector): JSAny { 81 // Load the next key from the enumeration array. 82 const key = UnsafeCast<JSAny>(cacheArray.objects[cacheIndex]); 83 84 if (receiver.map == cacheType) { 85 // The enum cache is in use for {receiver}, the {key} is definitely valid. 86 return key; 87 } 88 89 return ForInNextSlow( 90 context, slot, receiver, key, cacheType, maybeFeedbackVector); 91} 92 93} // namespace internal 94