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 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); |
| } |