| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 3c03b1560841bcd17587293056cb0771d681f8a7..29b2482199910ff3191a430e959a3910a318f3ac 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -6679,10 +6679,16 @@ static bool IsFastLiteral(Handle<JSObject> boilerplate,
|
| if (properties->length() > 0) {
|
| return false;
|
| } else {
|
| - int nof = boilerplate->map()->inobject_properties();
|
| - for (int i = 0; i < nof; i++) {
|
| + Handle<DescriptorArray> descriptors(
|
| + boilerplate->map()->instance_descriptors());
|
| + int limit = boilerplate->map()->NumberOfOwnDescriptors();
|
| + for (int i = 0; i < limit; i++) {
|
| + PropertyDetails details = descriptors->GetDetails(i);
|
| + if (details.type() != FIELD) continue;
|
| + Representation representation = details.representation();
|
| + int index = descriptors->GetFieldIndex(i);
|
| if ((*max_properties)-- == 0) return false;
|
| - Handle<Object> value(boilerplate->InObjectPropertyAt(i), isolate);
|
| + Handle<Object> value(boilerplate->InObjectPropertyAt(index), isolate);
|
| if (value->IsJSObject()) {
|
| Handle<JSObject> value_object = Handle<JSObject>::cast(value);
|
| if (!IsFastLiteral(value_object,
|
| @@ -6692,6 +6698,8 @@ static bool IsFastLiteral(Handle<JSObject> boilerplate,
|
| pointer_size)) {
|
| return false;
|
| }
|
| + } else if (representation.IsDouble()) {
|
| + *data_size += HeapNumber::kSize;
|
| }
|
| }
|
| }
|
| @@ -6741,6 +6749,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
| expr->fast_elements(),
|
| expr->literal_index(),
|
| expr->depth(),
|
| + expr->may_store_doubles(),
|
| expr->has_function()));
|
| }
|
|
|
| @@ -7047,9 +7056,33 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
|
| } else {
|
| offset += FixedArray::kHeaderSize;
|
| }
|
| + bool transition_to_field = lookup->IsTransitionToField(*map);
|
| + if (FLAG_track_double_fields && representation.IsDouble()) {
|
| + if (transition_to_field) {
|
| + NoObservableSideEffectsScope no_side_effects(this);
|
| + HInstruction* heap_number_size = AddInstruction(new(zone()) HConstant(
|
| + HeapNumber::kSize, Representation::Integer32()));
|
| + HInstruction* double_box = AddInstruction(new(zone()) HAllocate(
|
| + environment()->LookupContext(), heap_number_size,
|
| + HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE));
|
| + BuildStoreMap(double_box, isolate()->factory()->heap_number_map());
|
| + AddInstruction(new(zone()) HStoreNamedField(
|
| + double_box, name, value, true,
|
| + Representation::Double(), HeapNumber::kValueOffset));
|
| + value = double_box;
|
| + representation = Representation::Tagged();
|
| + } else {
|
| + HInstruction* double_box = AddInstruction(new(zone()) HLoadNamedField(
|
| + object, is_in_object, Representation::Tagged(), offset));
|
| + double_box->set_type(HType::HeapNumber());
|
| + return new(zone()) HStoreNamedField(
|
| + double_box, name, value, true,
|
| + Representation::Double(), HeapNumber::kValueOffset);
|
| + }
|
| + }
|
| HStoreNamedField* instr = new(zone()) HStoreNamedField(
|
| object, name, value, is_in_object, representation, offset);
|
| - if (lookup->IsTransitionToField(*map)) {
|
| + if (transition_to_field) {
|
| Handle<Map> transition(lookup->GetTransitionMapFromMap(*map));
|
| instr->set_transition(transition);
|
| // TODO(fschneider): Record the new map type of the object in the IR to
|
| @@ -7764,7 +7797,20 @@ HLoadNamedField* HGraphBuilder::DoBuildLoadNamedField(
|
| bool inobject,
|
| Representation representation,
|
| int offset) {
|
| - return new(zone()) HLoadNamedField(object, inobject, representation, offset);
|
| + bool load_double = false;
|
| + if (representation.IsDouble()) {
|
| + representation = Representation::Tagged();
|
| + load_double = FLAG_track_double_fields;
|
| + }
|
| + HLoadNamedField* field =
|
| + new(zone()) HLoadNamedField(object, inobject, representation, offset);
|
| + if (load_double) {
|
| + AddInstruction(field);
|
| + field->set_type(HType::HeapNumber());
|
| + return new(zone()) HLoadNamedField(
|
| + field, true, Representation::Double(), HeapNumber::kValueOffset);
|
| + }
|
| + return field;
|
| }
|
|
|
|
|
| @@ -10766,7 +10812,6 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy(
|
| elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
|
| elements->Size() : 0;
|
| int elements_offset = *offset + object_size;
|
| - int inobject_properties = boilerplate_object->map()->inobject_properties();
|
| if (create_allocation_site_info) {
|
| elements_offset += AllocationSiteInfo::kSize;
|
| *offset += AllocationSiteInfo::kSize;
|
| @@ -10780,32 +10825,49 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy(
|
| // Copy in-object properties.
|
| HValue* object_properties =
|
| AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset));
|
| - for (int i = 0; i < inobject_properties; i++) {
|
| +
|
| + Handle<DescriptorArray> descriptors(
|
| + boilerplate_object->map()->instance_descriptors());
|
| + int limit = boilerplate_object->map()->NumberOfOwnDescriptors();
|
| +
|
| + for (int i = 0; i < limit; i++) {
|
| + PropertyDetails details = descriptors->GetDetails(i);
|
| + if (details.type() != FIELD) continue;
|
| + int index = descriptors->GetFieldIndex(i);
|
| + int property_offset = boilerplate_object->GetInObjectPropertyOffset(index);
|
| + Handle<Name> name(descriptors->GetKey(i));
|
| Handle<Object> value =
|
| - Handle<Object>(boilerplate_object->InObjectPropertyAt(i),
|
| + Handle<Object>(boilerplate_object->InObjectPropertyAt(index),
|
| isolate());
|
| if (value->IsJSObject()) {
|
| Handle<JSObject> value_object = Handle<JSObject>::cast(value);
|
| Handle<JSObject> original_value_object = Handle<JSObject>::cast(
|
| - Handle<Object>(original_boilerplate_object->InObjectPropertyAt(i),
|
| + Handle<Object>(original_boilerplate_object->InObjectPropertyAt(index),
|
| isolate()));
|
| HInstruction* value_instruction =
|
| AddInstruction(new(zone) HInnerAllocatedObject(target, *offset));
|
| - // TODO(verwaest): choose correct storage.
|
| AddInstruction(new(zone) HStoreNamedField(
|
| - object_properties, factory->unknown_field_string(), value_instruction,
|
| - true, Representation::Tagged(),
|
| - boilerplate_object->GetInObjectPropertyOffset(i)));
|
| + object_properties, name, value_instruction, true,
|
| + Representation::Tagged(), property_offset));
|
| BuildEmitDeepCopy(value_object, original_value_object, target,
|
| offset, DONT_TRACK_ALLOCATION_SITE);
|
| } else {
|
| - // TODO(verwaest): choose correct storage.
|
| + Representation representation = details.representation();
|
| HInstruction* value_instruction = AddInstruction(new(zone) HConstant(
|
| value, Representation::Tagged()));
|
| + if (representation.IsDouble()) {
|
| + HInstruction* double_box =
|
| + AddInstruction(new(zone) HInnerAllocatedObject(target, *offset));
|
| + BuildStoreMap(double_box, factory->heap_number_map());
|
| + AddInstruction(new(zone) HStoreNamedField(
|
| + double_box, name, value_instruction, true,
|
| + Representation::Double(), HeapNumber::kValueOffset));
|
| + value_instruction = double_box;
|
| + *offset += HeapNumber::kSize;
|
| + }
|
| AddInstruction(new(zone) HStoreNamedField(
|
| - object_properties, factory->unknown_field_string(), value_instruction,
|
| - true, Representation::Tagged(),
|
| - boilerplate_object->GetInObjectPropertyOffset(i)));
|
| + object_properties, name, value_instruction, true,
|
| + Representation::Tagged(), property_offset));
|
| }
|
| }
|
|
|
|
|