Revision: 11243
Author:   [email protected]
Date:     Thu Apr  5 08:36:31 2012
Log:      Ensure HAllocateObject always allocates in new-space.

This is needed so that we can start removing write-barriers in optimized
code if we can prove that the receiver object is always in new-space.

TEST=cctest/test-heap/OptimizedAllocationAlwaysInNewSpace

Review URL: https://chromiumcodereview.appspot.com/10008007
http://code.google.com/p/v8/source/detail?r=11243

Modified:
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/hydrogen-instructions.h
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc
 /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
 /branches/bleeding_edge/test/cctest/test-heap.cc

=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Fri Mar 23 09:37:54 2012 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Thu Apr 5 08:36:31 2012
@@ -4471,6 +4471,14 @@
                         scratch2,
                         deferred->entry(),
                         TAG_OBJECT);
+
+  __ bind(deferred->exit());
+  if (FLAG_debug_code) {
+    Label is_in_new_space;
+    __ JumpIfInNewSpace(result, scratch, &is_in_new_space);
+    __ Abort("Allocated object is not in new-space");
+    __ bind(&is_in_new_space);
+  }

   // Load the initial map.
   Register map = scratch;
@@ -4490,14 +4498,14 @@
       __ str(scratch, FieldMemOperand(result, property_offset));
     }
   }
-
-  __ bind(deferred->exit());
 }


 void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
   Register result = ToRegister(instr->result());
   Handle<JSFunction> constructor = instr->hydrogen()->constructor();
+  Handle<Map> initial_map(constructor->initial_map());
+  int instance_size = initial_map->instance_size();

   // TODO(3095996): Get rid of this. For now, we need to make the
   // result register contain a valid pointer because it is already
@@ -4505,9 +4513,9 @@
   __ mov(result, Operand(0));

   PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
-  __ LoadHeapObject(r0, constructor);
+  __ mov(r0, Operand(Smi::FromInt(instance_size)));
   __ push(r0);
-  CallRuntimeFromDeferred(Runtime::kNewObject, 1, instr);
+  CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
   __ StoreToSafepointRegisterSlot(r0, result);
 }

=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Fri Mar 30 06:22:39 2012 +++ /branches/bleeding_edge/src/hydrogen-instructions.h Thu Apr 5 08:36:31 2012
@@ -4405,6 +4405,9 @@
     SetOperandAt(0, context);
     set_representation(Representation::Tagged());
   }
+
+  // Maximum instance size for which allocations will be inlined.
+  static const int kMaxSize = 64 * kPointerSize;

   HValue* context() { return OperandAt(0); }
   Handle<JSFunction> constructor() { return constructor_; }
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Thu Apr  5 06:24:52 2012
+++ /branches/bleeding_edge/src/hydrogen.cc     Thu Apr  5 08:36:31 2012
@@ -6048,7 +6048,8 @@
 // Checks whether allocation using the given constructor can be inlined.
 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
   return constructor->has_initial_map() &&
-      constructor->initial_map()->instance_type() == JS_OBJECT_TYPE;
+      constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
+ constructor->initial_map()->instance_size() < HAllocateObject::kMaxSize;
 }


=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Fri Mar 23 09:37:54 2012 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Thu Apr 5 08:36:31 2012
@@ -4305,6 +4305,14 @@
                         scratch,
                         deferred->entry(),
                         TAG_OBJECT);
+
+  __ bind(deferred->exit());
+  if (FLAG_debug_code) {
+    Label is_in_new_space;
+    __ JumpIfInNewSpace(result, scratch, &is_in_new_space);
+    __ Abort("Allocated object is not in new-space");
+    __ bind(&is_in_new_space);
+  }

   // Load the initial map.
   Register map = scratch;
@@ -4340,14 +4348,14 @@
       __ mov(FieldOperand(result, property_offset), scratch);
     }
   }
-
-  __ bind(deferred->exit());
 }


 void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
   Register result = ToRegister(instr->result());
   Handle<JSFunction> constructor = instr->hydrogen()->constructor();
+  Handle<Map> initial_map(constructor->initial_map());
+  int instance_size = initial_map->instance_size();

   // TODO(3095996): Get rid of this. For now, we need to make the
   // result register contain a valid pointer because it is already
@@ -4355,8 +4363,9 @@
   __ Set(result, Immediate(0));

   PushSafepointRegistersScope scope(this);
-  __ PushHeapObject(constructor);
-  CallRuntimeFromDeferred(Runtime::kNewObject, 1, instr, instr->context());
+  __ push(Immediate(Smi::FromInt(instance_size)));
+  CallRuntimeFromDeferred(
+      Runtime::kAllocateInNewSpace, 1, instr, instr->context());
   __ StoreToSafepointRegisterSlot(result, eax);
 }

=======================================
--- /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Wed Mar 28 05:44:04 2012 +++ /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Thu Apr 5 08:36:31 2012
@@ -4366,6 +4366,14 @@
                         scratch2,
                         deferred->entry(),
                         TAG_OBJECT);
