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