From 171e62e589aa952ef560c10efc7dcd02f3e161a7 Mon Sep 17 00:00:00 2001 From: "ishell@chromium.org" Date: Mon, 29 Sep 2014 13:11:27 +0000 Subject: [PATCH] ExtendStorageStub added, it is aimed for extending objects backing store when it runs out of space. R=yangguo@chromium.org Review URL: https://codereview.chromium.org/587203002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24286 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/interface-descriptors-arm.cc | 3 + src/arm64/interface-descriptors-arm64.cc | 3 + src/code-stubs-hydrogen.cc | 79 +++++++++++++++++++--- src/code-stubs.cc | 5 ++ src/code-stubs.h | 39 +++++++++++ src/hydrogen.cc | 51 ++++++++++---- src/hydrogen.h | 8 ++- src/ia32/interface-descriptors-ia32.cc | 3 + src/ic/arm/handler-compiler-arm.cc | 15 ++-- src/ic/arm64/handler-compiler-arm64.cc | 14 ++-- src/ic/ia32/handler-compiler-ia32.cc | 17 ++--- src/ic/ic.cc | 26 +------ src/ic/ic.h | 1 - src/ic/mips/handler-compiler-mips.cc | 16 ++--- src/ic/mips64/handler-compiler-mips64.cc | 15 ++-- src/ic/x64/handler-compiler-x64.cc | 17 ++--- src/ic/x87/handler-compiler-x87.cc | 17 ++--- src/interface-descriptors.cc | 7 ++ src/interface-descriptors.h | 17 +++++ src/mips/interface-descriptors-mips.cc | 3 + src/mips64/interface-descriptors-mips64.cc | 3 + src/objects.cc | 11 +-- src/objects.h | 4 -- src/x64/interface-descriptors-x64.cc | 3 + src/x87/interface-descriptors-x87.cc | 3 + 25 files changed, 254 insertions(+), 126 deletions(-) diff --git a/src/arm/interface-descriptors-arm.cc b/src/arm/interface-descriptors-arm.cc index 9bbc1f58c1..cc4b000a61 100644 --- a/src/arm/interface-descriptors-arm.cc +++ b/src/arm/interface-descriptors-arm.cc @@ -29,6 +29,9 @@ const Register StoreDescriptor::NameRegister() { return r2; } const Register StoreDescriptor::ValueRegister() { return r0; } +const Register ExtendStorageDescriptor::MapRegister() { return r3; } + + const Register ElementTransitionAndStoreDescriptor::MapRegister() { return r3; } diff --git a/src/arm64/interface-descriptors-arm64.cc b/src/arm64/interface-descriptors-arm64.cc index 690c8c28ee..f216e30786 100644 --- a/src/arm64/interface-descriptors-arm64.cc +++ b/src/arm64/interface-descriptors-arm64.cc @@ -29,6 +29,9 @@ const Register StoreDescriptor::NameRegister() { return x2; } const Register StoreDescriptor::ValueRegister() { return x0; } +const Register ExtendStorageDescriptor::MapRegister() { return x3; } + + const Register ElementTransitionAndStoreDescriptor::MapRegister() { return x3; } diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc index dafef522f1..00726df676 100644 --- a/src/code-stubs-hydrogen.cc +++ b/src/code-stubs-hydrogen.cc @@ -64,7 +64,8 @@ class CodeStubGraphBuilderBase : public HGraphBuilder { HLoadNamedField* BuildLoadNamedField(HValue* object, FieldIndex index); void BuildStoreNamedField(HValue* object, HValue* value, FieldIndex index, - Representation representation); + Representation representation, + bool transition_to_field); enum ArgumentClass { NONE, @@ -721,7 +722,7 @@ Handle KeyedLoadSloppyArgumentsStub::GenerateCode() { void CodeStubGraphBuilderBase::BuildStoreNamedField( HValue* object, HValue* value, FieldIndex index, - Representation representation) { + Representation representation, bool transition_to_field) { DCHECK(!index.is_double() || representation.IsDouble()); int offset = index.offset(); HObjectAccess access = @@ -730,12 +731,31 @@ void CodeStubGraphBuilderBase::BuildStoreNamedField( : HObjectAccess::ForBackingStoreOffset(offset, representation); if (representation.IsDouble()) { - // Load the heap number. - object = Add( - object, static_cast(NULL), - access.WithRepresentation(Representation::Tagged())); - // Store the double value into it. - access = HObjectAccess::ForHeapNumberValue(); + HObjectAccess heap_number_access = + access.WithRepresentation(Representation::Tagged()); + if (transition_to_field) { + // The store requires a mutable HeapNumber to be allocated. + NoObservableSideEffectsScope no_side_effects(this); + HInstruction* heap_number_size = Add(HeapNumber::kSize); + + // TODO(hpayer): Allocation site pretenuring support. + HInstruction* heap_number = + Add(heap_number_size, HType::HeapObject(), NOT_TENURED, + MUTABLE_HEAP_NUMBER_TYPE); + AddStoreMapConstant(heap_number, + isolate()->factory()->mutable_heap_number_map()); + Add(heap_number, HObjectAccess::ForHeapNumberValue(), + value); + // Store the new mutable heap number into the object. + access = heap_number_access; + value = heap_number; + } else { + // Load the heap number. + object = Add(object, static_cast(NULL), + heap_number_access); + // Store the double value into it. + access = HObjectAccess::ForHeapNumberValue(); + } } else if (representation.IsHeapObject()) { BuildCheckHeapObject(value); } @@ -747,7 +767,7 @@ void CodeStubGraphBuilderBase::BuildStoreNamedField( template <> HValue* CodeStubGraphBuilder::BuildCodeStub() { BuildStoreNamedField(GetParameter(0), GetParameter(2), casted_stub()->index(), - casted_stub()->representation()); + casted_stub()->representation(), false); return GetParameter(2); } @@ -755,6 +775,47 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { Handle StoreFieldStub::GenerateCode() { return DoGenerateCode(this); } +template <> +HValue* CodeStubGraphBuilder::BuildCodeStub() { + HValue* object = GetParameter(ExtendStorageDescriptor::kReceiverIndex); + HValue* properties = + Add(object, static_cast(NULL), + HObjectAccess::ForPropertiesPointer()); + HValue* length = AddLoadFixedArrayLength(properties); + HValue* delta = Add(static_cast(JSObject::kFieldsAdded)); + HValue* new_capacity = AddUncasted(length, delta); + + // Grow properties array. + ElementsKind kind = FAST_ELEMENTS; + Add(new_capacity, + Add((Page::kMaxRegularHeapObjectSize - + FixedArray::kHeaderSize) >> + ElementsKindToShiftSize(kind))); + + // Reuse this code for properties backing store allocation. + HValue* new_properties = BuildAllocateAndInitializeArray(kind, new_capacity); + + BuildCopyProperties(properties, new_properties, length, new_capacity); + + // Store the new value into the "extended" object. + Add(object, HObjectAccess::ForPropertiesPointer(), + new_properties); + + BuildStoreNamedField( + object, GetParameter(ExtendStorageDescriptor::kValueIndex), + casted_stub()->index(), casted_stub()->representation(), true); + + // And finally update the map after the new field is added. + Add(object, HObjectAccess::ForMap(), + GetParameter(ExtendStorageDescriptor::kMapIndex)); + + return GetParameter(ExtendStorageDescriptor::kValueIndex); +} + + +Handle ExtendStorageStub::GenerateCode() { return DoGenerateCode(this); } + + template <> HValue* CodeStubGraphBuilder::BuildCodeStub() { HValue* string = BuildLoadNamedField(GetParameter(0), diff --git a/src/code-stubs.cc b/src/code-stubs.cc index 5c9e1a2b86..e7d5664af9 100644 --- a/src/code-stubs.cc +++ b/src/code-stubs.cc @@ -614,6 +614,11 @@ void ElementsTransitionAndStoreStub::InitializeDescriptor( } +CallInterfaceDescriptor ExtendStorageStub::GetCallInterfaceDescriptor() { + return ExtendStorageDescriptor(isolate()); +} + + static void InitializeVectorLoadStub(Isolate* isolate, CodeStubDescriptor* descriptor, Address deoptimization_handler) { diff --git a/src/code-stubs.h b/src/code-stubs.h index b127782c6e..c6a3b2097e 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -80,6 +80,7 @@ namespace internal { V(VectorKeyedLoad) \ V(VectorLoad) \ /* IC Handler stubs */ \ + V(ExtendStorage) \ V(LoadConstant) \ V(LoadField) \ V(KeyedLoadSloppyArguments) \ @@ -998,6 +999,44 @@ class StoreFieldStub : public HandlerStub { }; +// Extend storage is called in a store inline cache when +// it is necessary to extend the properties array of a +// JSObject. +class ExtendStorageStub : public HandlerStub { + public: + ExtendStorageStub(Isolate* isolate, FieldIndex index, + Representation representation) + : HandlerStub(isolate) { + int property_index_key = index.GetFieldAccessStubKey(); + uint8_t repr = PropertyDetails::EncodeRepresentation(representation); + set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) | + RepresentationBits::encode(repr)); + } + + FieldIndex index() const { + int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key()); + return FieldIndex::FromFieldAccessStubKey(property_index_key); + } + + Representation representation() { + uint8_t repr = RepresentationBits::decode(sub_minor_key()); + return PropertyDetails::DecodeRepresentation(repr); + } + + virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE; + + protected: + virtual Code::Kind kind() const { return Code::STORE_IC; } + virtual Code::StubType GetStubType() { return Code::FAST; } + + private: + class StoreFieldByIndexBits : public BitField {}; + class RepresentationBits : public BitField {}; + + DEFINE_HANDLER_CODE_STUB(ExtendStorage, HandlerStub); +}; + + class StoreGlobalStub : public HandlerStub { public: StoreGlobalStub(Isolate* isolate, bool is_constant, bool check_global) diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 301e7e40fa..d72aadea16 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -2626,16 +2626,15 @@ void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, } -HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( - ElementsKind kind, - HValue* capacity) { +HValue* HGraphBuilder::BuildAllocateAndInitializeArray(ElementsKind kind, + HValue* capacity) { // The HForceRepresentation is to prevent possible deopt on int-smi // conversion after allocation but before the new object fields are set. capacity = AddUncasted(capacity, Representation::Smi()); HValue* size_in_bytes = BuildCalculateElementsSize(kind, capacity); - HValue* new_elements = BuildAllocateElements(kind, size_in_bytes); - BuildInitializeElementsHeader(new_elements, kind, capacity); - return new_elements; + HValue* new_array = BuildAllocateElements(kind, size_in_bytes); + BuildInitializeElementsHeader(new_array, kind, capacity); + return new_array; } @@ -2754,8 +2753,8 @@ HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >> ElementsKindToShiftSize(new_kind))); - HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( - new_kind, new_capacity); + HValue* new_elements = + BuildAllocateAndInitializeArray(new_kind, new_capacity); BuildCopyElements(elements, kind, new_elements, new_kind, length, new_capacity); @@ -2789,12 +2788,6 @@ void HGraphBuilder::BuildFillElementsWithValue(HValue* elements, } } - // Since we're about to store a hole value, the store instruction below must - // assume an elements kind that supports heap object values. - if (IsFastSmiOrObjectElementsKind(elements_kind)) { - elements_kind = FAST_HOLEY_ELEMENTS; - } - if (initial_capacity >= 0) { for (int i = 0; i < initial_capacity; i++) { HInstruction* key = Add(i); @@ -2832,10 +2825,40 @@ void HGraphBuilder::BuildFillElementsWithHole(HValue* elements, ? Add(factory->the_hole_value()) : Add(nan_double); + // Since we're about to store a hole value, the store instruction below must + // assume an elements kind that supports heap object values. + if (IsFastSmiOrObjectElementsKind(elements_kind)) { + elements_kind = FAST_HOLEY_ELEMENTS; + } + BuildFillElementsWithValue(elements, elements_kind, from, to, hole); } +void HGraphBuilder::BuildCopyProperties(HValue* from_properties, + HValue* to_properties, HValue* length, + HValue* capacity) { + ElementsKind kind = FAST_ELEMENTS; + + BuildFillElementsWithValue(to_properties, kind, length, capacity, + graph()->GetConstantUndefined()); + + LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement); + + HValue* key = builder.BeginBody(length, graph()->GetConstant0(), Token::GT); + + key = AddUncasted(key, graph()->GetConstant1()); + key->ClearFlag(HValue::kCanOverflow); + + HValue* element = + Add(from_properties, key, static_cast(NULL), kind); + + Add(to_properties, key, element, kind); + + builder.EndBody(); +} + + void HGraphBuilder::BuildCopyElements(HValue* from_elements, ElementsKind from_elements_kind, HValue* to_elements, diff --git a/src/hydrogen.h b/src/hydrogen.h index d507643e5f..384c79d84b 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -1805,8 +1805,9 @@ class HGraphBuilder { ElementsKind kind, HValue* capacity); - HValue* BuildAllocateElementsAndInitializeElementsHeader(ElementsKind kind, - HValue* capacity); + // Build allocation and header initialization code for respective successor + // of FixedArrayBase. + HValue* BuildAllocateAndInitializeArray(ElementsKind kind, HValue* capacity); // |array| must have been allocated with enough room for // 1) the JSArray and 2) an AllocationMemento if mode requires it. @@ -1838,6 +1839,9 @@ class HGraphBuilder { HValue* from, HValue* to); + void BuildCopyProperties(HValue* from_properties, HValue* to_properties, + HValue* length, HValue* capacity); + void BuildCopyElements(HValue* from_elements, ElementsKind from_elements_kind, HValue* to_elements, diff --git a/src/ia32/interface-descriptors-ia32.cc b/src/ia32/interface-descriptors-ia32.cc index 3a0d5268e0..f1af19b93d 100644 --- a/src/ia32/interface-descriptors-ia32.cc +++ b/src/ia32/interface-descriptors-ia32.cc @@ -29,6 +29,9 @@ const Register StoreDescriptor::NameRegister() { return ecx; } const Register StoreDescriptor::ValueRegister() { return eax; } +const Register ExtendStorageDescriptor::MapRegister() { return ebx; } + + const Register ElementTransitionAndStoreDescriptor::MapRegister() { return ebx; } diff --git a/src/ic/arm/handler-compiler-arm.cc b/src/ic/arm/handler-compiler-arm.cc index 5314d48ff6..7aa155c4c0 100644 --- a/src/ic/arm/handler-compiler-arm.cc +++ b/src/ic/arm/handler-compiler-arm.cc @@ -396,14 +396,13 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( if (details.type() == FIELD && Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { // The properties must be extended before we can store the value. - // We jump to a runtime call that extends the properties array. - __ push(receiver_reg); - __ mov(r2, Operand(transition)); - __ Push(r2, r0); - __ TailCallExternalReference( - ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), - isolate()), - 3, 1); + __ mov(ExtendStorageDescriptor::NameRegister(), Operand(name)); + __ mov(ExtendStorageDescriptor::MapRegister(), Operand(transition)); + + ExtendStorageStub stub(isolate(), + FieldIndex::ForDescriptor(*transition, descriptor), + representation); + GenerateTailCall(masm(), stub.GetCode()); return; } diff --git a/src/ic/arm64/handler-compiler-arm64.cc b/src/ic/arm64/handler-compiler-arm64.cc index f7f82bc9a4..0923992718 100644 --- a/src/ic/arm64/handler-compiler-arm64.cc +++ b/src/ic/arm64/handler-compiler-arm64.cc @@ -441,13 +441,13 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( if (details.type() == FIELD && Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { // The properties must be extended before we can store the value. - // We jump to a runtime call that extends the properties array. - __ Mov(scratch1, Operand(transition)); - __ Push(receiver_reg, scratch1, value_reg); - __ TailCallExternalReference( - ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), - isolate()), - 3, 1); + __ Mov(ExtendStorageDescriptor::NameRegister(), Operand(name)); + __ Mov(ExtendStorageDescriptor::MapRegister(), Operand(transition)); + + ExtendStorageStub stub(isolate(), + FieldIndex::ForDescriptor(*transition, descriptor), + representation); + GenerateTailCall(masm(), stub.GetCode()); return; } diff --git a/src/ic/ia32/handler-compiler-ia32.cc b/src/ic/ia32/handler-compiler-ia32.cc index fd971541b9..f37fbf2892 100644 --- a/src/ic/ia32/handler-compiler-ia32.cc +++ b/src/ic/ia32/handler-compiler-ia32.cc @@ -390,16 +390,13 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( if (details.type() == FIELD && Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { // The properties must be extended before we can store the value. - // We jump to a runtime call that extends the properties array. - __ pop(scratch1); // Return address. - __ push(receiver_reg); - __ push(Immediate(transition)); - __ push(value_reg); - __ push(scratch1); - __ TailCallExternalReference( - ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), - isolate()), - 3, 1); + __ mov(ExtendStorageDescriptor::NameRegister(), Immediate(name)); + __ mov(ExtendStorageDescriptor::MapRegister(), Immediate(transition)); + + ExtendStorageStub stub(isolate(), + FieldIndex::ForDescriptor(*transition, descriptor), + representation); + GenerateTailCall(masm(), stub.GetCode()); return; } diff --git a/src/ic/ic.cc b/src/ic/ic.cc index 500fa1fb7b..b1363f150d 100644 --- a/src/ic/ic.cc +++ b/src/ic/ic.cc @@ -2094,7 +2094,7 @@ RUNTIME_FUNCTION(StoreIC_Miss) { RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) { TimerEventScope timer(isolate); HandleScope scope(isolate); - DCHECK(args.length() == 3); + DCHECK(args.length() == 3 || args.length() == 4); StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); Handle receiver = args.at(0); Handle key = args.at(1); @@ -2106,30 +2106,6 @@ RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) { } -// Extend storage is called in a store inline cache when -// it is necessary to extend the properties array of a -// JSObject. -RUNTIME_FUNCTION(SharedStoreIC_ExtendStorage) { - TimerEventScope timer(isolate); - HandleScope shs(isolate); - DCHECK(args.length() == 3); - - // Convert the parameters - Handle object = args.at(0); - Handle transition = args.at(1); - Handle value = args.at(2); - - // Check the object has run out out property space. - DCHECK(object->HasFastProperties()); - DCHECK(object->map()->unused_property_fields() == 0); - - JSObject::MigrateToNewProperty(object, transition, value); - - // Return the stored value. - return *value; -} - - // Used from ic-.cc. RUNTIME_FUNCTION(KeyedStoreIC_Miss) { TimerEventScope timer(isolate); diff --git a/src/ic/ic.h b/src/ic/ic.h index d86d2b7b64..e1facd6358 100644 --- a/src/ic/ic.h +++ b/src/ic/ic.h @@ -21,7 +21,6 @@ namespace internal { ICU(CallIC_Customization_Miss) \ ICU(StoreIC_Miss) \ ICU(StoreIC_Slow) \ - ICU(SharedStoreIC_ExtendStorage) \ ICU(KeyedStoreIC_Miss) \ ICU(KeyedStoreIC_Slow) \ /* Utilities for IC stubs. */ \ diff --git a/src/ic/mips/handler-compiler-mips.cc b/src/ic/mips/handler-compiler-mips.cc index 5b4555fa84..0abbed99df 100644 --- a/src/ic/mips/handler-compiler-mips.cc +++ b/src/ic/mips/handler-compiler-mips.cc @@ -391,14 +391,14 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( if (details.type() == FIELD && Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { // The properties must be extended before we can store the value. - // We jump to a runtime call that extends the properties array. - __ push(receiver_reg); - __ li(a2, Operand(transition)); - __ Push(a2, a0); - __ TailCallExternalReference( - ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), - isolate()), - 3, 1); + __ mov(ExtendStorageDescriptor::NameRegister(), Operand(name)); + __ mov(ExtendStorageDescriptor::MapRegister(), Operand(transition)); + + + ExtendStorageStub stub(isolate(), + FieldIndex::ForDescriptor(*transition, descriptor), + representation); + GenerateTailCall(masm(), stub.GetCode()); return; } diff --git a/src/ic/mips64/handler-compiler-mips64.cc b/src/ic/mips64/handler-compiler-mips64.cc index f44226f772..009b5756ae 100644 --- a/src/ic/mips64/handler-compiler-mips64.cc +++ b/src/ic/mips64/handler-compiler-mips64.cc @@ -391,14 +391,13 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( if (details.type() == FIELD && Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { // The properties must be extended before we can store the value. - // We jump to a runtime call that extends the properties array. - __ push(receiver_reg); - __ li(a2, Operand(transition)); - __ Push(a2, a0); - __ TailCallExternalReference( - ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), - isolate()), - 3, 1); + __ Mov(ExtendStorageDescriptor::NameRegister(), Operand(name)); + __ Mov(ExtendStorageDescriptor::MapRegister(), Operand(transition)); + + ExtendStorageStub stub(isolate(), + FieldIndex::ForDescriptor(*transition, descriptor), + representation); + GenerateTailCall(masm(), stub.GetCode()); return; } diff --git a/src/ic/x64/handler-compiler-x64.cc b/src/ic/x64/handler-compiler-x64.cc index c4d6ecfe7c..f2f73b3efb 100644 --- a/src/ic/x64/handler-compiler-x64.cc +++ b/src/ic/x64/handler-compiler-x64.cc @@ -384,16 +384,13 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( if (details.type() == FIELD && Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { // The properties must be extended before we can store the value. - // We jump to a runtime call that extends the properties array. - __ PopReturnAddressTo(scratch1); - __ Push(receiver_reg); - __ Push(transition); - __ Push(value_reg); - __ PushReturnAddressFrom(scratch1); - __ TailCallExternalReference( - ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), - isolate()), - 3, 1); + __ Move(ExtendStorageDescriptor::NameRegister(), name); + __ Move(ExtendStorageDescriptor::MapRegister(), transition); + + ExtendStorageStub stub(isolate(), + FieldIndex::ForDescriptor(*transition, descriptor), + representation); + GenerateTailCall(masm(), stub.GetCode()); return; } diff --git a/src/ic/x87/handler-compiler-x87.cc b/src/ic/x87/handler-compiler-x87.cc index e706998c38..3c74827632 100644 --- a/src/ic/x87/handler-compiler-x87.cc +++ b/src/ic/x87/handler-compiler-x87.cc @@ -392,16 +392,13 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( if (details.type() == FIELD && Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { // The properties must be extended before we can store the value. - // We jump to a runtime call that extends the properties array. - __ pop(scratch1); // Return address. - __ push(receiver_reg); - __ push(Immediate(transition)); - __ push(value_reg); - __ push(scratch1); - __ TailCallExternalReference( - ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), - isolate()), - 3, 1); + __ mov(ExtendStorageDescriptor::NameRegister(), Immediate(name)); + __ mov(ExtendStorageDescriptor::MapRegister(), Immediate(transition)); + + ExtendStorageStub stub(isolate(), + FieldIndex::ForDescriptor(*transition, descriptor), + representation); + GenerateTailCall(masm(), stub.GetCode()); return; } diff --git a/src/interface-descriptors.cc b/src/interface-descriptors.cc index 62d710581f..e9f76bdf2d 100644 --- a/src/interface-descriptors.cc +++ b/src/interface-descriptors.cc @@ -74,6 +74,13 @@ void StoreDescriptor::Initialize(CallInterfaceDescriptorData* data) { } +void ExtendStorageDescriptor::Initialize(CallInterfaceDescriptorData* data) { + Register registers[] = {ContextRegister(), ReceiverRegister(), NameRegister(), + ValueRegister(), MapRegister()}; + data->Initialize(arraysize(registers), registers, NULL); +} + + void ElementTransitionAndStoreDescriptor::Initialize( CallInterfaceDescriptorData* data) { Register registers[] = {ContextRegister(), ValueRegister(), MapRegister(), diff --git a/src/interface-descriptors.h b/src/interface-descriptors.h index b773c916ec..059ae7e62f 100644 --- a/src/interface-descriptors.h +++ b/src/interface-descriptors.h @@ -16,6 +16,7 @@ class PlatformInterfaceDescriptor; #define INTERFACE_DESCRIPTOR_LIST(V) \ V(Load) \ V(Store) \ + V(ExtendStorage) \ V(ElementTransitionAndStore) \ V(Instanceof) \ V(VectorLoadICTrampoline) \ @@ -213,6 +214,22 @@ class StoreDescriptor : public CallInterfaceDescriptor { }; +class ExtendStorageDescriptor : public StoreDescriptor { + public: + DECLARE_DESCRIPTOR(ExtendStorageDescriptor, StoreDescriptor) + + // Extends StoreDescriptor with Map parameter. + enum ParameterIndices { + kReceiverIndex, + kNameIndex, + kValueIndex, + kMapIndex, + kParameterCount + }; + static const Register MapRegister(); +}; + + class ElementTransitionAndStoreDescriptor : public StoreDescriptor { public: DECLARE_DESCRIPTOR(ElementTransitionAndStoreDescriptor, StoreDescriptor) diff --git a/src/mips/interface-descriptors-mips.cc b/src/mips/interface-descriptors-mips.cc index 936ce20acc..070228ddd2 100644 --- a/src/mips/interface-descriptors-mips.cc +++ b/src/mips/interface-descriptors-mips.cc @@ -29,6 +29,9 @@ const Register StoreDescriptor::NameRegister() { return a2; } const Register StoreDescriptor::ValueRegister() { return a0; } +const Register ExtendStorageDescriptor::MapRegister() { return a3; } + + const Register ElementTransitionAndStoreDescriptor::MapRegister() { return a3; } diff --git a/src/mips64/interface-descriptors-mips64.cc b/src/mips64/interface-descriptors-mips64.cc index 8759bdd9bd..06db808831 100644 --- a/src/mips64/interface-descriptors-mips64.cc +++ b/src/mips64/interface-descriptors-mips64.cc @@ -29,6 +29,9 @@ const Register StoreDescriptor::NameRegister() { return a2; } const Register StoreDescriptor::ValueRegister() { return a0; } +const Register ExtendStorageDescriptor::MapRegister() { return a3; } + + const Register ElementTransitionAndStoreDescriptor::MapRegister() { return a3; } diff --git a/src/objects.cc b/src/objects.cc index 482b5beae8..57130e77c7 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -1962,7 +1962,7 @@ void JSObject::MigrateFastToFast(Handle object, Handle new_map) { } DCHECK(number_of_fields == old_number_of_fields + 1); - // This migration is a transition from a map that has run out out property + // This migration is a transition from a map that has run out of property // space. Therefore it could be done by extending the backing store. Handle old_storage = handle(object->properties(), isolate); Handle new_storage = @@ -3753,15 +3753,6 @@ bool JSObject::TryMigrateInstance(Handle object) { } -void JSObject::MigrateToNewProperty(Handle object, - Handle map, - Handle value) { - JSObject::MigrateToMap(object, map); - if (map->GetLastDescriptorDetails().type() != FIELD) return; - object->WriteToField(map->LastAdded(), *value); -} - - void JSObject::WriteToField(int descriptor, Object* value) { DisallowHeapAllocation no_gc; diff --git a/src/objects.h b/src/objects.h index f2e17d34bb..5486d2aad7 100644 --- a/src/objects.h +++ b/src/objects.h @@ -2209,10 +2209,6 @@ class JSObject: public JSReceiver { Handle name, Handle old_value); - static void MigrateToNewProperty(Handle object, - Handle transition, - Handle value); - private: friend class DictionaryElementsAccessor; friend class JSReceiver; diff --git a/src/x64/interface-descriptors-x64.cc b/src/x64/interface-descriptors-x64.cc index 84fdca4fb9..05c24ced96 100644 --- a/src/x64/interface-descriptors-x64.cc +++ b/src/x64/interface-descriptors-x64.cc @@ -29,6 +29,9 @@ const Register StoreDescriptor::NameRegister() { return rcx; } const Register StoreDescriptor::ValueRegister() { return rax; } +const Register ExtendStorageDescriptor::MapRegister() { return rbx; } + + const Register ElementTransitionAndStoreDescriptor::MapRegister() { return rbx; } diff --git a/src/x87/interface-descriptors-x87.cc b/src/x87/interface-descriptors-x87.cc index 8dfad3633c..46af75c333 100644 --- a/src/x87/interface-descriptors-x87.cc +++ b/src/x87/interface-descriptors-x87.cc @@ -29,6 +29,9 @@ const Register StoreDescriptor::NameRegister() { return ecx; } const Register StoreDescriptor::ValueRegister() { return eax; } +const Register ExtendStorageDescriptor::MapRegister() { return ebx; } + + const Register ElementTransitionAndStoreDescriptor::MapRegister() { return ebx; }