diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc index 85a60118b7..5d0783a18a 100644 --- a/src/code-stub-assembler.cc +++ b/src/code-stub-assembler.cc @@ -6,7 +6,6 @@ #include "src/code-factory.h" #include "src/frames-inl.h" #include "src/frames.h" -#include "src/ic/handler-configuration.h" #include "src/ic/stub-cache.h" namespace v8 { @@ -3426,261 +3425,31 @@ void CodeStubAssembler::TryProbeStubCache( } } -// |is_jsarray| should be non-zero for JSArrays. -void CodeStubAssembler::EmitBoundsCheck(Node* object, Node* elements, - Node* intptr_key, Node* is_jsarray, - Label* miss) { - Variable var_length(this, MachineRepresentation::kTagged); - Label if_array(this), length_loaded(this, &var_length); - GotoUnless(WordEqual(is_jsarray, IntPtrConstant(0)), &if_array); - { - var_length.Bind(SmiUntag(LoadFixedArrayBaseLength(elements))); - Goto(&length_loaded); - } - Bind(&if_array); - { - var_length.Bind(SmiUntag(LoadObjectField(object, JSArray::kLengthOffset))); - Goto(&length_loaded); - } - Bind(&length_loaded); - GotoUnless(UintPtrLessThan(intptr_key, var_length.value()), miss); -} - -// |key| should be untagged (int32). -void CodeStubAssembler::EmitElementLoad(Node* object, Node* elements, - Node* elements_kind, Node* key, - Label* if_hole, Label* rebox_double, - Variable* var_double_value, - Label* miss) { - Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this), - if_fast_double(this), if_fast_holey_double(this), - unimplemented_elements_kind(this); - STATIC_ASSERT(LAST_ELEMENTS_KIND == LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND); - GotoIf( - IntPtrGreaterThanOrEqual( - elements_kind, IntPtrConstant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)), - &if_typed_array); - - int32_t kinds[] = {// Handled by if_fast_packed. - FAST_SMI_ELEMENTS, FAST_ELEMENTS, - // Handled by if_fast_holey. - FAST_HOLEY_SMI_ELEMENTS, FAST_HOLEY_ELEMENTS, - // Handled by if_fast_double. - FAST_DOUBLE_ELEMENTS, - // Handled by if_fast_holey_double. - FAST_HOLEY_DOUBLE_ELEMENTS}; - Label* labels[] = {// FAST_{SMI,}_ELEMENTS - &if_fast_packed, &if_fast_packed, - // FAST_HOLEY_{SMI,}_ELEMENTS - &if_fast_holey, &if_fast_holey, - // FAST_DOUBLE_ELEMENTS - &if_fast_double, - // FAST_HOLEY_DOUBLE_ELEMENTS - &if_fast_holey_double}; - Switch(elements_kind, &unimplemented_elements_kind, kinds, labels, - arraysize(kinds)); - Bind(&unimplemented_elements_kind); - { - // Crash if we get here. - DebugBreak(); - Goto(miss); - } - - Bind(&if_fast_packed); - { - Comment("fast packed elements"); - // 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. - Return(LoadFixedArrayElement(elements, key)); - } - - Bind(&if_fast_holey); - { - Comment("fast holey elements"); - Node* element = LoadFixedArrayElement(elements, key); - GotoIf(WordEqual(element, TheHoleConstant()), if_hole); - Return(element); - } - - Bind(&if_fast_double); - { - Comment("packed double elements"); - var_double_value->Bind( - LoadFixedDoubleArrayElement(elements, key, MachineType::Float64())); - Goto(rebox_double); - } - - Bind(&if_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), if_hole); - } else { - Node* element_upper = LoadFixedDoubleArrayElement( - elements, key, MachineType::Uint32(), kIeeeDoubleExponentWordOffset); - GotoIf(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)), - if_hole); - } - var_double_value->Bind( - LoadFixedDoubleArrayElement(elements, key, MachineType::Float64())); - Goto(rebox_double); - } - - Bind(&if_typed_array); - { - Comment("typed elements"); - // Check if buffer has been neutered. - Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); - Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset, - MachineType::Uint32()); - Node* neutered_bit = - Word32And(bitfield, Int32Constant(JSArrayBuffer::WasNeutered::kMask)); - 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(kTypedElementsKindCount)); - - for (int i = 0; i < kTypedElementsKindCount; i++) { - ElementsKind kind = static_cast(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]; - } - } -} - -void CodeStubAssembler::HandleLoadICHandlerCase( - const LoadICParameters* p, Node* handler, Label* miss, - ElementSupport support_elements) { +void CodeStubAssembler::HandleLoadICHandlerCase(const LoadICParameters* p, + Node* handler, Label* miss) { Comment("have_handler"); Label call_handler(this); GotoUnless(WordIsSmi(handler), &call_handler); - // |handler| is a Smi, encoding what to do. See handler-configuration.h - // for the encoding format. + // |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); - if (support_elements == kSupportElements) { - Label property(this); - Node* handler_type = - WordAnd(handler_word, IntPtrConstant(LoadHandlerTypeBit::kMask)); - GotoUnless( - WordEqual(handler_type, IntPtrConstant(kLoadICHandlerForElements)), - &property); - - Comment("element_load"); - GotoUnless(WordIsSmi(p->name), miss); - Node* key = SmiUntag(p->name); - Node* elements = LoadElements(p->receiver); - Node* is_jsarray = - WordAnd(handler_word, IntPtrConstant(KeyedLoadIsJsArray::kMask)); - EmitBoundsCheck(p->receiver, elements, key, is_jsarray, miss); - Label if_hole(this); - - Node* elements_kind = BitFieldDecode(handler_word); - - EmitElementLoad(p->receiver, elements, elements_kind, key, &if_hole, - &rebox_double, &var_double_value, miss); - - Bind(&if_hole); - { - Comment("convert hole"); - Node* convert_hole = - WordAnd(handler_word, IntPtrConstant(KeyedLoadConvertHole::kMask)); - 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(&property); - Comment("property_load"); - } - // |handler_word| is a field index as obtained by // FieldIndex.GetLoadByFieldOffset(): Label inobject_double(this), out_of_object(this), out_of_object_double(this); - Node* inobject_bit = - WordAnd(handler_word, IntPtrConstant(FieldOffsetIsInobject::kMask)); - Node* double_bit = - WordAnd(handler_word, IntPtrConstant(FieldOffsetIsDouble::kMask)); - Node* offset = - WordSar(handler_word, IntPtrConstant(FieldOffsetOffset::kShift)); + Node* inobject_bit = WordAnd( + handler_word, IntPtrConstant(FieldIndex::FieldOffsetIsInobject::kMask)); + Node* double_bit = WordAnd( + handler_word, IntPtrConstant(FieldIndex::FieldOffsetIsDouble::kMask)); + Node* offset = WordSar( + handler_word, IntPtrConstant(FieldIndex::FieldOffsetOffset::kShift)); GotoIf(WordEqual(inobject_bit, IntPtrConstant(0)), &out_of_object); @@ -3781,7 +3550,7 @@ void CodeStubAssembler::KeyedLoadIC(const LoadICParameters* p) { &var_handler, &try_polymorphic); Bind(&if_handler); { - HandleLoadICHandlerCase(p, var_handler.value(), &miss, kSupportElements); + HandleLoadICHandlerCase(p, var_handler.value(), &miss); } Bind(&try_polymorphic); diff --git a/src/code-stub-assembler.h b/src/code-stub-assembler.h index a51827b28f..46a0cb5ca3 100644 --- a/src/code-stub-assembler.h +++ b/src/code-stub-assembler.h @@ -509,6 +509,9 @@ class CodeStubAssembler : public compiler::CodeAssembler { Variable* var_handler, Label* if_miss, int unroll_count); + void HandleLoadICHandlerCase(const LoadICParameters* p, + compiler::Node* handler, Label* miss); + compiler::Node* StubCachePrimaryOffset(compiler::Node* name, compiler::Node* map); @@ -549,19 +552,6 @@ class CodeStubAssembler : public compiler::CodeAssembler { compiler::Node* value); private: - enum ElementSupport { kOnlyProperties, kSupportElements }; - - void HandleLoadICHandlerCase( - const LoadICParameters* p, compiler::Node* handler, Label* miss, - ElementSupport support_elements = kOnlyProperties); - void EmitBoundsCheck(compiler::Node* object, compiler::Node* elements, - compiler::Node* intptr_key, compiler::Node* is_jsarray, - Label* miss); - void EmitElementLoad(compiler::Node* object, compiler::Node* elements, - compiler::Node* elements_kind, compiler::Node* key, - Label* if_hole, Label* rebox_double, - Variable* var_double_value, Label* miss); - compiler::Node* ElementOffsetFromIndex(compiler::Node* index, ElementsKind kind, ParameterMode mode, int base_size = 0); diff --git a/src/field-index-inl.h b/src/field-index-inl.h index c2f25bb7f0..f79394824f 100644 --- a/src/field-index-inl.h +++ b/src/field-index-inl.h @@ -6,7 +6,6 @@ #define V8_FIELD_INDEX_INL_H_ #include "src/field-index.h" -#include "src/ic/handler-configuration.h" namespace v8 { namespace internal { @@ -89,7 +88,7 @@ inline int FieldIndex::GetLoadByFieldIndex() const { // FieldIndex object from it. // static inline FieldIndex FieldIndex::ForLoadByFieldOffset(Map* map, int offset) { - DCHECK(LoadHandlerTypeBit::decode(offset) == kLoadICHandlerForProperties); + DCHECK(offset & 1); // Property marker (as opposed to element). bool is_inobject = FieldOffsetIsInobject::decode(offset); bool is_double = FieldOffsetIsDouble::decode(offset); int field_index = FieldOffsetOffset::decode(offset) >> kPointerSizeLog2; @@ -115,7 +114,7 @@ inline int FieldIndex::GetLoadByFieldOffset() const { return FieldOffsetIsInobject::encode(is_inobject()) | FieldOffsetIsDouble::encode(is_double()) | FieldOffsetOffset::encode(index() << kPointerSizeLog2) | - LoadHandlerTypeBit::encode(kLoadICHandlerForProperties); + 1; // Property marker (as opposed to element). } inline FieldIndex FieldIndex::ForDescriptor(Map* map, int descriptor_index) { diff --git a/src/field-index.h b/src/field-index.h index 404c0f613f..13bb94be41 100644 --- a/src/field-index.h +++ b/src/field-index.h @@ -81,6 +81,13 @@ class FieldIndex final { } bool operator!=(FieldIndex const& other) const { return !(*this == other); } + // For GetLoadByFieldOffset. + class FieldOffsetIsInobject : public BitField {}; + class FieldOffsetIsDouble : public BitField {}; + class FieldOffsetOffset : public BitField {}; + // Make sure we don't overflow into the sign bit. + STATIC_ASSERT(FieldOffsetOffset::kNext <= kSmiValueSize - 1); + private: FieldIndex(bool is_inobject, int local_index, bool is_double, int inobject_properties, int first_inobject_property_offset, diff --git a/src/ic/handler-compiler.cc b/src/ic/handler-compiler.cc index b6b81def54..a1d1467ab1 100644 --- a/src/ic/handler-compiler.cc +++ b/src/ic/handler-compiler.cc @@ -6,7 +6,6 @@ #include "src/field-type.h" #include "src/ic/call-optimization.h" -#include "src/ic/handler-configuration.h" #include "src/ic/ic-inl.h" #include "src/ic/ic.h" #include "src/isolate-inl.h" @@ -578,7 +577,7 @@ Handle NamedStoreHandlerCompiler::CompileStoreCallback( #undef __ // static -Handle ElementHandlerCompiler::GetKeyedLoadHandler( +Handle ElementHandlerCompiler::GetKeyedLoadHandler( Handle receiver_map, Isolate* isolate) { if (receiver_map->has_indexed_interceptor() && !receiver_map->GetIndexedInterceptor()->getter()->IsUndefined(isolate) && @@ -611,18 +610,10 @@ Handle ElementHandlerCompiler::GetKeyedLoadHandler( bool convert_hole_to_undefined = is_js_array && elements_kind == FAST_HOLEY_ELEMENTS && *receiver_map == isolate->get_initial_js_array_map(elements_kind); - if (FLAG_tf_load_ic_stub) { - int config = KeyedLoadElementsKind::encode(elements_kind) | - KeyedLoadConvertHole::encode(convert_hole_to_undefined) | - KeyedLoadIsJsArray::encode(is_js_array) | - LoadHandlerTypeBit::encode(kLoadICHandlerForElements); - return handle(Smi::FromInt(config), isolate); - } else { - TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadFastElementStub); - return LoadFastElementStub(isolate, is_js_array, elements_kind, - convert_hole_to_undefined) - .GetCode(); - } + TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadFastElementStub); + return LoadFastElementStub(isolate, is_js_array, elements_kind, + convert_hole_to_undefined) + .GetCode(); } void ElementHandlerCompiler::CompileElementHandlers( diff --git a/src/ic/handler-compiler.h b/src/ic/handler-compiler.h index 525889b80b..242e497b77 100644 --- a/src/ic/handler-compiler.h +++ b/src/ic/handler-compiler.h @@ -279,8 +279,8 @@ class ElementHandlerCompiler : public PropertyHandlerCompiler { virtual ~ElementHandlerCompiler() {} - static Handle GetKeyedLoadHandler(Handle receiver_map, - Isolate* isolate); + static Handle GetKeyedLoadHandler(Handle receiver_map, + Isolate* isolate); void CompileElementHandlers(MapHandleList* receiver_maps, List>* handlers); diff --git a/src/ic/handler-configuration.h b/src/ic/handler-configuration.h deleted file mode 100644 index bf7c4770b9..0000000000 --- a/src/ic/handler-configuration.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2016 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef V8_IC_HANDLER_CONFIGURATION_H_ -#define V8_IC_HANDLER_CONFIGURATION_H_ - -#include "src/elements-kind.h" -#include "src/globals.h" -#include "src/utils.h" - -namespace v8 { -namespace internal { - -enum LoadHandlerType { - kLoadICHandlerForElements = 0, - kLoadICHandlerForProperties = 1 -}; - -class LoadHandlerTypeBit : public BitField {}; - -// Encoding for configuration Smis for property loads: -class FieldOffsetIsInobject - : public BitField {}; -class FieldOffsetIsDouble - : public BitField {}; -class FieldOffsetOffset : public BitField { -}; -// Make sure we don't overflow into the sign bit. -STATIC_ASSERT(FieldOffsetOffset::kNext <= kSmiValueSize - 1); - -// Encoding for configuration Smis for elements loads: -class KeyedLoadIsJsArray : public BitField { -}; -class KeyedLoadConvertHole - : public BitField {}; -class KeyedLoadElementsKind - : public BitField {}; -// Make sure we don't overflow into the sign bit. -STATIC_ASSERT(KeyedLoadElementsKind::kNext <= kSmiValueSize - 1); - -} // namespace internal -} // namespace v8 - -#endif // V8_IC_HANDLER_CONFIGURATION_H_ diff --git a/src/ic/ic.cc b/src/ic/ic.cc index d92d22df40..6e647ced4b 100644 --- a/src/ic/ic.cc +++ b/src/ic/ic.cc @@ -1328,7 +1328,7 @@ void KeyedLoadIC::UpdateLoadElement(Handle receiver) { TargetMaps(&target_receiver_maps); if (target_receiver_maps.length() == 0) { - Handle handler = + Handle handler = ElementHandlerCompiler::GetKeyedLoadHandler(receiver_map, isolate()); return ConfigureVectorState(Handle(), receiver_map, handler); } @@ -1357,7 +1357,7 @@ void KeyedLoadIC::UpdateLoadElement(Handle receiver) { IsMoreGeneralElementsKindTransition( target_receiver_maps.at(0)->elements_kind(), Handle::cast(receiver)->GetElementsKind())) { - Handle handler = + Handle handler = ElementHandlerCompiler::GetKeyedLoadHandler(receiver_map, isolate()); return ConfigureVectorState(Handle(), receiver_map, handler); }