ExtendStorageStub added, it is aimed for extending objects backing store when it...
authorishell@chromium.org <ishell@chromium.org>
Mon, 29 Sep 2014 13:11:27 +0000 (13:11 +0000)
committerishell@chromium.org <ishell@chromium.org>
Mon, 29 Sep 2014 13:11:27 +0000 (13:11 +0000)
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

25 files changed:
src/arm/interface-descriptors-arm.cc
src/arm64/interface-descriptors-arm64.cc
src/code-stubs-hydrogen.cc
src/code-stubs.cc
src/code-stubs.h
src/hydrogen.cc
src/hydrogen.h
src/ia32/interface-descriptors-ia32.cc
src/ic/arm/handler-compiler-arm.cc
src/ic/arm64/handler-compiler-arm64.cc
src/ic/ia32/handler-compiler-ia32.cc
src/ic/ic.cc
src/ic/ic.h
src/ic/mips/handler-compiler-mips.cc
src/ic/mips64/handler-compiler-mips64.cc
src/ic/x64/handler-compiler-x64.cc
src/ic/x87/handler-compiler-x87.cc
src/interface-descriptors.cc
src/interface-descriptors.h
src/mips/interface-descriptors-mips.cc
src/mips64/interface-descriptors-mips64.cc
src/objects.cc
src/objects.h
src/x64/interface-descriptors-x64.cc
src/x87/interface-descriptors-x87.cc

