Commit 8ee507f1 authored by Sathya Gunasekaran's avatar Sathya Gunasekaran Committed by Commit Bot

[ic] Inline constant fields in IC

Previously, the handler would load the constant field from the holder
everytime by using the descriptor index. Instead, this patch inlines
the constant field directly into the handler.

Change-Id: Ia731811b135897033f4c5dc973031a30f25a64ed
Bug: v8:9616
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1688829
Commit-Queue: Sathya Gunasekaran  <gsathya@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63332}
parent e66cee7e
......@@ -301,6 +301,7 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase(
TNode<WordT> handler_word = SmiUntag(smi_handler);
TNode<IntPtrT> handler_kind =
Signed(DecodeWord<LoadHandler::KindBits>(handler_word));
if (support_elements == kSupportElements) {
TVARIABLE(IntPtrT, var_intptr_index);
Label if_element(this), if_indexed_string(this), if_property(this),
......@@ -429,9 +430,11 @@ void AccessorAssembler::HandleLoadICSmiHandlerLoadNamedCase(
module_export(this, Label::kDeferred), proxy(this, Label::kDeferred),
native_data_property(this, Label::kDeferred),
api_getter(this, Label::kDeferred);
GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kField)), &field);
GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kConstant)),
GotoIf(WordEqual(handler_kind,
IntPtrConstant(LoadHandler::kConstantFromPrototype)),
&constant);
GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kNonExistent)),
......@@ -479,11 +482,7 @@ void AccessorAssembler::HandleLoadICSmiHandlerLoadNamedCase(
BIND(&constant);
{
Comment("constant_load");
TNode<IntPtrT> descriptor =
Signed(DecodeWord<LoadHandler::DescriptorBits>(handler_word));
Node* value = LoadDescriptorValue(LoadMap(holder), descriptor);
exit_point->Return(value);
exit_point->Return(holder);
}
BIND(&normal);
......@@ -625,7 +624,8 @@ void AccessorAssembler::HandleLoadICSmiHandlerHasNamedCase(
GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kField)),
&return_true);
GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kConstant)),
GotoIf(WordEqual(handler_kind,
IntPtrConstant(LoadHandler::kConstantFromPrototype)),
&return_true);
GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kNonExistent)),
......@@ -835,21 +835,37 @@ void AccessorAssembler::HandleLoadICProtoHandler(
},
miss, ic_mode);
TNode<MaybeObject> maybe_holder = LoadHandlerDataField(handler, 1);
TNode<MaybeObject> maybe_holder_or_constant =
LoadHandlerDataField(handler, 1);
Label load_from_cached_holder(this), done(this);
Label load_from_cached_holder(this), is_smi(this), done(this);
Branch(IsStrongReferenceTo(maybe_holder, NullConstant()), &done,
GotoIf(TaggedIsSmi(maybe_holder_or_constant), &is_smi);
Branch(IsStrongReferenceTo(maybe_holder_or_constant, NullConstant()), &done,
&load_from_cached_holder);
BIND(&load_from_cached_holder);
BIND(&is_smi);
{
// For regular holders, having passed the receiver map check and the
// validity cell check implies that |holder| is alive. However, for global
// object receivers, |maybe_holder| may be cleared.
CSA_ASSERT(this, IsWeakOrCleared(maybe_holder));
Node* holder = GetHeapObjectAssumeWeak(maybe_holder, miss);
CSA_ASSERT(
this,
WordEqual(
Signed(DecodeWord<LoadHandler::KindBits>(SmiUntag(smi_handler))),
IntPtrConstant(LoadHandler::kConstantFromPrototype)));
if (access_mode == LoadAccessMode::kHas) {
exit_point->Return(TrueConstant());
} else {
exit_point->Return(maybe_holder_or_constant);
}
}
BIND(&load_from_cached_holder);
{
// For regular holders, having passed the receiver map check and
// the validity cell check implies that |holder| is
// alive. However, for global object receivers, |maybe_holder| may
// be cleared.
CSA_ASSERT(this, IsWeakOrCleared(maybe_holder_or_constant));
Node* holder = GetHeapObjectAssumeWeak(maybe_holder_or_constant, miss);
var_holder->Bind(holder);
Goto(&done);
}
......
......@@ -51,8 +51,8 @@ Handle<Smi> LoadHandler::LoadField(Isolate* isolate, FieldIndex field_index) {
return handle(Smi::FromInt(config), isolate);
}
Handle<Smi> LoadHandler::LoadConstant(Isolate* isolate, int descriptor) {
int config = KindBits::encode(kConstant) | DescriptorBits::encode(descriptor);
Handle<Smi> LoadHandler::LoadConstantFromPrototype(Isolate* isolate) {
int config = KindBits::encode(kConstantFromPrototype);
return handle(Smi::FromInt(config), isolate);
}
......
......@@ -37,7 +37,7 @@ class LoadHandler final : public DataHandler {
kNormal,
kGlobal,
kField,
kConstant,
kConstantFromPrototype,
kAccessor,
kNativeDataProperty,
kApiGetter,
......@@ -116,8 +116,9 @@ class LoadHandler final : public DataHandler {
// Creates a Smi-handler for loading a field from fast object.
static inline Handle<Smi> LoadField(Isolate* isolate, FieldIndex field_index);
// Creates a Smi-handler for loading a constant from fast object.
static inline Handle<Smi> LoadConstant(Isolate* isolate, int descriptor);
// Creates a Smi-handler for loading a cached constant from fast
// prototype object.
static inline Handle<Smi> LoadConstantFromPrototype(Isolate* isolate);
// Creates a Smi-handler for calling a getter on a fast object.
static inline Handle<Smi> LoadAccessor(Isolate* isolate, int descriptor);
......
......@@ -897,6 +897,18 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
if (receiver_is_holder) return smi_handler;
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH);
}
if (lookup->constness() == PropertyConstness::kConst &&
!receiver_is_holder) {
DCHECK(!lookup->is_dictionary_holder());
smi_handler = LoadHandler::LoadConstantFromPrototype(isolate());
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH);
Handle<Object> value = lookup->GetDataValue();
MaybeObjectHandle weak_value =
value->IsSmi() ? MaybeObjectHandle(*value, isolate())
: MaybeObjectHandle::Weak(*value, isolate());
return LoadHandler::LoadFromPrototype(isolate(), map, holder,
smi_handler, weak_value);
}
return LoadHandler::LoadFromPrototype(isolate(), map, holder,
smi_handler);
}
......
......@@ -680,6 +680,10 @@ void Map::UpdateFieldType(Isolate* isolate, int descriptor, Handle<Name> name,
if (details.location() != kField) return;
DCHECK_EQ(kData, details.kind());
if (new_constness != details.constness() && is_prototype_map()) {
JSObject::InvalidatePrototypeChains(*this);
}
Zone zone(isolate->allocator(), ZONE_NAME);
ZoneQueue<Map> backlog(&zone);
backlog.push(*this);
......
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