Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(222)

Unified Diff: src/hydrogen.cc

Issue 12880017: Build fast literals in hydrogen. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);
« src/hydrogen.h ('K') | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698