Commit 5a6ff768 authored by Marja Hölttä's avatar Marja Hölttä Committed by Commit Bot

[IC] Clarify receiver vs holder vs lookup start object

LoadICParameters already has separate fields for receiver and holder,
though, in practice, they were always equal. Moreover, the holder didn't
mean holder, but the lookup start object.

This CL makes parts of the IC layer reusable for cases where they are
not equal, by clarifying whether we're accessing the receiver, the
lookup_start_object, or the holder.

List of changes:

StoreICParameters:
- Detached from LoadICParameters, now they are independent classes.

LoadICParameters:
- Renamed holder to lookup_start_object.

TryProbeStubCache:
- Renamed receiver to lookup_start_object.

LoadIC:
LoadIC_BytecodeHandler:
LoadIC_NoFeedback:
KeyedLoadIC:
KeyedLoadICGeneric:
KeyedLoadICPolymorphicName:
- These won't be reused in the receiver != lookup_start_object case,
so added asserts that receiver == lookup_start_object.

TryMonomorphicCase:
HandlePolymorphicCase:
LoadIC_Noninlined:
GenericElementLoad:
- Renamed receiver_map param to lookup_start_object_map. The callers
either assert receiver == lookup_start_object, or read the map from the
lookup start object.

GenericPropertyLoad:
- Renamed receiver param to lookup_start_object.
- Renamed receiver_map param to lookup_start_object_map. The callers
either assert receiver == lookup_start_object, or read the map from the
lookup start object.

CallGetterIfAccessor:
- Added the holder parameter and used it accordingly.


