Chromium Code Reviews| 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); |
| } |