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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11243 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 581e9368
......@@ -4472,6 +4472,14 @@ void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
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;
__ LoadHeapObject(map, constructor);
......@@ -4490,14 +4498,14 @@ void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
__ 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 @@ void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
__ 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);
}
......
......@@ -4406,6 +4406,9 @@ class HAllocateObject: public HTemplateInstruction<1> {
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_; }
......
......@@ -6048,7 +6048,8 @@ void HGraphBuilder::VisitCall(Call* expr) {
// 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;
}
......
......@@ -4306,6 +4306,14 @@ void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
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;
__ LoadHeapObject(scratch, constructor);
......@@ -4340,14 +4348,14 @@ void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
__ 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 @@ void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
__ 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);
}
......
......@@ -4367,6 +4367,14 @@ void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
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;
__ LoadHeapObject(map, constructor);
......@@ -4385,14 +4393,14 @@ void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
__ 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 @@ void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
__ 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);
}
......
......@@ -4080,6 +4080,14 @@ void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
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;
__ LoadHeapObject(scratch, constructor);
......@@ -4114,14 +4122,14 @@ void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
__ 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 @@ void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
__ 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);
}
......
......@@ -1264,9 +1264,9 @@ static void FillUpNewSpace(NewSpace* new_space) {
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 @@ TEST(ResetSharedFunctionInfoCountersDuringMarkSweep) {
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));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment