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

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, 8 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
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 476317cae842c6aef80513a1592b1ef3441d7226..d9d1a68d0fb33db1086e4b2c8bab6a34c6c4ce53 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -6182,33 +6182,38 @@ 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;
- Handle<Object> boilerplate(closure->literals()->get(expr->literal_index()),
- isolate());
- if (boilerplate->IsJSObject() &&
- IsFastLiteral(Handle<JSObject>::cast(boilerplate),
- HFastLiteral::kMaxLiteralDepth,
+ int max_properties = kMaxFastLiteralProperties;
+ Handle<Object> original_boilerplate(closure->literals()->get(
+ expr->literal_index()), isolate());
+ if (original_boilerplate->IsJSObject() &&
+ IsFastLiteral(Handle<JSObject>::cast(original_boilerplate),
+ kMaxFastLiteralDepth,
&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);
+ Handle<JSObject> original_boilerplate_object =
+ Handle<JSObject>::cast(original_boilerplate);
+ Handle<JSObject> boilerplate_object =
+ DeepCopy(original_boilerplate_object);
+
+ literal = BuildFastLiteral(context,
+ boilerplate_object,
+ original_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());
@@ -6305,9 +6310,10 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
}
}
- Handle<JSObject> boilerplate = Handle<JSObject>::cast(raw_boilerplate);
+ Handle<JSObject> original_boilerplate_object =
+ Handle<JSObject>::cast(raw_boilerplate);
ElementsKind boilerplate_elements_kind =
- Handle<JSObject>::cast(boilerplate)->GetElementsKind();
+ Handle<JSObject>::cast(original_boilerplate_object)->GetElementsKind();
// TODO(mvstanton): This heuristic is only a temporary solution. In the
// end, we want to quit creating allocation site info after a certain number
@@ -6317,32 +6323,35 @@ 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;
- if (IsFastLiteral(boilerplate,
- HFastLiteral::kMaxLiteralDepth,
+ int max_properties = kMaxFastLiteralProperties;
+ if (IsFastLiteral(original_boilerplate_object,
+ kMaxFastLiteralDepth,
&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);
+
+ Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object);
+ literal = BuildFastLiteral(context,
+ boilerplate_object,
+ original_boilerplate_object,
+ 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,
+ original_boilerplate_object,
+ 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;
@@ -10081,6 +10090,240 @@ HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
}
+HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
+ HValue* context,
+ Handle<JSObject> boilerplate_object,
+ Handle<JSObject> original_boilerplate_object,
+ int size,
+ AllocationSiteMode mode,
+ BailoutId id) {
+ Zone* zone = this->zone();
+
+ HValue* size_in_bytes =
+ AddInstruction(new(zone) HConstant(size, Representation::Integer32()));
+ HInstruction* result =
+ AddInstruction(new(zone) HAllocate(context,
+ size_in_bytes,
+ HType::JSObject(),
+ HAllocate::CAN_ALLOCATE_IN_NEW_SPACE));
+ int offset = 0;
+ BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, result,
+ &offset, mode, id);
+ ASSERT_EQ(size, offset);
+ return result;
+}
+
+
+void HOptimizedGraphBuilder::BuildEmitDeepCopy(
+ Handle<JSObject> boilerplate_object,
+ Handle<JSObject> original_boilerplate_object,
+ HInstruction* target,
+ int* offset,
+ AllocationSiteMode mode,
+ BailoutId id) {
+ Zone* zone = this->zone();
+ Factory* factory = isolate()->factory();
+
+ HInstruction* original_boilerplate = AddInstruction(new(zone) HConstant(
+ original_boilerplate_object, Representation::Tagged()));
+
+ bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE &&
+ boilerplate_object->map()->CanTrackAllocationSite();
+
+ // Only elements backing stores for non-COW arrays need to be copied.
+ Handle<FixedArrayBase> elements(boilerplate_object->elements());
+ Handle<FixedArrayBase> original_elements(
+ original_boilerplate_object->elements());
+ ElementsKind kind = boilerplate_object->map()->elements_kind();
+
+ // Increase the offset so that subsequent objects end up right after
+ // this object and its backing store.
+ int object_offset = *offset;
+ int object_size = boilerplate_object->map()->instance_size();
+ int elements_size = (elements->length() > 0 &&
+ 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;
+ }
+
+ *offset += object_size + elements_size;
+
+ HValue* object_elements = BuildCopyObjectHeader(boilerplate_object, target,
+ object_offset, elements_offset, elements_size, id);
+
+ // Copy in-object properties.
+ HValue* object_properties =
+ AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset));
+ for (int i = 0; i < inobject_properties; i++) {
+ Handle<Object> value =
+ Handle<Object>(boilerplate_object->InObjectPropertyAt(i),
+ 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),
+ isolate()));
+ HInstruction* value_instruction =
+ AddInstruction(new(zone) HInnerAllocatedObject(target, *offset));
+ AddInstruction(new(zone) HStoreNamedField(
+ object_properties, factory->unknown_field_string(), value_instruction,
+ true, boilerplate_object->GetInObjectPropertyOffset(i)));
+ AddSimulate(id);
+ BuildEmitDeepCopy(value_object, original_value_object, target,
+ offset, DONT_TRACK_ALLOCATION_SITE, id);
+ } else {
+ HInstruction* value_instruction = AddInstruction(new(zone) HConstant(
+ value, Representation::Tagged()));
+ AddInstruction(new(zone) HStoreNamedField(
+ object_properties, factory->unknown_field_string(), value_instruction,
+ true, boilerplate_object->GetInObjectPropertyOffset(i)));
+ AddSimulate(id);
+ }
+ }
+
+ // Build Allocation Site Info if desired
+ if (create_allocation_site_info) {
+ HValue* alloc_site =
+ AddInstruction(new(zone) HInnerAllocatedObject(target, 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->payload_string(),
+ original_boilerplate,
+ true, alloc_payload_offset));
+ AddSimulate(id);
+ }
+
+ if (object_elements != NULL) {
+ HInstruction* boilerplate_elements = AddInstruction(new(zone) HConstant(
+ elements, Representation::Tagged()));
+
+ int elements_length = elements->length();
+ HValue* object_elements_length =
+ AddInstruction(new(zone) HConstant(
+ elements_length, Representation::Integer32()));
+
+ BuildInitializeElements(object_elements, kind, object_elements_length);
+
+ // Copy elements backing store content.
+ 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);
+ Handle<FixedArray> original_fast_elements =
+ Handle<FixedArray>::cast(original_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);
+ Handle<JSObject> original_value_object = Handle<JSObject>::cast(
+ Handle<Object>(original_fast_elements->get(i), isolate()));
+ HInstruction* value_instruction =
+ AddInstruction(new(zone) HInnerAllocatedObject(target, *offset));
+ AddInstruction(new(zone) HStoreKeyed(
+ object_elements, key_constant, value_instruction, kind));
+ AddSimulate(id);
+ BuildEmitDeepCopy(value_object, original_value_object, target,
+ 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();
+ }
+ }
+}
+
+
+HValue* HOptimizedGraphBuilder::BuildCopyObjectHeader(
+ Handle<JSObject> boilerplate_object,
+ HInstruction* target,
+ int object_offset,
+ int elements_offset,
+ int elements_size,
+ BailoutId id) {
+ ASSERT(boilerplate_object->properties()->length() == 0);
+ Zone* zone = this->zone();
+ Factory* factory = isolate()->factory();
+ HValue* result = NULL;
+
+ HValue* object_header =
+ AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset));
+ Handle<Map> boilerplate_object_map(boilerplate_object->map());
+ BuildStoreMap(object_header, boilerplate_object_map, id);
+
+ HInstruction* elements;
+ if (elements_size == 0) {
+ Handle<Object> elements_field =
+ Handle<Object>(boilerplate_object->elements(), isolate());
+ elements = AddInstruction(new(zone) HConstant(
+ elements_field, Representation::Tagged()));
+ } else {
+ elements = AddInstruction(new(zone) HInnerAllocatedObject(
+ target, elements_offset));
+ result = elements;
+ }
+ HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField(
+ object_header,
+ factory->elements_field_string(),
+ elements,
+ true, JSObject::kElementsOffset));
+ elements_store->SetGVNFlag(kChangesElementsPointer);
+ AddSimulate(id);
+
+ Handle<Object> properties_field =
+ Handle<Object>(boilerplate_object->properties(), isolate());
+ ASSERT(*properties_field == isolate()->heap()->empty_fixed_array());
+ HInstruction* properties = AddInstruction(new(zone) HConstant(
+ properties_field, Representation::None()));
+ AddInstruction(new(zone) HStoreNamedField(object_header,
+ factory->empty_string(),
+ properties,
+ true, JSObject::kPropertiesOffset));
+ AddSimulate(id);
+
+ if (boilerplate_object->IsJSArray()) {
+ Handle<JSArray> boilerplate_array =
+ Handle<JSArray>::cast(boilerplate_object);
+ Handle<Object> length_field =
+ Handle<Object>(boilerplate_array->length(), isolate());
+ HInstruction* length = AddInstruction(new(zone) HConstant(
+ length_field, Representation::None()));
+ HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField(
+ object_header,
+ factory->length_field_string(),
+ length,
+ true, JSArray::kLengthOffset));
+ length_store->SetGVNFlag(kChangesArrayLengths);
+ AddSimulate(id);
+ }
+
+ return result;
+}
+
+
void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698