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), |