Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(593)

Unified Diff: src/ic/accessor-assembler.cc

Issue 2733563002: [ic] Inline LoadIC into LdaNamedProperty bytecode handler (Closed)
Patch Set: Remove LoadFeedbackSlot Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ic/accessor-assembler.h ('k') | src/interpreter/interpreter.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ic/accessor-assembler.cc
diff --git a/src/ic/accessor-assembler.cc b/src/ic/accessor-assembler.cc
index 5645124ccdfa622305fa6eab89f28700f06d83b2..9e40a37fe1710824e5de29e5d0fbbe9e672523d7 100644
--- a/src/ic/accessor-assembler.cc
+++ b/src/ic/accessor-assembler.cc
@@ -61,6 +61,10 @@ void AccessorAssembler::HandlePolymorphicCase(Node* receiver_map,
Comment("HandlePolymorphicCase");
DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
+ // Deferred so the unrolled case can omit frame construction in bytecode
+ // handler.
+ Label loop(this, Label::kDeferred);
+
// Iterate {feedback} array.
const int kEntrySize = 2;
@@ -77,8 +81,10 @@ void AccessorAssembler::HandlePolymorphicCase(Node* receiver_map,
Bind(&next_entry);
}
+ Goto(&loop);
// Loop from {unroll_count}*kEntrySize to {length}.
+ Bind(&loop);
Node* init = IntPtrConstant(unroll_count * kEntrySize);
Node* length = LoadAndUntagFixedArrayBaseLength(feedback);
BuildFastLoop(
@@ -141,9 +147,8 @@ void AccessorAssembler::HandleKeyedStorePolymorphicCase(
void AccessorAssembler::HandleLoadICHandlerCase(
const LoadICParameters* p, Node* handler, Label* miss,
- ElementSupport support_elements) {
+ ExitPoint* exit_point, ElementSupport support_elements) {
Comment("have_handler");
- ExitPoint direct_exit(this);
Variable var_holder(this, MachineRepresentation::kTagged, p->receiver);
Variable var_smi_handler(this, MachineRepresentation::kTagged, handler);
@@ -160,21 +165,21 @@ void AccessorAssembler::HandleLoadICHandlerCase(
Bind(&if_smi_handler);
{
HandleLoadICSmiHandlerCase(p, var_holder.value(), var_smi_handler.value(),
- miss, &direct_exit, support_elements);
+ miss, exit_point, support_elements);
}
Bind(&try_proto_handler);
{
GotoIf(IsCodeMap(LoadMap(handler)), &call_handler);
HandleLoadICProtoHandlerCase(p, handler, &var_holder, &var_smi_handler,
- &if_smi_handler, miss, &direct_exit, false);
+ &if_smi_handler, miss, exit_point, false);
}
Bind(&call_handler);
{
typedef LoadWithVectorDescriptor Descriptor;
- TailCallStub(Descriptor(isolate()), handler, p->context, p->receiver,
- p->name, p->slot, p->vector);
+ exit_point->ReturnCallStub(Descriptor(isolate()), handler, p->context,
+ p->receiver, p->name, p->slot, p->vector);
}
}
@@ -273,8 +278,7 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase(
Comment("property_load");
}
- Label constant(this, Label::kDeferred), field(this),
- normal(this, Label::kDeferred);
+ Label constant(this), field(this), normal(this, Label::kDeferred);
GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForFields)),
&field);
@@ -664,7 +668,7 @@ void AccessorAssembler::HandleStoreICProtoHandler(const StoreICParameters* p,
Node* transition = var_transition.value();
Node* handler_word = SmiUntag(smi_handler);
- GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(transition)), miss);
+ GotoIf(IsDeprecatedMap(transition), miss);
Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kStoreNormal)),
@@ -1322,6 +1326,8 @@ void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map,
const LoadICParameters* p,
Label* slow,
UseStubCache use_stub_cache) {
+ ExitPoint direct_exit(this);
+
Comment("key is unique name");
Label if_found_on_receiver(this), if_property_dictionary(this),
lookup_prototype_chain(this);
@@ -1368,7 +1374,7 @@ void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map,
TryProbeStubCache(isolate()->load_stub_cache(), receiver, key,
&found_handler, &var_handler, &stub_cache_miss);
Bind(&found_handler);
- { HandleLoadICHandlerCase(p, var_handler.value(), slow); }
+ { HandleLoadICHandlerCase(p, var_handler.value(), slow, &direct_exit); }
Bind(&stub_cache_miss);
{
@@ -1576,54 +1582,136 @@ void AccessorAssembler::TryProbeStubCache(StubCache* stub_cache, Node* receiver,
//////////////////// Entry points into private implementation (one per stub).
+void AccessorAssembler::LoadIC_BytecodeHandler(const LoadICParameters* p,
+ ExitPoint* exit_point) {
+ // Must be kept in sync with LoadIC.
+
+ // This function is hand-tuned to omit frame construction for common cases,
+ // e.g.: monomorphic field and constant loads through smi handlers.
+ // Polymorphic ICs with a hit in the first two entries also omit frames.
+ // TODO(jgruber): Frame omission is fragile and can be affected by minor
+ // changes in control flow and logic. We currently have no way of ensuring
+ // that no frame is constructed, so it's easy to break this optimization by
+ // accident.
+ Label stub_call(this, Label::kDeferred), miss(this, Label::kDeferred);
+
+ // Inlined fast path.
+ {
+ Comment("LoadIC_BytecodeHandler_fast");
+
+ Node* recv_map = LoadReceiverMap(p->receiver);
+ GotoIf(IsDeprecatedMap(recv_map), &miss);
+
+ Variable var_handler(this, MachineRepresentation::kTagged);
+ Label try_polymorphic(this), if_handler(this, &var_handler);
+
+ Node* feedback =
+ TryMonomorphicCase(p->slot, p->vector, recv_map, &if_handler,
+ &var_handler, &try_polymorphic);
+
+ Bind(&if_handler);
+ HandleLoadICHandlerCase(p, var_handler.value(), &miss, exit_point);
+
+ Bind(&try_polymorphic);
+ {
+ GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()),
+ &stub_call);
+ HandlePolymorphicCase(recv_map, feedback, &if_handler, &var_handler,
+ &miss, 2);
+ }
+ }
+
+ Bind(&stub_call);
+ {
+ Comment("LoadIC_BytecodeHandler_noninlined");
+
+ // Call into the stub that implements the non-inlined parts of LoadIC.
+ Callable ic = CodeFactory::LoadICInOptimizedCode_Noninlined(isolate());
+ Node* code_target = HeapConstant(ic.code());
+ exit_point->ReturnCallStub(ic.descriptor(), code_target, p->context,
+ p->receiver, p->name, p->slot, p->vector);
+ }
+
+ Bind(&miss);
+ {
+ Comment("LoadIC_BytecodeHandler_miss");
+
+ exit_point->ReturnCallRuntime(Runtime::kLoadIC_Miss, p->context,
+ p->receiver, p->name, p->slot, p->vector);
+ }
+}
+
void AccessorAssembler::LoadIC(const LoadICParameters* p) {
+ // Must be kept in sync with LoadIC_BytecodeHandler.
+
+ ExitPoint direct_exit(this);
+
Variable var_handler(this, MachineRepresentation::kTagged);
- Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred),
- try_megamorphic(this, Label::kDeferred),
- try_uninitialized(this, Label::kDeferred), miss(this, Label::kDeferred);
+ Label if_handler(this, &var_handler), non_inlined(this, Label::kDeferred),
+ try_polymorphic(this), miss(this, Label::kDeferred);
Node* receiver_map = LoadReceiverMap(p->receiver);
- GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss);
+ GotoIf(IsDeprecatedMap(receiver_map), &miss);
// Check monomorphic case.
Node* feedback =
TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler,
&var_handler, &try_polymorphic);
Bind(&if_handler);
- { HandleLoadICHandlerCase(p, var_handler.value(), &miss); }
+ HandleLoadICHandlerCase(p, var_handler.value(), &miss, &direct_exit);
Bind(&try_polymorphic);
{
// Check polymorphic case.
Comment("LoadIC_try_polymorphic");
GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()),
- &try_megamorphic);
+ &non_inlined);
HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler,
&miss, 2);
}
- Bind(&try_megamorphic);
+ Bind(&non_inlined);
+ LoadIC_Noninlined(p, receiver_map, feedback, &var_handler, &if_handler, &miss,
+ &direct_exit);
+
+ Bind(&miss);
+ direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver,
+ p->name, p->slot, p->vector);
+}
+
+void AccessorAssembler::LoadIC_Noninlined(const LoadICParameters* p,
+ Node* receiver_map, Node* feedback,
+ Variable* var_handler,
+ Label* if_handler, Label* miss,
+ ExitPoint* exit_point) {
+ Label try_uninitialized(this, Label::kDeferred);
+
+ // Neither deprecated map nor monomorphic. These cases are handled in the
+ // bytecode handler.
+ CSA_ASSERT(this, Word32BinaryNot(IsDeprecatedMap(receiver_map)));
+ CSA_ASSERT(this,
+ WordNotEqual(receiver_map, LoadWeakCellValueUnchecked(feedback)));
+ CSA_ASSERT(this, WordNotEqual(LoadMap(feedback), FixedArrayMapConstant()));
+ DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
+
{
// Check megamorphic case.
GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)),
&try_uninitialized);
TryProbeStubCache(isolate()->load_stub_cache(), p->receiver, p->name,
- &if_handler, &var_handler, &miss);
+ if_handler, var_handler, miss);
}
+
Bind(&try_uninitialized);
{
// Check uninitialized case.
GotoIfNot(
WordEqual(feedback, LoadRoot(Heap::kuninitialized_symbolRootIndex)),
- &miss);
- TailCallStub(CodeFactory::LoadIC_Uninitialized(isolate()), p->context,
- p->receiver, p->name, p->slot, p->vector);
- }
- Bind(&miss);
- {
- TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name,
- p->slot, p->vector);
+ miss);
+ exit_point->ReturnCallStub(CodeFactory::LoadIC_Uninitialized(isolate()),
+ p->context, p->receiver, p->name, p->slot,
+ p->vector);
}
}
@@ -1767,6 +1855,8 @@ void AccessorAssembler::LoadGlobalIC_MissCase(const LoadICParameters* p,
void AccessorAssembler::LoadGlobalIC(const LoadICParameters* p,
TypeofMode typeof_mode) {
+ // Must be kept in sync with Interpreter::BuildLoadGlobal.
+
ExitPoint direct_exit(this);
Label try_handler(this), miss(this);
@@ -1781,6 +1871,8 @@ void AccessorAssembler::LoadGlobalIC(const LoadICParameters* p,
}
void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) {
+ ExitPoint direct_exit(this);
+
Variable var_handler(this, MachineRepresentation::kTagged);
Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred),
try_megamorphic(this, Label::kDeferred),
@@ -1788,14 +1880,17 @@ void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) {
miss(this, Label::kDeferred);
Node* receiver_map = LoadReceiverMap(p->receiver);
- GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss);
+ GotoIf(IsDeprecatedMap(receiver_map), &miss);
// Check monomorphic case.
Node* feedback =
TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler,
&var_handler, &try_polymorphic);
Bind(&if_handler);
- { HandleLoadICHandlerCase(p, var_handler.value(), &miss, kSupportElements); }
+ {
+ HandleLoadICHandlerCase(p, var_handler.value(), &miss, &direct_exit,
+ kSupportElements);
+ }
Bind(&try_polymorphic);
{
@@ -1824,10 +1919,8 @@ void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) {
GotoIfNot(WordEqual(feedback, p->name), &miss);
// If the name comparison succeeded, we know we have a fixed array with
// at least one map/handler pair.
- Node* offset = ElementOffsetFromIndex(
- p->slot, FAST_HOLEY_ELEMENTS, SMI_PARAMETERS,
- FixedArray::kHeaderSize + kPointerSize - kHeapObjectTag);
- Node* array = Load(MachineType::AnyTagged(), p->vector, offset);
+ Node* array =
+ LoadFixedArrayElement(p->vector, p->slot, kPointerSize, SMI_PARAMETERS);
HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, &miss,
1);
}
@@ -1881,7 +1974,7 @@ void AccessorAssembler::StoreIC(const StoreICParameters* p) {
try_megamorphic(this, Label::kDeferred), miss(this, Label::kDeferred);
Node* receiver_map = LoadReceiverMap(p->receiver);
- GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss);
+ GotoIf(IsDeprecatedMap(receiver_map), &miss);
// Check monomorphic case.
Node* feedback =
@@ -1932,7 +2025,7 @@ void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p,
try_polymorphic_name(this, Label::kDeferred);
Node* receiver_map = LoadReceiverMap(p->receiver);
- GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss);
+ GotoIf(IsDeprecatedMap(receiver_map), &miss);
// Check monomorphic case.
Node* feedback =
@@ -2013,10 +2106,8 @@ void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p,
GotoIfNot(WordEqual(feedback, p->name), &miss);
// If the name comparison succeeded, we know we have a FixedArray with
// at least one map/handler pair.
- Node* offset = ElementOffsetFromIndex(
- p->slot, FAST_HOLEY_ELEMENTS, SMI_PARAMETERS,
- FixedArray::kHeaderSize + kPointerSize - kHeapObjectTag);
- Node* array = Load(MachineType::AnyTagged(), p->vector, offset);
+ Node* array = LoadFixedArrayElement(p->vector, p->slot, kPointerSize,
+ SMI_PARAMETERS);
HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler,
&miss, 1);
}
@@ -2044,6 +2135,34 @@ void AccessorAssembler::GenerateLoadIC() {
LoadIC(&p);
}
+void AccessorAssembler::GenerateLoadIC_Noninlined() {
+ typedef LoadWithVectorDescriptor Descriptor;
+
+ Node* receiver = Parameter(Descriptor::kReceiver);
+ Node* name = Parameter(Descriptor::kName);
+ Node* slot = Parameter(Descriptor::kSlot);
+ Node* vector = Parameter(Descriptor::kVector);
+ Node* context = Parameter(Descriptor::kContext);
+
+ ExitPoint direct_exit(this);
+ Variable var_handler(this, MachineRepresentation::kTagged);
+ Label if_handler(this, &var_handler), miss(this, Label::kDeferred);
+
+ Node* receiver_map = LoadReceiverMap(receiver);
+ Node* feedback = LoadFixedArrayElement(vector, slot, 0, SMI_PARAMETERS);
+
+ LoadICParameters p(context, receiver, name, slot, vector);
+ LoadIC_Noninlined(&p, receiver_map, feedback, &var_handler, &if_handler,
+ &miss, &direct_exit);
+
+ Bind(&if_handler);
+ HandleLoadICHandlerCase(&p, var_handler.value(), &miss, &direct_exit);
+
+ Bind(&miss);
+ direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name,
+ slot, vector);
+}
+
void AccessorAssembler::GenerateLoadIC_Uninitialized() {
typedef LoadWithVectorDescriptor Descriptor;
« no previous file with comments | « src/ic/accessor-assembler.h ('k') | src/interpreter/interpreter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698