Revision: 15306
Author: [email protected]
Date: Tue Jun 25 00:47:53 2013
Log: Added pretenuring support for fast literal allocation in old data
space.
BUG=
[email protected]
Review URL: https://codereview.chromium.org/17580011
http://code.google.com/p/v8/source/detail?r=15306
Modified:
/branches/bleeding_edge/src/hydrogen.cc
/branches/bleeding_edge/src/hydrogen.h
/branches/bleeding_edge/test/cctest/test-heap.cc
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc Mon Jun 24 07:34:07 2013
+++ /branches/bleeding_edge/src/hydrogen.cc Tue Jun 25 00:47:53 2013
@@ -9940,28 +9940,46 @@
int pointer_size,
AllocationSiteMode mode) {
Zone* zone = this->zone();
- int total_size = data_size + pointer_size;
-
NoObservableSideEffectsScope no_effects(this);
- HAllocate::Flags flags = HAllocate::CAN_ALLOCATE_IN_NEW_SPACE;
- // TODO(hpayer): add support for old data space
- if (isolate()->heap()->ShouldGloballyPretenure() &&
- data_size == 0) {
- flags = static_cast<HAllocate::Flags>(
- flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
+ HInstruction* target = NULL;
+ HInstruction* data_target = NULL;
+
+ HAllocate::Flags flags = HAllocate::DefaultFlags();
+
+ if (isolate()->heap()->ShouldGloballyPretenure()) {
+ if (data_size != 0) {
+ HAllocate::Flags data_flags =
+ static_cast<HAllocate::Flags>(HAllocate::DefaultFlags() |
+ HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE);
+ HValue* size_in_bytes = AddInstruction(new(zone)
HConstant(data_size));
+ data_target = AddInstruction(new(zone) HAllocate(
+ context, size_in_bytes, HType::JSObject(), data_flags));
+ Handle<Map> free_space_map = isolate()->factory()->free_space_map();
+ AddStoreMapConstant(data_target, free_space_map);
+ HObjectAccess access =
+ HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset);
+ AddStore(data_target, access, size_in_bytes);
+ }
+ if (pointer_size != 0) {
+ flags = static_cast<HAllocate::Flags>(
+ flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
+ HValue* size_in_bytes = AddInstruction(new(zone)
HConstant(pointer_size));
+ target = AddInstruction(new(zone) HAllocate(context,
+ size_in_bytes, HType::JSObject(), flags));
+ }
+ } else {
+ HValue* size_in_bytes =
+ AddInstruction(new(zone) HConstant(data_size + pointer_size));
+ target = AddInstruction(new(zone) HAllocate(context, size_in_bytes,
+ HType::JSObject(), flags));
}
- HValue* size_in_bytes = AddInstruction(new(zone) HConstant(total_size));
- HInstruction* result =
- AddInstruction(new(zone) HAllocate(context,
- size_in_bytes,
- HType::JSObject(),
- flags));
int offset = 0;
- BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object,
result,
- &offset, mode);
- return result;
+ int data_offset = 0;
+ BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object,
target,
+ &offset, data_target, &data_offset, mode);
+ return target;
}
@@ -9970,6 +9988,8 @@
Handle<JSObject> original_boilerplate_object,
HInstruction* target,
int* offset,
+ HInstruction* data_target,
+ int* data_offset,
AllocationSiteMode mode) {
Zone* zone = this->zone();
@@ -9978,30 +9998,38 @@
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 elements_offset = 0;
- *offset += object_size + elements_size;
+ if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) {
+ elements_offset = *data_offset;
+ *data_offset += elements_size;
+ } else {
+ // Place elements right after this object.
+ elements_offset = *offset + object_size;
+ *offset += elements_size;
+ }
+ // Increase the offset so that subsequent objects end up right after this
+ // object (and it's elements if they are allocated in the same space).
+ *offset += object_size;
// Copy object elements if non-COW.
HValue* object_elements = BuildEmitObjectHeader(boilerplate_object,
target,
- object_offset, elements_offset, elements_size);
+ data_target, object_offset, elements_offset, elements_size);
if (object_elements != NULL) {
BuildEmitElements(elements, original_elements, kind, object_elements,
- target, offset);
+ target, offset, data_target, data_offset);
}
// Copy in-object properties.
HValue* object_properties =
AddInstruction(new(zone) HInnerAllocatedObject(target,
object_offset));
BuildEmitInObjectProperties(boilerplate_object,
original_boilerplate_object,
- object_properties, target, offset);
+ object_properties, target, offset, data_target, data_offset);
// Create allocation site info.
if (mode == TRACK_ALLOCATION_SITE &&
@@ -10018,6 +10046,7 @@
HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader(
Handle<JSObject> boilerplate_object,
HInstruction* target,
+ HInstruction* data_target,
int object_offset,
int elements_offset,
int elements_size) {
@@ -10036,8 +10065,13 @@
Handle<Object>(boilerplate_object->elements(), isolate());
elements = AddInstruction(new(zone) HConstant(elements_field));
} else {
- elements = AddInstruction(new(zone) HInnerAllocatedObject(
- target, elements_offset));
+ if (data_target != NULL &&
boilerplate_object->HasFastDoubleElements()) {
+ elements = AddInstruction(new(zone) HInnerAllocatedObject(
+ data_target, elements_offset));
+ } else {
+ elements = AddInstruction(new(zone) HInnerAllocatedObject(
+ target, elements_offset));
+ }
result = elements;
}
AddStore(object_header, HObjectAccess::ForElementsPointer(), elements);
@@ -10074,7 +10108,9 @@
Handle<JSObject> original_boilerplate_object,
HValue* object_properties,
HInstruction* target,
- int* offset) {
+ int* offset,
+ HInstruction* data_target,
+ int* data_offset) {
Zone* zone = this->zone();
Handle<DescriptorArray> descriptors(
boilerplate_object->map()->instance_descriptors());
@@ -10108,7 +10144,7 @@
AddStore(object_properties, access, value_instruction);
BuildEmitDeepCopy(value_object, original_value_object, target,
- offset, DONT_TRACK_ALLOCATION_SITE);
+ offset, data_target, data_offset, DONT_TRACK_ALLOCATION_SITE);
} else {
Representation representation = details.representation();
HInstruction* value_instruction =
@@ -10116,14 +10152,21 @@
if (representation.IsDouble()) {
// Allocate a HeapNumber box and store the value into it.
- HInstruction* double_box =
- AddInstruction(new(zone) HInnerAllocatedObject(target,
*offset));
+ HInstruction* double_box;
+ if (data_target != NULL) {
+ double_box = AddInstruction(new(zone) HInnerAllocatedObject(
+ data_target, *data_offset));
+ *data_offset += HeapNumber::kSize;
+ } else {
+ double_box = AddInstruction(new(zone) HInnerAllocatedObject(
+ target, *offset));
+ *offset += HeapNumber::kSize;
+ }
AddStoreMapConstant(double_box,
isolate()->factory()->heap_number_map());
AddStore(double_box, HObjectAccess::ForHeapNumberValue(),
value_instruction, Representation::Double());
value_instruction = double_box;
- *offset += HeapNumber::kSize;
}
AddStore(object_properties, access, value_instruction);
@@ -10148,7 +10191,9 @@
ElementsKind kind,
HValue* object_elements,
HInstruction* target,
- int* offset) {
+ int* offset,
+ HInstruction* data_target,
+ int* data_offset) {
Zone* zone = this->zone();
int elements_length = elements->length();
@@ -10162,7 +10207,7 @@
BuildEmitFixedDoubleArray(elements, kind, object_elements);
} else if (elements->IsFixedArray()) {
BuildEmitFixedArray(elements, original_elements, kind, object_elements,
- target, offset);
+ target, offset, data_target, data_offset);
} else {
UNREACHABLE();
}
@@ -10195,7 +10240,9 @@
ElementsKind kind,
HValue* object_elements,
HInstruction* target,
- int* offset) {
+ int* offset,
+ HInstruction* data_target,
+ int* data_offset) {
Zone* zone = this->zone();
HInstruction* boilerplate_elements =
AddInstruction(new(zone) HConstant(elements));
@@ -10215,7 +10262,7 @@
AddInstruction(new(zone) HStoreKeyed(
object_elements, key_constant, value_instruction, kind));
BuildEmitDeepCopy(value_object, original_value_object, target,
- offset, DONT_TRACK_ALLOCATION_SITE);
+ offset, data_target, data_offset, DONT_TRACK_ALLOCATION_SITE);
} else {
HInstruction* value_instruction =
AddInstruction(new(zone) HLoadKeyed(
=======================================
--- /branches/bleeding_edge/src/hydrogen.h Mon Jun 24 07:34:07 2013
+++ /branches/bleeding_edge/src/hydrogen.h Tue Jun 25 00:47:53 2013
@@ -1828,13 +1828,16 @@
void BuildEmitDeepCopy(Handle<JSObject> boilerplat_object,
Handle<JSObject> object,
- HInstruction* result,
+ HInstruction* target,
int* offset,
+ HInstruction* data_target,
+ int* data_offset,
AllocationSiteMode mode);
MUST_USE_RESULT HValue* BuildEmitObjectHeader(
Handle<JSObject> boilerplat_object,
HInstruction* target,
+ HInstruction* data_target,
int object_offset,
int elements_offset,
int elements_size);
@@ -1843,14 +1846,18 @@
Handle<JSObject>
original_boilerplate_object,
HValue* object_properties,
HInstruction* target,
- int* offset);
+ int* offset,
+ HInstruction* data_target,
+ int* data_offset);
void BuildEmitElements(Handle<FixedArrayBase> elements,
Handle<FixedArrayBase> original_elements,
ElementsKind kind,
HValue* object_elements,
HInstruction* target,
- int* offset);
+ int* offset,
+ HInstruction* data_target,
+ int* data_offset);
void BuildEmitFixedDoubleArray(Handle<FixedArrayBase> elements,
ElementsKind kind,
@@ -1861,7 +1868,9 @@
ElementsKind kind,
HValue* object_elements,
HInstruction* target,
- int* offset);
+ int* offset,
+ HInstruction* data_target,
+ int* data_offset);
void AddCheckPrototypeMaps(Handle<JSObject> holder,
Handle<Map> receiver_map);
=======================================
--- /branches/bleeding_edge/test/cctest/test-heap.cc Thu Jun 20 03:48:14
2013
+++ /branches/bleeding_edge/test/cctest/test-heap.cc Tue Jun 25 00:47:53
2013
@@ -2109,8 +2109,7 @@
}
-// Test pretenuring of array literals allocated with HAllocate.
-TEST(OptimizedPretenuringArrayLiterals) {
+TEST(OptimizedPretenuringObjectArrayLiterals) {
i::FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return;
@@ -2118,11 +2117,9 @@
v8::HandleScope scope(CcTest::isolate());
HEAP->SetNewSpaceHighPromotionModeActive(true);
- AlwaysAllocateScope always_allocate;
v8::Local<v8::Value> res = CompileRun(
"function f() {"
- " var numbers = [1, 2, 3];"
- " numbers[0] = {};"
+ " var numbers = [{}, {}, {}];"
" return numbers;"
"};"
"f(); f(); f();"
@@ -2133,21 +2130,22 @@
v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
CHECK(HEAP->InOldPointerSpace(o->elements()));
+ CHECK(HEAP->InOldPointerSpace(*o));
}
-TEST(OptimizedPretenuringSimpleArrayLiterals) {
+TEST(OptimizedPretenuringMixedInObjectProperties) {
i::FLAG_allow_natives_syntax = true;
- i::FLAG_pretenuring = false;
CcTest::InitializeVM();
if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
+ HEAP->SetNewSpaceHighPromotionModeActive(true);
- AlwaysAllocateScope always_allocate;
v8::Local<v8::Value> res = CompileRun(
"function f() {"
- " return [1, 2, 3];"
+ " var numbers = {a: {c: 2.2, d: {}}, b: 1.1};"
+ " return numbers;"
"};"
"f(); f(); f();"
"%OptimizeFunctionOnNextCall(f);"
@@ -2156,7 +2154,168 @@
Handle<JSObject> o =
v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
- CHECK(HEAP->InNewSpace(*o));
+ CHECK(HEAP->InOldPointerSpace(*o));
+ CHECK(HEAP->InOldPointerSpace(o->RawFastPropertyAt(0)));
+ CHECK(HEAP->InOldDataSpace(o->RawFastPropertyAt(1)));
+
+ JSObject* inner_object =
reinterpret_cast<JSObject*>(o->RawFastPropertyAt(0));
+ CHECK(HEAP->InOldPointerSpace(inner_object));
+ CHECK(HEAP->InOldDataSpace(inner_object->RawFastPropertyAt(0)));
+ CHECK(HEAP->InOldPointerSpace(inner_object->RawFastPropertyAt(1)));
+}
+
+
+TEST(OptimizedPretenuringDoubleArrayProperties) {
+ i::FLAG_allow_natives_syntax = true;
+ CcTest::InitializeVM();
+ if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return;
+ if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
+ v8::HandleScope scope(CcTest::isolate());
+ HEAP->SetNewSpaceHighPromotionModeActive(true);
+
+ v8::Local<v8::Value> res = CompileRun(
+ "function f() {"
+ " var numbers = {a: 1.1, b: 2.2};"
+ " return numbers;"
+ "};"
+ "f(); f(); f();"
+ "%OptimizeFunctionOnNextCall(f);"
+ "f();");
+
+ Handle<JSObject> o =
+ v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
+
+ CHECK(HEAP->InOldPointerSpace(*o));
+ CHECK(HEAP->InOldDataSpace(o->properties()));
+}
+
+
+TEST(OptimizedPretenuringdoubleArrayLiterals) {
+ i::FLAG_allow_natives_syntax = true;
+ CcTest::InitializeVM();
+ if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return;
+ if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
+ v8::HandleScope scope(CcTest::isolate());
+ HEAP->SetNewSpaceHighPromotionModeActive(true);
+
+ v8::Local<v8::Value> res = CompileRun(
+ "function f() {"
+ " var numbers = [1.1, 2.2, 3.3];"
+ " return numbers;"
+ "};"
+ "f(); f(); f();"
+ "%OptimizeFunctionOnNextCall(f);"
+ "f();");
+
+ Handle<JSObject> o =
+ v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
+
+ CHECK(HEAP->InOldDataSpace(o->elements()));
+ CHECK(HEAP->InOldPointerSpace(*o));
+}
+
+
+TEST(OptimizedPretenuringNestedMixedArrayLiterals) {
+ i::FLAG_allow_natives_syntax = true;
+ CcTest::InitializeVM();
+ if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return;
+ if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
+ v8::HandleScope scope(CcTest::isolate());
+ HEAP->SetNewSpaceHighPromotionModeActive(true);
+
+ v8::Local<v8::Value> res = CompileRun(
+ "function f() {"
+ " var numbers = [[{}, {}, {}],[1.1, 2.2, 3.3]];"
+ " return numbers;"
+ "};"
+ "f(); f(); f();"
+ "%OptimizeFunctionOnNextCall(f);"
+ "f();");
+
+ v8::Local<v8::Value> int_array =
v8::Object::Cast(*res)->Get(v8_str("0"));
+ Handle<JSObject> int_array_handle =
+ v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(int_array));
+ v8::Local<v8::Value> double_array =
v8::Object::Cast(*res)->Get(v8_str("1"));
+ Handle<JSObject> double_array_handle =
+ v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(double_array));
+
+ Handle<JSObject> o =
+ v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
+ CHECK(HEAP->InOldPointerSpace(*o));
+ CHECK(HEAP->InOldPointerSpace(*int_array_handle));
+ CHECK(HEAP->InOldPointerSpace(int_array_handle->elements()));
+ CHECK(HEAP->InOldPointerSpace(*double_array_handle));
+ CHECK(HEAP->InOldDataSpace(double_array_handle->elements()));
+}
+
+
+TEST(OptimizedPretenuringNestedObjectLiterals) {
+ i::FLAG_allow_natives_syntax = true;
+ CcTest::InitializeVM();
+ if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return;
+ if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
+ v8::HandleScope scope(CcTest::isolate());
+ HEAP->SetNewSpaceHighPromotionModeActive(true);
+
+ v8::Local<v8::Value> res = CompileRun(
+ "function f() {"
+ " var numbers = [[{}, {}, {}],[{}, {}, {}]];"
+ " return numbers;"
+ "};"
+ "f(); f(); f();"
+ "%OptimizeFunctionOnNextCall(f);"
+ "f();");
+
+ v8::Local<v8::Value> int_array_1 =
v8::Object::Cast(*res)->Get(v8_str("0"));
+ Handle<JSObject> int_array_handle_1 =
+ v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(int_array_1));
+ v8::Local<v8::Value> int_array_2 =
v8::Object::Cast(*res)->Get(v8_str("1"));
+ Handle<JSObject> int_array_handle_2 =
+ v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(int_array_2));
+
+ Handle<JSObject> o =
+ v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
+ CHECK(HEAP->InOldPointerSpace(*o));
+ CHECK(HEAP->InOldPointerSpace(*int_array_handle_1));
+ CHECK(HEAP->InOldPointerSpace(int_array_handle_1->elements()));
+ CHECK(HEAP->InOldPointerSpace(*int_array_handle_2));
+ CHECK(HEAP->InOldPointerSpace(int_array_handle_2->elements()));
+}
+
+
+TEST(OptimizedPretenuringNestedDoubleLiterals) {
+ i::FLAG_allow_natives_syntax = true;
+ CcTest::InitializeVM();
+ if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return;
+ if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
+ v8::HandleScope scope(CcTest::isolate());
+ HEAP->SetNewSpaceHighPromotionModeActive(true);
+
+ v8::Local<v8::Value> res = CompileRun(
+ "function f() {"
+ " var numbers = [[1.1, 1.2, 1.3],[2.1, 2.2, 2.3]];"
+ " return numbers;"
+ "};"
+ "f(); f(); f();"
+ "%OptimizeFunctionOnNextCall(f);"
+ "f();");
+
+ v8::Local<v8::Value> double_array_1 =
+ v8::Object::Cast(*res)->Get(v8_str("0"));
+ Handle<JSObject> double_array_handle_1 =
+ v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(double_array_1));
+ v8::Local<v8::Value> double_array_2 =
+ v8::Object::Cast(*res)->Get(v8_str("1"));
+ Handle<JSObject> double_array_handle_2 =
+ v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(double_array_2));
+
+ Handle<JSObject> o =
+ v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
+ CHECK(HEAP->InOldPointerSpace(*o));
+ CHECK(HEAP->InOldPointerSpace(*double_array_handle_1));
+ CHECK(HEAP->InOldDataSpace(double_array_handle_1->elements()));
+ CHECK(HEAP->InOldPointerSpace(*double_array_handle_2));
+ CHECK(HEAP->InOldDataSpace(double_array_handle_2->elements()));
}
@@ -2168,7 +2327,6 @@
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
- AlwaysAllocateScope always_allocate;
v8::Local<v8::Value> res = CompileRun(
"function f() {"
" var numbers = new Array(1, 2, 3);"
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.