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