Index: src/code-stubs-hydrogen.cc |
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc |
index 3a9688a899f8d43597eb95a54a07719207b7da2f..6b7488c3a76650d6b8f4400708ff1ad3fc77c7fb 100644 |
--- a/src/code-stubs-hydrogen.cc |
+++ b/src/code-stubs-hydrogen.cc |
@@ -63,7 +63,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, |
@@ -602,7 +603,7 @@ Handle<Code> LoadConstantStub::GenerateCode() { return DoGenerateCode(this); } |
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 = |
@@ -611,12 +612,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); |
} |
@@ -628,7 +648,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); |
} |
@@ -637,6 +657,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)); |