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.


Reply via email to