Lithium: avoid registers for constants when possible.

BUG=

Review URL: https://codereview.chromium.org/14364010

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14460 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mvstanton@chromium.org 2013-04-26 14:04:07 +00:00
parent cb2e54d1ff
commit 84355ae411
11 changed files with 85 additions and 64 deletions

View File

@ -552,6 +552,11 @@ LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
}
LOperand* LChunkBuilder::UseConstant(HValue* value) {
return chunk_->DefineConstantOperand(HConstant::cast(value));
}
LOperand* LChunkBuilder::UseAny(HValue* value) {
return value->IsConstant()
? chunk_->DefineConstantOperand(HConstant::cast(value))
@ -2378,7 +2383,9 @@ LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
info()->MarkAsDeferredCalling();
LOperand* size = UseTempRegister(instr->size());
LOperand* size = instr->size()->IsConstant()
? UseConstant(instr->size())
: UseTempRegister(instr->size());
LOperand* temp1 = TempRegister();
LOperand* temp2 = TempRegister();
LAllocate* result = new(zone()) LAllocate(size, temp1, temp2);

View File

@ -2787,6 +2787,9 @@ class LChunkBuilder BASE_EMBEDDED {
MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value);
MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value);
// An input operand in a constant operand.
MUST_USE_RESULT LOperand* UseConstant(HValue* value);
// An input operand in register, stack slot or a constant operand.
// Will not be moved to a register even if one is freely available.
MUST_USE_RESULT LOperand* UseAny(HValue* value);

View File

@ -5473,7 +5473,6 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
Register size = ToRegister(instr->size());
Register result = ToRegister(instr->result());
// TODO(3095996): Get rid of this. For now, we need to make the
@ -5482,8 +5481,16 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
__ mov(result, Operand(Smi::FromInt(0)));
PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
__ SmiTag(size, size);
__ push(size);
if (instr->size()->IsRegister()) {
Register size = ToRegister(instr->size());
ASSERT(!size.is(result));
__ SmiTag(size);
__ push(size);
} else {
int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
__ Push(Smi::FromInt(size));
}
if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
CallRuntimeFromDeferred(
Runtime::kAllocateInOldPointerSpace, 1, instr);

View File