index 9bbc1f5..cc4b000 100644 (file)
@@ -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; }
 
 
index 690c8c2..f216e30 100644 (file)
@@ -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; }
 
 
index dafef52..00726df 100644 (file)
@@ -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<Code> 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<HLoadNamedField>(
-        object, static_cast<HValue*>(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<HConstant>(HeapNumber::kSize);
+
+      // TODO(hpayer): Allocation site pretenuring support.
+      HInstruction* heap_number =
+          Add<HAllocate>(heap_number_size, HType::HeapObject(), NOT_TENURED,
+                         MUTABLE_HEAP_NUMBER_TYPE);
+      AddStoreMapConstant(heap_number,
+                          isolate()->factory()->mutable_heap_number_map());
+      Add<HStoreNamedField>(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<HLoadNamedField>(object, static_cast<HValue*>(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<StoreFieldStub>::BuildCodeStub() {
   BuildStoreNamedField(GetParameter(0), GetParameter(2), casted_stub()->index(),
-                       casted_stub()->representation());
+                       casted_stub()->representation(), false);
   return GetParameter(2);
 }
 
@@ -756,6 +776,47 @@ Handle<Code> StoreFieldStub::GenerateCode() { return DoGenerateCode(this); }
 
 
 template <>
+HValue* CodeStubGraphBuilder<ExtendStorageStub>::BuildCodeStub() {
+  HValue* object = GetParameter(ExtendStorageDescriptor::kReceiverIndex);
+  HValue* properties =
+      Add<HLoadNamedField>(object, static_cast<HValue*>(NULL),
+                           HObjectAccess::ForPropertiesPointer());
+  HValue* length = AddLoadFixedArrayLength(properties);
+  HValue* delta = Add<HConstant>(static_cast<int32_t>(JSObject::kFieldsAdded));
+  HValue* new_capacity = AddUncasted<HAdd>(length, delta);
+
+  // Grow properties array.
+  ElementsKind kind = FAST_ELEMENTS;
+  Add<HBoundsCheck>(new_capacity,
+                    Add<HConstant>((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<HStoreNamedField>(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<HStoreNamedField>(object, HObjectAccess::ForMap(),
+                        GetParameter(ExtendStorageDescriptor::kMapIndex));
+
+  return GetParameter(ExtendStorageDescriptor::kValueIndex);
+}
+
+
+Handle<Code> ExtendStorageStub::GenerateCode() { return DoGenerateCode(this); }
+
+
+template <>
 HValue* CodeStubGraphBuilder<StringLengthStub>::BuildCodeStub() {
   HValue* string = BuildLoadNamedField(GetParameter(0),
       FieldIndex::ForInObjectOffset(JSValue::kValueOffset));
index 5c9e1a2..e7d5664 100644 (file)
@@ -614,6 +614,11 @@ void ElementsTransitionAndStoreStub::InitializeDescriptor(
 }
 
 
+CallInterfaceDescriptor ExtendStorageStub::GetCallInterfaceDescriptor() {
+  return ExtendStorageDescriptor(isolate());
+}
+
+
 static void InitializeVectorLoadStub(Isolate* isolate,
                                      CodeStubDescriptor* descriptor,
                                      Address deoptimization_handler) {
index b127782..c6a3b20 100644 (file)
@@ -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<int, 0, 13> {};
+  class RepresentationBits : public BitField<uint8_t, 13, 4> {};
+
+  DEFINE_HANDLER_CODE_STUB(ExtendStorage, HandlerStub);
+};
+
+
 class StoreGlobalStub : public HandlerStub {
  public:
   StoreGlobalStub(Isolate* isolate, bool is_constant, bool check_global)
index 301e7e4..d72aade 100644 (file)
@@ -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<HForceRepresentation>(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<HConstant>(i);
@@ -2832,10 +2825,40 @@ void HGraphBuilder::BuildFillElementsWithHole(HValue* elements,
       ? Add<HConstant>(factory->the_hole_value())
       : Add<HConstant>(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<HSub>(key, graph()->GetConstant1());
+  key->ClearFlag(HValue::kCanOverflow);
+
+  HValue* element =
+      Add<HLoadKeyed>(from_properties, key, static_cast<HValue*>(NULL), kind);
+
+  Add<HStoreKeyed>(to_properties, key, element, kind);
+
+  builder.EndBody();
+}
+
+
 void HGraphBuilder::BuildCopyElements(HValue* from_elements,
                                       ElementsKind from_elements_kind,
                                       HValue* to_elements,
index d507643..384c79d 100644 (file)
@@ -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,
index 3a0d526..f1af19b 100644 (file)
@@ -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;
 }
index 5314d48..7aa155c 100644 (file)
@@ -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;
   }
 
index f7f82bc..0923992 100644 (file)
@@ -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;
   }
 
index fd97154..f37fbf2 100644 (file)
@@ -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;
   }
 
index 500fa1f..b1363f1 100644 (file)
@@ -2094,7 +2094,7 @@ RUNTIME_FUNCTION(StoreIC_Miss) {
 RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) {
   TimerEventScope<TimerEventIcMiss> timer(isolate);
   HandleScope scope(isolate);
-  DCHECK(args.length() == 3);
+  DCHECK(args.length() == 3 || args.length() == 4);
   StoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
   Handle<Object> receiver = args.at<Object>(0);
   Handle<String> key = args.at<String>(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<TimerEventIcMiss> timer(isolate);
-  HandleScope shs(isolate);
-  DCHECK(args.length() == 3);
-
-  // Convert the parameters
-  Handle<JSObject> object = args.at<JSObject>(0);
-  Handle<Map> transition = args.at<Map>(1);
-  Handle<Object> value = args.at<Object>(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-<arch>.cc.
 RUNTIME_FUNCTION(KeyedStoreIC_Miss) {
   TimerEventScope<TimerEventIcMiss> timer(isolate);
index d86d2b7..e1facd6 100644 (file)
@@ -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. */        \
index 5b4555f..0abbed9 100644 (file)
@@ -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;
   }
 
index f44226f..009b575 100644 (file)
@@ -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;
   }
 
index c4d6ecf..f2f73b3 100644 (file)
@@ -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;
   }
 
index e706998..3c74827 100644 (file)
@@ -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;
   }
 
index 62d7105..e9f76bd 100644 (file)
@@ -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(),
index b773c91..059ae7e 100644 (file)
@@ -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)
index 936ce20..070228d 100644 (file)
@@ -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; }
 
 
index 8759bdd..06db808 100644 (file)
@@ -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; }
 
 
index 482b5be..57130e7 100644 (file)
@@ -1962,7 +1962,7 @@ void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> 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<FixedArray> old_storage = handle(object->properties(), isolate);
     Handle<FixedArray> new_storage =
@@ -3753,15 +3753,6 @@ bool JSObject::TryMigrateInstance(Handle<JSObject> object) {
 }
 
 
-void JSObject::MigrateToNewProperty(Handle<JSObject> object,
-                                    Handle<Map> map,
-                                    Handle<Object> 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;
 
index f2e17d3..5486d2a 100644 (file)
@@ -2209,10 +2209,6 @@ class JSObject: public JSReceiver {
                                   Handle<Name> name,
                                   Handle<Object> old_value);
 
-  static void MigrateToNewProperty(Handle<JSObject> object,
-                                   Handle<Map> transition,
-                                   Handle<Object> value);
-
  private:
   friend class DictionaryElementsAccessor;
   friend class JSReceiver;
index 84fdca4..05c24ce 100644 (file)
@@ -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;
 }
index 8dfad36..46af75c 100644 (file)
@@ -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;
 }