Index: src/x64/lithium-codegen-x64.cc |
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc |
index dbdc12e63f207bfe1e35ef52ce50488ecd133980..03a5bfd2ba19c2dc3d403e86710726ba978db9cb 100644 |
--- a/src/x64/lithium-codegen-x64.cc |
+++ b/src/x64/lithium-codegen-x64.cc |
@@ -64,6 +64,30 @@ class SafepointGenerator : public CallWrapper { |
}; |
+class LSmiFunctionInvoker : public MacroAssembler::SmiFunctionInvoker { |
+ public: |
+ LSmiFunctionInvoker(LCodeGen* codegen, |
+ LEnvironment* environment, |
+ bool check_minus_zero) |
+ : MacroAssembler::SmiFunctionInvoker(NULL), |
+ codegen_(codegen), |
+ environment_(environment), |
+ check_minus_zero_(check_minus_zero) { } |
+ virtual ~LSmiFunctionInvoker() { } |
+ virtual void Bailout() { |
+ codegen_->DeoptimizeIf(no_condition, environment_); |
+ } |
+ virtual Label* on_not_smi_result() { return NULL; } |
+ virtual bool reserve_source_operands() { return false; } |
+ virtual bool check_minus_zero() { return check_minus_zero_; } |
+ |
+ private: |
+ LCodeGen* codegen_; |
+ LEnvironment* environment_; |
+ bool check_minus_zero_; |
+}; |
+ |
+ |
#define __ masm()-> |
bool LCodeGen::GenerateCode() { |
@@ -416,8 +440,17 @@ bool LCodeGen::IsTaggedConstant(LConstantOperand* op) const { |
int32_t LCodeGen::ToInteger32(LConstantOperand* op) const { |
+ return ToRepresentation(op, Representation::Integer32()); |
+} |
+ |
+ |
+int32_t LCodeGen::ToRepresentation(LConstantOperand* op, |
+ const Representation& r) const { |
HConstant* constant = chunk_->LookupConstant(op); |
- return constant->Integer32Value(); |
+ int32_t value = constant->Integer32Value(); |
+ if (r.IsInteger32()) return value; |
+ ASSERT(r.IsSmiOrTagged()); |
+ return static_cast<int32_t>(reinterpret_cast<intptr_t>(Smi::FromInt(value))); |
} |
@@ -1362,16 +1395,29 @@ void LCodeGen::DoBitI(LBitI* instr) { |
ASSERT(left->IsRegister()); |
if (right->IsConstantOperand()) { |
- int right_operand = ToInteger32(LConstantOperand::cast(right)); |
+ int right_operand = ToRepresentation(LConstantOperand::cast(right), |
+ instr->hydrogen()->representation()); |
switch (instr->op()) { |
case Token::BIT_AND: |
- __ andl(ToRegister(left), Immediate(right_operand)); |
+ if (instr->hydrogen()->representation().IsSmi()) { |
danno
2013/08/07 18:41:26
Is this really correct (here and below)? The non-s
haitao.feng
2013/08/12 09:54:24
It is really correct. This code utilizes a hardwar
|
+ __ and_(ToRegister(left), Immediate(right_operand)); |
+ } else { |
+ __ andl(ToRegister(left), Immediate(right_operand)); |
+ } |
break; |
case Token::BIT_OR: |
- __ orl(ToRegister(left), Immediate(right_operand)); |
+ if (instr->hydrogen()->representation().IsSmi()) { |
+ __ or_(ToRegister(left), Immediate(right_operand)); |
danno
2013/08/07 18:41:26
Same here.
haitao.feng
2013/08/12 09:54:24
Explained above.
|
+ } else { |
+ __ orl(ToRegister(left), Immediate(right_operand)); |
+ } |
break; |
case Token::BIT_XOR: |
- __ xorl(ToRegister(left), Immediate(right_operand)); |
+ if (instr->hydrogen()->representation().IsSmi()) { |
danno
2013/08/07 18:41:26
Same here.
haitao.feng
2013/08/12 09:54:24
Explained above.
|
+ __ xor_(ToRegister(left), Immediate(right_operand)); |
+ } else { |
+ __ xorl(ToRegister(left), Immediate(right_operand)); |
+ } |
break; |
default: |
UNREACHABLE(); |
@@ -1466,7 +1512,14 @@ void LCodeGen::DoShiftI(LShiftI* instr) { |
case Token::SHL: |
if (shift_count != 0) { |
if (instr->hydrogen_value()->representation().IsSmi()) { |
- __ shl(ToRegister(left), Immediate(shift_count)); |
+ if (kSmiValueSize == 32 || !instr->can_deopt()) { |
+ __ shl(ToRegister(left), Immediate(shift_count)); |
+ } else { |
+ ASSERT(kSmiValueSize == 31 && instr->can_deopt()); |
+ LSmiFunctionInvoker invoker(this, instr->environment(), false); |
+ __ SmiShiftLeftConstant(ToRegister(left), ToRegister(left), |
+ shift_count, invoker); |
+ } |
} else { |
__ shll(ToRegister(left), Immediate(shift_count)); |
} |
@@ -1487,16 +1540,27 @@ void LCodeGen::DoSubI(LSubI* instr) { |
if (right->IsConstantOperand()) { |
__ subl(ToRegister(left), |
- Immediate(ToInteger32(LConstantOperand::cast(right)))); |
+ Immediate(ToRepresentation(LConstantOperand::cast(right), |
+ instr->hydrogen()->representation()))); |
} else if (right->IsRegister()) { |
if (instr->hydrogen_value()->representation().IsSmi()) { |
- __ subq(ToRegister(left), ToRegister(right)); |
+ if (kSmiValueSize == 32) { |
+ __ subq(ToRegister(left), ToRegister(right)); |
+ } else { |
+ ASSERT(kSmiValueSize == 31); |
+ __ subl(ToRegister(left), ToRegister(right)); |
+ } |
} else { |
__ subl(ToRegister(left), ToRegister(right)); |
} |
} else { |
if (instr->hydrogen_value()->representation().IsSmi()) { |
- __ subq(ToRegister(left), ToOperand(right)); |
+ if (kSmiValueSize == 32) { |
+ __ subq(ToRegister(left), ToOperand(right)); |
+ } else { |
+ ASSERT(kSmiValueSize == 31); |
+ __ subl(ToRegister(left), ToOperand(right)); |
+ } |
} else { |
__ subl(ToRegister(left), ToOperand(right)); |
} |
@@ -1505,6 +1569,11 @@ void LCodeGen::DoSubI(LSubI* instr) { |
if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
DeoptimizeIf(overflow, instr->environment()); |
} |
+ |
+ if (kSmiValueSize == 31 && |
+ instr->hydrogen_value()->representation().IsSmi()) { |
+ __ movsxlq(ToRegister(left), ToRegister(left)); |
+ } |
} |
@@ -1680,9 +1749,15 @@ void LCodeGen::DoAddI(LAddI* instr) { |
if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) { |
if (right->IsConstantOperand()) { |
- int32_t offset = ToInteger32(LConstantOperand::cast(right)); |
- __ leal(ToRegister(instr->result()), |
- MemOperand(ToRegister(left), offset)); |
+ int32_t offset = ToRepresentation(LConstantOperand::cast(right), |
+ instr->hydrogen()->representation()); |
+ if (instr->hydrogen()->representation().IsSmi()) { |
+ __ lea(ToRegister(instr->result()), |
danno
2013/08/07 18:41:26
Here and below, I think all Smi operations should
haitao.feng
2013/08/12 09:54:24
Done.
|
+ MemOperand(ToRegister(left), offset)); |
+ } else { |
+ __ leal(ToRegister(instr->result()), |
+ MemOperand(ToRegister(left), offset)); |
+ } |
} else { |
Operand address(ToRegister(left), ToRegister(right), times_1, 0); |
if (instr->hydrogen()->representation().IsSmi()) { |
@@ -1694,16 +1769,27 @@ void LCodeGen::DoAddI(LAddI* instr) { |
} else { |
if (right->IsConstantOperand()) { |
__ addl(ToRegister(left), |
- Immediate(ToInteger32(LConstantOperand::cast(right)))); |
+ Immediate(ToRepresentation(LConstantOperand::cast(right), |
+ instr->hydrogen()->representation()))); |
} else if (right->IsRegister()) { |
if (instr->hydrogen_value()->representation().IsSmi()) { |
- __ addq(ToRegister(left), ToRegister(right)); |
+ if (kSmiValueSize == 32) { |
+ __ addq(ToRegister(left), ToRegister(right)); |
+ } else { |
+ ASSERT(kSmiValueSize == 31); |
+ __ addl(ToRegister(left), ToRegister(right)); |
+ } |
} else { |
__ addl(ToRegister(left), ToRegister(right)); |
} |
} else { |
if (instr->hydrogen_value()->representation().IsSmi()) { |
- __ addq(ToRegister(left), ToOperand(right)); |
+ if (kSmiValueSize == 32) { |
+ __ addq(ToRegister(left), ToOperand(right)); |
+ } else { |
+ ASSERT(kSmiValueSize == 31); |
+ __ addl(ToRegister(left), ToOperand(right)); |
+ } |
} else { |
__ addl(ToRegister(left), ToOperand(right)); |
} |
@@ -1711,6 +1797,11 @@ void LCodeGen::DoAddI(LAddI* instr) { |
if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
DeoptimizeIf(overflow, instr->environment()); |
} |
+ |
+ if (kSmiValueSize == 31 && |
+ instr->hydrogen_value()->representation().IsSmi()) { |
+ __ movsxlq(ToRegister(left), ToRegister(left)); |
+ } |
} |
} |
@@ -1728,8 +1819,8 @@ void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
Register left_reg = ToRegister(left); |
if (right->IsConstantOperand()) { |
Immediate right_imm = |
- Immediate(ToInteger32(LConstantOperand::cast(right))); |
- ASSERT(!instr->hydrogen_value()->representation().IsSmi()); |
+ Immediate(ToRepresentation(LConstantOperand::cast(right), |
+ instr->hydrogen()->representation())); |
__ cmpl(left_reg, right_imm); |
__ j(condition, &return_left, Label::kNear); |
__ movq(left_reg, right_imm); |
@@ -2927,7 +3018,10 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { |
// gets replaced during bound check elimination with the index argument |
// to the bounds check, which can be tagged, so that case must be |
// handled here, too. |
- if (instr->hydrogen()->IsDehoisted()) { |
+ if (kSmiValueSize == 31 && |
+ instr->hydrogen()->key()->representation().IsSmi()) { |
+ __ SmiToInteger64(key_reg, key_reg); |
+ } else if (instr->hydrogen()->IsDehoisted()) { |
// Sign extend key because it could be a 32 bit negative value |
// and the dehoisted address computation happens in 64 bits |
__ movsxlq(key_reg, key_reg); |
@@ -2998,7 +3092,10 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { |
// representation for the key to be an integer, the input gets replaced |
// during bound check elimination with the index argument to the bounds |
// check, which can be tagged, so that case must be handled here, too. |
- if (instr->hydrogen()->IsDehoisted()) { |
+ if (kSmiValueSize == 31 && |
+ instr->hydrogen()->key()->representation().IsSmi()) { |
+ __ SmiToInteger64(key_reg, key_reg); |
+ } else if (instr->hydrogen()->IsDehoisted()) { |
// Sign extend key because it could be a 32 bit negative value |
// and the dehoisted address computation happens in 64 bits |
__ movsxlq(key_reg, key_reg); |
@@ -3038,7 +3135,10 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
// gets replaced during bound check elimination with the index |
// argument to the bounds check, which can be tagged, so that |
// case must be handled here, too. |
- if (instr->hydrogen()->IsDehoisted()) { |
+ if (kSmiValueSize == 31 && |
+ instr->hydrogen()->key()->representation().IsSmi()) { |
+ __ SmiToInteger64(key_reg, key_reg); |
+ } else if (instr->hydrogen()->IsDehoisted()) { |
// Sign extend key because it could be a 32 bit negative value |
// and the dehoisted address computation happens in 64 bits |
__ movsxlq(key_reg, key_reg); |
@@ -3426,12 +3526,17 @@ void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { |
} |
-void LCodeGen::EmitInteger64MathAbs(LMathAbs* instr) { |
+void LCodeGen::EmitSmiMathAbs(LMathAbs* instr) { |
haitao.feng
2013/08/06 07:58:56
Please ignore this part as Weiliang submitted a CL
|
Register input_reg = ToRegister(instr->value()); |
__ testq(input_reg, input_reg); |
Label is_positive; |
__ j(not_sign, &is_positive, Label::kNear); |
- __ neg(input_reg); // Sets flags. |
+ if (kSmiValueSize == 32) { |
+ __ neg(input_reg); // Sets flags. |
+ } else { |
+ ASSERT(kSmiValueSize == 31); |
+ __ negl(input_reg); // Sets flags. |
+ } |
DeoptimizeIf(negative, instr->environment()); |
__ bind(&is_positive); |
} |
@@ -3463,16 +3568,14 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) { |
} else if (r.IsInteger32()) { |
EmitIntegerMathAbs(instr); |
} else if (r.IsSmi()) { |
- EmitInteger64MathAbs(instr); |
+ EmitSmiMathAbs(instr); |
} else { // Tagged case. |
DeferredMathAbsTaggedHeapNumber* deferred = |
new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); |
Register input_reg = ToRegister(instr->value()); |
// Smi check. |
__ JumpIfNotSmi(input_reg, deferred->entry()); |
- __ SmiToInteger32(input_reg, input_reg); |
- EmitIntegerMathAbs(instr); |
- __ Integer32ToSmi(input_reg, input_reg); |
+ EmitSmiMathAbs(instr); |
__ bind(deferred->exit()); |
} |
} |
@@ -4140,7 +4243,10 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
// gets replaced during bound check elimination with the index |
// argument to the bounds check, which can be tagged, so that case |
// must be handled here, too. |
- if (instr->hydrogen()->IsDehoisted()) { |
+ if (kSmiValueSize == 31 && |
+ instr->hydrogen()->key()->representation().IsSmi()) { |
+ __ SmiToInteger64(key_reg, key_reg); |
+ } else if (instr->hydrogen()->IsDehoisted()) { |
// Sign extend key because it could be a 32 bit negative value |
// and the dehoisted address computation happens in 64 bits |
__ movsxlq(key_reg, key_reg); |
@@ -4202,7 +4308,10 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { |
// input gets replaced during bound check elimination with the index |
// argument to the bounds check, which can be tagged, so that case |
// must be handled here, too. |
- if (instr->hydrogen()->IsDehoisted()) { |
+ if (kSmiValueSize == 31 && |
+ instr->hydrogen()->key()->representation().IsSmi()) { |
+ __ SmiToInteger64(key_reg, key_reg); |
+ } else if (instr->hydrogen()->IsDehoisted()) { |
// Sign extend key because it could be a 32 bit negative value |
// and the dehoisted address computation happens in 64 bits |
__ movsxlq(key_reg, key_reg); |
@@ -4243,7 +4352,10 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { |
// input gets replaced during bound check elimination with the index |
// argument to the bounds check, which can be tagged, so that case |
// must be handled here, too. |
- if (instr->hydrogen()->IsDehoisted()) { |
+ if (kSmiValueSize == 31 && |
+ instr->hydrogen()->key()->representation().IsSmi()) { |
+ __ SmiToInteger64(key_reg, key_reg); |
+ } else if (instr->hydrogen()->IsDehoisted()) { |
// Sign extend key because it could be a 32 bit negative value |
// and the dehoisted address computation happens in 64 bits |
__ movsxlq(key_reg, key_reg); |
@@ -4500,11 +4612,77 @@ void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { |
void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
- LOperand* input = instr->value(); |
- ASSERT(input->IsRegister() && input->Equals(instr->result())); |
- Register reg = ToRegister(input); |
+ if (kSmiValueSize == 32) { |
+ LOperand* input = instr->value(); |
+ ASSERT(input->IsRegister() && input->Equals(instr->result())); |
+ Register reg = ToRegister(input); |
- __ Integer32ToSmi(reg, reg); |
+ __ Integer32ToSmi(reg, reg); |
+ } else { |
+ ASSERT(kSmiValueSize == 31); |
+ class DeferredNumberTagI: public LDeferredCode { |
+ public: |
+ DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
+ : LDeferredCode(codegen), instr_(instr) { } |
+ virtual void Generate() { |
+ codegen()->DoDeferredNumberTagI(instr_); |
+ } |
+ virtual LInstruction* instr() { return instr_; } |
+ private: |
+ LNumberTagI* instr_; |
+ }; |
+ |
+ LOperand* input = instr->value(); |
+ ASSERT(input->IsRegister() && input->Equals(instr->result())); |
+ Register reg = ToRegister(input); |
+ |
+ DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); |
+ __ shll(reg, Immediate(kSmiTagSize + kSmiShiftSize)); |
+ __ j(overflow, deferred->entry()); |
+ __ movsxlq(reg, reg); |
+ __ bind(deferred->exit()); |
+ } |
+} |
+ |
+ |
+void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { |
+ ASSERT(kSmiValueSize == 31); |
+ Label slow; |
+ Register reg = ToRegister(instr->value()); |
+ Register tmp = reg.is(rax) ? kScratchRegister : rax; |
+ |
+ // Preserve the value of all registers. |
+ PushSafepointRegistersScope scope(this); |
+ |
+ Label done; |
+ // There was overflow, so bits 30 and 31 of the original integer |
+ // disagree. Try to allocate a heap number in new space and store |
+ // the value in there. If that fails, call the runtime system. |
+ __ SmiToInteger32(reg, reg); |
+ __ xorl(reg, Immediate(0x80000000)); |
+ __ cvtlsi2sd(xmm1, reg); |
+ |
+ if (FLAG_inline_new) { |
+ __ AllocateHeapNumber(reg, tmp, &slow); |
+ __ jmp(&done, Label::kNear); |
+ } |
+ |
+ // Slow case: Call the runtime system to do the number allocation. |
+ __ bind(&slow); |
+ |
+ // Put a valid pointer value in the stack slot where the result |
+ // register is stored, as this register is in the pointer map, but contains an |
+ // integer value. |
+ __ StoreToSafepointRegisterSlot(reg, Immediate(0)); |
+ CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
+ // Set the pointer to the new heap number in tmp. |
+ if (!reg.is(rax)) __ movq(reg, rax); |
+ |
+ // Heap number allocated. Put the value in xmm0 into the value of the |
+ // allocated heap number. |
+ __ bind(&done); |
+ __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm1); |
+ __ StoreToSafepointRegisterSlot(reg, reg); |
} |