[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: Igor Sheludko <ishell@chromium.org> Cr-Commit-Position: refs/heads/master@{#63332}
This commit is contained in:
parent
e66cee7e9e
commit
8ee507f1ca
@ -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(&is_smi);
|
||||
{
|
||||
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));
|
||||
Node* holder = GetHeapObjectAssumeWeak(maybe_holder, miss);
|
||||
|
||||
// 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);
|
||||
|
12
src/ic/ic.cc
12
src/ic/ic.cc
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user