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

Unified Diff: src/code-stub-assembler.cc

Issue 2182103002: [KeyedLoadIC] Support Smi "handlers" for simple field loads (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: implement KeyedLoadIC stub in CodeStubAssembler Created 4 years, 5 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
Index: src/code-stub-assembler.cc
diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
index b2f6114f57d466076fe6753497c99768fa7b306a..99e9003a9286aeb76584089f76483040c9218f96 100644
--- a/src/code-stub-assembler.cc
+++ b/src/code-stub-assembler.cc
@@ -2416,7 +2416,7 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map,
Node* elements = LoadElements(object);
Node* length = LoadFixedArrayBaseLength(elements);
- GotoIf(Int32GreaterThanOrEqual(index, SmiToWord32(length)), if_not_found);
+ GotoUnless(Uint32LessThan(index, SmiToWord32(length)), if_not_found);
Jakob Kummerow 2016/07/26 14:43:28 Drive-by fix: bounds checks should use unsigned co
Igor Sheludko 2016/07/26 16:25:11 Acknowledged.
Node* element = LoadFixedArrayElement(elements, index);
Node* the_hole = TheHoleConstant();
@@ -2427,7 +2427,7 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map,
Node* elements = LoadElements(object);
Node* length = LoadFixedArrayBaseLength(elements);
- GotoIf(Int32GreaterThanOrEqual(index, SmiToWord32(length)), if_not_found);
+ GotoUnless(Uint32LessThan(index, SmiToWord32(length)), if_not_found);
if (kPointerSize == kDoubleSize) {
Node* element =
@@ -2456,7 +2456,7 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map,
Assert(Int32LessThan(LoadInstanceType(string),
Int32Constant(FIRST_NONSTRING_TYPE)));
Node* length = LoadStringLength(string);
- GotoIf(Int32LessThan(index, SmiToWord32(length)), if_found);
+ GotoIf(Uint32LessThan(index, SmiToWord32(length)), if_found);
Goto(&if_isobjectorsmi);
}
Bind(&if_isslowstringwrapper);
@@ -2466,7 +2466,7 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map,
Assert(Int32LessThan(LoadInstanceType(string),
Int32Constant(FIRST_NONSTRING_TYPE)));
Node* length = LoadStringLength(string);
- GotoIf(Int32LessThan(index, SmiToWord32(length)), if_found);
+ GotoIf(Uint32LessThan(index, SmiToWord32(length)), if_found);
Goto(&if_isdictionary);
}
}
@@ -2977,6 +2977,66 @@ void CodeStubAssembler::TryProbeStubCache(
}
}
+void CodeStubAssembler::HaveLoadICHandler(const LoadICParameters* p,
+ Node* handler, Label* miss) {
+ Comment("have_handler");
+ Label call_handler(this);
+ GotoUnless(WordIsSmi(handler), &call_handler);
+
+ // |handler| is a Smi. It encodes a field index as obtained by
+ // FieldIndex.GetLoadByFieldOffset().
+ // TODO(jkummerow): For KeyedLoadICs, extend this scheme to encode
+ // fast *element* loads.
+ {
+ Variable var_double_value(this, MachineRepresentation::kFloat64);
+ Label rebox_double(this, &var_double_value);
+
+ Node* handler_word = SmiUntag(handler);
+ // |handler_word| is a field index as obtained by
+ // FieldIndex.GetLoadByFieldOffset():
+ // (offset << 3) | (is_double << 2) | (is_inobject << 1) | 1.
+ Label inobject_double(this), out_of_object(this),
+ out_of_object_double(this);
+ Node* inobject_bit = WordAnd(handler_word, IntPtrConstant(1 << 1));
+ Node* double_bit = WordAnd(handler_word, IntPtrConstant(1 << 2));
+ Node* offset = WordSar(handler_word, IntPtrConstant(3));
+
+ GotoIf(WordEqual(inobject_bit, IntPtrConstant(0)), &out_of_object);
+
+ GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &inobject_double);
+ Return(LoadObjectField(p->receiver, offset));
+
+ Bind(&inobject_double);
+ if (FLAG_unbox_double_fields) {
+ var_double_value.Bind(
+ LoadObjectField(p->receiver, offset, MachineType::Float64()));
+ } else {
+ Node* mutable_heap_number = LoadObjectField(p->receiver, offset);
+ var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number));
+ }
+ Goto(&rebox_double);
+
+ Bind(&out_of_object);
+ Node* properties = LoadProperties(p->receiver);
+ Node* value = LoadObjectField(properties, offset);
+ GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &out_of_object_double);
+ Return(value);
+
+ Bind(&out_of_object_double);
+ var_double_value.Bind(LoadHeapNumberValue(value));
+ Goto(&rebox_double);
+
+ Bind(&rebox_double);
+ Return(AllocateHeapNumberWithValue(var_double_value.value()));
+ }
+
+ // |handler| is a heap object. Must be code, call it.
+ Bind(&call_handler);
+ LoadWithVectorDescriptor descriptor(isolate());
+ TailCallStub(descriptor, handler, p->context, p->receiver, p->name, p->slot,
+ p->vector);
+}
+
void CodeStubAssembler::LoadIC(const LoadICParameters* p) {
Variable var_handler(this, MachineRepresentation::kTagged);
// TODO(ishell): defer blocks when it works.
@@ -2991,63 +3051,7 @@ void CodeStubAssembler::LoadIC(const LoadICParameters* p) {
&var_handler, &try_polymorphic);
Bind(&if_handler);
{
- Comment("LoadIC_if_handler");
- Label call_handler(this);
- Node* handler = var_handler.value();
- GotoUnless(WordIsSmi(handler), &call_handler);
-
- // |handler| is a Smi. It encodes a field index as obtained by
- // FieldIndex.GetLoadByFieldOffset().
- {
- Label inobject_double(this), out_of_object(this),
- out_of_object_double(this);
- Variable var_double_value(this, MachineRepresentation::kFloat64);
- Label rebox_double(this, &var_double_value);
-
- Node* handler_word = SmiToWord32(handler);
- // handler == (offset << 1) | is_double.
- Node* double_bit = Word32And(handler_word, Int32Constant(1));
- Node* offset = Word32Sar(handler_word, Int32Constant(1));
-
- // Negative index -> out of object.
- GotoIf(Int32LessThan(offset, Int32Constant(0)), &out_of_object);
-
- Node* offset_ptr = ChangeInt32ToIntPtr(offset);
- GotoUnless(Word32Equal(double_bit, Int32Constant(0)), &inobject_double);
- Return(LoadObjectField(p->receiver, offset_ptr));
-
- Bind(&inobject_double);
- if (FLAG_unbox_double_fields) {
- var_double_value.Bind(
- LoadObjectField(p->receiver, offset_ptr, MachineType::Float64()));
- } else {
- Node* mutable_heap_number = LoadObjectField(p->receiver, offset_ptr);
- var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number));
- }
- Goto(&rebox_double);
-
- Bind(&out_of_object);
- // |offset| == -actual_offset
- offset_ptr = ChangeInt32ToIntPtr(Int32Sub(Int32Constant(0), offset));
- Node* properties = LoadProperties(p->receiver);
- Node* value = LoadObjectField(properties, offset_ptr);
- GotoUnless(Word32Equal(double_bit, Int32Constant(0)),
- &out_of_object_double);
- Return(value);
-
- Bind(&out_of_object_double);
- var_double_value.Bind(LoadHeapNumberValue(value));
- Goto(&rebox_double);
-
- Bind(&rebox_double);
- Return(AllocateHeapNumberWithValue(var_double_value.value()));
- }
-
- // |handler| is a heap object. Must be code, call it.
- Bind(&call_handler);
- LoadWithVectorDescriptor descriptor(isolate());
- TailCallStub(descriptor, handler, p->context, p->receiver, p->name, p->slot,
- p->vector);
+ HaveLoadICHandler(p, var_handler.value(), &miss);
}
Bind(&try_polymorphic);
@@ -3078,6 +3082,68 @@ void CodeStubAssembler::LoadIC(const LoadICParameters* p) {
}
}
+void CodeStubAssembler::KeyedLoadIC(const LoadICParameters* p) {
+ Variable var_handler(this, MachineRepresentation::kTagged);
+ // TODO(ishell): defer blocks when it works.
+ Label if_handler(this, &var_handler), try_polymorphic(this),
+ try_megamorphic(this /*, Label::kDeferred*/),
+ try_polymorphic_name(this /*, Label::kDeferred*/),
+ miss(this /*, Label::kDeferred*/);
+
+ Node* receiver_map = LoadReceiverMap(p->receiver);
+
+ // Check monomorphic case.
+ Node* feedback = TryMonomorphicCase(p, receiver_map, &if_handler,
+ &var_handler, &try_polymorphic);
+ Bind(&if_handler);
+ {
+ HaveLoadICHandler(p, var_handler.value(), &miss);
+ }
+
+ Bind(&try_polymorphic);
+ {
+ // Check polymorphic case.
+ Comment("KeyedLoadIC_try_polymorphic");
+ GotoUnless(
+ WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)),
+ &try_megamorphic);
+ HandlePolymorphicCase(p, receiver_map, feedback, &if_handler, &var_handler,
+ &miss, 2);
+ }
+
+ Bind(&try_megamorphic);
+ {
+ // Check megamorphic case.
+ Comment("KeyedLoadIC_try_megamorphic");
+ GotoUnless(
+ WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)),
+ &try_polymorphic_name);
+ // TODO(jkummerow): Inline this? Or some of it?
+ TailCallStub(CodeFactory::KeyedLoadIC_Megamorphic(isolate()), p->context,
+ p->receiver, p->name, p->slot, p->vector);
+ }
+ Bind(&try_polymorphic_name);
+ {
+ // We might have a name in feedback, and a fixed array in the next slot.
+ Comment("KeyedLoadIC_try_polymorphic_name");
+ GotoUnless(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);
+ HandlePolymorphicCase(p, receiver_map, array, &if_handler, &var_handler,
+ &miss, 1);
+ }
+ Bind(&miss);
+ {
+ Comment("KeyedLoadIC_miss");
+ TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver,
+ p->name, p->slot, p->vector);
+ }
+}
+
void CodeStubAssembler::LoadGlobalIC(const LoadICParameters* p) {
Label try_handler(this), miss(this);
Node* weak_cell =
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/code-stubs.h » ('j') | src/code-stubs.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698