Improvements in lithium code generation. Recognizing if some operands are constants, we can often save on registers and instructions.
BUG= Review URL: https://codereview.chromium.org/14022011 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14364 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
f51b76425a
commit
37d11fb0f0
@ -2460,8 +2460,15 @@ LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
|
||||
LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
|
||||
info()->MarkAsRequiresFrame();
|
||||
LOperand* args = UseRegister(instr->arguments());
|
||||
LOperand* length = UseTempRegister(instr->length());
|
||||
LOperand* index = UseRegister(instr->index());
|
||||
LOperand* length;
|
||||
LOperand* index;
|
||||
if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
|
||||
length = UseRegisterOrConstant(instr->length());
|
||||
index = UseOrConstant(instr->index());
|
||||
} else {
|
||||
length = UseTempRegister(instr->length());
|
||||
index = Use(instr->index());
|
||||
}
|
||||
return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
|
||||
}
|
||||
|
||||
|
@ -3277,14 +3277,22 @@ void LCodeGen::DoLoadExternalArrayPointer(
|
||||
|
||||
void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
|
||||
Register arguments = ToRegister(instr->arguments());
|
||||
Register length = ToRegister(instr->length());
|
||||
Register index = ToRegister(instr->index());
|
||||
Register result = ToRegister(instr->result());
|
||||
// There are two words between the frame pointer and the last argument.
|
||||
// Subtracting from length accounts for one of them add one more.
|
||||
__ sub(length, length, index);
|
||||
__ add(length, length, Operand(1));
|
||||
__ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2));
|
||||
if (instr->length()->IsConstantOperand() &&
|
||||
instr->index()->IsConstantOperand()) {
|
||||
int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
|
||||
int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
|
||||
int index = (const_length - const_index) + 1;
|
||||
__ ldr(result, MemOperand(arguments, index * kPointerSize));
|
||||
} else {
|
||||
Register length = ToRegister(instr->length());
|
||||
Register index = ToRegister(instr->index());
|
||||
// There are two words between the frame pointer and the last argument.
|
||||
// Subtracting from length accounts for one of them add one more.
|
||||
__ sub(length, length, index);
|
||||
__ add(length, length, Operand(1));
|
||||
__ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -3196,13 +3196,21 @@ void LCodeGen::DoLoadExternalArrayPointer(
|
||||
|
||||
void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
|
||||
Register arguments = ToRegister(instr->arguments());
|
||||
Register length = ToRegister(instr->length());
|
||||
Operand index = ToOperand(instr->index());
|
||||
Register result = ToRegister(instr->result());
|
||||
// There are two words between the frame pointer and the last argument.
|
||||
// Subtracting from length accounts for one of them add one more.
|
||||
__ sub(length, index);
|
||||
__ mov(result, Operand(arguments, length, times_4, kPointerSize));
|
||||
if (instr->length()->IsConstantOperand() &&
|
||||
instr->index()->IsConstantOperand()) {
|
||||
int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
|
||||
int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
|
||||
int index = (const_length - const_index) + 1;
|
||||
__ mov(result, Operand(arguments, index * kPointerSize));
|
||||
} else {
|
||||
Register length = ToRegister(instr->length());
|
||||
Operand index = ToOperand(instr->index());
|
||||
// There are two words between the frame pointer and the last argument.
|
||||
// Subtracting from length accounts for one of them add one more.
|
||||
__ sub(length, index);
|
||||
__ mov(result, Operand(arguments, length, times_4, kPointerSize));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4220,7 +4228,6 @@ void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
|
||||
|
||||
void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
|
||||
Register object = ToRegister(instr->object());
|
||||
Register value = ToRegister(instr->value());
|
||||
int offset = instr->offset();
|
||||
|
||||
if (!instr->transition().is_null()) {
|
||||
@ -4246,34 +4253,42 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
|
||||
HType type = instr->hydrogen()->value()->type();
|
||||
SmiCheck check_needed =
|
||||
type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
|
||||
if (instr->is_in_object()) {
|
||||
__ mov(FieldOperand(object, offset), value);
|
||||
if (instr->hydrogen()->NeedsWriteBarrier()) {
|
||||
Register temp = ToRegister(instr->temp());
|
||||
// Update the write barrier for the object for in-object properties.
|
||||
__ RecordWriteField(object,
|
||||
offset,
|
||||
value,
|
||||
temp,
|
||||
GetSaveFPRegsMode(),
|
||||
EMIT_REMEMBERED_SET,
|
||||
check_needed);
|
||||
|
||||
Register write_register = object;
|
||||
if (!instr->is_in_object()) {
|
||||
write_register = ToRegister(instr->temp());
|
||||
__ mov(write_register,
|
||||
FieldOperand(object, JSObject::kPropertiesOffset));
|
||||
}
|
||||
|
||||
if (instr->value()->IsConstantOperand()) {
|
||||
LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
|
||||
if (IsInteger32(operand_value)) {
|
||||
int const_value = ToInteger32(operand_value);
|
||||
__ mov(FieldOperand(write_register, offset), Immediate(const_value));
|
||||
} else {
|
||||
if (operand_value->IsRegister()) {
|
||||
__ mov(FieldOperand(write_register, offset), ToRegister(operand_value));
|
||||
} else {
|
||||
Handle<Object> handle_value = ToHandle(operand_value);
|
||||
__ mov(FieldOperand(write_register, offset), handle_value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Register temp = ToRegister(instr->temp());
|
||||
__ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset));
|
||||
__ mov(FieldOperand(temp, offset), value);
|
||||
if (instr->hydrogen()->NeedsWriteBarrier()) {
|
||||
// Update the write barrier for the properties array.
|
||||
// object is used as a scratch register.
|
||||
__ RecordWriteField(temp,
|
||||
offset,
|
||||
value,
|
||||
object,
|
||||
GetSaveFPRegsMode(),
|
||||
EMIT_REMEMBERED_SET,
|
||||
check_needed);
|
||||
}
|
||||
__ mov(FieldOperand(write_register, offset), ToRegister(instr->value()));
|
||||
}
|
||||
|
||||
if (instr->hydrogen()->NeedsWriteBarrier()) {
|
||||
Register value = ToRegister(instr->value());
|
||||
Register temp = instr->is_in_object() ? ToRegister(instr->temp()) : object;
|
||||
// Update the write barrier for the object for in-object properties.
|
||||
__ RecordWriteField(write_register,
|
||||
offset,
|
||||
value,
|
||||
temp,
|
||||
GetSaveFPRegsMode(),
|
||||
EMIT_REMEMBERED_SET,
|
||||
check_needed);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4451,7 +4466,6 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
|
||||
|
||||
|
||||
void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
|
||||
Register value = ToRegister(instr->value());
|
||||
Register elements = ToRegister(instr->elements());
|
||||
Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
|
||||
|
||||
@ -4462,9 +4476,22 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
|
||||
FAST_ELEMENTS,
|
||||
FixedArray::kHeaderSize - kHeapObjectTag,
|
||||
instr->additional_index());
|
||||
__ mov(operand, value);
|
||||
if (instr->value()->IsRegister()) {
|
||||
__ mov(operand, ToRegister(instr->value()));
|
||||
} else {
|
||||
LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
|
||||
if (IsInteger32(operand_value)) {
|
||||
Smi* smi_value = Smi::FromInt(ToInteger32(operand_value));
|
||||
__ mov(operand, Immediate(smi_value));
|
||||
} else {
|
||||
Handle<Object> handle_value = ToHandle(operand_value);
|
||||
__ mov(operand, handle_value);
|
||||
}
|
||||
}
|
||||
|
||||
if (instr->hydrogen()->NeedsWriteBarrier()) {
|
||||
ASSERT(instr->value()->IsRegister());
|
||||
Register value = ToRegister(instr->value());
|
||||
ASSERT(!instr->key()->IsConstantOperand());
|
||||
HType type = instr->hydrogen()->value()->type();
|
||||
SmiCheck check_needed =
|
||||
|
@ -2297,19 +2297,21 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
val = UseX87TopOfStack(instr->value());
|
||||
}
|
||||
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
|
||||
|
||||
return new(zone()) LStoreKeyed(object, key, val);
|
||||
} else {
|
||||
ASSERT(instr->value()->representation().IsTagged());
|
||||
bool needs_write_barrier = instr->NeedsWriteBarrier();
|
||||
|
||||
LOperand* obj = UseRegister(instr->elements());
|
||||
LOperand* val = needs_write_barrier
|
||||
? UseTempRegister(instr->value())
|
||||
: UseRegisterAtStart(instr->value());
|
||||
LOperand* key = needs_write_barrier
|
||||
? UseTempRegister(instr->key())
|
||||
: UseRegisterOrConstantAtStart(instr->key());
|
||||
LOperand* val;
|
||||
LOperand* key;
|
||||
if (needs_write_barrier) {
|
||||
val = UseTempRegister(instr->value());
|
||||
key = UseTempRegister(instr->key());
|
||||
} else {
|
||||
val = UseRegisterOrConstantAtStart(instr->value());
|
||||
key = UseRegisterOrConstantAtStart(instr->key());
|
||||
}
|
||||
return new(zone()) LStoreKeyed(obj, key, val);
|
||||
}
|
||||
}
|
||||
@ -2409,9 +2411,22 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
|
||||
: UseRegisterAtStart(instr->object());
|
||||
}
|
||||
|
||||
LOperand* val = needs_write_barrier
|
||||
? UseTempRegister(instr->value())
|
||||
: UseRegister(instr->value());
|
||||
bool register_or_constant = false;
|
||||
if (instr->value()->IsConstant()) {
|
||||
HConstant* constant_value = HConstant::cast(instr->value());
|
||||
register_or_constant = constant_value->HasInteger32Value()
|
||||
|| constant_value->HasDoubleValue()
|
||||
|| constant_value->ImmortalImmovable();
|
||||
}
|
||||
|
||||
LOperand* val;
|
||||
if (needs_write_barrier) {
|
||||
val = UseTempRegister(instr->value());
|
||||
} else if (register_or_constant) {
|
||||
val = UseRegisterOrConstant(instr->value());
|
||||
} else {
|
||||
val = UseRegister(instr->value());
|
||||
}
|
||||
|
||||
// We only need a scratch register if we have a write barrier or we
|
||||
// have a store into the properties array (not in-object-property).
|
||||
@ -2579,8 +2594,15 @@ LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
|
||||
LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
|
||||
info()->MarkAsRequiresFrame();
|
||||
LOperand* args = UseRegister(instr->arguments());
|
||||
LOperand* length = UseTempRegister(instr->length());
|
||||
LOperand* index = Use(instr->index());
|
||||
LOperand* length;
|
||||
LOperand* index;
|
||||
if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
|
||||
length = UseRegisterOrConstant(instr->length());
|
||||
index = UseOrConstant(instr->index());
|
||||
} else {
|
||||
length = UseTempRegister(instr->length());
|
||||
index = Use(instr->index());
|
||||
}
|
||||
return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
|
||||
}
|
||||
|
||||
|
@ -2899,16 +2899,26 @@ void LCodeGen::DoLoadExternalArrayPointer(
|
||||
|
||||
void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
|
||||
Register arguments = ToRegister(instr->arguments());
|
||||
Register length = ToRegister(instr->length());
|
||||
Register result = ToRegister(instr->result());
|
||||
// There are two words between the frame pointer and the last argument.
|
||||
// Subtracting from length accounts for one of them add one more.
|
||||
if (instr->index()->IsRegister()) {
|
||||
__ subl(length, ToRegister(instr->index()));
|
||||
|
||||
if (instr->length()->IsConstantOperand() &&
|
||||
instr->index()->IsConstantOperand()) {
|
||||
int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
|
||||
int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
|
||||
int index = (const_length - const_index) + 1;
|
||||
__ movq(result, Operand(arguments, index * kPointerSize));
|
||||
} else {
|
||||
__ subl(length, ToOperand(instr->index()));
|
||||
Register length = ToRegister(instr->length());
|
||||
// There are two words between the frame pointer and the last argument.
|
||||
// Subtracting from length accounts for one of them add one more.
|
||||
if (instr->index()->IsRegister()) {
|
||||
__ subl(length, ToRegister(instr->index()));
|
||||
} else {
|
||||
__ subl(length, ToOperand(instr->index()));
|
||||
}
|
||||
__ movq(result,
|
||||
Operand(arguments, length, times_pointer_size, kPointerSize));
|
||||
}
|
||||
__ movq(result, Operand(arguments, length, times_pointer_size, kPointerSize));
|
||||
}
|
||||
|
||||
|
||||
@ -3916,7 +3926,6 @@ void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
|
||||
|
||||
void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
|
||||
Register object = ToRegister(instr->object());
|
||||
Register value = ToRegister(instr->value());
|
||||
int offset = instr->offset();
|
||||
|
||||
if (!instr->transition().is_null()) {
|
||||
@ -3942,34 +3951,42 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
|
||||
HType type = instr->hydrogen()->value()->type();
|
||||
SmiCheck check_needed =
|
||||
type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
|
||||
if (instr->is_in_object()) {
|
||||
__ movq(FieldOperand(object, offset), value);
|
||||
if (instr->hydrogen()->NeedsWriteBarrier()) {
|
||||
Register temp = ToRegister(instr->temp());
|
||||
// Update the write barrier for the object for in-object properties.
|
||||
__ RecordWriteField(object,
|
||||
offset,
|
||||
value,
|
||||
temp,
|
||||
kSaveFPRegs,
|
||||
EMIT_REMEMBERED_SET,
|
||||
check_needed);
|
||||
|
||||
Register write_register = object;
|
||||
if (!instr->is_in_object()) {
|
||||
write_register = ToRegister(instr->temp());
|
||||
__ movq(write_register, FieldOperand(object, JSObject::kPropertiesOffset));
|
||||
}
|
||||
|
||||
if (instr->value()->IsConstantOperand()) {
|
||||
LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
|
||||
if (IsInteger32Constant(operand_value)) {
|
||||
int const_value = ToInteger32(operand_value);
|
||||
__ movq(FieldOperand(write_register, offset), Immediate(const_value));
|
||||
} else {
|
||||
if (operand_value->IsRegister()) {
|
||||
__ movq(FieldOperand(write_register, offset),
|
||||
ToRegister(operand_value));
|
||||
} else {
|
||||
Handle<Object> handle_value = ToHandle(operand_value);
|
||||
__ Move(FieldOperand(write_register, offset), handle_value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Register temp = ToRegister(instr->temp());
|
||||
__ movq(temp, FieldOperand(object, JSObject::kPropertiesOffset));
|
||||
__ movq(FieldOperand(temp, offset), value);
|
||||
if (instr->hydrogen()->NeedsWriteBarrier()) {
|
||||
// Update the write barrier for the properties array.
|
||||
// object is used as a scratch register.
|
||||
__ RecordWriteField(temp,
|
||||
offset,
|
||||
value,
|
||||
object,
|
||||
kSaveFPRegs,
|
||||
EMIT_REMEMBERED_SET,
|
||||
check_needed);
|
||||
}
|
||||
__ movq(FieldOperand(write_register, offset), ToRegister(instr->value()));
|
||||
}
|
||||
|
||||
if (instr->hydrogen()->NeedsWriteBarrier()) {
|
||||
Register value = ToRegister(instr->value());
|
||||
Register temp = instr->is_in_object() ? ToRegister(instr->temp()) : object;
|
||||
// Update the write barrier for the object for in-object properties.
|
||||
__ RecordWriteField(write_register,
|
||||
offset,
|
||||
value,
|
||||
temp,
|
||||
kSaveFPRegs,
|
||||
EMIT_REMEMBERED_SET,
|
||||
check_needed);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4135,7 +4152,6 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
|
||||
|
||||
|
||||
void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
|
||||
Register value = ToRegister(instr->value());
|
||||
Register elements = ToRegister(instr->elements());
|
||||
LOperand* key = instr->key();
|
||||
if (!key->IsConstantOperand()) {
|
||||
@ -4160,8 +4176,22 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
|
||||
FAST_ELEMENTS,
|
||||
FixedArray::kHeaderSize - kHeapObjectTag,
|
||||
instr->additional_index());
|
||||
if (instr->value()->IsRegister()) {
|
||||
__ movq(operand, ToRegister(instr->value()));
|
||||
} else {
|
||||
LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
|
||||
if (IsInteger32Constant(operand_value)) {
|
||||
Smi* smi_value = Smi::FromInt(ToInteger32(operand_value));
|
||||
__ Move(operand, smi_value);
|
||||
} else {
|
||||
Handle<Object> handle_value = ToHandle(operand_value);
|
||||
__ Move(operand, handle_value);
|
||||
}
|
||||
}
|
||||
|
||||
if (instr->hydrogen()->NeedsWriteBarrier()) {
|
||||
ASSERT(instr->value()->IsRegister());
|
||||
Register value = ToRegister(instr->value());
|
||||
ASSERT(!instr->key()->IsConstantOperand());
|
||||
HType type = instr->hydrogen()->value()->type();
|
||||
SmiCheck check_needed =
|
||||
@ -4169,15 +4199,12 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
|
||||
// Compute address of modified element and store it into key register.
|
||||
Register key_reg(ToRegister(key));
|
||||
__ lea(key_reg, operand);
|
||||
__ movq(Operand(key_reg, 0), value);
|
||||
__ RecordWrite(elements,
|
||||
key_reg,
|
||||
value,
|
||||
kSaveFPRegs,
|
||||
EMIT_REMEMBERED_SET,
|
||||
check_needed);
|
||||
} else {
|
||||
__ movq(operand, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2139,7 +2139,7 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
ASSERT(instr->value()->representation().IsTagged());
|
||||
object = UseTempRegister(instr->elements());
|
||||
val = needs_write_barrier ? UseTempRegister(instr->value())
|
||||
: UseRegisterAtStart(instr->value());
|
||||
: UseRegisterOrConstantAtStart(instr->value());
|
||||
key = (clobbers_key || needs_write_barrier)
|
||||
? UseTempRegister(instr->key())
|
||||
: UseRegisterOrConstantAtStart(instr->key());
|
||||
@ -2236,9 +2236,22 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
|
||||
: UseRegisterAtStart(instr->object());
|
||||
}
|
||||
|
||||
LOperand* val = needs_write_barrier
|
||||
? UseTempRegister(instr->value())
|
||||
: UseRegister(instr->value());
|
||||
bool register_or_constant = false;
|
||||
if (instr->value()->IsConstant()) {
|
||||
HConstant* constant_value = HConstant::cast(instr->value());
|
||||
register_or_constant = constant_value->HasInteger32Value()
|
||||
|| constant_value->HasDoubleValue()
|
||||
|| constant_value->ImmortalImmovable();
|
||||
}
|
||||
|
||||
LOperand* val;
|
||||
if (needs_write_barrier) {
|
||||
val = UseTempRegister(instr->value());
|
||||
} else if (register_or_constant) {
|
||||
val = UseRegisterOrConstant(instr->value());
|
||||
} else {
|
||||
val = UseRegister(instr->value());
|
||||
}
|
||||
|
||||
// We only need a scratch register if we have a write barrier or we
|
||||
// have a store into the properties array (not in-object-property).
|
||||
@ -2382,8 +2395,15 @@ LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
|
||||
LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
|
||||
info()->MarkAsRequiresFrame();
|
||||
LOperand* args = UseRegister(instr->arguments());
|
||||
LOperand* length = UseTempRegister(instr->length());
|
||||
LOperand* index = Use(instr->index());
|
||||
LOperand* length;
|
||||
LOperand* index;
|
||||
if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
|
||||
length = UseRegisterOrConstant(instr->length());
|
||||
index = UseOrConstant(instr->index());
|
||||
} else {
|
||||
length = UseTempRegister(instr->length());
|
||||
index = Use(instr->index());
|
||||
}
|
||||
return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user