+
+  __ bind(deferred->exit());
+  if (FLAG_debug_code) {
+    Label is_in_new_space;
+    __ JumpIfInNewSpace(result, scratch, &is_in_new_space);
+    __ Abort("Allocated object is not in new-space");
+    __ bind(&is_in_new_space);
+  }

   // Load the initial map.
   Register map = scratch;
@@ -4385,14 +4393,14 @@
       __ sw(scratch, FieldMemOperand(result, property_offset));
     }
   }
-
-  __ bind(deferred->exit());
 }


 void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
   Register result = ToRegister(instr->result());
   Handle<JSFunction> constructor = instr->hydrogen()->constructor();
+  Handle<Map> initial_map(constructor->initial_map());
+  int instance_size = initial_map->instance_size();

   // TODO(3095996): Get rid of this. For now, we need to make the
   // result register contain a valid pointer because it is already
@@ -4400,9 +4408,9 @@
   __ mov(result, zero_reg);

   PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
-  __ LoadHeapObject(a0, constructor);
+  __ li(a0, Operand(Smi::FromInt(instance_size)));
   __ push(a0);
-  CallRuntimeFromDeferred(Runtime::kNewObject, 1, instr);
+  CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
   __ StoreToSafepointRegisterSlot(v0, result);
 }

=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Fri Mar 23 09:37:54 2012 +++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Thu Apr 5 08:36:31 2012
@@ -4079,6 +4079,14 @@
                         scratch,
                         deferred->entry(),
                         TAG_OBJECT);
+
+  __ bind(deferred->exit());
+  if (FLAG_debug_code) {
+    Label is_in_new_space;
+    __ JumpIfInNewSpace(result, scratch, &is_in_new_space);
+    __ Abort("Allocated object is not in new-space");
+    __ bind(&is_in_new_space);
+  }

   // Load the initial map.
   Register map = scratch;
@@ -4114,14 +4122,14 @@
       __ movq(FieldOperand(result, property_offset), scratch);
     }
   }
-
-  __ bind(deferred->exit());
 }


 void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
   Register result = ToRegister(instr->result());
   Handle<JSFunction> constructor = instr->hydrogen()->constructor();
+  Handle<Map> initial_map(constructor->initial_map());
+  int instance_size = initial_map->instance_size();

   // TODO(3095996): Get rid of this. For now, we need to make the
   // result register contain a valid pointer because it is already
@@ -4129,8 +4137,8 @@
   __ Set(result, 0);

   PushSafepointRegistersScope scope(this);
-  __ PushHeapObject(constructor);
-  CallRuntimeFromDeferred(Runtime::kNewObject, 1, instr);
+  __ Push(Smi::FromInt(instance_size));
+  CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
   __ StoreToSafepointRegisterSlot(result, rax);
 }

=======================================
--- /branches/bleeding_edge/test/cctest/test-heap.cc Tue Apr 3 10:22:05 2012 +++ /branches/bleeding_edge/test/cctest/test-heap.cc Thu Apr 5 08:36:31 2012
@@ -1264,9 +1264,9 @@
   v8::HandleScope scope;
   AlwaysAllocateScope always_allocate;
   intptr_t available = new_space->EffectiveCapacity() - new_space->Size();
- intptr_t number_of_fillers = (available / FixedArray::SizeFor(1000)) - 10;
+  intptr_t number_of_fillers = (available / FixedArray::SizeFor(32)) - 1;
   for (intptr_t i = 0; i < number_of_fillers; i++) {
-    CHECK(HEAP->InNewSpace(*FACTORY->NewFixedArray(1000, NOT_TENURED)));
+    CHECK(HEAP->InNewSpace(*FACTORY->NewFixedArray(32, NOT_TENURED)));
   }
 }

@@ -1680,3 +1680,33 @@
   CHECK_EQ(0, f->shared()->opt_count());
   CHECK_EQ(0, f->shared()->code()->profiler_ticks());
 }
+
+
+// Test that HAllocateObject will always return an object in new-space.
+TEST(OptimizedAllocationAlwaysInNewSpace) {
+  i::FLAG_allow_natives_syntax = true;
+  InitializeVM();
+  if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return;
+  v8::HandleScope scope;
+
+  FillUpNewSpace(HEAP->new_space());
+  AlwaysAllocateScope always_allocate;
+  v8::Local<v8::Value> res = CompileRun(
+      "function c(x) {"
+      "  this.x = x;"
+      "  for (var i = 0; i < 32; i++) {"
+      "    this['x' + i] = x;"
+      "  }"
+      "}"
+      "function f(x) { return new c(x); };"
+      "f(1); f(2); f(3);"
+      "%OptimizeFunctionOnNextCall(f);"
+      "f(4);");
+  CHECK(res->IsObject());
+ CHECK(res->ToObject()->GetRealNamedProperty(v8_str("x"))->Int32Value() == 4);
+
+  Handle<JSObject> o =
+      v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
+
+  CHECK(HEAP->InNewSpace(*o));
+}

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to