| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 3561516726b383f92738c7acb9da598f8a459e0f..d0c898afe97dee3384bc453dfb0f33c00a3bfc73 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -1367,9 +1367,9 @@ HValue* HGraphBuilder::BuildAllocateElements(HValue* context,
|
| }
|
|
|
|
|
| -void HGraphBuilder::BuildInitializeElements(HValue* elements,
|
| - ElementsKind kind,
|
| - HValue* capacity) {
|
| +void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
|
| + ElementsKind kind,
|
| + HValue* capacity) {
|
| Factory* factory = isolate()->factory();
|
| Handle<Map> map = IsFastDoubleElementsKind(kind)
|
| ? factory->fixed_double_array_map()
|
| @@ -1383,11 +1383,12 @@ void HGraphBuilder::BuildInitializeElements(HValue* elements,
|
| }
|
|
|
|
|
| -HValue* HGraphBuilder::BuildAllocateAndInitializeElements(HValue* context,
|
| - ElementsKind kind,
|
| - HValue* capacity) {
|
| +HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader(
|
| + HValue* context,
|
| + ElementsKind kind,
|
| + HValue* capacity) {
|
| HValue* new_elements = BuildAllocateElements(context, kind, capacity);
|
| - BuildInitializeElements(new_elements, kind, capacity);
|
| + BuildInitializeElementsHeader(new_elements, kind, capacity);
|
| return new_elements;
|
| }
|
|
|
| @@ -1488,8 +1489,8 @@ HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
|
|
|
| BuildNewSpaceArrayCheck(new_capacity, kind);
|
|
|
| - HValue* new_elements =
|
| - BuildAllocateAndInitializeElements(context, kind, new_capacity);
|
| + HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader(
|
| + context, kind, new_capacity);
|
|
|
| BuildCopyElements(context, elements, kind,
|
| new_elements, kind,
|
| @@ -1892,7 +1893,7 @@ HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes,
|
| length_field);
|
|
|
| // Initialize the elements
|
| - builder()->BuildInitializeElements(elements_location_, kind_, capacity);
|
| + builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity);
|
|
|
| if (fill_with_hole) {
|
| builder()->BuildFillElementsWithHole(context, elements_location_, kind_,
|
| @@ -9910,13 +9911,6 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy(
|
| AllocationSiteMode mode) {
|
| Zone* zone = this->zone();
|
|
|
| - HInstruction* original_boilerplate = AddInstruction(new(zone) HConstant(
|
| - original_boilerplate_object, Representation::Tagged()));
|
| -
|
| - bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE &&
|
| - boilerplate_object->map()->CanTrackAllocationSite();
|
| -
|
| - // Only elements backing stores for non-COW arrays need to be copied.
|
| Handle<FixedArrayBase> elements(boilerplate_object->elements());
|
| Handle<FixedArrayBase> original_elements(
|
| original_boilerplate_object->elements());
|
| @@ -9930,20 +9924,98 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy(
|
| elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
|
| elements->Size() : 0;
|
| int elements_offset = *offset + object_size;
|
| - if (create_allocation_site_info) {
|
| - elements_offset += AllocationSiteInfo::kSize;
|
| - *offset += AllocationSiteInfo::kSize;
|
| - }
|
|
|
| *offset += object_size + elements_size;
|
|
|
| - HValue* object_elements = BuildCopyObjectHeader(boilerplate_object, target,
|
| + // Copy object elements if non-COW.
|
| + HValue* object_elements = BuildEmitObjectHeader(boilerplate_object, target,
|
| object_offset, elements_offset, elements_size);
|
| + if (object_elements != NULL) {
|
| + BuildEmitElements(elements, original_elements, kind, object_elements,
|
| + target, offset);
|
| + }
|
|
|
| // Copy in-object properties.
|
| HValue* object_properties =
|
| AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset));
|
| + BuildEmitInObjectProperties(boilerplate_object, original_boilerplate_object,
|
| + object_properties, target, offset);
|
| +
|
| + // Create allocation site info.
|
| + if (mode == TRACK_ALLOCATION_SITE &&
|
| + boilerplate_object->map()->CanTrackAllocationSite()) {
|
| + elements_offset += AllocationSiteInfo::kSize;
|
| + *offset += AllocationSiteInfo::kSize;
|
| + HInstruction* original_boilerplate = AddInstruction(new(zone) HConstant(
|
| + original_boilerplate_object, Representation::Tagged()));
|
| + BuildCreateAllocationSiteInfo(target, JSArray::kSize, original_boilerplate);
|
| + }
|
| +}
|
| +
|
| +
|
| +HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader(
|
| + Handle<JSObject> boilerplate_object,
|
| + HInstruction* target,
|
| + int object_offset,
|
| + int elements_offset,
|
| + int elements_size) {
|
| + ASSERT(boilerplate_object->properties()->length() == 0);
|
| + Zone* zone = this->zone();
|
| + HValue* result = NULL;
|
| +
|
| + HValue* object_header =
|
| + AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset));
|
| + Handle<Map> boilerplate_object_map(boilerplate_object->map());
|
| + AddStoreMapConstant(object_header, boilerplate_object_map);
|
|
|
| + HInstruction* elements;
|
| + if (elements_size == 0) {
|
| + Handle<Object> elements_field =
|
| + Handle<Object>(boilerplate_object->elements(), isolate());
|
| + elements = AddInstruction(new(zone) HConstant(
|
| + elements_field, Representation::Tagged()));
|
| + } else {
|
| + elements = AddInstruction(new(zone) HInnerAllocatedObject(
|
| + target, elements_offset));
|
| + result = elements;
|
| + }
|
| + AddStore(object_header, HObjectAccess::ForElementsPointer(), elements);
|
| +
|
| + Handle<Object> properties_field =
|
| + Handle<Object>(boilerplate_object->properties(), isolate());
|
| + ASSERT(*properties_field == isolate()->heap()->empty_fixed_array());
|
| + HInstruction* properties = AddInstruction(new(zone) HConstant(
|
| + properties_field, Representation::None()));
|
| + HObjectAccess access = HObjectAccess::ForPropertiesPointer();
|
| + AddStore(object_header, access, properties);
|
| +
|
| + if (boilerplate_object->IsJSArray()) {
|
| + Handle<JSArray> boilerplate_array =
|
| + Handle<JSArray>::cast(boilerplate_object);
|
| + Handle<Object> length_field =
|
| + Handle<Object>(boilerplate_array->length(), isolate());
|
| + HInstruction* length = AddInstruction(new(zone) HConstant(
|
| + length_field, Representation::None()));
|
| +
|
| + ASSERT(boilerplate_array->length()->IsSmi());
|
| + Representation representation =
|
| + IsFastElementsKind(boilerplate_array->GetElementsKind())
|
| + ? Representation::Smi() : Representation::Tagged();
|
| + AddStore(object_header, HObjectAccess::ForArrayLength(),
|
| + length, representation);
|
| + }
|
| +
|
| + return result;
|
| +}
|
| +
|
| +
|
| +void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
|
| + Handle<JSObject> boilerplate_object,
|
| + Handle<JSObject> original_boilerplate_object,
|
| + HValue* object_properties,
|
| + HInstruction* target,
|
| + int* offset) {
|
| + Zone* zone = this->zone();
|
| Handle<DescriptorArray> descriptors(
|
| boilerplate_object->map()->instance_descriptors());
|
| int limit = boilerplate_object->map()->NumberOfOwnDescriptors();
|
| @@ -10006,126 +10078,97 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy(
|
| HObjectAccess access = HObjectAccess::ForJSObjectOffset(i);
|
| AddStore(object_properties, access, value_instruction);
|
| }
|
| -
|
| - // Build Allocation Site Info if desired
|
| - if (create_allocation_site_info) {
|
| - BuildCreateAllocationSiteInfo(target, JSArray::kSize, original_boilerplate);
|
| - }
|
| -
|
| - if (object_elements != NULL) {
|
| - HInstruction* boilerplate_elements = AddInstruction(new(zone) HConstant(
|
| - elements, Representation::Tagged()));
|
| -
|
| - int elements_length = elements->length();
|
| - HValue* object_elements_length =
|
| - AddInstruction(new(zone) HConstant(
|
| - elements_length, Representation::Integer32()));
|
| -
|
| - BuildInitializeElements(object_elements, kind, object_elements_length);
|
| -
|
| - // Copy elements backing store content.
|
| - if (elements->IsFixedDoubleArray()) {
|
| - for (int i = 0; i < elements_length; i++) {
|
| - HValue* key_constant =
|
| - AddInstruction(new(zone) HConstant(i, Representation::Integer32()));
|
| - HInstruction* value_instruction =
|
| - AddInstruction(new(zone) HLoadKeyed(
|
| - boilerplate_elements, key_constant, NULL, kind,
|
| - ALLOW_RETURN_HOLE));
|
| - HInstruction* store = AddInstruction(new(zone) HStoreKeyed(
|
| - object_elements, key_constant, value_instruction, kind));
|
| - store->ClearFlag(HValue::kDeoptimizeOnUndefined);
|
| - }
|
| - } else if (elements->IsFixedArray()) {
|
| - Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
|
| - Handle<FixedArray> original_fast_elements =
|
| - Handle<FixedArray>::cast(original_elements);
|
| - for (int i = 0; i < elements_length; i++) {
|
| - Handle<Object> value(fast_elements->get(i), isolate());
|
| - HValue* key_constant =
|
| - AddInstruction(new(zone) HConstant(i, Representation::Integer32()));
|
| - if (value->IsJSObject()) {
|
| - Handle<JSObject> value_object = Handle<JSObject>::cast(value);
|
| - Handle<JSObject> original_value_object = Handle<JSObject>::cast(
|
| - Handle<Object>(original_fast_elements->get(i), isolate()));
|
| - HInstruction* value_instruction =
|
| - AddInstruction(new(zone) HInnerAllocatedObject(target, *offset));
|
| - AddInstruction(new(zone) HStoreKeyed(
|
| - object_elements, key_constant, value_instruction, kind));
|
| - BuildEmitDeepCopy(value_object, original_value_object, target,
|
| - offset, DONT_TRACK_ALLOCATION_SITE);
|
| - } else {
|
| - HInstruction* value_instruction =
|
| - AddInstruction(new(zone) HLoadKeyed(
|
| - boilerplate_elements, key_constant, NULL, kind,
|
| - ALLOW_RETURN_HOLE));
|
| - AddInstruction(new(zone) HStoreKeyed(
|
| - object_elements, key_constant, value_instruction, kind));
|
| - }
|
| - }
|
| - } else {
|
| - UNREACHABLE();
|
| - }
|
| - }
|
| }
|
|
|
|
|
| -HValue* HOptimizedGraphBuilder::BuildCopyObjectHeader(
|
| - Handle<JSObject> boilerplate_object,
|
| +void HOptimizedGraphBuilder::BuildEmitElements(
|
| + Handle<FixedArrayBase> elements,
|
| + Handle<FixedArrayBase> original_elements,
|
| + ElementsKind kind,
|
| + HValue* object_elements,
|
| HInstruction* target,
|
| - int object_offset,
|
| - int elements_offset,
|
| - int elements_size) {
|
| - ASSERT(boilerplate_object->properties()->length() == 0);
|
| + int* offset) {
|
| Zone* zone = this->zone();
|
| - HValue* result = NULL;
|
|
|
| - HValue* object_header =
|
| - AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset));
|
| - Handle<Map> boilerplate_object_map(boilerplate_object->map());
|
| - AddStoreMapConstant(object_header, boilerplate_object_map);
|
| + int elements_length = elements->length();
|
| + HValue* object_elements_length =
|
| + AddInstruction(new(zone) HConstant(
|
| + elements_length, Representation::Integer32()));
|
|
|
| - HInstruction* elements;
|
| - if (elements_size == 0) {
|
| - Handle<Object> elements_field =
|
| - Handle<Object>(boilerplate_object->elements(), isolate());
|
| - elements = AddInstruction(new(zone) HConstant(
|
| - elements_field, Representation::Tagged()));
|
| + BuildInitializeElementsHeader(object_elements, kind, object_elements_length);
|
| +
|
| + // Copy elements backing store content.
|
| + if (elements->IsFixedDoubleArray()) {
|
| + BuildEmitFixedDoubleArray(elements, kind, object_elements);
|
| + } else if (elements->IsFixedArray()) {
|
| + BuildEmitFixedArray(elements, original_elements, kind, object_elements,
|
| + target, offset);
|
| } else {
|
| - elements = AddInstruction(new(zone) HInnerAllocatedObject(
|
| - target, elements_offset));
|
| - result = elements;
|
| + UNREACHABLE();
|
| }
|
| - AddStore(object_header, HObjectAccess::ForElementsPointer(), elements);
|
| -
|
| - Handle<Object> properties_field =
|
| - Handle<Object>(boilerplate_object->properties(), isolate());
|
| - ASSERT(*properties_field == isolate()->heap()->empty_fixed_array());
|
| - HInstruction* properties = AddInstruction(new(zone) HConstant(
|
| - properties_field, Representation::None()));
|
| - HObjectAccess access = HObjectAccess::ForPropertiesPointer();
|
| - AddStore(object_header, access, properties);
|
| +}
|
|
|
| - if (boilerplate_object->IsJSArray()) {
|
| - Handle<JSArray> boilerplate_array =
|
| - Handle<JSArray>::cast(boilerplate_object);
|
| - Handle<Object> length_field =
|
| - Handle<Object>(boilerplate_array->length(), isolate());
|
| - HInstruction* length = AddInstruction(new(zone) HConstant(
|
| - length_field, Representation::None()));
|
|
|
| - ASSERT(boilerplate_array->length()->IsSmi());
|
| - Representation representation =
|
| - IsFastElementsKind(boilerplate_array->GetElementsKind())
|
| - ? Representation::Smi() : Representation::Tagged();
|
| - AddStore(object_header, HObjectAccess::ForArrayLength(),
|
| - length, representation);
|
| +void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
|
| + Handle<FixedArrayBase> elements,
|
| + ElementsKind kind,
|
| + HValue* object_elements) {
|
| + Zone* zone = this->zone();
|
| + HInstruction* boilerplate_elements = AddInstruction(new(zone) HConstant(
|
| + elements, Representation::Tagged()));
|
| + int elements_length = elements->length();
|
| + for (int i = 0; i < elements_length; i++) {
|
| + HValue* key_constant =
|
| + AddInstruction(new(zone) HConstant(i, Representation::Integer32()));
|
| + HInstruction* value_instruction =
|
| + AddInstruction(new(zone) HLoadKeyed(
|
| + boilerplate_elements, key_constant, NULL, kind, ALLOW_RETURN_HOLE));
|
| + HInstruction* store = AddInstruction(new(zone) HStoreKeyed(
|
| + object_elements, key_constant, value_instruction, kind));
|
| + store->ClearFlag(HValue::kDeoptimizeOnUndefined);
|
| + }
|
| +}
|
| +
|
| +
|
| +void HOptimizedGraphBuilder::BuildEmitFixedArray(
|
| + Handle<FixedArrayBase> elements,
|
| + Handle<FixedArrayBase> original_elements,
|
| + ElementsKind kind,
|
| + HValue* object_elements,
|
| + HInstruction* target,
|
| + int* offset) {
|
| + Zone* zone = this->zone();
|
| + HInstruction* boilerplate_elements = AddInstruction(new(zone) HConstant(
|
| + elements, Representation::Tagged()));
|
| + int elements_length = elements->length();
|
| + Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
|
| + Handle<FixedArray> original_fast_elements =
|
| + Handle<FixedArray>::cast(original_elements);
|
| + for (int i = 0; i < elements_length; i++) {
|
| + Handle<Object> value(fast_elements->get(i), isolate());
|
| + HValue* key_constant =
|
| + AddInstruction(new(zone) HConstant(i, Representation::Integer32()));
|
| + if (value->IsJSObject()) {
|
| + Handle<JSObject> value_object = Handle<JSObject>::cast(value);
|
| + Handle<JSObject> original_value_object = Handle<JSObject>::cast(
|
| + Handle<Object>(original_fast_elements->get(i), isolate()));
|
| + HInstruction* value_instruction =
|
| + AddInstruction(new(zone) HInnerAllocatedObject(target, *offset));
|
| + AddInstruction(new(zone) HStoreKeyed(
|
| + object_elements, key_constant, value_instruction, kind));
|
| + BuildEmitDeepCopy(value_object, original_value_object, target,
|
| + offset, DONT_TRACK_ALLOCATION_SITE);
|
| + } else {
|
| + HInstruction* value_instruction =
|
| + AddInstruction(new(zone) HLoadKeyed(
|
| + boilerplate_elements, key_constant, NULL, kind,
|
| + ALLOW_RETURN_HOLE));
|
| + AddInstruction(new(zone) HStoreKeyed(
|
| + object_elements, key_constant, value_instruction, kind));
|
| + }
|
| }
|
| -
|
| - return result;
|
| }
|
|
|
| -
|
| void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
|
| ASSERT(!HasStackOverflow());
|
| ASSERT(current_block() != NULL);
|
|
|