Commit f4a3028b authored by Sathya Gunasekaran's avatar Sathya Gunasekaran Committed by Commit Bot

Reland "[ic] Inline constant fields in IC"

This reverts commit f6e08f43.

This patch doesn't allow thin/cons strings to be inlined as weak refs
to them are not supported by the GC.

Bug: v8:9616
Change-Id: I0407654bd9d20fe0182de4b8554e21ddbce8b28c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1774720
Commit-Queue: Sathya Gunasekaran  <gsathya@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63478}
parent ef2df57a
......@@ -303,6 +303,7 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase(
TNode<IntPtrT> handler_word = SmiUntag(smi_handler);
TNode<IntPtrT> handler_kind =
Signed(DecodeWord<LoadHandler::KindBits>(handler_word));
if (support_elements == kSupportElements) {
Label if_element(this), if_indexed_string(this), if_property(this);
GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kElement)),
......@@ -428,9 +429,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)),
......@@ -478,11 +481,7 @@ void AccessorAssembler::HandleLoadICSmiHandlerLoadNamedCase(
BIND(&constant);
{
Comment("constant_load");
TNode<IntPtrT> descriptor =
Signed(DecodeWord<LoadHandler::DescriptorBits>(handler_word));
TNode<Object> value = LoadDescriptorValue(LoadMap(holder), descriptor);
exit_point->Return(value);
exit_point->Return(holder);
}
BIND(&normal);
......@@ -626,7 +625,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)),
......@@ -834,21 +834,38 @@ 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));
TNode<HeapObject> 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));
TNode<HeapObject> 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);
......
......@@ -903,6 +903,33 @@ 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());
Handle<Object> value = lookup->GetDataValue();
if (value->IsThinString()) {
value = handle(ThinString::cast(*value)->actual(), isolate());
}
// Non internalized strings could turn into thin/cons strings
// when internalized. Weak references to thin/cons strings are
// not supported in the GC. If concurrent marking is running
// and the thin/cons string is marked but the actual string is
// not, then the weak reference could be missed.
if (!value->IsString() ||
(value->IsString() && value->IsInternalizedString())) {
MaybeObjectHandle weak_value =
value->IsSmi() ? MaybeObjectHandle(*value, isolate())
: MaybeObjectHandle::Weak(*value, isolate());
smi_handler = LoadHandler::LoadConstantFromPrototype(isolate());
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH);
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