Index: src/x64/lithium-codegen-x64.cc |
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc |
index 6f45b81082a93fe5eda2d44901872425a49f215c..7115f37091bc924dbd4a56eecb757549d7dcbb9e 100644 |
--- a/src/x64/lithium-codegen-x64.cc |
+++ b/src/x64/lithium-codegen-x64.cc |
@@ -411,8 +411,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))); |
} |
@@ -1301,14 +1310,24 @@ void LCodeGen::DoMulI(LMulI* instr) { |
} else if (right->IsStackSlot()) { |
if (instr->hydrogen_value()->representation().IsSmi()) { |
__ SmiToInteger32(left, left); |
- __ imul(left, ToOperand(right)); |
+ if (kSmiValueSize == 32) { |
+ __ imul(left, ToOperand(right)); |
danno
2013/08/01 16:45:41
Move this switching into the macro assembler, you
|
+ } else { |
+ ASSERT(kSmiValueSize == 31); |
+ __ imull(left, ToOperand(right)); |
+ } |
} else { |
__ imull(left, ToOperand(right)); |
} |
} else { |
if (instr->hydrogen_value()->representation().IsSmi()) { |
__ SmiToInteger32(left, left); |
- __ imul(left, ToRegister(right)); |
+ if (kSmiValueSize == 32) { |
+ __ imul(left, ToOperand(right)); |
+ } else { |
+ ASSERT(kSmiValueSize == 31); |
+ __ imull(left, ToOperand(right)); |
+ } |
} else { |
__ imull(left, ToRegister(right)); |
} |
@@ -1318,6 +1337,11 @@ void LCodeGen::DoMulI(LMulI* instr) { |
DeoptimizeIf(overflow, instr->environment()); |
} |
+ if (kSmiValueSize == 31 && |
+ instr->hydrogen_value()->representation().IsSmi()) { |
+ __ movsxlq(left, left); |
+ } |
+ |
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
// Bail out if the result is supposed to be negative zero. |
Label done; |
@@ -1350,16 +1374,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()) { |
+ __ 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)); |
+ } else { |
+ __ orl(ToRegister(left), Immediate(right_operand)); |
+ } |
break; |
case Token::BIT_XOR: |
- __ xorl(ToRegister(left), Immediate(right_operand)); |
+ if (instr->hydrogen()->representation().IsSmi()) { |
+ __ xor_(ToRegister(left), Immediate(right_operand)); |
+ } else { |
+ __ xorl(ToRegister(left), Immediate(right_operand)); |
+ } |
break; |
default: |
UNREACHABLE(); |
@@ -1475,16 +1512,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)); |
} |
@@ -1493,6 +1541,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)); |
+ } |
} |
@@ -1663,9 +1716,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()), |
+ 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()) { |
@@ -1677,16 +1736,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)); |
} |
@@ -1694,6 +1764,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)); |
+ } |
} |
} |
@@ -1711,8 +1786,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); |
@@ -2910,7 +2985,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); |
@@ -2981,7 +3059,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); |
@@ -3021,7 +3102,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); |
@@ -4097,7 +4181,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); |
@@ -4159,7 +4246,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); |
@@ -4200,7 +4290,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); |
@@ -4486,11 +4579,76 @@ 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) { |
+ 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); |
} |