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