Chromium Code Reviews| Index: src/hydrogen.cc | 
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc | 
| index 5e36f68684f28e9556b8e90e2cbbc9d1253c36d4..1914faec9ba439834ff63276f9ed32c6ea2b29fd 100644 | 
| --- a/src/hydrogen.cc | 
| +++ b/src/hydrogen.cc | 
| @@ -1329,8 +1329,8 @@ HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, | 
| Handle<Map> map, | 
| BailoutId id) { | 
| Zone* zone = this->zone(); | 
| - HValue* map_constant = | 
| - AddInstruction(new(zone) HConstant(map, Representation::Tagged())); | 
| + HConstant* map_constant = new(zone) HConstant(map, Representation::Tagged()); | 
| + AddInstruction(map_constant); | 
| return BuildStoreMap(object, map_constant, id); | 
| } | 
| @@ -1590,6 +1590,257 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context, | 
| } | 
| +HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, | 
| + ElementsKind kind, | 
| + HValue* allocation_site_payload) : | 
| + builder_(builder), | 
| + kind_(kind), | 
| + allocation_site_payload_(allocation_site_payload) { | 
| + // Determine mode | 
| + mode_ = AllocationSiteInfo::GetMode(kind); | 
| +} | 
| + | 
| + | 
| +HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { | 
| + // Get the global context, the native context, the map array | 
| + HInstruction* global_object = AddInstruction(new(zone()) | 
| + HGlobalObject(context)); | 
| + HInstruction* native_context = AddInstruction(new(zone()) | 
| + HLoadNamedField(global_object, true, GlobalObject::kNativeContextOffset)); | 
| + size_t offset = Context::kHeaderSize + | 
| + kPointerSize * Context::JS_ARRAY_MAPS_INDEX; | 
| + HInstruction* map_array = AddInstruction(new(zone()) | 
| + HLoadNamedField(native_context, true, offset)); | 
| + offset = kind_ * kPointerSize + FixedArrayBase::kHeaderSize; | 
| + return AddInstruction(new(zone()) HLoadNamedField(map_array, true, offset)); | 
| +} | 
| + | 
| + | 
| +HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( | 
| + HValue* length_node) { | 
| + HValue* context = builder()->environment()->LookupContext(); | 
| + ASSERT(length_node != NULL); | 
| + | 
| + int base_size = JSArray::kSize; | 
| + if (mode_ == TRACK_ALLOCATION_SITE) { | 
| + base_size += AllocationSiteInfo::kSize; | 
| + } | 
| + | 
| + if (IsFastDoubleElementsKind(kind_)) { | 
| + base_size += FixedDoubleArray::kHeaderSize; | 
| + } else { | 
| + base_size += FixedArray::kHeaderSize; | 
| + } | 
| + | 
| + HInstruction* elements_size_value = new(zone()) | 
| + HConstant(elements_size(), Representation::Integer32()); | 
| + AddInstruction(elements_size_value); | 
| + HInstruction* mul = HMul::New(zone(), context, length_node, | 
| + elements_size_value); | 
| + mul->ChangeRepresentation(Representation::Integer32()); | 
| + mul->ClearFlag(HValue::kCanOverflow); | 
| + AddInstruction(mul); | 
| + AddSimulate(); | 
| + | 
| + HInstruction* base = new(zone()) HConstant(base_size, | 
| + Representation::Integer32()); | 
| + AddInstruction(base); | 
| + HInstruction* total_size = HAdd::New(zone(), context, base, mul); | 
| + total_size->ChangeRepresentation(Representation::Integer32()); | 
| + total_size->ClearFlag(HValue::kCanOverflow); | 
| + AddInstruction(total_size); | 
| + AddSimulate(); | 
| + return total_size; | 
| +} | 
| + | 
| + | 
| +HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { | 
| + int base_size = JSArray::kSize; | 
| + if (mode_ == TRACK_ALLOCATION_SITE) { | 
| + base_size += AllocationSiteInfo::kSize; | 
| + } | 
| + | 
| + if (initial_capacity() > 0) { | 
| + base_size += IsFastDoubleElementsKind(kind_) | 
| + ? FixedDoubleArray::SizeFor(initial_capacity()) | 
| + : FixedArray::SizeFor(initial_capacity()); | 
| + } | 
| + | 
| + HConstant* array_size = | 
| + new(zone()) HConstant(base_size, Representation::Integer32()); | 
| + AddInstruction(array_size); | 
| + return array_size; | 
| +} | 
| + | 
| + | 
| +HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { | 
| + HValue* size_in_bytes = EstablishEmptyArrayAllocationSize(); | 
| + HConstant* capacity = | 
| + new(zone()) HConstant(initial_capacity(), Representation::Integer32()); | 
| + AddInstruction(capacity); | 
| + return AllocateArray(size_in_bytes, capacity, NULL, true); | 
| +} | 
| + | 
| + | 
| +HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, | 
| + HValue* capacity, | 
| + HValue* length_field, | 
| + bool fill_with_hole) { | 
| + HValue* context = builder()->environment()->LookupContext(); | 
| + Isolate* isolate = builder()->graph()->isolate(); | 
| 
 
mvstanton
2013/04/15 15:14:49
Hannes: How about for symmetry with BuildCopyObjec
 
mvstanton
2013/04/16 11:48:52
Done. And I continued in this spirit, finding seve
 
 | 
| + | 
| + // Allocate (dealing with failure appropriately) | 
| + HAllocate::Flags flags = HAllocate::CAN_ALLOCATE_IN_NEW_SPACE; | 
| + if (IsFastDoubleElementsKind(kind_)) { | 
| + flags = static_cast<HAllocate::Flags>( | 
| + flags | HAllocate::ALLOCATE_DOUBLE_ALIGNED); | 
| + } | 
| + | 
| + HAllocate* new_object = new(zone()) HAllocate(context, size_in_bytes, | 
| 
 
mvstanton
2013/04/15 15:14:49
Hannes: How about if HAllocate deals with the ALLO
 
mvstanton
2013/04/16 11:48:52
I made a useful helper function to improve this. I
 
 | 
| + HType::JSArray(), flags); | 
| + AddInstruction(new_object); | 
| + | 
| + // Fill in the fields: map, properties, length | 
| + HValue* map = EmitMapCode(context); | 
| + builder()->BuildStoreMap(new_object, map, BailoutId::StubEntry()); | 
| + | 
| + HConstant* empty_fixed_array = | 
| + new(zone()) HConstant( | 
| + Handle<FixedArray>(isolate->heap()->empty_fixed_array()), | 
| + Representation::Tagged()); | 
| + AddInstruction(empty_fixed_array); | 
| + | 
| + AddInstruction(new(zone()) HStoreNamedField(new_object, | 
| + isolate->factory()->properties_field_symbol(), | 
| + empty_fixed_array, | 
| + true, | 
| + JSArray::kPropertiesOffset)); | 
| + AddSimulate(FIXED_SIMULATE); | 
| + | 
| + HValue* zero = builder()->graph()->GetConstant0(); | 
| + HValue* array_length_field = zero; | 
| + if (length_field != NULL) { | 
| + array_length_field = length_field; | 
| + } | 
| + AddInstruction(new(zone()) HStoreNamedField(new_object, | 
| + isolate->factory()->length_field_string(), | 
| + array_length_field, | 
| + true, | 
| + JSArray::kLengthOffset)); | 
| + AddSimulate(FIXED_SIMULATE); | 
| + | 
| + if (mode_ == TRACK_ALLOCATION_SITE) { | 
| 
 
mvstanton
2013/04/15 15:14:49
Hannes: Factor this out to combine with the piece
 
mvstanton
2013/04/16 11:48:52
Done.
 
 | 
| + // Fill in the payload | 
| + HInnerAllocatedObject* allocation_info_site = new(zone()) | 
| + HInnerAllocatedObject(new_object, JSArray::kSize); | 
| + AddInstruction(allocation_info_site); | 
| + builder()->BuildStoreMap(allocation_info_site, | 
| + Handle<Map>(isolate->heap()->allocation_site_info_map()), | 
| + BailoutId::StubEntry()); | 
| + AddInstruction(new(zone()) HStoreNamedField(allocation_info_site, | 
| + isolate->factory()->payload_field_symbol(), | 
| + allocation_site_payload_, | 
| + true, | 
| + AllocationSiteInfo::kPayloadOffset)); | 
| + AddSimulate(FIXED_SIMULATE); | 
| + } | 
| + | 
| + if (length_field == NULL && initial_capacity() == 0) { | 
| + AddInstruction(new(zone()) HStoreNamedField(new_object, | 
| + isolate->factory()->elements_field_string(), | 
| + empty_fixed_array, | 
| + true, | 
| + JSArray::kElementsOffset)); | 
| + AddSimulate(FIXED_SIMULATE); | 
| + } else { | 
| + int elements_location = JSArray::kSize; | 
| + if (mode_ == TRACK_ALLOCATION_SITE) { | 
| + elements_location += AllocationSiteInfo::kSize; | 
| + } | 
| + | 
| + elements_location_ = new(zone()) HInnerAllocatedObject(new_object, | 
| + elements_location); | 
| + AddInstruction(elements_location_); | 
| + | 
| + AddInstruction(new(zone()) HStoreNamedField(new_object, | 
| + isolate->factory()->elements_field_string(), | 
| + elements_location_, | 
| + true, | 
| + JSArray::kElementsOffset)); | 
| + AddSimulate(FIXED_SIMULATE); | 
| + | 
| + // Initialize the elements | 
| + Handle<Map> map_elements = IsFastDoubleElementsKind(kind_) | 
| + ? isolate->factory()->fixed_double_array_map() | 
| + : isolate->factory()->fixed_array_map(); | 
| + builder()->BuildStoreMap(elements_location_, map_elements, | 
| + BailoutId::StubEntry()); | 
| + | 
| + Handle<String> fixed_array_length_field_name = | 
| + isolate->factory()->length_field_string(); | 
| + HInstruction* store_length = | 
| + new(zone()) HStoreNamedField(elements_location_, | 
| + fixed_array_length_field_name, | 
| + capacity, | 
| + true, | 
| + FixedArray::kLengthOffset); | 
| + AddInstruction(store_length); | 
| + AddSimulate(FIXED_SIMULATE); | 
| + | 
| + if (fill_with_hole) { | 
| + FillWithHole(capacity, length_field == NULL); | 
| + } | 
| + } | 
| + | 
| + return new_object; | 
| +} | 
| + | 
| + | 
| +void HGraphBuilder::JSArrayBuilder::FillWithHole(HValue* capacity, | 
| + bool nominally_empty) { | 
| + Isolate* isolate = builder()->graph()->isolate(); | 
| + HValue* context = builder()->environment()->LookupContext(); | 
| + double nan_double = FixedDoubleArray::hole_nan_as_double(); | 
| + HConstant* hole = (IsFastSmiElementsKind(kind_) || | 
| + IsFastObjectElementsKind(kind_)) | 
| 
 
mvstanton
2013/04/15 15:14:49
lines above replace with IsFastDoubleElementsKind(
 
mvstanton
2013/04/16 11:48:52
Done. Actually I could merge this function with an
 
 | 
| + ? new(zone()) HConstant(isolate->factory()->the_hole_value(), | 
| + Representation::Tagged()) | 
| + : new(zone()) HConstant(nan_double, Representation::Double()); | 
| + | 
| + AddInstruction(hole); | 
| + | 
| + static const int kLoopUnfoldLimit = 4; | 
| + if (nominally_empty && initial_capacity() <= kLoopUnfoldLimit) { | 
| 
 
mvstanton
2013/04/15 15:14:49
move kLoopUnfoldLimit up to initial_capacity() def
 
 | 
| + for (int i = 0; i < initial_capacity(); i ++) { | 
| + HInstruction* key; | 
| + if (i == 0) { | 
| + key = graph()->GetConstant0(); | 
| + } else if (i == 1) { | 
| + key = graph()->GetConstant1(); | 
| + } else { | 
| + key = AddInstruction(new(zone()) | 
| + HConstant(i, Representation::Integer32())); | 
| + } | 
| + AddInstruction(new(zone()) HStoreKeyed(elements_location_, key, hole, | 
| + kind_)); | 
| + AddSimulate(REMOVABLE_SIMULATE); | 
| + } | 
| + } else { | 
| + LoopBuilder loop_builder(builder(), | 
| + context, | 
| + LoopBuilder::kPostIncrement); | 
| + HValue* zero = graph()->GetConstant0(); | 
| + HValue* start = zero; | 
| + HValue* key = loop_builder.BeginBody(start, capacity, Token::LT); | 
| + | 
| + AddInstruction(new(zone()) HStoreKeyed(elements_location_, key, hole, | 
| + kind_)); | 
| + AddSimulate(REMOVABLE_SIMULATE); | 
| + loop_builder.EndBody(); | 
| + } | 
| +} | 
| + | 
| + | 
| HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, | 
| TypeFeedbackOracle* oracle) | 
| : HGraphBuilder(info), |