Slightly improved register assignment for %_IsObject on IA32 and ARM.
The new approach uses one temp register instead of two on IA32. The ARM instructions are modified so the input can be UseAtStart again. Review URL: http://codereview.chromium.org/7274025 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8451 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
e859416b9f
commit
2760bd2927
@ -1098,7 +1098,7 @@ LInstruction* LChunkBuilder::DoTest(HTest* instr) {
|
|||||||
HIsObject* compare = HIsObject::cast(v);
|
HIsObject* compare = HIsObject::cast(v);
|
||||||
ASSERT(compare->value()->representation().IsTagged());
|
ASSERT(compare->value()->representation().IsTagged());
|
||||||
LOperand* temp = TempRegister();
|
LOperand* temp = TempRegister();
|
||||||
return new LIsObjectAndBranch(UseRegister(compare->value()), temp);
|
return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()), temp);
|
||||||
} else if (v->IsCompareObjectEq()) {
|
} else if (v->IsCompareObjectEq()) {
|
||||||
HCompareObjectEq* compare = HCompareObjectEq::cast(v);
|
HCompareObjectEq* compare = HCompareObjectEq::cast(v);
|
||||||
return new LCmpObjectEqAndBranch(UseRegisterAtStart(compare->left()),
|
return new LCmpObjectEqAndBranch(UseRegisterAtStart(compare->left()),
|
||||||
|
@ -705,7 +705,7 @@ class LIsNullAndBranch: public LControlInstruction<1, 0> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class LIsObject: public LTemplateInstruction<1, 1, 1> {
|
class LIsObject: public LTemplateInstruction<1, 1, 0> {
|
||||||
public:
|
public:
|
||||||
explicit LIsObject(LOperand* value) {
|
explicit LIsObject(LOperand* value) {
|
||||||
inputs_[0] = value;
|
inputs_[0] = value;
|
||||||
@ -715,7 +715,7 @@ class LIsObject: public LTemplateInstruction<1, 1, 1> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class LIsObjectAndBranch: public LControlInstruction<1, 2> {
|
class LIsObjectAndBranch: public LControlInstruction<1, 1> {
|
||||||
public:
|
public:
|
||||||
LIsObjectAndBranch(LOperand* value, LOperand* temp) {
|
LIsObjectAndBranch(LOperand* value, LOperand* temp) {
|
||||||
inputs_[0] = value;
|
inputs_[0] = value;
|
||||||
|
@ -1796,13 +1796,13 @@ void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
|
|||||||
|
|
||||||
Condition LCodeGen::EmitIsObject(Register input,
|
Condition LCodeGen::EmitIsObject(Register input,
|
||||||
Register temp1,
|
Register temp1,
|
||||||
Register temp2,
|
|
||||||
Label* is_not_object,
|
Label* is_not_object,
|
||||||
Label* is_object) {
|
Label* is_object) {
|
||||||
|
Register temp2 = scratch0();
|
||||||
__ JumpIfSmi(input, is_not_object);
|
__ JumpIfSmi(input, is_not_object);
|
||||||
|
|
||||||
__ LoadRoot(temp1, Heap::kNullValueRootIndex);
|
__ LoadRoot(temp2, Heap::kNullValueRootIndex);
|
||||||
__ cmp(input, temp1);
|
__ cmp(input, temp2);
|
||||||
__ b(eq, is_object);
|
__ b(eq, is_object);
|
||||||
|
|
||||||
// Load map.
|
// Load map.
|
||||||
@ -1824,10 +1824,9 @@ Condition LCodeGen::EmitIsObject(Register input,
|
|||||||
void LCodeGen::DoIsObject(LIsObject* instr) {
|
void LCodeGen::DoIsObject(LIsObject* instr) {
|
||||||
Register reg = ToRegister(instr->InputAt(0));
|
Register reg = ToRegister(instr->InputAt(0));
|
||||||
Register result = ToRegister(instr->result());
|
Register result = ToRegister(instr->result());
|
||||||
Register temp = scratch0();
|
|
||||||
Label is_false, is_true, done;
|
Label is_false, is_true, done;
|
||||||
|
|
||||||
Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true);
|
Condition true_cond = EmitIsObject(reg, result, &is_false, &is_true);
|
||||||
__ b(true_cond, &is_true);
|
__ b(true_cond, &is_true);
|
||||||
|
|
||||||
__ bind(&is_false);
|
__ bind(&is_false);
|
||||||
@ -1852,7 +1851,7 @@ void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
|
|||||||
Label* false_label = chunk_->GetAssemblyLabel(false_block);
|
Label* false_label = chunk_->GetAssemblyLabel(false_block);
|
||||||
|
|
||||||
Condition true_cond =
|
Condition true_cond =
|
||||||
EmitIsObject(reg, temp1, temp2, false_label, true_label);
|
EmitIsObject(reg, temp1, false_label, true_label);
|
||||||
|
|
||||||
EmitBranch(true_block, false_block, true_cond);
|
EmitBranch(true_block, false_block, true_cond);
|
||||||
}
|
}
|
||||||
|
@ -280,7 +280,6 @@ class LCodeGen BASE_EMBEDDED {
|
|||||||
// true and false label should be made, to optimize fallthrough.
|
// true and false label should be made, to optimize fallthrough.
|
||||||
Condition EmitIsObject(Register input,
|
Condition EmitIsObject(Register input,
|
||||||
Register temp1,
|
Register temp1,
|
||||||
Register temp2,
|
|
||||||
Label* is_not_object,
|
Label* is_not_object,
|
||||||
Label* is_object);
|
Label* is_object);
|
||||||
|
|
||||||
|
@ -1637,13 +1637,8 @@ void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
|
|||||||
|
|
||||||
Condition LCodeGen::EmitIsObject(Register input,
|
Condition LCodeGen::EmitIsObject(Register input,
|
||||||
Register temp1,
|
Register temp1,
|
||||||
Register temp2,
|
|
||||||
Label* is_not_object,
|
Label* is_not_object,
|
||||||
Label* is_object) {
|
Label* is_object) {
|
||||||
ASSERT(!input.is(temp1));
|
|
||||||
ASSERT(!input.is(temp2));
|
|
||||||
ASSERT(!temp1.is(temp2));
|
|
||||||
|
|
||||||
__ JumpIfSmi(input, is_not_object);
|
__ JumpIfSmi(input, is_not_object);
|
||||||
|
|
||||||
__ cmp(input, isolate()->factory()->null_value());
|
__ cmp(input, isolate()->factory()->null_value());
|
||||||
@ -1651,14 +1646,14 @@ Condition LCodeGen::EmitIsObject(Register input,
|
|||||||
|
|
||||||
__ mov(temp1, FieldOperand(input, HeapObject::kMapOffset));
|
__ mov(temp1, FieldOperand(input, HeapObject::kMapOffset));
|
||||||
// Undetectable objects behave like undefined.
|
// Undetectable objects behave like undefined.
|
||||||
__ movzx_b(temp2, FieldOperand(temp1, Map::kBitFieldOffset));
|
__ test_b(FieldOperand(temp1, Map::kBitFieldOffset),
|
||||||
__ test(temp2, Immediate(1 << Map::kIsUndetectable));
|
1 << Map::kIsUndetectable);
|
||||||
__ j(not_zero, is_not_object);
|
__ j(not_zero, is_not_object);
|
||||||
|
|
||||||
__ movzx_b(temp2, FieldOperand(temp1, Map::kInstanceTypeOffset));
|
__ movzx_b(temp1, FieldOperand(temp1, Map::kInstanceTypeOffset));
|
||||||
__ cmp(temp2, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
|
__ cmp(temp1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
|
||||||
__ j(below, is_not_object);
|
__ j(below, is_not_object);
|
||||||
__ cmp(temp2, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
|
__ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
|
||||||
return below_equal;
|
return below_equal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1666,10 +1661,9 @@ Condition LCodeGen::EmitIsObject(Register input,
|
|||||||
void LCodeGen::DoIsObject(LIsObject* instr) {
|
void LCodeGen::DoIsObject(LIsObject* instr) {
|
||||||
Register reg = ToRegister(instr->InputAt(0));
|
Register reg = ToRegister(instr->InputAt(0));
|
||||||
Register result = ToRegister(instr->result());
|
Register result = ToRegister(instr->result());
|
||||||
Register temp = ToRegister(instr->TempAt(0));
|
|
||||||
Label is_false, is_true, done;
|
Label is_false, is_true, done;
|
||||||
|
|
||||||
Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true);
|
Condition true_cond = EmitIsObject(reg, result, &is_false, &is_true);
|
||||||
__ j(true_cond, &is_true);
|
__ j(true_cond, &is_true);
|
||||||
|
|
||||||
__ bind(&is_false);
|
__ bind(&is_false);
|
||||||
@ -1686,14 +1680,13 @@ void LCodeGen::DoIsObject(LIsObject* instr) {
|
|||||||
void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
|
void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
|
||||||
Register reg = ToRegister(instr->InputAt(0));
|
Register reg = ToRegister(instr->InputAt(0));
|
||||||
Register temp = ToRegister(instr->TempAt(0));
|
Register temp = ToRegister(instr->TempAt(0));
|
||||||
Register temp2 = ToRegister(instr->TempAt(1));
|
|
||||||
|
|
||||||
int true_block = chunk_->LookupDestination(instr->true_block_id());
|
int true_block = chunk_->LookupDestination(instr->true_block_id());
|
||||||
int false_block = chunk_->LookupDestination(instr->false_block_id());
|
int false_block = chunk_->LookupDestination(instr->false_block_id());
|
||||||
Label* true_label = chunk_->GetAssemblyLabel(true_block);
|
Label* true_label = chunk_->GetAssemblyLabel(true_block);
|
||||||
Label* false_label = chunk_->GetAssemblyLabel(false_block);
|
Label* false_label = chunk_->GetAssemblyLabel(false_block);
|
||||||
|
|
||||||
Condition true_cond = EmitIsObject(reg, temp, temp2, false_label, true_label);
|
Condition true_cond = EmitIsObject(reg, temp, false_label, true_label);
|
||||||
|
|
||||||
EmitBranch(true_block, false_block, true_cond);
|
EmitBranch(true_block, false_block, true_cond);
|
||||||
}
|
}
|
||||||
|
@ -277,7 +277,6 @@ class LCodeGen BASE_EMBEDDED {
|
|||||||
// true and false label should be made, to optimize fallthrough.
|
// true and false label should be made, to optimize fallthrough.
|
||||||
Condition EmitIsObject(Register input,
|
Condition EmitIsObject(Register input,
|
||||||
Register temp1,
|
Register temp1,
|
||||||
Register temp2,
|
|
||||||
Label* is_not_object,
|
Label* is_not_object,
|
||||||
Label* is_object);
|
Label* is_object);
|
||||||
|
|
||||||
|
@ -1096,11 +1096,8 @@ LInstruction* LChunkBuilder::DoTest(HTest* instr) {
|
|||||||
} else if (v->IsIsObject()) {
|
} else if (v->IsIsObject()) {
|
||||||
HIsObject* compare = HIsObject::cast(v);
|
HIsObject* compare = HIsObject::cast(v);
|
||||||
ASSERT(compare->value()->representation().IsTagged());
|
ASSERT(compare->value()->representation().IsTagged());
|
||||||
LOperand* temp1 = TempRegister();
|
LOperand* temp = TempRegister();
|
||||||
LOperand* temp2 = TempRegister();
|
return new LIsObjectAndBranch(UseRegister(compare->value()), temp);
|
||||||
return new LIsObjectAndBranch(UseRegister(compare->value()),
|
|
||||||
temp1,
|
|
||||||
temp2);
|
|
||||||
} else if (v->IsCompareObjectEq()) {
|
} else if (v->IsCompareObjectEq()) {
|
||||||
HCompareObjectEq* compare = HCompareObjectEq::cast(v);
|
HCompareObjectEq* compare = HCompareObjectEq::cast(v);
|
||||||
return new LCmpObjectEqAndBranch(UseRegisterAtStart(compare->left()),
|
return new LCmpObjectEqAndBranch(UseRegisterAtStart(compare->left()),
|
||||||
@ -1546,7 +1543,7 @@ LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) {
|
|||||||
ASSERT(instr->value()->representation().IsTagged());
|
ASSERT(instr->value()->representation().IsTagged());
|
||||||
LOperand* value = UseRegister(instr->value());
|
LOperand* value = UseRegister(instr->value());
|
||||||
|
|
||||||
return DefineAsRegister(new LIsObject(value, TempRegister()));
|
return DefineAsRegister(new LIsObject(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -692,23 +692,21 @@ class LIsNullAndBranch: public LControlInstruction<1, 1> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class LIsObject: public LTemplateInstruction<1, 1, 1> {
|
class LIsObject: public LTemplateInstruction<1, 1, 0> {
|
||||||
public:
|
public:
|
||||||
LIsObject(LOperand* value, LOperand* temp) {
|
explicit LIsObject(LOperand* value) {
|
||||||
inputs_[0] = value;
|
inputs_[0] = value;
|
||||||
temps_[0] = temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLARE_CONCRETE_INSTRUCTION(IsObject, "is-object")
|
DECLARE_CONCRETE_INSTRUCTION(IsObject, "is-object")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class LIsObjectAndBranch: public LControlInstruction<1, 2> {
|
class LIsObjectAndBranch: public LControlInstruction<1, 1> {
|
||||||
public:
|
public:
|
||||||
LIsObjectAndBranch(LOperand* value, LOperand* temp, LOperand* temp2) {
|
LIsObjectAndBranch(LOperand* value, LOperand* temp) {
|
||||||
inputs_[0] = value;
|
inputs_[0] = value;
|
||||||
temps_[0] = temp;
|
temps_[0] = temp;
|
||||||
temps_[1] = temp2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
|
DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
|
||||||
|
Loading…
Reference in New Issue
Block a user