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

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

Issue 2180273002: [KeyedLoadIC] Support Smi "handlers" for element loads (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@keyed-load-ic-fieldindex
Patch Set: rebased 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 6e3cd99dd5b2083f68d5dc37ab10aed543e705ed..fa927c21cc7337e7bd25e015f10104457b1eb990 100644
--- a/src/code-stub-assembler.cc
+++ b/src/code-stub-assembler.cc
@@ -6,6 +6,7 @@
#include "src/code-factory.h"
#include "src/frames-inl.h"
#include "src/frames.h"
+#include "src/ic/handler-compiler.h"
#include "src/ic/stub-cache.h"
namespace v8 {
@@ -2977,21 +2978,214 @@ void CodeStubAssembler::TryProbeStubCache(
}
}
-void CodeStubAssembler::HandleLoadICHandlerCase(const LoadICParameters* p,
- Node* handler, Label* miss) {
+void CodeStubAssembler::HandleLoadICHandlerCase(
+ const LoadICParameters* p, Node* handler, Label* miss,
+ ElementSupport support_elements) {
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.
+ // |handler| is a Smi, encoding what to do. The last bit distinguishes
+ // element and property loads.
{
Variable var_double_value(this, MachineRepresentation::kFloat64);
Label rebox_double(this, &var_double_value);
Node* handler_word = SmiUntag(handler);
+ if (support_elements == kSupportElements) {
Igor Sheludko 2016/07/28 10:01:11 I think this new code (and maybe the property case
Jakob Kummerow 2016/08/03 11:44:11 Done (did some splitting, though not exactly here)
+ Variable var_length(this, MachineRepresentation::kTagged);
+ Label property(this), is_array(this), length_loaded(this, &var_length);
+ Node* is_element_bit = WordAnd(handler_word, IntPtrConstant(1));
Igor Sheludko 2016/07/28 10:01:11 It would be nice to have such a SmiHandlerIsProper
Jakob Kummerow 2016/08/03 11:44:09 Done.
+ GotoUnless(WordEqual(is_element_bit, IntPtrConstant(0)), &property);
+
+ Comment("element_load");
+ GotoUnless(WordIsSmi(p->name), miss);
Igor Sheludko 2016/07/28 10:01:11 Future improvement: support "123"-like unique stri
Jakob Kummerow 2016/08/03 11:44:09 Possibly, yes. That change would have to be made i
+ Node* key = SmiUntag(p->name);
+ Node* elements = LoadElements(p->receiver);
+ Node* is_jsarray = WordAnd(
+ handler_word,
+ IntPtrConstant(ElementHandlerCompiler::KeyedLoadIsJsarray::kMask));
+ GotoUnless(WordEqual(is_jsarray, IntPtrConstant(0)), &is_array);
+ var_length.Bind(SmiUntag(LoadFixedArrayBaseLength(elements)));
+ Goto(&length_loaded);
+ Bind(&is_array);
Igor Sheludko 2016/07/28 10:01:11 Consider wrapping blocks in {} for readability.
Jakob Kummerow 2016/08/03 11:44:09 Done.
+ var_length.Bind(
+ SmiUntag(LoadObjectField(p->receiver, JSArray::kLengthOffset)));
+ Goto(&length_loaded);
+
+ Bind(&length_loaded);
Igor Sheludko 2016/07/28 10:01:11 Same here.
Jakob Kummerow 2016/08/03 11:44:12 Done.
+ // Bounds check.
+ GotoUnless(UintPtrLessThan(key, var_length.value()), miss);
+ Node* convert_hole = WordAnd(
Igor Sheludko 2016/07/28 10:01:11 You can probably move this to if_hole block althou
Jakob Kummerow 2016/08/03 11:44:11 Done.
+ handler_word,
+ IntPtrConstant(ElementHandlerCompiler::KeyedLoadConvertHole::kMask));
+ Node* elements_kind =
+ WordShr(handler_word,
+ IntPtrConstant(
+ ElementHandlerCompiler::KeyedLoadElementsKind::kShift));
+
+ Label typed_array(this), fast_packed(this), fast_holey(this),
Igor Sheludko 2016/07/28 10:01:10 As far as I understand we have a kind of naming co
Jakob Kummerow 2016/08/03 11:44:11 Done.
+ fast_double(this), fast_holey_double(this), hole(this);
Igor Sheludko 2016/07/28 10:01:11 STATIC_ASSERT(LAST_ELEMENTS_KIND == LAST_FIXED_TYP
Jakob Kummerow 2016/08/03 11:44:11 Done.
+ GotoIf(IntPtrGreaterThanOrEqual(
+ elements_kind,
+ IntPtrConstant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)),
+ &typed_array);
+#define JUMP_IF_KIND(kind, label) \
+ GotoIf(WordEqual(elements_kind, IntPtrConstant(kind)), label);
Igor Sheludko 2016/07/28 10:01:10 It looks like a switch construct will fit better h
Jakob Kummerow 2016/08/03 11:44:09 Done.
+
+ JUMP_IF_KIND(FAST_SMI_ELEMENTS, &fast_packed);
+ JUMP_IF_KIND(FAST_ELEMENTS, &fast_packed);
+ JUMP_IF_KIND(FAST_HOLEY_SMI_ELEMENTS, &fast_holey);
+ JUMP_IF_KIND(FAST_HOLEY_ELEMENTS, &fast_holey);
+ JUMP_IF_KIND(FAST_DOUBLE_ELEMENTS, &fast_double);
+ JUMP_IF_KIND(FAST_HOLEY_DOUBLE_ELEMENTS, &fast_holey_double);
+ // All other kinds are unimplemented.
+ DebugBreak();
Igor Sheludko 2016/07/28 10:01:11 ?
Jakob Kummerow 2016/08/03 11:44:11 I want to crash if we get here. Think "UNREACHABLE
+ Goto(miss);
+#undef JUMP_IF_KIND
+
+ Bind(&fast_packed);
+ Comment("fast packed elements");
Igor Sheludko 2016/07/28 10:01:11 Consider wrapping blocks in {} for readability.
Jakob Kummerow 2016/08/03 11:44:11 Done.
+ // TODO(jkummerow): The Load*Element helpers add movsxlq instructions
+ // on x64 which we don't need here, because |key| is an IntPtr already.
+ // Do something about that.
Igor Sheludko 2016/07/28 10:01:10 We just need to introduce INTPTR_PARAMETERS mode.
Jakob Kummerow 2016/08/03 11:44:09 Yes, that's what I was thinking too. Follow-up CL.
+ Return(LoadFixedArrayElement(elements, key));
+
+ Bind(&fast_holey);
+ {
+ Comment("fast holey elements");
+ Node* element = LoadFixedArrayElement(elements, key);
+ GotoIf(WordEqual(element, TheHoleConstant()), &hole);
+ Return(element);
+ }
+
+ Bind(&fast_double);
+ Comment("packed double elements");
Igor Sheludko 2016/07/28 10:01:11 Same here.
Jakob Kummerow 2016/08/03 11:44:09 Done.
+ var_double_value.Bind(
+ LoadFixedDoubleArrayElement(elements, key, MachineType::Float64()));
+ Goto(&rebox_double);
+
+ Bind(&fast_holey_double);
+ {
+ Comment("holey double elements");
+ if (kPointerSize == kDoubleSize) {
+ Node* raw_element =
+ LoadFixedDoubleArrayElement(elements, key, MachineType::Uint64());
+ Node* the_hole = Int64Constant(kHoleNanInt64);
+ GotoIf(Word64Equal(raw_element, the_hole), &hole);
+ } else {
+ Node* element_upper =
+ LoadFixedDoubleArrayElement(elements, key, MachineType::Uint32(),
+ kIeeeDoubleExponentWordOffset);
+ GotoIf(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)),
+ &hole);
+ }
+ var_double_value.Bind(
+ LoadFixedDoubleArrayElement(elements, key, MachineType::Float64()));
+ Goto(&rebox_double);
+ }
+
+ Bind(&hole);
+ {
+ Comment("convert hole");
+ GotoIf(WordEqual(convert_hole, IntPtrConstant(0)), miss);
+ Node* protector_cell = LoadRoot(Heap::kArrayProtectorRootIndex);
+ GotoUnless(
+ WordEqual(LoadObjectField(protector_cell, Cell::kValueOffset),
+ SmiConstant(Smi::FromInt(Isolate::kArrayProtectorValid))),
+ miss);
+ Return(UndefinedConstant());
+ }
+
+ Bind(&typed_array);
Igor Sheludko 2016/07/28 10:01:11 And here.
Jakob Kummerow 2016/08/03 11:44:09 Done.
+ Comment("typed elements");
+ // Check if buffer has been neutered.
+ Node* buffer =
+ LoadObjectField(p->receiver, JSArrayBufferView::kBufferOffset);
+ Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset,
+ MachineType::Uint32());
+ Node* neutered_bit = Word32And(
+ bitfield, Int32Constant(1 << JSArrayBuffer::WasNeutered::kShift));
Igor Sheludko 2016/07/28 10:01:11 JSArrayBuffer::WasNeutered::kMask?
Jakob Kummerow 2016/08/03 11:44:09 Done.
+ GotoUnless(Word32Equal(neutered_bit, Int32Constant(0)), miss);
+ // Backing store = external_pointer + base_pointer.
+ Node* external_pointer =
+ LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
+ MachineType::Pointer());
+ Node* base_pointer =
+ LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
+ Node* backing_store = IntPtrAdd(external_pointer, base_pointer);
+
+ const int kTypedElementsKindCount =
+ LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND -
+ FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND + 1;
+ Label* elements_kind_labels[kTypedElementsKindCount];
+ int32_t elements_kinds[kTypedElementsKindCount];
+ for (int i = 0; i < kTypedElementsKindCount; i++) {
+ elements_kinds[i] = i + FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND;
+ elements_kind_labels[i] = new Label(this);
+ }
+ Switch(elements_kind, miss, elements_kinds, elements_kind_labels,
+ static_cast<size_t>(kTypedElementsKindCount));
+
+ for (int i = 0; i < kTypedElementsKindCount; i++) {
+ ElementsKind kind = static_cast<ElementsKind>(elements_kinds[i]);
+ Bind(elements_kind_labels[i]);
+ Comment(ElementsKindToString(kind));
+ switch (kind) {
+ case UINT8_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS:
+ Return(SmiTag(Load(MachineType::Uint8(), backing_store, key)));
+ break;
+ case INT8_ELEMENTS:
+ Return(SmiTag(Load(MachineType::Int8(), backing_store, key)));
+ break;
+ case UINT16_ELEMENTS: {
+ Node* index = WordShl(key, IntPtrConstant(1));
+ Return(SmiTag(Load(MachineType::Uint16(), backing_store, index)));
+ break;
+ }
+ case INT16_ELEMENTS: {
+ Node* index = WordShl(key, IntPtrConstant(1));
+ Return(SmiTag(Load(MachineType::Int16(), backing_store, index)));
+ break;
+ }
+ case UINT32_ELEMENTS: {
+ Node* index = WordShl(key, IntPtrConstant(2));
+ Node* element = Load(MachineType::Uint32(), backing_store, index);
+ Return(ChangeUint32ToTagged(element));
+ break;
+ }
+ case INT32_ELEMENTS: {
+ Node* index = WordShl(key, IntPtrConstant(2));
+ Node* element = Load(MachineType::Int32(), backing_store, index);
+ Return(ChangeInt32ToTagged(element));
+ break;
+ }
+ case FLOAT32_ELEMENTS: {
+ Node* index = WordShl(key, IntPtrConstant(2));
+ Node* element = Load(MachineType::Float32(), backing_store, index);
+ var_double_value.Bind(ChangeFloat32ToFloat64(element));
+ Goto(&rebox_double);
+ break;
+ }
+ case FLOAT64_ELEMENTS: {
+ Node* index = WordShl(key, IntPtrConstant(3));
+ Node* element = Load(MachineType::Float64(), backing_store, index);
+ var_double_value.Bind(element);
+ Goto(&rebox_double);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ // Don't forget to clean up.
+ delete elements_kind_labels[i];
+ }
+
+ Bind(&property);
+ Comment("property_load");
+ }
+
// |handler_word| is a field index as obtained by
// FieldIndex.GetLoadByFieldOffset():
Label inobject_double(this), out_of_object(this),
@@ -3102,7 +3296,7 @@ void CodeStubAssembler::KeyedLoadIC(const LoadICParameters* p) {
&var_handler, &try_polymorphic);
Bind(&if_handler);
{
- HandleLoadICHandlerCase(p, var_handler.value(), &miss);
+ HandleLoadICHandlerCase(p, var_handler.value(), &miss, kSupportElements);
}
Bind(&try_polymorphic);
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/ic/handler-compiler.h » ('j') | src/ic/handler-compiler.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698