Commit 347092ac authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[ic] Load name/context lazily in LdaNamedProperty

Introduces LazyLoadICParameters which allow a LazyNode for context and
name. These aren't used on the fast path, so we want to avoid reading
them for both performance and register pressure reasons.

Change-Id: Ifb637cf4782ce984feee9af503998e7539beb823
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1686665
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62539}
parent 27998dbe
This diff is collapsed.
...@@ -68,21 +68,75 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { ...@@ -68,21 +68,75 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
} }
struct LoadICParameters { struct LoadICParameters {
LoadICParameters(Node* context, Node* receiver, Node* name, Node* slot, LoadICParameters(TNode<Context> context, Node* receiver, Node* name,
Node* vector, Node* holder = nullptr) Node* slot, Node* vector, Node* holder = nullptr)
: context(context), : context_(context),
receiver(receiver), receiver_(receiver),
name(name), name_(name),
slot(slot), slot_(slot),
vector(vector), vector_(vector),
holder(holder ? holder : receiver) {} holder_(holder ? holder : receiver) {}
Node* context; LoadICParameters(const LoadICParameters* p, Node* unique_name)
Node* receiver; : context_(p->context_),
Node* name; receiver_(p->receiver_),
Node* slot; name_(unique_name),
Node* vector; slot_(p->slot_),
Node* holder; vector_(p->vector_),
holder_(p->holder_) {}
TNode<Context> context() const { return context_; }
Node* receiver() const { return receiver_; }
Node* name() const { return name_; }
Node* slot() const { return slot_; }
Node* vector() const { return vector_; }
Node* holder() const { return holder_; }
private:
TNode<Context> context_;
Node* receiver_;
Node* name_;
Node* slot_;
Node* vector_;
Node* holder_;
};
struct LazyLoadICParameters {
LazyLoadICParameters(LazyNode<Context> context, Node* receiver,
LazyNode<Object> name, Node* slot, Node* vector,
Node* holder = nullptr)
: context_(context),
receiver_(receiver),
name_(name),
slot_(slot),
vector_(vector),
holder_(holder ? holder : receiver) {}
explicit LazyLoadICParameters(const LoadICParameters* p)
: receiver_(p->receiver()),
slot_(p->slot()),
vector_(p->vector()),
holder_(p->holder()) {
TNode<Context> p_context = p->context();
context_ = [=] { return p_context; };
TNode<Object> p_name = TNode<Object>::UncheckedCast(p->name());
name_ = [=] { return p_name; };
}
TNode<Context> context() const { return context_(); }
Node* receiver() const { return receiver_; }
Node* name() const { return name_(); }
Node* slot() const { return slot_; }
Node* vector() const { return vector_; }
Node* holder() const { return holder_; }
private:
LazyNode<Context> context_;
Node* receiver_;
LazyNode<Object> name_;
Node* slot_;
Node* vector_;
Node* holder_;
}; };
void LoadGlobalIC(Node* vector, Node* slot, void LoadGlobalIC(Node* vector, Node* slot,
...@@ -93,7 +147,8 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { ...@@ -93,7 +147,8 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
// Specialized LoadIC for inlined bytecode handler, hand-tuned to omit frame // Specialized LoadIC for inlined bytecode handler, hand-tuned to omit frame
// construction on common paths. // construction on common paths.
void LoadIC_BytecodeHandler(const LoadICParameters* p, ExitPoint* exit_point); void LoadIC_BytecodeHandler(const LazyLoadICParameters* p,
ExitPoint* exit_point);
// Loads dataX field from the DataHandler object. // Loads dataX field from the DataHandler object.
TNode<MaybeObject> LoadHandlerDataField(SloppyTNode<DataHandler> handler, TNode<MaybeObject> LoadHandlerDataField(SloppyTNode<DataHandler> handler,
...@@ -101,11 +156,15 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { ...@@ -101,11 +156,15 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
protected: protected:
struct StoreICParameters : public LoadICParameters { struct StoreICParameters : public LoadICParameters {
StoreICParameters(Node* context, Node* receiver, Node* name, StoreICParameters(TNode<Context> context, Node* receiver, Node* name,
SloppyTNode<Object> value, Node* slot, Node* vector) SloppyTNode<Object> value, Node* slot, Node* vector)
: LoadICParameters(context, receiver, name, slot, vector), : LoadICParameters(context, receiver, name, slot, vector),
value(value) {} value_(value) {}
SloppyTNode<Object> value;
SloppyTNode<Object> value() const { return value_; }
private:
SloppyTNode<Object> value_;
}; };
enum class LoadAccessMode { kLoad, kHas }; enum class LoadAccessMode { kLoad, kHas };
...@@ -182,13 +241,13 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { ...@@ -182,13 +241,13 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
// LoadIC implementation. // LoadIC implementation.
void HandleLoadICHandlerCase( void HandleLoadICHandlerCase(
const LoadICParameters* p, TNode<Object> handler, Label* miss, const LazyLoadICParameters* p, TNode<Object> handler, Label* miss,
ExitPoint* exit_point, ICMode ic_mode = ICMode::kNonGlobalIC, ExitPoint* exit_point, ICMode ic_mode = ICMode::kNonGlobalIC,
OnNonExistent on_nonexistent = OnNonExistent::kReturnUndefined, OnNonExistent on_nonexistent = OnNonExistent::kReturnUndefined,
ElementSupport support_elements = kOnlyProperties, ElementSupport support_elements = kOnlyProperties,
LoadAccessMode access_mode = LoadAccessMode::kLoad); LoadAccessMode access_mode = LoadAccessMode::kLoad);
void HandleLoadICSmiHandlerCase(const LoadICParameters* p, Node* holder, void HandleLoadICSmiHandlerCase(const LazyLoadICParameters* p, Node* holder,
SloppyTNode<Smi> smi_handler, SloppyTNode<Smi> smi_handler,
SloppyTNode<Object> handler, Label* miss, SloppyTNode<Object> handler, Label* miss,
ExitPoint* exit_point, ExitPoint* exit_point,
...@@ -196,18 +255,18 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { ...@@ -196,18 +255,18 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
ElementSupport support_elements, ElementSupport support_elements,
LoadAccessMode access_mode); LoadAccessMode access_mode);
void HandleLoadICProtoHandler(const LoadICParameters* p, Node* handler, void HandleLoadICProtoHandler(const LazyLoadICParameters* p, Node* handler,
Variable* var_holder, Variable* var_smi_handler, Variable* var_holder, Variable* var_smi_handler,
Label* if_smi_handler, Label* miss, Label* if_smi_handler, Label* miss,
ExitPoint* exit_point, ICMode ic_mode, ExitPoint* exit_point, ICMode ic_mode,
LoadAccessMode access_mode); LoadAccessMode access_mode);
void HandleLoadCallbackProperty(const LoadICParameters* p, void HandleLoadCallbackProperty(const LazyLoadICParameters* p,
TNode<JSObject> holder, TNode<JSObject> holder,
TNode<WordT> handler_word, TNode<WordT> handler_word,
ExitPoint* exit_point); ExitPoint* exit_point);
void HandleLoadAccessor(const LoadICParameters* p, void HandleLoadAccessor(const LazyLoadICParameters* p,
TNode<CallHandlerInfo> call_handler_info, TNode<CallHandlerInfo> call_handler_info,
TNode<WordT> handler_word, TNode<DataHandler> handler, TNode<WordT> handler_word, TNode<DataHandler> handler,
TNode<IntPtrT> handler_kind, ExitPoint* exit_point); TNode<IntPtrT> handler_kind, ExitPoint* exit_point);
...@@ -220,13 +279,13 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { ...@@ -220,13 +279,13 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
Node* receiver, Label* can_access, Label* miss); Node* receiver, Label* can_access, Label* miss);
void HandleLoadICSmiHandlerLoadNamedCase( void HandleLoadICSmiHandlerLoadNamedCase(
const LoadICParameters* p, Node* holder, TNode<IntPtrT> handler_kind, const LazyLoadICParameters* p, Node* holder, TNode<IntPtrT> handler_kind,
TNode<WordT> handler_word, Label* rebox_double, TNode<WordT> handler_word, Label* rebox_double,
Variable* var_double_value, SloppyTNode<Object> handler, Label* miss, Variable* var_double_value, SloppyTNode<Object> handler, Label* miss,
ExitPoint* exit_point, OnNonExistent on_nonexistent, ExitPoint* exit_point, OnNonExistent on_nonexistent,
ElementSupport support_elements); ElementSupport support_elements);
void HandleLoadICSmiHandlerHasNamedCase(const LoadICParameters* p, void HandleLoadICSmiHandlerHasNamedCase(const LazyLoadICParameters* p,
Node* holder, Node* holder,
TNode<IntPtrT> handler_kind, TNode<IntPtrT> handler_kind,
Label* miss, ExitPoint* exit_point); Label* miss, ExitPoint* exit_point);
......
...@@ -775,7 +775,7 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( ...@@ -775,7 +775,7 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
TNode<DescriptorArray> descriptors = LoadMapDescriptors(receiver_map); TNode<DescriptorArray> descriptors = LoadMapDescriptors(receiver_map);
Label descriptor_found(this), lookup_transition(this); Label descriptor_found(this), lookup_transition(this);
TVARIABLE(IntPtrT, var_name_index); TVARIABLE(IntPtrT, var_name_index);
DescriptorLookup(p->name, descriptors, bitfield3, &descriptor_found, DescriptorLookup(p->name(), descriptors, bitfield3, &descriptor_found,
&var_name_index, &lookup_transition); &var_name_index, &lookup_transition);
BIND(&descriptor_found); BIND(&descriptor_found);
...@@ -801,18 +801,18 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( ...@@ -801,18 +801,18 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
BIND(&data_property); BIND(&data_property);
{ {
CheckForAssociatedProtector(p->name, slow); CheckForAssociatedProtector(p->name(), slow);
OverwriteExistingFastDataProperty(receiver, receiver_map, descriptors, OverwriteExistingFastDataProperty(receiver, receiver_map, descriptors,
name_index, details, p->value, slow, name_index, details, p->value(), slow,
false); false);
exit_point->Return(p->value); exit_point->Return(p->value());
} }
} }
BIND(&lookup_transition); BIND(&lookup_transition);
{ {
Comment("lookup transition"); Comment("lookup transition");
TNode<Map> transition_map = FindCandidateStoreICTransitionMapHandler( TNode<Map> transition_map = FindCandidateStoreICTransitionMapHandler(
receiver_map, CAST(p->name), slow); receiver_map, CAST(p->name()), slow);
// Validate the transition handler candidate and apply the transition. // Validate the transition handler candidate and apply the transition.
StoreTransitionMapFlags flags = kValidateTransitionHandler; StoreTransitionMapFlags flags = kValidateTransitionHandler;
...@@ -820,7 +820,7 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( ...@@ -820,7 +820,7 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
flags = StoreTransitionMapFlags(flags | kCheckPrototypeValidity); flags = StoreTransitionMapFlags(flags | kCheckPrototypeValidity);
} }
HandleStoreICTransitionMapHandlerCase(p, transition_map, slow, flags); HandleStoreICTransitionMapHandlerCase(p, transition_map, slow, flags);
exit_point->Return(p->value); exit_point->Return(p->value());
} }
} }
...@@ -833,7 +833,7 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( ...@@ -833,7 +833,7 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
TVARIABLE(IntPtrT, var_name_index); TVARIABLE(IntPtrT, var_name_index);
Label dictionary_found(this, &var_name_index), not_found(this); Label dictionary_found(this, &var_name_index), not_found(this);
TNode<NameDictionary> properties = CAST(LoadSlowProperties(CAST(receiver))); TNode<NameDictionary> properties = CAST(LoadSlowProperties(CAST(receiver)));
NameDictionaryLookup<NameDictionary>(properties, CAST(p->name), NameDictionaryLookup<NameDictionary>(properties, CAST(p->name()),
&dictionary_found, &var_name_index, &dictionary_found, &var_name_index,
&not_found); &not_found);
BIND(&dictionary_found); BIND(&dictionary_found);
...@@ -858,38 +858,39 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( ...@@ -858,38 +858,39 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
BIND(&overwrite); BIND(&overwrite);
{ {
CheckForAssociatedProtector(p->name, slow); CheckForAssociatedProtector(p->name(), slow);
StoreValueByKeyIndex<NameDictionary>(properties, var_name_index.value(), StoreValueByKeyIndex<NameDictionary>(properties, var_name_index.value(),
p->value); p->value());
exit_point->Return(p->value); exit_point->Return(p->value());
} }
} }
BIND(&not_found); BIND(&not_found);
{ {
CheckForAssociatedProtector(p->name, slow); CheckForAssociatedProtector(p->name(), slow);
Label extensible(this); Label extensible(this);
Node* bitfield3 = LoadMapBitField3(receiver_map); Node* bitfield3 = LoadMapBitField3(receiver_map);
GotoIf(IsPrivateSymbol(p->name), &extensible); GotoIf(IsPrivateSymbol(p->name()), &extensible);
Branch(IsSetWord32<Map::IsExtensibleBit>(bitfield3), &extensible, slow); Branch(IsSetWord32<Map::IsExtensibleBit>(bitfield3), &extensible, slow);
BIND(&extensible); BIND(&extensible);
if (ShouldCheckPrototype()) { if (ShouldCheckPrototype()) {
DCHECK(ShouldCallSetter()); DCHECK(ShouldCallSetter());
LookupPropertyOnPrototypeChain( LookupPropertyOnPrototypeChain(
receiver_map, p->name, &accessor, &var_accessor_pair, receiver_map, p->name(), &accessor, &var_accessor_pair,
&var_accessor_holder, &var_accessor_holder,
ShouldReconfigureExisting() ? nullptr : &readonly, slow); ShouldReconfigureExisting() ? nullptr : &readonly, slow);
} }
Label add_dictionary_property_slow(this); Label add_dictionary_property_slow(this);
InvalidateValidityCellIfPrototype(receiver_map, bitfield3); InvalidateValidityCellIfPrototype(receiver_map, bitfield3);
Add<NameDictionary>(properties, CAST(p->name), p->value, Add<NameDictionary>(properties, CAST(p->name()), p->value(),
&add_dictionary_property_slow); &add_dictionary_property_slow);
exit_point->Return(p->value); exit_point->Return(p->value());
BIND(&add_dictionary_property_slow); BIND(&add_dictionary_property_slow);
exit_point->ReturnCallRuntime(Runtime::kAddDictionaryProperty, p->context, exit_point->ReturnCallRuntime(Runtime::kAddDictionaryProperty,
p->receiver, p->name, p->value); p->context(), p->receiver(), p->name(),
p->value());
} }
} }
...@@ -908,8 +909,8 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( ...@@ -908,8 +909,8 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
GotoIfNot(IsCallableMap(setter_map), &not_callable); GotoIfNot(IsCallableMap(setter_map), &not_callable);
Callable callable = CodeFactory::Call(isolate()); Callable callable = CodeFactory::Call(isolate());
CallJS(callable, p->context, setter, receiver, p->value); CallJS(callable, p->context(), setter, receiver, p->value());
exit_point->Return(p->value); exit_point->Return(p->value());
BIND(&not_callable); BIND(&not_callable);
{ {
...@@ -917,17 +918,17 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( ...@@ -917,17 +918,17 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
if (maybe_language_mode.To(&language_mode)) { if (maybe_language_mode.To(&language_mode)) {
if (language_mode == LanguageMode::kStrict) { if (language_mode == LanguageMode::kStrict) {
exit_point->ReturnCallRuntime( exit_point->ReturnCallRuntime(
Runtime::kThrowTypeError, p->context, Runtime::kThrowTypeError, p->context(),
SmiConstant(MessageTemplate::kNoSetterInCallback), p->name, SmiConstant(MessageTemplate::kNoSetterInCallback), p->name(),
var_accessor_holder.value()); var_accessor_holder.value());
} else { } else {
exit_point->Return(p->value); exit_point->Return(p->value());
} }
} else { } else {
CallRuntime(Runtime::kThrowTypeErrorIfStrict, p->context, CallRuntime(Runtime::kThrowTypeErrorIfStrict, p->context(),
SmiConstant(MessageTemplate::kNoSetterInCallback), SmiConstant(MessageTemplate::kNoSetterInCallback),
p->name, var_accessor_holder.value()); p->name(), var_accessor_holder.value());
exit_point->Return(p->value); exit_point->Return(p->value());
} }
} }
} }
...@@ -939,17 +940,17 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( ...@@ -939,17 +940,17 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
LanguageMode language_mode; LanguageMode language_mode;
if (maybe_language_mode.To(&language_mode)) { if (maybe_language_mode.To(&language_mode)) {
if (language_mode == LanguageMode::kStrict) { if (language_mode == LanguageMode::kStrict) {
Node* type = Typeof(p->receiver); Node* type = Typeof(p->receiver());
ThrowTypeError(p->context, MessageTemplate::kStrictReadOnlyProperty, ThrowTypeError(p->context(), MessageTemplate::kStrictReadOnlyProperty,
p->name, type, p->receiver); p->name(), type, p->receiver());
} else { } else {
exit_point->Return(p->value); exit_point->Return(p->value());
} }
} else { } else {
CallRuntime(Runtime::kThrowTypeErrorIfStrict, p->context, CallRuntime(Runtime::kThrowTypeErrorIfStrict, p->context(),
SmiConstant(MessageTemplate::kStrictReadOnlyProperty), SmiConstant(MessageTemplate::kStrictReadOnlyProperty),
p->name, Typeof(p->receiver), p->receiver); p->name(), Typeof(p->receiver()), p->receiver());
exit_point->Return(p->value); exit_point->Return(p->value());
} }
} }
} }
...@@ -1062,7 +1063,7 @@ void KeyedStoreGenericAssembler::StoreIC_Uninitialized() { ...@@ -1062,7 +1063,7 @@ void KeyedStoreGenericAssembler::StoreIC_Uninitialized() {
BIND(&store_property); BIND(&store_property);
{ {
StoreICParameters p(context, receiver, name, value, slot, vector); StoreICParameters p(CAST(context), receiver, name, value, slot, vector);
EmitGenericPropertyStore(receiver, receiver_map, &p, &miss); EmitGenericPropertyStore(receiver, receiver_map, &p, &miss);
} }
......
...@@ -512,17 +512,18 @@ IGNITION_HANDLER(LdaNamedProperty, InterpreterAssembler) { ...@@ -512,17 +512,18 @@ IGNITION_HANDLER(LdaNamedProperty, InterpreterAssembler) {
// Load receiver. // Load receiver.
Node* recv = LoadRegisterAtOperandIndex(0); Node* recv = LoadRegisterAtOperandIndex(0);
// Load the name. // Load the name and context lazily.
// TODO(jgruber): Not needed for monomorphic smi handler constant/field case. LazyNode<Name> name = [=] {
Node* name = LoadConstantPoolEntryAtOperandIndex(1); return CAST(LoadConstantPoolEntryAtOperandIndex(1));
Node* context = GetContext(); };
LazyNode<Context> context = [=] { return CAST(GetContext()); };
Label done(this); Label done(this);
Variable var_result(this, MachineRepresentation::kTagged); Variable var_result(this, MachineRepresentation::kTagged);
ExitPoint exit_point(this, &done, &var_result); ExitPoint exit_point(this, &done, &var_result);
AccessorAssembler::LoadICParameters params(context, recv, name, smi_slot, AccessorAssembler::LazyLoadICParameters params(context, recv, name, smi_slot,
feedback_vector); feedback_vector);
AccessorAssembler accessor_asm(state()); AccessorAssembler accessor_asm(state());
accessor_asm.LoadIC_BytecodeHandler(&params, &exit_point); accessor_asm.LoadIC_BytecodeHandler(&params, &exit_point);
......
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