Bug: v8:9237
Change-Id: I27aca08f58bd66cc9bd1b1baf9f1ff5565d795eb
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2362918
Commit-Queue: Marja Hölttä <marja@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69606}
parent e8f8bf0a
...@@ -8167,7 +8167,7 @@ void CodeStubAssembler::ForEachEnumerableOwnProperty( ...@@ -8167,7 +8167,7 @@ void CodeStubAssembler::ForEachEnumerableOwnProperty(
{ {
Label slow_load(this, Label::kDeferred); Label slow_load(this, Label::kDeferred);
var_value = CallGetterIfAccessor(var_value.value(), var_value = CallGetterIfAccessor(var_value.value(), object,
var_details.value(), context, var_details.value(), context,
object, &slow_load, kCallJSGetter); object, &slow_load, kCallJSGetter);
Goto(&callback); Goto(&callback);
...@@ -8569,12 +8569,14 @@ void CodeStubAssembler::LoadPropertyFromGlobalDictionary( ...@@ -8569,12 +8569,14 @@ void CodeStubAssembler::LoadPropertyFromGlobalDictionary(
Comment("] LoadPropertyFromGlobalDictionary"); Comment("] LoadPropertyFromGlobalDictionary");
} }
// |value| is the property backing store's contents, which is either a value // |value| is the property backing store's contents, which is either a value or
// or an accessor pair, as specified by |details|. // an accessor pair, as specified by |details|. |holder| is a JSObject or a
// Returns either the original value, or the result of the getter call. // PropertyCell (TODO: use UnionT). Returns either the original value, or the
// result of the getter call.
TNode<Object> CodeStubAssembler::CallGetterIfAccessor( TNode<Object> CodeStubAssembler::CallGetterIfAccessor(
TNode<Object> value, TNode<Uint32T> details, TNode<Context> context, TNode<Object> value, TNode<HeapObject> holder, TNode<Uint32T> details,
TNode<Object> receiver, Label* if_bailout, GetOwnPropertyMode mode) { TNode<Context> context, TNode<Object> receiver, Label* if_bailout,
GetOwnPropertyMode mode) {
TVARIABLE(Object, var_value, value); TVARIABLE(Object, var_value, value);
Label done(this), if_accessor_info(this, Label::kDeferred); Label done(this), if_accessor_info(this, Label::kDeferred);
...@@ -8614,7 +8616,7 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor( ...@@ -8614,7 +8616,7 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor(
GotoIfNot(IsTheHole(cached_property_name), if_bailout); GotoIfNot(IsTheHole(cached_property_name), if_bailout);
TNode<NativeContext> creation_context = TNode<NativeContext> creation_context =
GetCreationContext(CAST(receiver), if_bailout); GetCreationContext(CAST(holder), if_bailout);
var_value = CallBuiltin( var_value = CallBuiltin(
Builtins::kCallFunctionTemplate_CheckAccessAndCompatibleReceiver, Builtins::kCallFunctionTemplate_CheckAccessAndCompatibleReceiver,
creation_context, getter, IntPtrConstant(0), receiver); creation_context, getter, IntPtrConstant(0), receiver);
...@@ -8628,17 +8630,16 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor( ...@@ -8628,17 +8630,16 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor(
// AccessorInfo case. // AccessorInfo case.
BIND(&if_accessor_info); BIND(&if_accessor_info);
{ {
CSA_ASSERT(this, TaggedIsNotSmi(receiver));
TNode<AccessorInfo> accessor_info = CAST(value); TNode<AccessorInfo> accessor_info = CAST(value);
Label if_array(this), if_function(this), if_wrapper(this); Label if_array(this), if_function(this), if_wrapper(this);
// Dispatch based on {receiver} instance type. // Dispatch based on {holder} instance type.
TNode<Map> receiver_map = LoadMap(CAST(receiver)); TNode<Map> holder_map = LoadMap(holder);
TNode<Uint16T> receiver_instance_type = LoadMapInstanceType(receiver_map); TNode<Uint16T> holder_instance_type = LoadMapInstanceType(holder_map);
GotoIf(IsJSArrayInstanceType(receiver_instance_type), &if_array); GotoIf(IsJSArrayInstanceType(holder_instance_type), &if_array);
GotoIf(IsJSFunctionInstanceType(receiver_instance_type), &if_function); GotoIf(IsJSFunctionInstanceType(holder_instance_type), &if_function);
Branch(IsJSPrimitiveWrapperInstanceType(receiver_instance_type), Branch(IsJSPrimitiveWrapperInstanceType(holder_instance_type), &if_wrapper,
&if_wrapper, if_bailout); if_bailout);
// JSArray AccessorInfo case. // JSArray AccessorInfo case.
BIND(&if_array); BIND(&if_array);
...@@ -8647,7 +8648,7 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor( ...@@ -8647,7 +8648,7 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor(
GotoIfNot(IsLengthString( GotoIfNot(IsLengthString(
LoadObjectField(accessor_info, AccessorInfo::kNameOffset)), LoadObjectField(accessor_info, AccessorInfo::kNameOffset)),
if_bailout); if_bailout);
TNode<JSArray> array = CAST(receiver); TNode<JSArray> array = CAST(holder);
var_value = LoadJSArrayLength(array); var_value = LoadJSArrayLength(array);
Goto(&done); Goto(&done);
} }
...@@ -8660,9 +8661,9 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor( ...@@ -8660,9 +8661,9 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor(
LoadObjectField(accessor_info, AccessorInfo::kNameOffset)), LoadObjectField(accessor_info, AccessorInfo::kNameOffset)),
if_bailout); if_bailout);
GotoIfPrototypeRequiresRuntimeLookup(CAST(receiver), receiver_map, TNode<JSFunction> function = CAST(holder);
if_bailout); GotoIfPrototypeRequiresRuntimeLookup(function, holder_map, if_bailout);
var_value = LoadJSFunctionPrototype(CAST(receiver), if_bailout); var_value = LoadJSFunctionPrototype(function, if_bailout);
Goto(&done); Goto(&done);
} }
...@@ -8674,11 +8675,10 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor( ...@@ -8674,11 +8675,10 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor(
GotoIfNot(IsLengthString( GotoIfNot(IsLengthString(
LoadObjectField(accessor_info, AccessorInfo::kNameOffset)), LoadObjectField(accessor_info, AccessorInfo::kNameOffset)),
if_bailout); if_bailout);
TNode<Object> receiver_value = TNode<Object> holder_value = LoadJSPrimitiveWrapperValue(CAST(holder));
LoadJSPrimitiveWrapperValue(CAST(receiver)); GotoIfNot(TaggedIsNotSmi(holder_value), if_bailout);
GotoIfNot(TaggedIsNotSmi(receiver_value), if_bailout); GotoIfNot(IsString(CAST(holder_value)), if_bailout);
GotoIfNot(IsString(CAST(receiver_value)), if_bailout); var_value = LoadStringLengthAsSmi(CAST(holder_value));
var_value = LoadStringLengthAsSmi(CAST(receiver_value));
Goto(&done); Goto(&done);
} }
} }
...@@ -8754,8 +8754,8 @@ void CodeStubAssembler::TryGetOwnProperty( ...@@ -8754,8 +8754,8 @@ void CodeStubAssembler::TryGetOwnProperty(
*var_raw_value = *var_value; *var_raw_value = *var_value;
} }
TNode<Object> value = TNode<Object> value =
CallGetterIfAccessor(var_value->value(), var_details->value(), context, CallGetterIfAccessor(var_value->value(), object, var_details->value(),
receiver, if_bailout, mode); context, receiver, if_bailout, mode);
*var_value = value; *var_value = value;
Goto(if_found_value); Goto(if_found_value);
} }
......
...@@ -3527,6 +3527,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -3527,6 +3527,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
Label* bailout); Label* bailout);
TNode<Object> CallGetterIfAccessor(TNode<Object> value, TNode<Object> CallGetterIfAccessor(TNode<Object> value,
TNode<HeapObject> holder,
TNode<Uint32T> details, TNode<Uint32T> details,
TNode<Context> context, TNode<Context> context,
TNode<Object> receiver, Label* if_bailout, TNode<Object> receiver, Label* if_bailout,
......
...@@ -65,7 +65,7 @@ TNode<MaybeObject> AccessorAssembler::LoadHandlerDataField( ...@@ -65,7 +65,7 @@ TNode<MaybeObject> AccessorAssembler::LoadHandlerDataField(
TNode<MaybeObject> AccessorAssembler::TryMonomorphicCase( TNode<MaybeObject> AccessorAssembler::TryMonomorphicCase(
TNode<TaggedIndex> slot, TNode<FeedbackVector> vector, TNode<TaggedIndex> slot, TNode<FeedbackVector> vector,
TNode<Map> receiver_map, Label* if_handler, TNode<Map> lookup_start_object_map, Label* if_handler,
TVariable<MaybeObject>* var_handler, Label* if_miss) { TVariable<MaybeObject>* var_handler, Label* if_miss) {
Comment("TryMonomorphicCase"); Comment("TryMonomorphicCase");
DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
...@@ -83,7 +83,7 @@ TNode<MaybeObject> AccessorAssembler::TryMonomorphicCase( ...@@ -83,7 +83,7 @@ TNode<MaybeObject> AccessorAssembler::TryMonomorphicCase(
// Try to quickly handle the monomorphic case without knowing for sure // Try to quickly handle the monomorphic case without knowing for sure
// if we have a weak reference in feedback. // if we have a weak reference in feedback.
GotoIfNot(IsWeakReferenceTo(feedback, receiver_map), if_miss); GotoIfNot(IsWeakReferenceTo(feedback, lookup_start_object_map), if_miss);
TNode<MaybeObject> handler = UncheckedCast<MaybeObject>( TNode<MaybeObject> handler = UncheckedCast<MaybeObject>(
Load(MachineType::AnyTagged(), vector, Load(MachineType::AnyTagged(), vector,
...@@ -95,8 +95,8 @@ TNode<MaybeObject> AccessorAssembler::TryMonomorphicCase( ...@@ -95,8 +95,8 @@ TNode<MaybeObject> AccessorAssembler::TryMonomorphicCase(
} }
void AccessorAssembler::HandlePolymorphicCase( void AccessorAssembler::HandlePolymorphicCase(
TNode<Map> receiver_map, TNode<WeakFixedArray> feedback, Label* if_handler, TNode<Map> lookup_start_object_map, TNode<WeakFixedArray> feedback,
TVariable<MaybeObject>* var_handler, Label* if_miss) { Label* if_handler, TVariable<MaybeObject>* var_handler, Label* if_miss) {
Comment("HandlePolymorphicCase"); Comment("HandlePolymorphicCase");
DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
...@@ -118,7 +118,8 @@ void AccessorAssembler::HandlePolymorphicCase( ...@@ -118,7 +118,8 @@ void AccessorAssembler::HandlePolymorphicCase(
TNode<MaybeObject> maybe_cached_map = TNode<MaybeObject> maybe_cached_map =
LoadWeakFixedArrayElement(feedback, var_index.value()); LoadWeakFixedArrayElement(feedback, var_index.value());
CSA_ASSERT(this, IsWeakOrCleared(maybe_cached_map)); CSA_ASSERT(this, IsWeakOrCleared(maybe_cached_map));
GotoIfNot(IsWeakReferenceTo(maybe_cached_map, receiver_map), &loop_next); GotoIfNot(IsWeakReferenceTo(maybe_cached_map, lookup_start_object_map),
&loop_next);
// Found, now call handler. // Found, now call handler.
TNode<MaybeObject> handler = TNode<MaybeObject> handler =
...@@ -140,7 +141,7 @@ void AccessorAssembler::HandleLoadICHandlerCase( ...@@ -140,7 +141,7 @@ void AccessorAssembler::HandleLoadICHandlerCase(
ElementSupport support_elements, LoadAccessMode access_mode) { ElementSupport support_elements, LoadAccessMode access_mode) {
Comment("have_handler"); Comment("have_handler");
TVARIABLE(Object, var_holder, p->holder()); TVARIABLE(Object, var_holder, p->lookup_start_object());
TVARIABLE(Object, var_smi_handler, handler); TVARIABLE(Object, var_smi_handler, handler);
Label if_smi_handler(this, {&var_holder, &var_smi_handler}); Label if_smi_handler(this, {&var_holder, &var_smi_handler});
...@@ -212,7 +213,7 @@ void AccessorAssembler::HandleLoadAccessor( ...@@ -212,7 +213,7 @@ void AccessorAssembler::HandleLoadAccessor(
TNode<Object> data = TNode<Object> data =
LoadObjectField(call_handler_info, CallHandlerInfo::kDataOffset); LoadObjectField(call_handler_info, CallHandlerInfo::kDataOffset);
TVARIABLE(HeapObject, api_holder, CAST(p->receiver())); TVARIABLE(HeapObject, api_holder, CAST(p->lookup_start_object()));
Label load(this); Label load(this);
GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kApiGetter)), GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kApiGetter)),
&load); &load);
...@@ -222,7 +223,7 @@ void AccessorAssembler::HandleLoadAccessor( ...@@ -222,7 +223,7 @@ void AccessorAssembler::HandleLoadAccessor(
WordEqual(handler_kind, WordEqual(handler_kind,
IntPtrConstant(LoadHandler::kApiGetterHolderIsPrototype))); IntPtrConstant(LoadHandler::kApiGetterHolderIsPrototype)));
api_holder = LoadMapPrototype(LoadMap(CAST(p->receiver()))); api_holder = LoadMapPrototype(LoadMap(CAST(p->lookup_start_object())));
Goto(&load); Goto(&load);
BIND(&load); BIND(&load);
...@@ -546,9 +547,9 @@ void AccessorAssembler::HandleLoadICSmiHandlerLoadNamedCase( ...@@ -546,9 +547,9 @@ void AccessorAssembler::HandleLoadICSmiHandlerLoadNamedCase(
TVARIABLE(Object, var_value); TVARIABLE(Object, var_value);
LoadPropertyFromNameDictionary(properties, var_name_index.value(), LoadPropertyFromNameDictionary(properties, var_name_index.value(),
&var_details, &var_value); &var_details, &var_value);
TNode<Object> value = TNode<Object> value = CallGetterIfAccessor(
CallGetterIfAccessor(var_value.value(), var_details.value(), var_value.value(), CAST(holder), var_details.value(), p->context(),
p->context(), p->receiver(), miss); p->receiver(), miss);
exit_point->Return(value); exit_point->Return(value);
} }
} }
...@@ -631,8 +632,8 @@ void AccessorAssembler::HandleLoadICSmiHandlerLoadNamedCase( ...@@ -631,8 +632,8 @@ void AccessorAssembler::HandleLoadICSmiHandlerLoadNamedCase(
CAST(holder), PropertyCell::kPropertyDetailsRawOffset)); CAST(holder), PropertyCell::kPropertyDetailsRawOffset));
GotoIf(IsTheHole(value), miss); GotoIf(IsTheHole(value), miss);
exit_point->Return(CallGetterIfAccessor(value, details, p->context(), exit_point->Return(CallGetterIfAccessor(value, CAST(holder), details,
p->receiver(), miss)); p->context(), p->receiver(), miss));
} }
BIND(&interceptor); BIND(&interceptor);
...@@ -907,9 +908,9 @@ void AccessorAssembler::HandleLoadICProtoHandler( ...@@ -907,9 +908,9 @@ void AccessorAssembler::HandleLoadICProtoHandler(
TVARIABLE(Object, var_value); TVARIABLE(Object, var_value);
LoadPropertyFromNameDictionary(properties, name_index, &var_details, LoadPropertyFromNameDictionary(properties, name_index, &var_details,
&var_value); &var_value);
TNode<Object> value = TNode<Object> value = CallGetterIfAccessor(
CallGetterIfAccessor(var_value.value(), var_details.value(), var_value.value(), CAST(var_holder->value()), var_details.value(),
p->context(), p->receiver(), miss); p->context(), p->receiver(), miss);
exit_point->Return(value); exit_point->Return(value);
} }
}, },
...@@ -1614,9 +1615,8 @@ void AccessorAssembler::HandleStoreICProtoHandler( ...@@ -1614,9 +1615,8 @@ void AccessorAssembler::HandleStoreICProtoHandler(
BIND(&if_add_normal); BIND(&if_add_normal);
{ {
// This is a case of "transitioning store" to a dictionary mode object // This is a case of "transitioning store" to a dictionary mode object
// when the property is still does not exist. The "existing property" // when the property does not exist. The "existing property" case is
// case is covered above by LookupOnReceiver bit handling of the smi // covered above by LookupOnReceiver bit handling of the smi handler.
// handler.
Label slow(this); Label slow(this);
TNode<Map> receiver_map = LoadMap(CAST(p->receiver())); TNode<Map> receiver_map = LoadMap(CAST(p->receiver()));
InvalidateValidityCellIfPrototype(receiver_map); InvalidateValidityCellIfPrototype(receiver_map);
...@@ -2281,10 +2281,10 @@ void AccessorAssembler::InvalidateValidityCellIfPrototype( ...@@ -2281,10 +2281,10 @@ void AccessorAssembler::InvalidateValidityCellIfPrototype(
BIND(&cont); BIND(&cont);
} }
void AccessorAssembler::GenericElementLoad(TNode<HeapObject> receiver, void AccessorAssembler::GenericElementLoad(
TNode<Map> receiver_map, TNode<HeapObject> lookup_start_object, TNode<Map> lookup_start_object_map,
TNode<Int32T> instance_type, TNode<Int32T> lookup_start_object_instance_type, TNode<IntPtrT> index,
TNode<IntPtrT> index, Label* slow) { Label* slow) {
Comment("integer index"); Comment("integer index");
ExitPoint direct_exit(this); ExitPoint direct_exit(this);
...@@ -2293,18 +2293,22 @@ void AccessorAssembler::GenericElementLoad(TNode<HeapObject> receiver, ...@@ -2293,18 +2293,22 @@ void AccessorAssembler::GenericElementLoad(TNode<HeapObject> receiver,
Label return_undefined(this); Label return_undefined(this);
// Receivers requiring non-standard element accesses (interceptors, access // Receivers requiring non-standard element accesses (interceptors, access
// checks, strings and string wrappers, proxies) are handled in the runtime. // checks, strings and string wrappers, proxies) are handled in the runtime.
GotoIf(IsCustomElementsReceiverInstanceType(instance_type), &if_custom); GotoIf(
TNode<Int32T> elements_kind = LoadMapElementsKind(receiver_map); IsCustomElementsReceiverInstanceType(lookup_start_object_instance_type),
TNode<BoolT> is_jsarray_condition = IsJSArrayInstanceType(instance_type); &if_custom);
TNode<Int32T> elements_kind = LoadMapElementsKind(lookup_start_object_map);
TNode<BoolT> is_jsarray_condition =
IsJSArrayInstanceType(lookup_start_object_instance_type);
TVARIABLE(Float64T, var_double_value); TVARIABLE(Float64T, var_double_value);
Label rebox_double(this, &var_double_value); Label rebox_double(this, &var_double_value);
// Unimplemented elements kinds fall back to a runtime call. // Unimplemented elements kinds fall back to a runtime call.
Label* unimplemented_elements_kind = slow; Label* unimplemented_elements_kind = slow;
IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1); IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1);
EmitElementLoad(receiver, elements_kind, index, is_jsarray_condition, EmitElementLoad(lookup_start_object, elements_kind, index,
&if_element_hole, &rebox_double, &var_double_value, is_jsarray_condition, &if_element_hole, &rebox_double,
unimplemented_elements_kind, &if_oob, slow, &direct_exit); &var_double_value, unimplemented_elements_kind, &if_oob, slow,
&direct_exit);
BIND(&rebox_double); BIND(&rebox_double);
Return(AllocateHeapNumberWithValue(var_double_value.value())); Return(AllocateHeapNumberWithValue(var_double_value.value()));
...@@ -2314,7 +2318,8 @@ void AccessorAssembler::GenericElementLoad(TNode<HeapObject> receiver, ...@@ -2314,7 +2318,8 @@ void AccessorAssembler::GenericElementLoad(TNode<HeapObject> receiver,
Comment("out of bounds"); Comment("out of bounds");
// On TypedArrays, all OOB loads (positive and negative) return undefined // On TypedArrays, all OOB loads (positive and negative) return undefined
// without ever checking the prototype chain. // without ever checking the prototype chain.
GotoIf(IsJSTypedArrayInstanceType(instance_type), &return_undefined); GotoIf(IsJSTypedArrayInstanceType(lookup_start_object_instance_type),
&return_undefined);
// Positive OOB indices within JSArray index range are effectively the same // Positive OOB indices within JSArray index range are effectively the same
// as hole loads. Larger keys and negative keys are named loads. // as hole loads. Larger keys and negative keys are named loads.
if (Is64()) { if (Is64()) {
...@@ -2329,35 +2334,35 @@ void AccessorAssembler::GenericElementLoad(TNode<HeapObject> receiver, ...@@ -2329,35 +2334,35 @@ void AccessorAssembler::GenericElementLoad(TNode<HeapObject> receiver,
BIND(&if_element_hole); BIND(&if_element_hole);
{ {
Comment("found the hole"); Comment("found the hole");
BranchIfPrototypesHaveNoElements(receiver_map, &return_undefined, slow); BranchIfPrototypesHaveNoElements(lookup_start_object_map, &return_undefined,
slow);
} }
BIND(&if_custom); BIND(&if_custom);
{ {
Comment("check if string"); Comment("check if string");
GotoIfNot(IsStringInstanceType(instance_type), slow); GotoIfNot(IsStringInstanceType(lookup_start_object_instance_type), slow);
Comment("load string character"); Comment("load string character");
TNode<IntPtrT> length = LoadStringLengthAsWord(CAST(receiver)); TNode<IntPtrT> length = LoadStringLengthAsWord(CAST(lookup_start_object));
GotoIfNot(UintPtrLessThan(index, length), slow); GotoIfNot(UintPtrLessThan(index, length), slow);
IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1); IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1);
TailCallBuiltin(Builtins::kStringCharAt, NoContextConstant(), receiver, TailCallBuiltin(Builtins::kStringCharAt, NoContextConstant(),
index); lookup_start_object, index);
} }
BIND(&return_undefined); BIND(&return_undefined);
Return(UndefinedConstant()); Return(UndefinedConstant());
} }
void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver, void AccessorAssembler::GenericPropertyLoad(
TNode<Map> receiver_map, TNode<HeapObject> lookup_start_object, TNode<Map> lookup_start_object_map,
TNode<Int32T> instance_type, TNode<Int32T> lookup_start_object_instance_type, const LoadICParameters* p,
const LoadICParameters* p, Label* slow, UseStubCache use_stub_cache) {
Label* slow, DCHECK_EQ(lookup_start_object, p->receiver_and_lookup_start_object());
UseStubCache use_stub_cache) {
ExitPoint direct_exit(this); ExitPoint direct_exit(this);
Comment("key is unique name"); Comment("key is unique name");
Label if_found_on_receiver(this), if_property_dictionary(this), Label if_found_on_lookup_start_object(this), if_property_dictionary(this),
lookup_prototype_chain(this), special_receiver(this); lookup_prototype_chain(this), special_receiver(this);
TVARIABLE(Uint32T, var_details); TVARIABLE(Uint32T, var_details);
TVARIABLE(Object, var_value); TVARIABLE(Object, var_value);
...@@ -2366,16 +2371,18 @@ void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver, ...@@ -2366,16 +2371,18 @@ void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver,
// Receivers requiring non-standard accesses (interceptors, access // Receivers requiring non-standard accesses (interceptors, access
// checks, strings and string wrappers) are handled in the runtime. // checks, strings and string wrappers) are handled in the runtime.
GotoIf(IsSpecialReceiverInstanceType(instance_type), &special_receiver); GotoIf(IsSpecialReceiverInstanceType(lookup_start_object_instance_type),
&special_receiver);
// Check if the receiver has fast or slow properties. // Check if the lookup_start_object has fast or slow properties.
TNode<Uint32T> bitfield3 = LoadMapBitField3(receiver_map); TNode<Uint32T> bitfield3 = LoadMapBitField3(lookup_start_object_map);
GotoIf(IsSetWord32<Map::Bits3::IsDictionaryMapBit>(bitfield3), GotoIf(IsSetWord32<Map::Bits3::IsDictionaryMapBit>(bitfield3),
&if_property_dictionary); &if_property_dictionary);
// Try looking up the property on the receiver; if unsuccessful, look // Try looking up the property on the lookup_start_object; if unsuccessful,
// for a handler in the stub cache. // look for a handler in the stub cache.
TNode<DescriptorArray> descriptors = LoadMapDescriptors(receiver_map); TNode<DescriptorArray> descriptors =
LoadMapDescriptors(lookup_start_object_map);
Label if_descriptor_found(this), try_stub_cache(this); Label if_descriptor_found(this), try_stub_cache(this);
TVARIABLE(IntPtrT, var_name_index); TVARIABLE(IntPtrT, var_name_index);
...@@ -2386,10 +2393,10 @@ void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver, ...@@ -2386,10 +2393,10 @@ void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver,
BIND(&if_descriptor_found); BIND(&if_descriptor_found);
{ {
LoadPropertyFromFastObject(receiver, receiver_map, descriptors, LoadPropertyFromFastObject(lookup_start_object, lookup_start_object_map,
var_name_index.value(), &var_details, descriptors, var_name_index.value(),
&var_value); &var_details, &var_value);
Goto(&if_found_on_receiver); Goto(&if_found_on_lookup_start_object);
} }
if (use_stub_cache == kUseStubCache) { if (use_stub_cache == kUseStubCache) {
...@@ -2404,7 +2411,7 @@ void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver, ...@@ -2404,7 +2411,7 @@ void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver,
Comment("stub cache probe for fast property load"); Comment("stub cache probe for fast property load");
TVARIABLE(MaybeObject, var_handler); TVARIABLE(MaybeObject, var_handler);
Label found_handler(this, &var_handler), stub_cache_miss(this); Label found_handler(this, &var_handler), stub_cache_miss(this);
TryProbeStubCache(isolate()->load_stub_cache(), receiver, name, TryProbeStubCache(isolate()->load_stub_cache(), lookup_start_object, name,
&found_handler, &var_handler, &stub_cache_miss); &found_handler, &var_handler, &stub_cache_miss);
BIND(&found_handler); BIND(&found_handler);
{ {
...@@ -2418,8 +2425,9 @@ void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver, ...@@ -2418,8 +2425,9 @@ void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver,
// TODO(jkummerow): Check if the property exists on the prototype // TODO(jkummerow): Check if the property exists on the prototype
// chain. If it doesn't, then there's no point in missing. // chain. If it doesn't, then there's no point in missing.
Comment("KeyedLoadGeneric_miss"); Comment("KeyedLoadGeneric_miss");
TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context(), p->receiver(), TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context(),
name, p->slot(), p->vector()); p->receiver_and_lookup_start_object(), name, p->slot(),
p->vector());
} }
} }
...@@ -2431,7 +2439,8 @@ void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver, ...@@ -2431,7 +2439,8 @@ void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver,
TVARIABLE(IntPtrT, var_name_index); TVARIABLE(IntPtrT, var_name_index);
Label dictionary_found(this, &var_name_index); Label dictionary_found(this, &var_name_index);
TNode<NameDictionary> properties = CAST(LoadSlowProperties(CAST(receiver))); TNode<NameDictionary> properties =
CAST(LoadSlowProperties(CAST(lookup_start_object)));
NameDictionaryLookup<NameDictionary>(properties, name, &dictionary_found, NameDictionaryLookup<NameDictionary>(properties, name, &dictionary_found,
&var_name_index, &var_name_index,
&lookup_prototype_chain); &lookup_prototype_chain);
...@@ -2439,14 +2448,15 @@ void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver, ...@@ -2439,14 +2448,15 @@ void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver,
{ {
LoadPropertyFromNameDictionary(properties, var_name_index.value(), LoadPropertyFromNameDictionary(properties, var_name_index.value(),
&var_details, &var_value); &var_details, &var_value);
Goto(&if_found_on_receiver); Goto(&if_found_on_lookup_start_object);
} }
} }
BIND(&if_found_on_receiver); BIND(&if_found_on_lookup_start_object);
{ {
TNode<Object> value = CallGetterIfAccessor( TNode<Object> value = CallGetterIfAccessor(
var_value.value(), var_details.value(), p->context(), receiver, slow); var_value.value(), lookup_start_object, var_details.value(),
p->context(), p->receiver(), slow);
IncrementCounter(isolate()->counters()->ic_keyed_load_generic_symbol(), 1); IncrementCounter(isolate()->counters()->ic_keyed_load_generic_symbol(), 1);
Return(value); Return(value);
} }
...@@ -2458,8 +2468,8 @@ void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver, ...@@ -2458,8 +2468,8 @@ void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver,
Label return_undefined(this), is_private_symbol(this); Label return_undefined(this), is_private_symbol(this);
Label loop(this, {&var_holder_map, &var_holder_instance_type}); Label loop(this, {&var_holder_map, &var_holder_instance_type});
var_holder_map = receiver_map; var_holder_map = lookup_start_object_map;
var_holder_instance_type = instance_type; var_holder_instance_type = lookup_start_object_instance_type;
GotoIf(IsPrivateSymbol(name), &is_private_symbol); GotoIf(IsPrivateSymbol(name), &is_private_symbol);
Goto(&loop); Goto(&loop);
...@@ -2476,9 +2486,9 @@ void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver, ...@@ -2476,9 +2486,9 @@ void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver,
var_holder_map = proto_map; var_holder_map = proto_map;
var_holder_instance_type = proto_instance_type; var_holder_instance_type = proto_instance_type;
Label next_proto(this), return_value(this, &var_value), goto_slow(this); Label next_proto(this), return_value(this, &var_value), goto_slow(this);
TryGetOwnProperty(p->context(), receiver, CAST(proto), proto_map, TryGetOwnProperty(p->context(), CAST(p->receiver()), CAST(proto),
proto_instance_type, name, &return_value, &var_value, proto_map, proto_instance_type, name, &return_value,
&next_proto, &goto_slow); &var_value, &next_proto, &goto_slow);
// This trampoline and the next are required to appease Turbofan's // This trampoline and the next are required to appease Turbofan's
// variable merging. // variable merging.
...@@ -2509,15 +2519,17 @@ void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver, ...@@ -2509,15 +2519,17 @@ void AccessorAssembler::GenericPropertyLoad(TNode<HeapObject> receiver,
BIND(&special_receiver); BIND(&special_receiver);
{ {
// TODO(jkummerow): Consider supporting JSModuleNamespace. // TODO(jkummerow): Consider supporting JSModuleNamespace.
GotoIfNot(InstanceTypeEqual(instance_type, JS_PROXY_TYPE), slow); GotoIfNot(
InstanceTypeEqual(lookup_start_object_instance_type, JS_PROXY_TYPE),
slow);
// Private field/symbol lookup is not supported. // Private field/symbol lookup is not supported.
GotoIf(IsPrivateSymbol(name), slow); GotoIf(IsPrivateSymbol(name), slow);
direct_exit.ReturnCallStub( direct_exit.ReturnCallStub(
Builtins::CallableFor(isolate(), Builtins::kProxyGetProperty), Builtins::CallableFor(isolate(), Builtins::kProxyGetProperty),
p->context(), receiver /*holder is the same as receiver*/, name, p->context(), lookup_start_object, name, p->receiver(),
receiver, SmiConstant(OnNonExistent::kReturnUndefined)); SmiConstant(OnNonExistent::kReturnUndefined));
} }
} }
...@@ -2605,7 +2617,7 @@ void AccessorAssembler::TryProbeStubCacheTable( ...@@ -2605,7 +2617,7 @@ void AccessorAssembler::TryProbeStubCacheTable(
} }
void AccessorAssembler::TryProbeStubCache(StubCache* stub_cache, void AccessorAssembler::TryProbeStubCache(StubCache* stub_cache,
TNode<Object> receiver, TNode<Object> lookup_start_object,
TNode<Name> name, Label* if_handler, TNode<Name> name, Label* if_handler,
TVariable<MaybeObject>* var_handler, TVariable<MaybeObject>* var_handler,
Label* if_miss) { Label* if_miss) {
...@@ -2614,15 +2626,17 @@ void AccessorAssembler::TryProbeStubCache(StubCache* stub_cache, ...@@ -2614,15 +2626,17 @@ void AccessorAssembler::TryProbeStubCache(StubCache* stub_cache,
Counters* counters = isolate()->counters(); Counters* counters = isolate()->counters();
IncrementCounter(counters->megamorphic_stub_cache_probes(), 1); IncrementCounter(counters->megamorphic_stub_cache_probes(), 1);
// Check that the {receiver} isn't a smi. // Check that the {lookup_start_object} isn't a smi.
GotoIf(TaggedIsSmi(receiver), &miss); GotoIf(TaggedIsSmi(lookup_start_object), &miss);
TNode<Map> receiver_map = LoadMap(CAST(receiver)); TNode<Map> lookup_start_object_map = LoadMap(CAST(lookup_start_object));
// Probe the primary table. // Probe the primary table.
TNode<IntPtrT> primary_offset = StubCachePrimaryOffset(name, receiver_map); TNode<IntPtrT> primary_offset =
StubCachePrimaryOffset(name, lookup_start_object_map);
TryProbeStubCacheTable(stub_cache, kPrimary, primary_offset, name, TryProbeStubCacheTable(stub_cache, kPrimary, primary_offset, name,
receiver_map, if_handler, var_handler, &try_secondary); lookup_start_object_map, if_handler, var_handler,
&try_secondary);
BIND(&try_secondary); BIND(&try_secondary);
{ {
...@@ -2630,7 +2644,8 @@ void AccessorAssembler::TryProbeStubCache(StubCache* stub_cache, ...@@ -2630,7 +2644,8 @@ void AccessorAssembler::TryProbeStubCache(StubCache* stub_cache,
TNode<IntPtrT> secondary_offset = TNode<IntPtrT> secondary_offset =
StubCacheSecondaryOffset(name, primary_offset); StubCacheSecondaryOffset(name, primary_offset);
TryProbeStubCacheTable(stub_cache, kSecondary, secondary_offset, name, TryProbeStubCacheTable(stub_cache, kSecondary, secondary_offset, name,
receiver_map, if_handler, var_handler, &miss); lookup_start_object_map, if_handler, var_handler,
&miss);
} }
BIND(&miss); BIND(&miss);
...@@ -2658,8 +2673,9 @@ void AccessorAssembler::LoadIC_BytecodeHandler(const LazyLoadICParameters* p, ...@@ -2658,8 +2673,9 @@ void AccessorAssembler::LoadIC_BytecodeHandler(const LazyLoadICParameters* p,
GotoIf(IsUndefined(p->vector()), &no_feedback); GotoIf(IsUndefined(p->vector()), &no_feedback);
TNode<Map> recv_map = LoadReceiverMap(p->receiver()); TNode<Map> lookup_start_object_map =
GotoIf(IsDeprecatedMap(recv_map), &miss); LoadReceiverMap(p->receiver_and_lookup_start_object());
GotoIf(IsDeprecatedMap(lookup_start_object_map), &miss);
// Inlined fast path. // Inlined fast path.
{ {
...@@ -2668,9 +2684,9 @@ void AccessorAssembler::LoadIC_BytecodeHandler(const LazyLoadICParameters* p, ...@@ -2668,9 +2684,9 @@ void AccessorAssembler::LoadIC_BytecodeHandler(const LazyLoadICParameters* p,
TVARIABLE(MaybeObject, var_handler); TVARIABLE(MaybeObject, var_handler);
Label try_polymorphic(this), if_handler(this, &var_handler); Label try_polymorphic(this), if_handler(this, &var_handler);
TNode<MaybeObject> feedback = TNode<MaybeObject> feedback = TryMonomorphicCase(
TryMonomorphicCase(p->slot(), CAST(p->vector()), recv_map, &if_handler, p->slot(), CAST(p->vector()), lookup_start_object_map, &if_handler,
&var_handler, &try_polymorphic); &var_handler, &try_polymorphic);
BIND(&if_handler); BIND(&if_handler);
HandleLoadICHandlerCase(p, CAST(var_handler.value()), &miss, exit_point); HandleLoadICHandlerCase(p, CAST(var_handler.value()), &miss, exit_point);
...@@ -2680,8 +2696,8 @@ void AccessorAssembler::LoadIC_BytecodeHandler(const LazyLoadICParameters* p, ...@@ -2680,8 +2696,8 @@ void AccessorAssembler::LoadIC_BytecodeHandler(const LazyLoadICParameters* p,
TNode<HeapObject> strong_feedback = TNode<HeapObject> strong_feedback =
GetHeapObjectIfStrong(feedback, &miss); GetHeapObjectIfStrong(feedback, &miss);
GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &stub_call); GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &stub_call);
HandlePolymorphicCase(recv_map, CAST(strong_feedback), &if_handler, HandlePolymorphicCase(lookup_start_object_map, CAST(strong_feedback),
&var_handler, &miss); &if_handler, &var_handler, &miss);
} }
} }
...@@ -2694,8 +2710,8 @@ void AccessorAssembler::LoadIC_BytecodeHandler(const LazyLoadICParameters* p, ...@@ -2694,8 +2710,8 @@ void AccessorAssembler::LoadIC_BytecodeHandler(const LazyLoadICParameters* p,
Builtins::CallableFor(isolate(), Builtins::kLoadIC_Noninlined); Builtins::CallableFor(isolate(), Builtins::kLoadIC_Noninlined);
TNode<Code> code_target = HeapConstant(ic.code()); TNode<Code> code_target = HeapConstant(ic.code());
exit_point->ReturnCallStub(ic.descriptor(), code_target, p->context(), exit_point->ReturnCallStub(ic.descriptor(), code_target, p->context(),
p->receiver(), p->name(), p->slot(), p->receiver_and_lookup_start_object(), p->name(),
p->vector()); p->slot(), p->vector());
} }
BIND(&no_feedback); BIND(&no_feedback);
...@@ -2727,12 +2743,13 @@ void AccessorAssembler::LoadIC(const LoadICParameters* p) { ...@@ -2727,12 +2743,13 @@ void AccessorAssembler::LoadIC(const LoadICParameters* p) {
Label if_handler(this, &var_handler), non_inlined(this, Label::kDeferred), Label if_handler(this, &var_handler), non_inlined(this, Label::kDeferred),
try_polymorphic(this), miss(this, Label::kDeferred); try_polymorphic(this), miss(this, Label::kDeferred);
TNode<Map> receiver_map = LoadReceiverMap(p->receiver()); TNode<Map> lookup_start_object_map =
GotoIf(IsDeprecatedMap(receiver_map), &miss); LoadReceiverMap(p->receiver_and_lookup_start_object());
GotoIf(IsDeprecatedMap(lookup_start_object_map), &miss);
// Check monomorphic case. // Check monomorphic case.
TNode<MaybeObject> feedback = TNode<MaybeObject> feedback =
TryMonomorphicCase(p->slot(), CAST(p->vector()), receiver_map, TryMonomorphicCase(p->slot(), CAST(p->vector()), lookup_start_object_map,
&if_handler, &var_handler, &try_polymorphic); &if_handler, &var_handler, &try_polymorphic);
BIND(&if_handler); BIND(&if_handler);
{ {
...@@ -2747,32 +2764,32 @@ void AccessorAssembler::LoadIC(const LoadICParameters* p) { ...@@ -2747,32 +2764,32 @@ void AccessorAssembler::LoadIC(const LoadICParameters* p) {
// Check polymorphic case. // Check polymorphic case.
Comment("LoadIC_try_polymorphic"); Comment("LoadIC_try_polymorphic");
GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &non_inlined); GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &non_inlined);
HandlePolymorphicCase(receiver_map, CAST(strong_feedback), &if_handler, HandlePolymorphicCase(lookup_start_object_map, CAST(strong_feedback),
&var_handler, &miss); &if_handler, &var_handler, &miss);
} }
BIND(&non_inlined); BIND(&non_inlined);
{ {
LoadIC_Noninlined(p, receiver_map, strong_feedback, &var_handler, LoadIC_Noninlined(p, lookup_start_object_map, strong_feedback, &var_handler,
&if_handler, &miss, &direct_exit); &if_handler, &miss, &direct_exit);
} }
BIND(&miss); BIND(&miss);
direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, p->context(), direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, p->context(),
p->receiver(), p->name(), p->slot(), p->receiver_and_lookup_start_object(),
p->vector()); p->name(), p->slot(), p->vector());
} }
void AccessorAssembler::LoadIC_Noninlined(const LoadICParameters* p, void AccessorAssembler::LoadIC_Noninlined(const LoadICParameters* p,
TNode<Map> receiver_map, TNode<Map> lookup_start_object_map,
TNode<HeapObject> feedback, TNode<HeapObject> feedback,
TVariable<MaybeObject>* var_handler, TVariable<MaybeObject>* var_handler,
Label* if_handler, Label* miss, Label* if_handler, Label* miss,
ExitPoint* exit_point) { ExitPoint* exit_point) {
// Neither deprecated map nor monomorphic. These cases are handled in the // Neither deprecated map nor monomorphic. These cases are handled in the
// bytecode handler. // bytecode handler.
CSA_ASSERT(this, Word32BinaryNot(IsDeprecatedMap(receiver_map))); CSA_ASSERT(this, Word32BinaryNot(IsDeprecatedMap(lookup_start_object_map)));
CSA_ASSERT(this, TaggedNotEqual(receiver_map, feedback)); CSA_ASSERT(this, TaggedNotEqual(lookup_start_object_map, feedback));
CSA_ASSERT(this, Word32BinaryNot(IsWeakFixedArrayMap(LoadMap(feedback)))); CSA_ASSERT(this, Word32BinaryNot(IsWeakFixedArrayMap(LoadMap(feedback))));
DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
...@@ -2780,7 +2797,7 @@ void AccessorAssembler::LoadIC_Noninlined(const LoadICParameters* p, ...@@ -2780,7 +2797,7 @@ void AccessorAssembler::LoadIC_Noninlined(const LoadICParameters* p,
// Check megamorphic case. // Check megamorphic case.
GotoIfNot(TaggedEqual(feedback, MegamorphicSymbolConstant()), miss); GotoIfNot(TaggedEqual(feedback, MegamorphicSymbolConstant()), miss);
TryProbeStubCache(isolate()->load_stub_cache(), p->receiver(), TryProbeStubCache(isolate()->load_stub_cache(), p->lookup_start_object(),
CAST(p->name()), if_handler, var_handler, miss); CAST(p->name()), if_handler, var_handler, miss);
} }
} }
...@@ -2788,12 +2805,12 @@ void AccessorAssembler::LoadIC_Noninlined(const LoadICParameters* p, ...@@ -2788,12 +2805,12 @@ void AccessorAssembler::LoadIC_Noninlined(const LoadICParameters* p,
void AccessorAssembler::LoadIC_NoFeedback(const LoadICParameters* p, void AccessorAssembler::LoadIC_NoFeedback(const LoadICParameters* p,
TNode<Smi> ic_kind) { TNode<Smi> ic_kind) {
Label miss(this, Label::kDeferred); Label miss(this, Label::kDeferred);
TNode<Object> receiver = p->receiver(); TNode<Object> lookup_start_object = p->receiver_and_lookup_start_object();
GotoIf(TaggedIsSmi(receiver), &miss); GotoIf(TaggedIsSmi(lookup_start_object), &miss);
TNode<Map> receiver_map = LoadMap(CAST(receiver)); TNode<Map> lookup_start_object_map = LoadMap(CAST(lookup_start_object));
GotoIf(IsDeprecatedMap(receiver_map), &miss); GotoIf(IsDeprecatedMap(lookup_start_object_map), &miss);
TNode<Uint16T> instance_type = LoadMapInstanceType(receiver_map); TNode<Uint16T> instance_type = LoadMapInstanceType(lookup_start_object_map);
{ {
// Special case for Function.prototype load, because it's very common // Special case for Function.prototype load, because it's very common
...@@ -2803,14 +2820,15 @@ void AccessorAssembler::LoadIC_NoFeedback(const LoadICParameters* p, ...@@ -2803,14 +2820,15 @@ void AccessorAssembler::LoadIC_NoFeedback(const LoadICParameters* p,
&not_function_prototype); &not_function_prototype);
GotoIfNot(IsPrototypeString(p->name()), &not_function_prototype); GotoIfNot(IsPrototypeString(p->name()), &not_function_prototype);
GotoIfPrototypeRequiresRuntimeLookup(CAST(receiver), receiver_map, GotoIfPrototypeRequiresRuntimeLookup(CAST(lookup_start_object),
lookup_start_object_map,
&not_function_prototype); &not_function_prototype);
Return(LoadJSFunctionPrototype(CAST(receiver), &miss)); Return(LoadJSFunctionPrototype(CAST(lookup_start_object), &miss));
BIND(&not_function_prototype); BIND(&not_function_prototype);
} }
GenericPropertyLoad(CAST(receiver), receiver_map, instance_type, p, &miss, GenericPropertyLoad(CAST(lookup_start_object), lookup_start_object_map,
kDontUseStubCache); instance_type, p, &miss, kDontUseStubCache);
BIND(&miss); BIND(&miss);
{ {
...@@ -2923,11 +2941,11 @@ void AccessorAssembler::LoadGlobalIC_TryHandlerCase( ...@@ -2923,11 +2941,11 @@ void AccessorAssembler::LoadGlobalIC_TryHandlerCase(
TNode<NativeContext> native_context = LoadNativeContext(context); TNode<NativeContext> native_context = LoadNativeContext(context);
TNode<JSGlobalProxy> receiver = TNode<JSGlobalProxy> receiver =
CAST(LoadContextElement(native_context, Context::GLOBAL_PROXY_INDEX)); CAST(LoadContextElement(native_context, Context::GLOBAL_PROXY_INDEX));
TNode<Object> holder = TNode<Object> global =
LoadContextElement(native_context, Context::EXTENSION_INDEX); LoadContextElement(native_context, Context::EXTENSION_INDEX);
LazyLoadICParameters p([=] { return context; }, receiver, lazy_name, LazyLoadICParameters p([=] { return context; }, receiver, lazy_name,
[=] { return slot; }, vector, holder); [=] { return slot; }, vector, global);
HandleLoadICHandlerCase(&p, handler, miss, exit_point, ICMode::kGlobalIC, HandleLoadICHandlerCase(&p, handler, miss, exit_point, ICMode::kGlobalIC,
on_nonexistent); on_nonexistent);
...@@ -3019,14 +3037,15 @@ void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p, ...@@ -3019,14 +3037,15 @@ void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p,
try_polymorphic_name(this, Label::kDeferred), try_polymorphic_name(this, Label::kDeferred),
miss(this, Label::kDeferred), generic(this, Label::kDeferred); miss(this, Label::kDeferred), generic(this, Label::kDeferred);
TNode<Map> receiver_map = LoadReceiverMap(p->receiver()); TNode<Map> lookup_start_object_map =
GotoIf(IsDeprecatedMap(receiver_map), &miss); LoadReceiverMap(p->receiver_and_lookup_start_object());
GotoIf(IsDeprecatedMap(lookup_start_object_map), &miss);
GotoIf(IsUndefined(p->vector()), &generic); GotoIf(IsUndefined(p->vector()), &generic);
// Check monomorphic case. // Check monomorphic case.
TNode<MaybeObject> feedback = TNode<MaybeObject> feedback =
TryMonomorphicCase(p->slot(), CAST(p->vector()), receiver_map, TryMonomorphicCase(p->slot(), CAST(p->vector()), lookup_start_object_map,
&if_handler, &var_handler, &try_polymorphic); &if_handler, &var_handler, &try_polymorphic);
BIND(&if_handler); BIND(&if_handler);
{ {
...@@ -3043,8 +3062,8 @@ void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p, ...@@ -3043,8 +3062,8 @@ void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p,
// Check polymorphic case. // Check polymorphic case.
Comment("KeyedLoadIC_try_polymorphic"); Comment("KeyedLoadIC_try_polymorphic");
GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &try_megamorphic); GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &try_megamorphic);
HandlePolymorphicCase(receiver_map, CAST(strong_feedback), &if_handler, HandlePolymorphicCase(lookup_start_object_map, CAST(strong_feedback),
&var_handler, &miss); &if_handler, &var_handler, &miss);
} }
BIND(&try_megamorphic); BIND(&try_megamorphic);
...@@ -3136,9 +3155,9 @@ void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) { ...@@ -3136,9 +3155,9 @@ void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) {
TVARIABLE(Object, var_name, p->name()); TVARIABLE(Object, var_name, p->name());
Label if_runtime(this, Label::kDeferred); Label if_runtime(this, Label::kDeferred);
TNode<Object> receiver = p->receiver(); TNode<Object> lookup_start_object = p->lookup_start_object();
GotoIf(TaggedIsSmi(receiver), &if_runtime); GotoIf(TaggedIsSmi(lookup_start_object), &if_runtime);
GotoIf(IsNullOrUndefined(receiver), &if_runtime); GotoIf(IsNullOrUndefined(lookup_start_object), &if_runtime);
{ {
TVARIABLE(IntPtrT, var_index); TVARIABLE(IntPtrT, var_index);
...@@ -3152,9 +3171,9 @@ void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) { ...@@ -3152,9 +3171,9 @@ void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) {
BIND(&if_unique_name); BIND(&if_unique_name);
{ {
LoadICParameters pp(p, var_unique.value()); LoadICParameters pp(p, var_unique.value());
TNode<Map> receiver_map = LoadMap(CAST(receiver)); TNode<Map> lookup_start_object_map = LoadMap(CAST(lookup_start_object));
TNode<Uint16T> instance_type = LoadMapInstanceType(receiver_map); GenericPropertyLoad(CAST(lookup_start_object), lookup_start_object_map,
GenericPropertyLoad(CAST(receiver), receiver_map, instance_type, &pp, LoadMapInstanceType(lookup_start_object_map), &pp,
&if_runtime); &if_runtime);
} }
...@@ -3185,9 +3204,11 @@ void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) { ...@@ -3185,9 +3204,11 @@ void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) {
// experiments with this have shown that it causes too much traffic // experiments with this have shown that it causes too much traffic
// on the stub cache. We may want to re-evaluate that in the future. // on the stub cache. We may want to re-evaluate that in the future.
LoadICParameters pp(p, var_unique.value()); LoadICParameters pp(p, var_unique.value());
TNode<Map> receiver_map = LoadMap(CAST(receiver)); TNode<Map> lookup_start_object_map =
TNode<Uint16T> instance_type = LoadMapInstanceType(receiver_map); LoadMap(CAST(lookup_start_object));
GenericPropertyLoad(CAST(receiver), receiver_map, instance_type, &pp, GenericPropertyLoad(CAST(lookup_start_object),
lookup_start_object_map,
LoadMapInstanceType(lookup_start_object_map), &pp,
&if_runtime, kDontUseStubCache); &if_runtime, kDontUseStubCache);
} }
} else { } else {
...@@ -3197,9 +3218,9 @@ void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) { ...@@ -3197,9 +3218,9 @@ void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) {
BIND(&if_index); BIND(&if_index);
{ {
TNode<Map> receiver_map = LoadMap(CAST(receiver)); TNode<Map> lookup_start_object_map = LoadMap(CAST(lookup_start_object));
TNode<Uint16T> instance_type = LoadMapInstanceType(receiver_map); GenericElementLoad(CAST(lookup_start_object), lookup_start_object_map,
GenericElementLoad(CAST(receiver), receiver_map, instance_type, LoadMapInstanceType(lookup_start_object_map),
var_index.value(), &if_runtime); var_index.value(), &if_runtime);
} }
} }
...@@ -3219,8 +3240,8 @@ void AccessorAssembler::KeyedLoadICPolymorphicName(const LoadICParameters* p, ...@@ -3219,8 +3240,8 @@ void AccessorAssembler::KeyedLoadICPolymorphicName(const LoadICParameters* p,
TVARIABLE(MaybeObject, var_handler); TVARIABLE(MaybeObject, var_handler);
Label if_handler(this, &var_handler), miss(this, Label::kDeferred); Label if_handler(this, &var_handler), miss(this, Label::kDeferred);
TNode<Object> receiver = p->receiver(); TNode<Object> lookup_start_object = p->lookup_start_object();
TNode<Map> receiver_map = LoadReceiverMap(receiver); TNode<Map> lookup_start_object_map = LoadReceiverMap(lookup_start_object);
TNode<Name> name = CAST(p->name()); TNode<Name> name = CAST(p->name());
TNode<FeedbackVector> vector = CAST(p->vector()); TNode<FeedbackVector> vector = CAST(p->vector());
TNode<TaggedIndex> slot = p->slot(); TNode<TaggedIndex> slot = p->slot();
...@@ -3229,15 +3250,16 @@ void AccessorAssembler::KeyedLoadICPolymorphicName(const LoadICParameters* p, ...@@ -3229,15 +3250,16 @@ void AccessorAssembler::KeyedLoadICPolymorphicName(const LoadICParameters* p,
// When we get here, we know that the {name} matches the recorded // When we get here, we know that the {name} matches the recorded
// feedback name in the {vector} and can safely be used for the // feedback name in the {vector} and can safely be used for the
// LoadIC handler logic below. // LoadIC handler logic below.
CSA_ASSERT(this, Word32BinaryNot(IsDeprecatedMap(receiver_map))); CSA_ASSERT(this, Word32BinaryNot(IsDeprecatedMap(lookup_start_object_map)));
CSA_ASSERT(this, TaggedEqual(name, LoadFeedbackVectorSlot(vector, slot)), CSA_ASSERT(this, TaggedEqual(name, LoadFeedbackVectorSlot(vector, slot)),
name, vector); name, vector);
// Check if we have a matching handler for the {receiver_map}. // Check if we have a matching handler for the {lookup_start_object_map}.
TNode<MaybeObject> feedback_element = TNode<MaybeObject> feedback_element =
LoadFeedbackVectorSlot(vector, slot, kTaggedSize); LoadFeedbackVectorSlot(vector, slot, kTaggedSize);
TNode<WeakFixedArray> array = CAST(feedback_element); TNode<WeakFixedArray> array = CAST(feedback_element);
HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, &miss); HandlePolymorphicCase(lookup_start_object_map, array, &if_handler,
&var_handler, &miss);
BIND(&if_handler); BIND(&if_handler);
{ {
...@@ -3252,10 +3274,10 @@ void AccessorAssembler::KeyedLoadICPolymorphicName(const LoadICParameters* p, ...@@ -3252,10 +3274,10 @@ void AccessorAssembler::KeyedLoadICPolymorphicName(const LoadICParameters* p,
BIND(&miss); BIND(&miss);
{ {
Comment("KeyedLoadIC_miss"); Comment("KeyedLoadIC_miss");
TailCallRuntime(access_mode == LoadAccessMode::kLoad TailCallRuntime(
? Runtime::kKeyedLoadIC_Miss access_mode == LoadAccessMode::kLoad ? Runtime::kKeyedLoadIC_Miss
: Runtime::kKeyedHasIC_Miss, : Runtime::kKeyedHasIC_Miss,
context, receiver, name, slot, vector); context, p->receiver_and_lookup_start_object(), name, slot, vector);
} }
} }
...@@ -3679,13 +3701,13 @@ void AccessorAssembler::GenerateLoadIC_Noninlined() { ...@@ -3679,13 +3701,13 @@ void AccessorAssembler::GenerateLoadIC_Noninlined() {
TVARIABLE(MaybeObject, var_handler); TVARIABLE(MaybeObject, var_handler);
Label if_handler(this, &var_handler), miss(this, Label::kDeferred); Label if_handler(this, &var_handler), miss(this, Label::kDeferred);
TNode<Map> receiver_map = LoadReceiverMap(receiver);
TNode<MaybeObject> feedback_element = LoadFeedbackVectorSlot(vector, slot); TNode<MaybeObject> feedback_element = LoadFeedbackVectorSlot(vector, slot);
TNode<HeapObject> feedback = CAST(feedback_element); TNode<HeapObject> feedback = CAST(feedback_element);
LoadICParameters p(context, receiver, name, slot, vector); LoadICParameters p(context, receiver, name, slot, vector);
LoadIC_Noninlined(&p, receiver_map, feedback, &var_handler, &if_handler, TNode<Map> lookup_start_object_map = LoadReceiverMap(p.lookup_start_object());
&miss, &direct_exit); LoadIC_Noninlined(&p, lookup_start_object_map, feedback, &var_handler,
&if_handler, &miss, &direct_exit);
BIND(&if_handler); BIND(&if_handler);
{ {
......
...@@ -55,9 +55,10 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { ...@@ -55,9 +55,10 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
void GenerateStoreInArrayLiteralIC(); void GenerateStoreInArrayLiteralIC();
void TryProbeStubCache(StubCache* stub_cache, TNode<Object> receiver, void TryProbeStubCache(StubCache* stub_cache,
TNode<Name> name, Label* if_handler, TNode<Object> lookup_start_object, TNode<Name> name,
TVariable<MaybeObject>* var_handler, Label* if_miss); Label* if_handler, TVariable<MaybeObject>* var_handler,
Label* if_miss);
TNode<IntPtrT> StubCachePrimaryOffsetForTesting(TNode<Name> name, TNode<IntPtrT> StubCachePrimaryOffsetForTesting(TNode<Name> name,
TNode<Map> map) { TNode<Map> map) {
...@@ -69,16 +70,17 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { ...@@ -69,16 +70,17 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
} }
struct LoadICParameters { struct LoadICParameters {
LoadICParameters(TNode<Context> context, LoadICParameters(
base::Optional<TNode<Object>> receiver, TNode<Object> name, TNode<Context> context, TNode<Object> receiver, TNode<Object> name,
TNode<TaggedIndex> slot, TNode<HeapObject> vector, TNode<TaggedIndex> slot, TNode<HeapObject> vector,
base::Optional<TNode<Object>> holder = base::nullopt) base::Optional<TNode<Object>> lookup_start_object = base::nullopt)
: context_(context), : context_(context),
receiver_(receiver), receiver_(receiver),
name_(name), name_(name),
slot_(slot), slot_(slot),
vector_(vector), vector_(vector),
holder_(holder ? holder.value() : receiver) {} lookup_start_object_(lookup_start_object ? lookup_start_object.value()
: receiver) {}
LoadICParameters(const LoadICParameters* p, TNode<Object> unique_name) LoadICParameters(const LoadICParameters* p, TNode<Object> unique_name)
: context_(p->context_), : context_(p->context_),
...@@ -86,41 +88,52 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { ...@@ -86,41 +88,52 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
name_(unique_name), name_(unique_name),
slot_(p->slot_), slot_(p->slot_),
vector_(p->vector_), vector_(p->vector_),
holder_(p->holder_) {} lookup_start_object_(p->lookup_start_object_) {}
TNode<Context> context() const { return context_; } TNode<Context> context() const { return context_; }
TNode<Object> receiver() const { return receiver_.value(); } TNode<Object> receiver() const { return receiver_; }
TNode<Object> name() const { return name_; } TNode<Object> name() const { return name_; }
TNode<TaggedIndex> slot() const { return slot_; } TNode<TaggedIndex> slot() const { return slot_; }
TNode<HeapObject> vector() const { return vector_; } TNode<HeapObject> vector() const { return vector_; }
TNode<Object> holder() const { return holder_.value(); } TNode<Object> lookup_start_object() const {
bool receiver_is_null() const { return !receiver_.has_value(); } return lookup_start_object_.value();
}
// Usable in cases where the receiver and the lookup start object are
// expected to be the same, i.e., when "receiver != lookup_start_object"
// case is not supported or not expected by the surrounding code.
TNode<Object> receiver_and_lookup_start_object() const {
DCHECK_EQ(receiver_, lookup_start_object_);
return receiver_;
}
private: private:
TNode<Context> context_; TNode<Context> context_;
base::Optional<TNode<Object>> receiver_; TNode<Object> receiver_;
TNode<Object> name_; TNode<Object> name_;
TNode<TaggedIndex> slot_; TNode<TaggedIndex> slot_;
TNode<HeapObject> vector_; TNode<HeapObject> vector_;
base::Optional<TNode<Object>> holder_; base::Optional<TNode<Object>> lookup_start_object_;
}; };
struct LazyLoadICParameters { struct LazyLoadICParameters {
LazyLoadICParameters(LazyNode<Context> context, TNode<Object> receiver, LazyLoadICParameters(
LazyNode<Object> name, LazyNode<TaggedIndex> slot, LazyNode<Context> context, TNode<Object> receiver,
TNode<HeapObject> vector, LazyNode<Object> name, LazyNode<TaggedIndex> slot,
base::Optional<TNode<Object>> holder = base::nullopt) TNode<HeapObject> vector,
base::Optional<TNode<Object>> lookup_start_object = base::nullopt)
: context_(context), : context_(context),
receiver_(receiver), receiver_(receiver),
name_(name), name_(name),
slot_(slot), slot_(slot),
vector_(vector), vector_(vector),
holder_(holder ? holder.value() : receiver) {} lookup_start_object_(lookup_start_object ? lookup_start_object.value()
: receiver) {}
explicit LazyLoadICParameters(const LoadICParameters* p) explicit LazyLoadICParameters(const LoadICParameters* p)
: receiver_(p->receiver()), : receiver_(p->receiver()),
vector_(p->vector()), vector_(p->vector()),
holder_(p->holder()) { lookup_start_object_(p->lookup_start_object()) {
slot_ = [=] { return p->slot(); }; slot_ = [=] { return p->slot(); };
context_ = [=] { return p->context(); }; context_ = [=] { return p->context(); };
name_ = [=] { return p->name(); }; name_ = [=] { return p->name(); };
...@@ -131,7 +144,15 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { ...@@ -131,7 +144,15 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
TNode<Object> name() const { return name_(); } TNode<Object> name() const { return name_(); }
TNode<TaggedIndex> slot() const { return slot_(); } TNode<TaggedIndex> slot() const { return slot_(); }
TNode<HeapObject> vector() const { return vector_; } TNode<HeapObject> vector() const { return vector_; }
TNode<Object> holder() const { return holder_; } TNode<Object> lookup_start_object() const { return lookup_start_object_; }
// Usable in cases where the receiver and the lookup start object are
// expected to be the same, i.e., when "receiver != lookup_start_object"
// case is not supported or not expected by the surrounding code.
TNode<Object> receiver_and_lookup_start_object() const {
DCHECK_EQ(receiver_, lookup_start_object_);
return receiver_;
}
private: private:
LazyNode<Context> context_; LazyNode<Context> context_;
...@@ -139,7 +160,7 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { ...@@ -139,7 +160,7 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
LazyNode<Object> name_; LazyNode<Object> name_;
LazyNode<TaggedIndex> slot_; LazyNode<TaggedIndex> slot_;
TNode<HeapObject> vector_; TNode<HeapObject> vector_;
TNode<Object> holder_; TNode<Object> lookup_start_object_;
}; };
void LoadGlobalIC(TNode<HeapObject> maybe_feedback_vector, void LoadGlobalIC(TNode<HeapObject> maybe_feedback_vector,
...@@ -158,18 +179,34 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { ...@@ -158,18 +179,34 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
int data_index); int data_index);
protected: protected:
struct StoreICParameters : public LoadICParameters { struct StoreICParameters {
StoreICParameters(TNode<Context> context, StoreICParameters(TNode<Context> context,
base::Optional<TNode<Object>> receiver, base::Optional<TNode<Object>> receiver,
TNode<Object> name, TNode<Object> value, TNode<Object> name, TNode<Object> value,
TNode<TaggedIndex> slot, TNode<HeapObject> vector) TNode<TaggedIndex> slot, TNode<HeapObject> vector)
: LoadICParameters(context, receiver, name, slot, vector), : context_(context),
value_(value) {} receiver_(receiver),
name_(name),
value_(value),
slot_(slot),
vector_(vector) {}
TNode<Context> context() const { return context_; }
TNode<Object> receiver() const { return receiver_.value(); }
TNode<Object> name() const { return name_; }
TNode<Object> value() const { return value_; } TNode<Object> value() const { return value_; }
TNode<TaggedIndex> slot() const { return slot_; }
TNode<HeapObject> vector() const { return vector_; }
bool receiver_is_null() const { return !receiver_.has_value(); }
private: private:
TNode<Context> context_;
base::Optional<TNode<Object>> receiver_;
TNode<Object> name_;
TNode<Object> value_; TNode<Object> value_;
TNode<TaggedIndex> slot_;
TNode<HeapObject> vector_;
}; };
enum class LoadAccessMode { kLoad, kHas }; enum class LoadAccessMode { kLoad, kHas };
...@@ -213,7 +250,8 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { ...@@ -213,7 +250,8 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
// LoadIC contains the full LoadIC logic, while LoadIC_Noninlined contains // LoadIC contains the full LoadIC logic, while LoadIC_Noninlined contains
// logic not inlined into Ignition bytecode handlers. // logic not inlined into Ignition bytecode handlers.
void LoadIC(const LoadICParameters* p); void LoadIC(const LoadICParameters* p);
void LoadIC_Noninlined(const LoadICParameters* p, TNode<Map> receiver_map, void LoadIC_Noninlined(const LoadICParameters* p,
TNode<Map> lookup_start_object_map,
TNode<HeapObject> feedback, TNode<HeapObject> feedback,
TVariable<MaybeObject>* var_handler, Label* if_handler, TVariable<MaybeObject>* var_handler, Label* if_handler,
Label* miss, ExitPoint* exit_point); Label* miss, ExitPoint* exit_point);
...@@ -244,11 +282,11 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { ...@@ -244,11 +282,11 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
// Checks monomorphic case. Returns {feedback} entry of the vector. // Checks monomorphic case. Returns {feedback} entry of the vector.
TNode<MaybeObject> TryMonomorphicCase(TNode<TaggedIndex> slot, TNode<MaybeObject> TryMonomorphicCase(TNode<TaggedIndex> slot,
TNode<FeedbackVector> vector, TNode<FeedbackVector> vector,
TNode<Map> receiver_map, TNode<Map> lookup_start_object_map,
Label* if_handler, Label* if_handler,
TVariable<MaybeObject>* var_handler, TVariable<MaybeObject>* var_handler,
Label* if_miss); Label* if_miss);
void HandlePolymorphicCase(TNode<Map> receiver_map, void HandlePolymorphicCase(TNode<Map> lookup_start_object_map,
TNode<WeakFixedArray> feedback, Label* if_handler, TNode<WeakFixedArray> feedback, Label* if_handler,
TVariable<MaybeObject>* var_handler, TVariable<MaybeObject>* var_handler,
Label* if_miss); Label* if_miss);
...@@ -356,13 +394,15 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { ...@@ -356,13 +394,15 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
// KeyedLoadIC_Generic implementation. // KeyedLoadIC_Generic implementation.
void GenericElementLoad(TNode<HeapObject> receiver, TNode<Map> receiver_map, void GenericElementLoad(TNode<HeapObject> lookup_start_object,
TNode<Int32T> instance_type, TNode<IntPtrT> index, TNode<Map> lookup_start_object_map,
Label* slow); TNode<Int32T> lookup_start_object_instance_type,
TNode<IntPtrT> index, Label* slow);
enum UseStubCache { kUseStubCache, kDontUseStubCache }; enum UseStubCache { kUseStubCache, kDontUseStubCache };
void GenericPropertyLoad(TNode<HeapObject> receiver, TNode<Map> receiver_map, void GenericPropertyLoad(TNode<HeapObject> lookup_start_object,
TNode<Int32T> instance_type, TNode<Map> lookup_start_object_map,
TNode<Int32T> lookup_start_object_instance_type,
const LoadICParameters* p, Label* slow, const LoadICParameters* p, Label* slow,
UseStubCache use_stub_cache = kUseStubCache); UseStubCache use_stub_cache = kUseStubCache);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment