Set a fixed scratch register for ARM code generation
r9 is now set as a fixed scratch register for ARM code generation. removed some unneeded allocation of temporary registers and use the scratch register instead. Review URL: http://codereview.chromium.org/5976014 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6162 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
aa396c5779
commit
71d863e5de
@ -66,13 +66,14 @@ namespace internal {
|
|||||||
// such that we use an enum in optimized mode, and the struct in debug
|
// such that we use an enum in optimized mode, and the struct in debug
|
||||||
// mode. This way we get the compile-time error checking in debug mode
|
// mode. This way we get the compile-time error checking in debug mode
|
||||||
// and best performance in optimized code.
|
// and best performance in optimized code.
|
||||||
//
|
|
||||||
// Core register
|
// Core register
|
||||||
struct Register {
|
struct Register {
|
||||||
static const int kNumRegisters = 16;
|
static const int kNumRegisters = 16;
|
||||||
static const int kNumAllocatableRegisters = 8;
|
static const int kNumAllocatableRegisters = 8;
|
||||||
|
|
||||||
static int ToAllocationIndex(Register reg) {
|
static int ToAllocationIndex(Register reg) {
|
||||||
|
ASSERT(reg.code() < kNumAllocatableRegisters);
|
||||||
return reg.code();
|
return reg.code();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +133,7 @@ const Register r5 = { 5 };
|
|||||||
const Register r6 = { 6 };
|
const Register r6 = { 6 };
|
||||||
const Register r7 = { 7 };
|
const Register r7 = { 7 };
|
||||||
const Register r8 = { 8 }; // Used as context register.
|
const Register r8 = { 8 }; // Used as context register.
|
||||||
const Register r9 = { 9 };
|
const Register r9 = { 9 }; // Used as lithium codegen scratch register.
|
||||||
const Register r10 = { 10 }; // Used as roots register.
|
const Register r10 = { 10 }; // Used as roots register.
|
||||||
const Register fp = { 11 };
|
const Register fp = { 11 };
|
||||||
const Register ip = { 12 };
|
const Register ip = { 12 };
|
||||||
|
@ -1222,7 +1222,6 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
|
|||||||
ASSERT(compare->value()->representation().IsTagged());
|
ASSERT(compare->value()->representation().IsTagged());
|
||||||
|
|
||||||
return new LHasInstanceTypeAndBranch(UseRegisterAtStart(compare->value()),
|
return new LHasInstanceTypeAndBranch(UseRegisterAtStart(compare->value()),
|
||||||
TempRegister(),
|
|
||||||
first_id,
|
first_id,
|
||||||
second_id);
|
second_id);
|
||||||
} else if (v->IsHasCachedArrayIndex()) {
|
} else if (v->IsHasCachedArrayIndex()) {
|
||||||
@ -1235,11 +1234,8 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
|
|||||||
HIsNull* compare = HIsNull::cast(v);
|
HIsNull* compare = HIsNull::cast(v);
|
||||||
ASSERT(compare->value()->representation().IsTagged());
|
ASSERT(compare->value()->representation().IsTagged());
|
||||||
|
|
||||||
// We only need a temp register for non-strict compare.
|
|
||||||
LOperand* temp = compare->is_strict() ? NULL : TempRegister();
|
|
||||||
return new LIsNullAndBranch(UseRegisterAtStart(compare->value()),
|
return new LIsNullAndBranch(UseRegisterAtStart(compare->value()),
|
||||||
compare->is_strict(),
|
compare->is_strict(),
|
||||||
temp,
|
|
||||||
first_id,
|
first_id,
|
||||||
second_id);
|
second_id);
|
||||||
} else if (v->IsIsObject()) {
|
} else if (v->IsIsObject()) {
|
||||||
@ -1851,8 +1847,7 @@ LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
|
|||||||
LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
|
LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
|
||||||
HLoadFunctionPrototype* instr) {
|
HLoadFunctionPrototype* instr) {
|
||||||
return AssignEnvironment(DefineAsRegister(
|
return AssignEnvironment(DefineAsRegister(
|
||||||
new LLoadFunctionPrototype(UseRegister(instr->function()),
|
new LLoadFunctionPrototype(UseRegister(instr->function()))));
|
||||||
TempRegister())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -726,11 +726,9 @@ class LIsNullAndBranch: public LIsNull {
|
|||||||
public:
|
public:
|
||||||
LIsNullAndBranch(LOperand* value,
|
LIsNullAndBranch(LOperand* value,
|
||||||
bool is_strict,
|
bool is_strict,
|
||||||
LOperand* temp,
|
|
||||||
int true_block_id,
|
int true_block_id,
|
||||||
int false_block_id)
|
int false_block_id)
|
||||||
: LIsNull(value, is_strict),
|
: LIsNull(value, is_strict),
|
||||||
temp_(temp),
|
|
||||||
true_block_id_(true_block_id),
|
true_block_id_(true_block_id),
|
||||||
false_block_id_(false_block_id) { }
|
false_block_id_(false_block_id) { }
|
||||||
|
|
||||||
@ -741,10 +739,7 @@ class LIsNullAndBranch: public LIsNull {
|
|||||||
int true_block_id() const { return true_block_id_; }
|
int true_block_id() const { return true_block_id_; }
|
||||||
int false_block_id() const { return false_block_id_; }
|
int false_block_id() const { return false_block_id_; }
|
||||||
|
|
||||||
LOperand* temp() const { return temp_; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LOperand* temp_;
|
|
||||||
int true_block_id_;
|
int true_block_id_;
|
||||||
int false_block_id_;
|
int false_block_id_;
|
||||||
};
|
};
|
||||||
@ -839,11 +834,9 @@ class LHasInstanceType: public LUnaryOperation {
|
|||||||
class LHasInstanceTypeAndBranch: public LHasInstanceType {
|
class LHasInstanceTypeAndBranch: public LHasInstanceType {
|
||||||
public:
|
public:
|
||||||
LHasInstanceTypeAndBranch(LOperand* value,
|
LHasInstanceTypeAndBranch(LOperand* value,
|
||||||
LOperand* temporary,
|
|
||||||
int true_block_id,
|
int true_block_id,
|
||||||
int false_block_id)
|
int false_block_id)
|
||||||
: LHasInstanceType(value),
|
: LHasInstanceType(value),
|
||||||
temp_(temporary),
|
|
||||||
true_block_id_(true_block_id),
|
true_block_id_(true_block_id),
|
||||||
false_block_id_(false_block_id) { }
|
false_block_id_(false_block_id) { }
|
||||||
|
|
||||||
@ -855,10 +848,7 @@ class LHasInstanceTypeAndBranch: public LHasInstanceType {
|
|||||||
int true_block_id() const { return true_block_id_; }
|
int true_block_id() const { return true_block_id_; }
|
||||||
int false_block_id() const { return false_block_id_; }
|
int false_block_id() const { return false_block_id_; }
|
||||||
|
|
||||||
LOperand* temp() { return temp_; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LOperand* temp_;
|
|
||||||
int true_block_id_;
|
int true_block_id_;
|
||||||
int false_block_id_;
|
int false_block_id_;
|
||||||
};
|
};
|
||||||
@ -1263,17 +1253,12 @@ class LLoadNamedGeneric: public LUnaryOperation {
|
|||||||
|
|
||||||
class LLoadFunctionPrototype: public LUnaryOperation {
|
class LLoadFunctionPrototype: public LUnaryOperation {
|
||||||
public:
|
public:
|
||||||
LLoadFunctionPrototype(LOperand* function, LOperand* temporary)
|
LLoadFunctionPrototype(LOperand* function) : LUnaryOperation(function) { }
|
||||||
: LUnaryOperation(function), temporary_(temporary) { }
|
|
||||||
|
|
||||||
DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
|
DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
|
||||||
DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
|
DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
|
||||||
|
|
||||||
LOperand* function() const { return input(); }
|
LOperand* function() const { return input(); }
|
||||||
LOperand* temporary() const { return temporary_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
LOperand* temporary_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -598,7 +598,7 @@ void LCodeGen::DoParallelMove(LParallelMove* move) {
|
|||||||
DoubleRegister dbl_scratch = d0;
|
DoubleRegister dbl_scratch = d0;
|
||||||
LUnallocated marker_operand(LUnallocated::NONE);
|
LUnallocated marker_operand(LUnallocated::NONE);
|
||||||
|
|
||||||
Register core_scratch = r9;
|
Register core_scratch = scratch0();
|
||||||
bool destroys_core_scratch = false;
|
bool destroys_core_scratch = false;
|
||||||
|
|
||||||
LGapResolver resolver(move->move_operands(), &marker_operand);
|
LGapResolver resolver(move->move_operands(), &marker_operand);
|
||||||
@ -796,8 +796,8 @@ void LCodeGen::DoDivI(LDivI* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void LCodeGen::DoMulI(LMulI* instr) {
|
void LCodeGen::DoMulI(LMulI* instr) {
|
||||||
|
Register scratch = scratch0();
|
||||||
Register left = ToRegister(instr->left());
|
Register left = ToRegister(instr->left());
|
||||||
Register scratch = r9;
|
|
||||||
Register right = EmitLoadRegister(instr->right(), scratch);
|
Register right = EmitLoadRegister(instr->right(), scratch);
|
||||||
|
|
||||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) &&
|
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) &&
|
||||||
@ -859,6 +859,7 @@ void LCodeGen::DoBitI(LBitI* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void LCodeGen::DoShiftI(LShiftI* instr) {
|
void LCodeGen::DoShiftI(LShiftI* instr) {
|
||||||
|
Register scratch = scratch0();
|
||||||
LOperand* left = instr->left();
|
LOperand* left = instr->left();
|
||||||
LOperand* right = instr->right();
|
LOperand* right = instr->right();
|
||||||
ASSERT(left->Equals(instr->result()));
|
ASSERT(left->Equals(instr->result()));
|
||||||
@ -866,21 +867,21 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
|
|||||||
Register result = ToRegister(left);
|
Register result = ToRegister(left);
|
||||||
if (right->IsRegister()) {
|
if (right->IsRegister()) {
|
||||||
// Mask the right operand.
|
// Mask the right operand.
|
||||||
__ and_(r9, ToRegister(right), Operand(0x1F));
|
__ and_(scratch, ToRegister(right), Operand(0x1F));
|
||||||
switch (instr->op()) {
|
switch (instr->op()) {
|
||||||
case Token::SAR:
|
case Token::SAR:
|
||||||
__ mov(result, Operand(result, ASR, r9));
|
__ mov(result, Operand(result, ASR, scratch));
|
||||||
break;
|
break;
|
||||||
case Token::SHR:
|
case Token::SHR:
|
||||||
if (instr->can_deopt()) {
|
if (instr->can_deopt()) {
|
||||||
__ mov(result, Operand(result, LSR, r9), SetCC);
|
__ mov(result, Operand(result, LSR, scratch), SetCC);
|
||||||
DeoptimizeIf(mi, instr->environment());
|
DeoptimizeIf(mi, instr->environment());
|
||||||
} else {
|
} else {
|
||||||
__ mov(result, Operand(result, LSR, r9));
|
__ mov(result, Operand(result, LSR, scratch));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Token::SHL:
|
case Token::SHL:
|
||||||
__ mov(result, Operand(result, LSL, r9));
|
__ mov(result, Operand(result, LSL, scratch));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
@ -1105,11 +1106,10 @@ void LCodeGen::DoBranch(LBranch* instr) {
|
|||||||
// Test for double values. Zero is false.
|
// Test for double values. Zero is false.
|
||||||
Label call_stub;
|
Label call_stub;
|
||||||
DoubleRegister dbl_scratch = d0;
|
DoubleRegister dbl_scratch = d0;
|
||||||
Register core_scratch = r9;
|
Register scratch = scratch0();
|
||||||
ASSERT(!reg.is(core_scratch));
|
__ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
|
||||||
__ ldr(core_scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
|
|
||||||
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
|
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
|
||||||
__ cmp(core_scratch, Operand(ip));
|
__ cmp(scratch, Operand(ip));
|
||||||
__ b(ne, &call_stub);
|
__ b(ne, &call_stub);
|
||||||
__ sub(ip, reg, Operand(kHeapObjectTag));
|
__ sub(ip, reg, Operand(kHeapObjectTag));
|
||||||
__ vldr(dbl_scratch, ip, HeapNumber::kValueOffset);
|
__ vldr(dbl_scratch, ip, HeapNumber::kValueOffset);
|
||||||
@ -1250,6 +1250,7 @@ void LCodeGen::DoIsNull(LIsNull* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
|
void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
|
||||||
|
Register scratch = scratch0();
|
||||||
Register reg = ToRegister(instr->input());
|
Register reg = ToRegister(instr->input());
|
||||||
|
|
||||||
// TODO(fsc): If the expression is known to be a smi, then it's
|
// TODO(fsc): If the expression is known to be a smi, then it's
|
||||||
@ -1273,7 +1274,6 @@ void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
|
|||||||
__ b(eq, false_label);
|
__ b(eq, false_label);
|
||||||
// Check for undetectable objects by looking in the bit field in
|
// Check for undetectable objects by looking in the bit field in
|
||||||
// the map. The object has already been smi checked.
|
// the map. The object has already been smi checked.
|
||||||
Register scratch = ToRegister(instr->temp());
|
|
||||||
__ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
|
__ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
|
||||||
__ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
|
__ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
|
||||||
__ tst(scratch, Operand(1 << Map::kIsUndetectable));
|
__ tst(scratch, Operand(1 << Map::kIsUndetectable));
|
||||||
@ -1351,8 +1351,8 @@ void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
|
void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
|
||||||
|
Register scratch = scratch0();
|
||||||
Register input = ToRegister(instr->input());
|
Register input = ToRegister(instr->input());
|
||||||
Register temp = ToRegister(instr->temp());
|
|
||||||
|
|
||||||
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());
|
||||||
@ -1362,7 +1362,7 @@ void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
|
|||||||
__ tst(input, Operand(kSmiTagMask));
|
__ tst(input, Operand(kSmiTagMask));
|
||||||
__ b(eq, false_label);
|
__ b(eq, false_label);
|
||||||
|
|
||||||
__ CompareObjectType(input, temp, temp, instr->TestType());
|
__ CompareObjectType(input, scratch, scratch, instr->TestType());
|
||||||
EmitBranch(true_block, false_block, instr->BranchCondition());
|
EmitBranch(true_block, false_block, instr->BranchCondition());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1533,19 +1533,19 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
|
void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
|
||||||
|
Register scratch = scratch0();
|
||||||
Register function = ToRegister(instr->function());
|
Register function = ToRegister(instr->function());
|
||||||
Register temp = ToRegister(instr->temporary());
|
|
||||||
Register result = ToRegister(instr->result());
|
Register result = ToRegister(instr->result());
|
||||||
|
|
||||||
// Check that the function really is a function. Load map into the
|
// Check that the function really is a function. Load map into the
|
||||||
// result register.
|
// result register.
|
||||||
__ CompareObjectType(function, result, temp, JS_FUNCTION_TYPE);
|
__ CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE);
|
||||||
DeoptimizeIf(ne, instr->environment());
|
DeoptimizeIf(ne, instr->environment());
|
||||||
|
|
||||||
// Make sure that the function has an instance prototype.
|
// Make sure that the function has an instance prototype.
|
||||||
Label non_instance;
|
Label non_instance;
|
||||||
__ ldrb(temp, FieldMemOperand(result, Map::kBitFieldOffset));
|
__ ldrb(scratch, FieldMemOperand(result, Map::kBitFieldOffset));
|
||||||
__ tst(temp, Operand(1 << Map::kHasNonInstancePrototype));
|
__ tst(scratch, Operand(1 << Map::kHasNonInstancePrototype));
|
||||||
__ b(ne, &non_instance);
|
__ b(ne, &non_instance);
|
||||||
|
|
||||||
// Get the prototype or initial map from the function.
|
// Get the prototype or initial map from the function.
|
||||||
@ -1559,7 +1559,7 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
|
|||||||
|
|
||||||
// If the function does not have an initial map, we're done.
|
// If the function does not have an initial map, we're done.
|
||||||
Label done;
|
Label done;
|
||||||
__ CompareObjectType(result, temp, temp, MAP_TYPE);
|
__ CompareObjectType(result, scratch, scratch, MAP_TYPE);
|
||||||
__ b(ne, &done);
|
__ b(ne, &done);
|
||||||
|
|
||||||
// Get the prototype from the initial map.
|
// Get the prototype from the initial map.
|
||||||
@ -1895,10 +1895,10 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
DoubleRegister input_reg = ToDoubleRegister(instr->input());
|
DoubleRegister input_reg = ToDoubleRegister(instr->input());
|
||||||
|
Register scratch = scratch0();
|
||||||
Register reg = ToRegister(instr->result());
|
Register reg = ToRegister(instr->result());
|
||||||
Register temp1 = ToRegister(instr->temp1());
|
Register temp1 = ToRegister(instr->temp1());
|
||||||
Register temp2 = ToRegister(instr->temp2());
|
Register temp2 = ToRegister(instr->temp2());
|
||||||
Register scratch = r9;
|
|
||||||
|
|
||||||
DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr);
|
DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr);
|
||||||
if (FLAG_inline_new) {
|
if (FLAG_inline_new) {
|
||||||
@ -1946,8 +1946,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
|
|||||||
void LCodeGen::EmitNumberUntagD(Register input_reg,
|
void LCodeGen::EmitNumberUntagD(Register input_reg,
|
||||||
DoubleRegister result_reg,
|
DoubleRegister result_reg,
|
||||||
LEnvironment* env) {
|
LEnvironment* env) {
|
||||||
Register core_scratch = r9;
|
Register scratch = scratch0();
|
||||||
ASSERT(!input_reg.is(core_scratch));
|
|
||||||
SwVfpRegister flt_scratch = s0;
|
SwVfpRegister flt_scratch = s0;
|
||||||
ASSERT(!result_reg.is(d0));
|
ASSERT(!result_reg.is(d0));
|
||||||
|
|
||||||
@ -1958,9 +1957,9 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
|
|||||||
__ b(eq, &load_smi);
|
__ b(eq, &load_smi);
|
||||||
|
|
||||||
// Heap number map check.
|
// Heap number map check.
|
||||||
__ ldr(core_scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
|
__ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
|
||||||
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
|
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
|
||||||
__ cmp(core_scratch, Operand(ip));
|
__ cmp(scratch, Operand(ip));
|
||||||
__ b(eq, &heap_number);
|
__ b(eq, &heap_number);
|
||||||
|
|
||||||
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
|
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
|
||||||
@ -2002,16 +2001,15 @@ class DeferredTaggedToI: public LDeferredCode {
|
|||||||
void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
|
void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
|
||||||
Label done;
|
Label done;
|
||||||
Register input_reg = ToRegister(instr->input());
|
Register input_reg = ToRegister(instr->input());
|
||||||
Register core_scratch = r9;
|
Register scratch = scratch0();
|
||||||
ASSERT(!input_reg.is(core_scratch));
|
|
||||||
DoubleRegister dbl_scratch = d0;
|
DoubleRegister dbl_scratch = d0;
|
||||||
SwVfpRegister flt_scratch = s0;
|
SwVfpRegister flt_scratch = s0;
|
||||||
DoubleRegister dbl_tmp = ToDoubleRegister(instr->temp());
|
DoubleRegister dbl_tmp = ToDoubleRegister(instr->temp());
|
||||||
|
|
||||||
// Heap number map check.
|
// Heap number map check.
|
||||||
__ ldr(core_scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
|
__ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
|
||||||
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
|
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
|
||||||
__ cmp(core_scratch, Operand(ip));
|
__ cmp(scratch, Operand(ip));
|
||||||
|
|
||||||
if (instr->truncating()) {
|
if (instr->truncating()) {
|
||||||
Label heap_number;
|
Label heap_number;
|
||||||
@ -2123,11 +2121,12 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void LCodeGen::DoCheckMap(LCheckMap* instr) {
|
void LCodeGen::DoCheckMap(LCheckMap* instr) {
|
||||||
|
Register scratch = scratch0();
|
||||||
LOperand* input = instr->input();
|
LOperand* input = instr->input();
|
||||||
ASSERT(input->IsRegister());
|
ASSERT(input->IsRegister());
|
||||||
Register reg = ToRegister(input);
|
Register reg = ToRegister(input);
|
||||||
__ ldr(r9, FieldMemOperand(reg, HeapObject::kMapOffset));
|
__ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
|
||||||
__ cmp(r9, Operand(instr->hydrogen()->map()));
|
__ cmp(scratch, Operand(instr->hydrogen()->map()));
|
||||||
DeoptimizeIf(ne, instr->environment());
|
DeoptimizeIf(ne, instr->environment());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2224,8 +2223,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
|||||||
Register input,
|
Register input,
|
||||||
Handle<String> type_name) {
|
Handle<String> type_name) {
|
||||||
Condition final_branch_condition = no_condition;
|
Condition final_branch_condition = no_condition;
|
||||||
Register core_scratch = r9;
|
Register scratch = scratch0();
|
||||||
ASSERT(!input.is(core_scratch));
|
|
||||||
if (type_name->Equals(Heap::number_symbol())) {
|
if (type_name->Equals(Heap::number_symbol())) {
|
||||||
__ tst(input, Operand(kSmiTagMask));
|
__ tst(input, Operand(kSmiTagMask));
|
||||||
__ b(eq, true_label);
|
__ b(eq, true_label);
|
||||||
@ -2241,7 +2239,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
|||||||
__ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
|
__ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
|
||||||
__ tst(ip, Operand(1 << Map::kIsUndetectable));
|
__ tst(ip, Operand(1 << Map::kIsUndetectable));
|
||||||
__ b(ne, false_label);
|
__ b(ne, false_label);
|
||||||
__ CompareInstanceType(input, core_scratch, FIRST_NONSTRING_TYPE);
|
__ CompareInstanceType(input, scratch, FIRST_NONSTRING_TYPE);
|
||||||
final_branch_condition = lo;
|
final_branch_condition = lo;
|
||||||
|
|
||||||
} else if (type_name->Equals(Heap::boolean_symbol())) {
|
} else if (type_name->Equals(Heap::boolean_symbol())) {
|
||||||
@ -2267,10 +2265,10 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
|||||||
} else if (type_name->Equals(Heap::function_symbol())) {
|
} else if (type_name->Equals(Heap::function_symbol())) {
|
||||||
__ tst(input, Operand(kSmiTagMask));
|
__ tst(input, Operand(kSmiTagMask));
|
||||||
__ b(eq, false_label);
|
__ b(eq, false_label);
|
||||||
__ CompareObjectType(input, input, core_scratch, JS_FUNCTION_TYPE);
|
__ CompareObjectType(input, input, scratch, JS_FUNCTION_TYPE);
|
||||||
__ b(eq, true_label);
|
__ b(eq, true_label);
|
||||||
// Regular expressions => 'function' (they are callable).
|
// Regular expressions => 'function' (they are callable).
|
||||||
__ CompareInstanceType(input, core_scratch, JS_REGEXP_TYPE);
|
__ CompareInstanceType(input, scratch, JS_REGEXP_TYPE);
|
||||||
final_branch_condition = eq;
|
final_branch_condition = eq;
|
||||||
|
|
||||||
} else if (type_name->Equals(Heap::object_symbol())) {
|
} else if (type_name->Equals(Heap::object_symbol())) {
|
||||||
@ -2280,16 +2278,16 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
|||||||
__ cmp(input, ip);
|
__ cmp(input, ip);
|
||||||
__ b(eq, true_label);
|
__ b(eq, true_label);
|
||||||
// Regular expressions => 'function', not 'object'.
|
// Regular expressions => 'function', not 'object'.
|
||||||
__ CompareObjectType(input, input, core_scratch, JS_REGEXP_TYPE);
|
__ CompareObjectType(input, input, scratch, JS_REGEXP_TYPE);
|
||||||
__ b(eq, false_label);
|
__ b(eq, false_label);
|
||||||
// Check for undetectable objects => false.
|
// Check for undetectable objects => false.
|
||||||
__ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
|
__ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
|
||||||
__ tst(ip, Operand(1 << Map::kIsUndetectable));
|
__ tst(ip, Operand(1 << Map::kIsUndetectable));
|
||||||
__ b(ne, false_label);
|
__ b(ne, false_label);
|
||||||
// Check for JS objects => true.
|
// Check for JS objects => true.
|
||||||
__ CompareInstanceType(input, core_scratch, FIRST_JS_OBJECT_TYPE);
|
__ CompareInstanceType(input, scratch, FIRST_JS_OBJECT_TYPE);
|
||||||
__ b(lo, false_label);
|
__ b(lo, false_label);
|
||||||
__ CompareInstanceType(input, core_scratch, LAST_JS_OBJECT_TYPE);
|
__ CompareInstanceType(input, scratch, LAST_JS_OBJECT_TYPE);
|
||||||
final_branch_condition = ls;
|
final_branch_condition = ls;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -103,6 +103,8 @@ class LCodeGen BASE_EMBEDDED {
|
|||||||
HGraph* graph() const { return chunk_->graph(); }
|
HGraph* graph() const { return chunk_->graph(); }
|
||||||
MacroAssembler* masm() const { return masm_; }
|
MacroAssembler* masm() const { return masm_; }
|
||||||
|
|
||||||
|
Register scratch0() { return r9; }
|
||||||
|
|
||||||
int GetNextEmittedBlock(int block);
|
int GetNextEmittedBlock(int block);
|
||||||
LInstruction* GetNextInstruction();
|
LInstruction* GetNextInstruction();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user