@ -3265,6 +3265,12 @@ class HConstant: public HTemplateInstruction<0> {
std::isnan(double_value_));
}
bool InNewSpace() {
if (handle().is_null()) return false;
ALLOW_HANDLE_DEREF(isolate(), "using raw address");
return isolate()->heap()->InNewSpace(*handle());
}
bool ImmortalImmovable() const {
if (has_int32_value_) {
return false;

View File

@ -1494,6 +1494,7 @@ HInstruction* HGraphBuilder::BuildStoreMap(HValue* object,
HInstruction* store_map =
new(zone) HStoreNamedField(object, map_field_name, map,
true, JSObject::kMapOffset);
store_map->ClearGVNFlag(kChangesInobjectFields);
store_map->SetGVNFlag(kChangesMaps);
AddInstruction(store_map);
return store_map;

View File

@ -6025,18 +6025,24 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
Register size = ToRegister(instr->size());
Register result = ToRegister(instr->result());
__ SmiTag(size);
PushSafepointRegistersScope scope(this);
// TODO(3095996): Get rid of this. For now, we need to make the
// result register contain a valid pointer because it is already
// contained in the register pointer map.
if (!size.is(result)) {
__ StoreToSafepointRegisterSlot(result, size);
__ mov(result, Immediate(Smi::FromInt(0)));
PushSafepointRegistersScope scope(this);
if (instr->size()->IsRegister()) {
Register size = ToRegister(instr->size());
ASSERT(!size.is(result));
__ SmiTag(ToRegister(instr->size()));
__ push(size);
} else {
int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
__ push(Immediate(Smi::FromInt(size)));
}
__ push(size);
if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
CallRuntimeFromDeferred(
Runtime::kAllocateInOldPointerSpace, 1, instr, instr->context());

View File

@ -601,6 +601,11 @@ LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
}
LOperand* LChunkBuilder::UseConstant(HValue* value) {
return chunk_->DefineConstantOperand(HConstant::cast(value));
}
LOperand* LChunkBuilder::UseAny(HValue* value) {
return value->IsConstant()
? chunk_->DefineConstantOperand(HConstant::cast(value))
@ -2287,19 +2292,6 @@ LOperand* LChunkBuilder::GetStoreKeyedValueOperand(HStoreKeyed* instr) {
}
// DoStoreKeyed and DoStoreNamedField have special considerations for allowing
// use of a constant instead of a register.
static bool StoreConstantValueAllowed(HValue* value) {
if (value->IsConstant()) {
HConstant* constant_value = HConstant::cast(value);
return constant_value->HasSmiValue()
|| constant_value->HasDoubleValue()
|| constant_value->ImmortalImmovable();
}
return false;
}
LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
if (!instr->is_external()) {
ASSERT(instr->elements()->representation().IsTagged());
@ -2327,17 +2319,8 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
val = UseTempRegister(instr->value());
key = UseTempRegister(instr->key());
} else {
if (StoreConstantValueAllowed(instr->value())) {
val = UseRegisterOrConstantAtStart(instr->value());
} else {
val = UseRegisterAtStart(instr->value());
}
if (StoreConstantValueAllowed(instr->key())) {
key = UseRegisterOrConstantAtStart(instr->key());
} else {
key = UseRegisterAtStart(instr->key());
}
val = UseRegisterOrConstantAtStart(instr->value());
key = UseRegisterOrConstantAtStart(instr->key());
}
return new(zone()) LStoreKeyed(obj, key, val);
}
@ -2438,10 +2421,13 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
: UseRegisterAtStart(instr->object());
}
bool can_be_constant = instr->value()->IsConstant() &&
!HConstant::cast(instr->value())->InNewSpace();
LOperand* val;
if (needs_write_barrier) {
val = UseTempRegister(instr->value());
} else if (StoreConstantValueAllowed(instr->value())) {
} else if (can_be_constant) {
val = UseRegisterOrConstant(instr->value());
} else {
val = UseRegister(instr->value());
@ -2516,8 +2502,9 @@ LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
info()->MarkAsDeferredCalling();
LOperand* context = UseAny(instr->context());
// TODO(mvstanton): why can't size be a constant if possible?
LOperand* size = UseTempRegister(instr->size());
LOperand* size = instr->size()->IsConstant()
? UseConstant(instr->size())
: UseTempRegister(instr->size());
LOperand* temp = TempRegister();
LAllocate* result = new(zone()) LAllocate(context, size, temp);
return AssignPointerMap(DefineAsRegister(result));

View File

@ -2908,6 +2908,9 @@ class LChunkBuilder BASE_EMBEDDED {
MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value);
MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value);
// An input operand in a constant operand.
MUST_USE_RESULT LOperand* UseConstant(HValue* value);
// An input operand in register, stack slot or a constant operand.
// Will not be moved to a register even if one is freely available.
MUST_USE_RESULT LOperand* UseAny(HValue* value);

View File

@ -5122,17 +5122,24 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
Register size = ToRegister(instr->size());
Register result = ToRegister(instr->result());
// TODO(3095996): Get rid of this. For now, we need to make the
// result register contain a valid pointer because it is already
// contained in the register pointer map.
__ Set(result, 0);
__ Move(result, Smi::FromInt(0));
PushSafepointRegistersScope scope(this);
__ Integer32ToSmi(size, size);
__ push(size);
if (instr->size()->IsRegister()) {
Register size = ToRegister(instr->size());
ASSERT(!size.is(result));
__ Integer32ToSmi(size, size);
__ push(size);
} else {
int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
__ Push(Smi::FromInt(size));
}
if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
CallRuntimeFromDeferred(
Runtime::kAllocateInOldPointerSpace, 1, instr);

View File

@ -557,6 +557,11 @@ LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
}
LOperand* LChunkBuilder::UseConstant(HValue* value) {
return chunk_->DefineConstantOperand(HConstant::cast(value));
}
LOperand* LChunkBuilder::UseAny(HValue* value) {
return value->IsConstant()
? chunk_->DefineConstantOperand(HConstant::cast(value))
@ -2115,19 +2120,6 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
}
// DoStoreKeyed and DoStoreNamedField have special considerations for allowing
// use of a constant instead of a register.
static bool StoreConstantValueAllowed(HValue* value) {
if (value->IsConstant()) {
HConstant* constant_value = HConstant::cast(value);
return constant_value->HasSmiValue()
|| constant_value->HasDoubleValue()
|| constant_value->ImmortalImmovable();
}
return false;
}
LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
ElementsKind elements_kind = instr->elements_kind();
bool clobbers_key = instr->key()->representation().IsTagged();
@ -2151,18 +2143,12 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
val = UseTempRegister(instr->value());
key = UseTempRegister(instr->key());
} else {
if (StoreConstantValueAllowed(instr->value())) {
val = UseRegisterOrConstantAtStart(instr->value());
} else {
val = UseRegisterAtStart(instr->value());
}
val = UseRegisterOrConstantAtStart(instr->value());
if (clobbers_key) {
key = UseTempRegister(instr->key());
} else if (StoreConstantValueAllowed(instr->key())) {
key = UseRegisterOrConstantAtStart(instr->key());
} else {
key = UseRegisterAtStart(instr->key());
key = UseRegisterOrConstantAtStart(instr->key());
}
}
}
@ -2258,10 +2244,13 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
: UseRegisterAtStart(instr->object());
}
bool can_be_constant = instr->value()->IsConstant() &&
!HConstant::cast(instr->value())->InNewSpace();
LOperand* val;
if (needs_write_barrier) {
val = UseTempRegister(instr->value());
} else if (StoreConstantValueAllowed(instr->value())) {
} else if (can_be_constant) {
val = UseRegisterOrConstant(instr->value());
} else {
val = UseRegister(instr->value());
@ -2323,7 +2312,9 @@ LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
info()->MarkAsDeferredCalling();
LOperand* size = UseTempRegister(instr->size());
LOperand* size = instr->size()->IsConstant()
? UseConstant(instr->size())
: UseTempRegister(instr->size());
LOperand* temp = TempRegister();
LAllocate* result = new(zone()) LAllocate(size, temp);
return AssignPointerMap(DefineAsRegister(result));

View File

@ -2674,6 +2674,9 @@ class LChunkBuilder BASE_EMBEDDED {
MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value);
MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value);
// An input operand in a constant operand.
MUST_USE_RESULT LOperand* UseConstant(HValue* value);
// An input operand in register, stack slot or a constant operand.
// Will not be moved to a register even if one is freely available.
MUST_USE_RESULT LOperand* UseAny(HValue* value);