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