Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index 435805fbfbd62eb6e91e4dcb8e1bb67bdaa68ee2..bf839c5fe950f564dd964816acd137f80c8acdd5 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -6040,33 +6040,33 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| // Check whether to use fast or slow deep-copying for boilerplate. |
| int total_size = 0; |
| - int max_properties = HFastLiteral::kMaxLiteralProperties; |
| + int max_properties = kMaxLiteralProperties; |
| Handle<Object> boilerplate(closure->literals()->get(expr->literal_index()), |
| isolate()); |
| if (boilerplate->IsJSObject() && |
| IsFastLiteral(Handle<JSObject>::cast(boilerplate), |
| - HFastLiteral::kMaxLiteralDepth, |
| + kMaxLiteralDepth, |
| &max_properties, |
| &total_size)) { |
| Handle<JSObject> boilerplate_object = Handle<JSObject>::cast(boilerplate); |
| - literal = new(zone()) HFastLiteral(context, |
| - boilerplate_object, |
| - total_size, |
| - expr->literal_index(), |
| - expr->depth(), |
| - DONT_TRACK_ALLOCATION_SITE); |
| + literal = BuildFastLiteral(context, |
| + boilerplate_object, |
| + total_size, |
| + DONT_TRACK_ALLOCATION_SITE, |
| + environment()->previous_ast_id()); |
| } else { |
| - literal = new(zone()) HObjectLiteral(context, |
| - expr->constant_properties(), |
| - expr->fast_elements(), |
| - expr->literal_index(), |
| - expr->depth(), |
| - expr->has_function()); |
| + literal = AddInstruction( |
| + new(zone()) HObjectLiteral(context, |
| + expr->constant_properties(), |
| + expr->fast_elements(), |
| + expr->literal_index(), |
| + expr->depth(), |
| + expr->has_function())); |
| } |
| // The object is expected in the bailout environment during computation |
| // of the property values and is the value of the entire expression. |
| - PushAndAdd(literal); |
| + Push(literal); |
| expr->CalculateEmitStore(zone()); |
| @@ -6175,32 +6175,32 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| // Check whether to use fast or slow deep-copying for boilerplate. |
| int total_size = 0; |
| - int max_properties = HFastLiteral::kMaxLiteralProperties; |
| + int max_properties = kMaxLiteralProperties; |
| if (IsFastLiteral(boilerplate, |
| - HFastLiteral::kMaxLiteralDepth, |
| + kMaxLiteralDepth, |
| &max_properties, |
| &total_size)) { |
| if (mode == TRACK_ALLOCATION_SITE) { |
| total_size += AllocationSiteInfo::kSize; |
| } |
| - literal = new(zone()) HFastLiteral(context, |
| - boilerplate, |
| - total_size, |
| - expr->literal_index(), |
| - expr->depth(), |
| - mode); |
| + literal = BuildFastLiteral(context, |
| + boilerplate, |
| + total_size, |
| + mode, |
| + environment()->previous_ast_id()); |
| } else { |
| - literal = new(zone()) HArrayLiteral(context, |
| - boilerplate, |
| - length, |
| - expr->literal_index(), |
| - expr->depth(), |
| - mode); |
| + literal = AddInstruction( |
| + new(zone()) HArrayLiteral(context, |
| + boilerplate, |
| + length, |
| + expr->literal_index(), |
| + expr->depth(), |
| + mode)); |
| } |
| // The array is expected in the bailout environment during computation |
| // of the property values and is the value of the entire expression. |
| - PushAndAdd(literal); |
| + Push(literal); |
| HLoadElements* elements = NULL; |
| @@ -9897,6 +9897,201 @@ HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { |
| } |
| +HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( |
| + HValue* context, |
| + Handle<JSObject> boilerplate_object, |
| + int size, |
| + AllocationSiteMode mode, |
| + BailoutId id) { |
| + Zone* zone = this->zone(); |
| + Handle<Map> map(boilerplate_object->map()); |
| + ElementsKind kind = map->elements_kind(); |
| + bool packed = IsFastPackedElementsKind(kind); |
| + |
| + HInstruction* boilerplate = AddInstruction(new(zone) HConstant( |
| + boilerplate_object, Representation::Tagged())); |
|
danno
2013/04/02 21:08:47
Maybe I missed this, but where is the boilerplate
Hannes Payer (out of office)
2013/04/08 11:03:00
Done.
|
| + if (CanTransitionToMoreGeneralFastElementsKind(kind, packed)) { |
|
danno
2013/04/02 21:08:47
Can you get rid of this? If you make a copy of the
Hannes Payer (out of office)
2013/04/08 11:03:00
Done.
|
| + AddInstruction(new(zone) HCheckMaps(boilerplate, map, zone)); |
| + } |
| + |
| + HValue* size_in_bytes = |
| + AddInstruction(new(zone) HConstant(size, Representation::Integer32())); |
| + HInstruction* object = |
| + AddInstruction(new(zone) HAllocate(context, |
| + size_in_bytes, |
| + HType::JSObject(), |
| + HAllocate::CAN_ALLOCATE_IN_NEW_SPACE)); |
| + int offset = 0; |
| + BuildEmitDeepCopy(boilerplate_object, object, boilerplate, &offset, mode, id); |
| + ASSERT_EQ(size, offset); |
| + return object; |
| +} |
| + |
| + |
| +void HOptimizedGraphBuilder::BuildEmitDeepCopy(Handle<JSObject> object, |
| + HInstruction* result, |
| + HInstruction* source, |
|
danno
2013/04/02 21:08:47
I am not sure why you need to have both object and
Hannes Payer (out of office)
2013/04/08 11:03:00
Done.
|
| + int* offset, |
| + AllocationSiteMode mode, |
| + BailoutId id) { |
| + Zone* zone = this->zone(); |
| + Factory* factory = isolate()->factory(); |
| + |
| + bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && |
| + object->map()->CanTrackAllocationSite(); |
| + |
| + // Only elements backing stores for non-COW arrays need to be copied. |
| + Handle<FixedArrayBase> elements(object->elements()); |
| + ElementsKind kind = object->map()->elements_kind(); |
| + bool has_elements = elements->length() > 0 && |
| + elements->map() != isolate()->heap()->fixed_cow_array_map(); |
| + |
| + // Increase the offset so that subsequent objects end up right after |
| + // this object and its backing store. |
| + int object_offset = *offset; |
| + int object_size = object->map()->instance_size(); |
| + int elements_size = has_elements ? 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; |
| + |
| + // Copy object header. |
| + ASSERT(object->properties()->length() == 0); |
| + int inobject_properties = object->map()->inobject_properties(); |
| + int header_size = object_size - inobject_properties * kPointerSize; |
| + HValue* object_header = |
| + AddInstruction(new(zone) HInnerAllocatedObject(result, object_offset)); |
| + for (int i = 0; i < header_size; i += kPointerSize) { |
|
danno
2013/04/02 21:08:47
Be careful here. Specifically, when you copy the o
Hannes Payer (out of office)
2013/04/08 11:03:00
Done.
|
| + HInstruction* header_value; |
| + if (has_elements && i == JSObject::kElementsOffset) { |
| + header_value = AddInstruction(new(zone) HInnerAllocatedObject( |
| + result, elements_offset)); |
| + |
| + } else { |
| + header_value = AddInstruction(new(zone) HLoadNamedField(source, true, i)); |
|
danno
2013/04/02 21:08:47
Are you sure that it's OK not to deep copy the non
Hannes Payer (out of office)
2013/04/08 11:03:00
Now I am creating HConstants out of the boilerplat
|
| + } |
| + AddInstruction(new(zone) HStoreNamedField(object_header, |
|
danno
2013/04/02 21:08:47
Have you considered loading the value you want to
Hannes Payer (out of office)
2013/04/08 11:03:00
Done.
|
| + factory->empty_string(), |
| + header_value, |
| + true, i)); |
|
danno
2013/04/02 21:08:47
Needs to set the kChangesInobjectFields GVN flag
Hannes Payer (out of office)
2013/04/08 11:03:00
is done above.
|
| + AddSimulate(id); |
| + } |
| + |
| + // Copy in-object properties. |
| + HValue* object_properties = |
| + AddInstruction(new(zone) HInnerAllocatedObject(result, object_offset)); |
| + for (int i = 0; i < inobject_properties; i++) { |
|
danno
2013/04/02 21:08:47
You need to be very careful here to honor the GVN
Hannes Payer (out of office)
2013/04/08 11:03:00
is taken care of by HStoreNamedField.
|
| + Handle<Object> value = Handle<Object>(object->InObjectPropertyAt(i), |
| + isolate()); |
| + if (value->IsJSObject()) { |
| + Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| + HInstruction* value_instruction = |
| + AddInstruction(new(zone) HInnerAllocatedObject(result, *offset)); |
| + AddInstruction(new(zone) HStoreNamedField( |
| + object_properties, factory->empty_string(), value_instruction, true, |
|
danno
2013/04/02 21:08:47
Instead of empty_string, perhaps we should add a "
Hannes Payer (out of office)
2013/04/08 11:03:00
Done.
|
| + object->GetInObjectPropertyOffset(i))); |
| + AddSimulate(id); |
| + source = AddInstruction(new(zone) HConstant( |
|
danno
2013/04/02 21:08:47
name this something else, you mask the parameter c
Hannes Payer (out of office)
2013/04/08 11:03:00
removed
|
| + value, Representation::Tagged())); |
| + BuildEmitDeepCopy(value_object, result, source, offset, |
| + DONT_TRACK_ALLOCATION_SITE, id); |
| + } else { |
| + HInstruction* value_instruction = AddInstruction(new(zone) HConstant( |
| + value, Representation::Tagged())); |
|
danno
2013/04/02 21:08:47
The value must be a smi, but without actually sett
Hannes Payer (out of office)
2013/04/08 11:03:00
This is determined by the HType and not by the Rep
|
| + AddInstruction(new(zone) HStoreNamedField( |
| + object_properties, factory->empty_string(), value_instruction, true, |
| + object->GetInObjectPropertyOffset(i))); |
|
danno
2013/04/02 21:08:47
You need to be very careful here to honor the GVN
Hannes Payer (out of office)
2013/04/08 11:03:00
is done above.
|
| + AddSimulate(id); |
| + } |
| + } |
| + |
| + // Build Allocation Site Info if desired |
| + if (create_allocation_site_info) { |
| + HValue* alloc_site = |
| + AddInstruction(new(zone) HInnerAllocatedObject(result, JSArray::kSize)); |
| + Handle<Map> alloc_site_map(isolate()->heap()->allocation_site_info_map()); |
| + BuildStoreMap(alloc_site, alloc_site_map, id); |
| + int alloc_payload_offset = AllocationSiteInfo::kPayloadOffset; |
| + AddInstruction(new(zone) HStoreNamedField(alloc_site, |
| + factory->empty_string(), |
|
danno
2013/04/02 21:08:47
create a "payload_string()"
Hannes Payer (out of office)
2013/04/08 11:03:00
Done.
|
| + source, |
|
danno
2013/04/02 21:08:47
Can you really use the source for anything yet? It
Hannes Payer (out of office)
2013/04/08 11:03:00
I am using now the original_boilerplate.
|
| + true, alloc_payload_offset)); |
| + AddSimulate(id); |
| + } |
| + |
| + if (has_elements) { |
| + HValue* boilerplate_elements = |
| + AddInstruction(new(zone) HLoadElements(source, NULL)); |
|
danno
2013/04/02 21:08:47
In this method have a mix here of loading from sou
Hannes Payer (out of office)
2013/04/08 11:03:00
I think it is the right thing to use HLoadElements
|
| + HValue* object_elements = |
| + AddInstruction(new(zone) HInnerAllocatedObject( |
| + result, elements_offset)); |
| + AddInstruction(new(zone) HStoreNamedField(object_elements, |
|
danno
2013/04/02 21:08:47
Does this actually work? Why do you store boilerpl
Hannes Payer (out of office)
2013/04/08 11:03:00
Yes, this should be the same as what was done befo
|
| + factory->elements_field_string(), |
| + boilerplate_elements, |
| + true, JSObject::kElementsOffset)); |
| + AddSimulate(id); |
| + for (int i = 0; i < FixedArray::kHeaderSize; i += kPointerSize) { |
|
danno
2013/04/02 21:08:47
Consider refactoring HGraphBuilder::BuildAllocateE
Hannes Payer (out of office)
2013/04/08 11:03:00
Done.
|
| + HInstruction* value_instruction = |
| + AddInstruction(new(zone) HLoadNamedField( |
| + boilerplate_elements, true, i)); |
| + AddInstruction(new(zone) HStoreNamedField(object_elements, |
| + factory->empty_string(), |
| + value_instruction, |
| + true, i)); |
| + AddSimulate(id); |
| + } |
| + |
| + // Copy elements backing store content. |
| + int elements_length = elements->length(); |
|
danno
2013/04/02 21:08:47
I think you can use HGraphBuilder::BuildCopyElemen
Hannes Payer (out of office)
2013/04/08 11:03:00
I looked into it but the code below calls recursiv
|
| + 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)); |
| + AddInstruction(new(zone) HStoreKeyed( |
| + object_elements, key_constant, value_instruction, kind)); |
| + AddSimulate(id); |
| + } |
| + } else if (elements->IsFixedArray()) { |
| + Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(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); |
| + HInstruction* value_instruction = |
| + AddInstruction(new(zone) HInnerAllocatedObject(result, *offset)); |
| + AddInstruction(new(zone) HStoreKeyed( |
| + object_elements, key_constant, value_instruction, kind)); |
| + AddSimulate(id); |
| + source = AddInstruction(new(zone) HConstant( |
| + value_object, Representation::Tagged())); |
| + BuildEmitDeepCopy(value_object, result, source, offset, |
| + DONT_TRACK_ALLOCATION_SITE, id); |
| + } else { |
| + HInstruction* value_instruction = |
| + AddInstruction(new(zone) HLoadKeyed( |
| + boilerplate_elements, key_constant, NULL, kind)); |
| + AddInstruction(new(zone) HStoreKeyed( |
| + object_elements, key_constant, value_instruction, kind)); |
| + AddSimulate(id); |
| + } |
| + } |
| + } else { |
| + UNREACHABLE(); |
| + } |
| + } |
| +} |
| + |
| + |
| + |
| void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
| ASSERT(!HasStackOverflow()); |
| ASSERT(current_block() != NULL); |