// 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(maybeFeedbackVector)); try { const vector = Cast(maybeFeedbackVector) otherwise CallRuntime; return Cast(ic::LoadFeedbackVectorSlot(vector, slot)) otherwise CallRuntime; } label CallRuntime deferred { const result = UnsafeCast(runtime::GetTemplateObject( description, shared, Convert(Signed(slot)))); const vector = Cast(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, FeedbackVector, uintptr); extern macro MaybeUpdateFeedback( SmiTagged, Undefined | FeedbackVector, uintptr, constexpr bool); @export transitioning macro ForInNextSlow( context: Context, slot: uintptr, receiver: JSAnyNotSmi, key: JSAny, cacheType: Object, maybeFeedbackVector: Undefined|FeedbackVector, guaranteedFeedback: constexpr bool): JSAny { assert(receiver.map != cacheType); // Handled on the fast path. MaybeUpdateFeedback( SmiTag(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(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, true); } } // namespace internal