Index: src/ia32/lithium-codegen-ia32.cc |
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc |
index 10115b1ac4744b14b0043293e0fc783b862502f5..d988ff0ee23590a17a7505210598267cc0f85255 100644 |
--- a/src/ia32/lithium-codegen-ia32.cc |
+++ b/src/ia32/lithium-codegen-ia32.cc |
@@ -446,6 +446,7 @@ bool LCodeGen::GenerateDeferredCode() { |
Comment(";;; Deferred code"); |
} |
code->Generate(); |
+ __ bind(code->done()); |
if (NeedsDeferredFrame()) { |
Comment(";;; Destroy frame"); |
ASSERT(frame_is_built_); |
@@ -5273,94 +5274,39 @@ void LCodeGen::EmitNumberUntagD(Register input_reg, |
} |
-void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
- Label done, heap_number; |
+void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) { |
Register input_reg = ToRegister(instr->value()); |
- // Heap number map check. |
- __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
- factory()->heap_number_map()); |
if (instr->truncating()) { |
+ Label heap_number, slow_case; |
+ |
+ // Heap number map check. |
+ __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
+ factory()->heap_number_map()); |
__ j(equal, &heap_number, Label::kNear); |
+ |
// Check for undefined. Undefined is converted to zero for truncating |
// conversions. |
__ cmp(input_reg, factory()->undefined_value()); |
__ RecordComment("Deferred TaggedToI: cannot truncate"); |
DeoptimizeIf(not_equal, instr->environment()); |
__ mov(input_reg, 0); |
- __ jmp(&done, Label::kNear); |
+ __ jmp(done); |
__ bind(&heap_number); |
- if (CpuFeatures::IsSupported(SSE3)) { |
- CpuFeatureScope scope(masm(), SSE3); |
- Label convert; |
- // Use more powerful conversion when sse3 is available. |
- // Load x87 register with heap number. |
- __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); |
- // Get exponent alone and check for too-big exponent. |
- __ mov(input_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
- __ and_(input_reg, HeapNumber::kExponentMask); |
- const uint32_t kTooBigExponent = |
- (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; |
- __ cmp(Operand(input_reg), Immediate(kTooBigExponent)); |
- __ j(less, &convert, Label::kNear); |
- // Pop FPU stack before deoptimizing. |
- __ fstp(0); |
- __ RecordComment("Deferred TaggedToI: exponent too big"); |
- DeoptimizeIf(no_condition, instr->environment()); |
- |
- // Reserve space for 64 bit answer. |
- __ bind(&convert); |
- __ sub(Operand(esp), Immediate(kDoubleSize)); |
- // Do conversion, which cannot fail because we checked the exponent. |
- __ fisttp_d(Operand(esp, 0)); |
- __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. |
- __ add(Operand(esp), Immediate(kDoubleSize)); |
- } else if (CpuFeatures::IsSupported(SSE2)) { |
- CpuFeatureScope scope(masm(), SSE2); |
- XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); |
- __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
- __ cvttsd2si(input_reg, Operand(xmm0)); |
- __ cmp(input_reg, 0x80000000u); |
- __ j(not_equal, &done); |
- // Check if the input was 0x8000000 (kMinInt). |
- // If no, then we got an overflow and we deoptimize. |
- ExternalReference min_int = ExternalReference::address_of_min_int(); |
- __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); |
- __ ucomisd(xmm_temp, xmm0); |
- DeoptimizeIf(not_equal, instr->environment()); |
- DeoptimizeIf(parity_even, instr->environment()); // NaN. |
- } else { |
- UNREACHABLE(); |
- } |
- } else if (CpuFeatures::IsSupported(SSE2)) { |
- CpuFeatureScope scope(masm(), SSE2); |
- // Deoptimize if we don't have a heap number. |
- __ RecordComment("Deferred TaggedToI: not a heap number"); |
- DeoptimizeIf(not_equal, instr->environment()); |
- |
- XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); |
- __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
- __ cvttsd2si(input_reg, Operand(xmm0)); |
- __ cvtsi2sd(xmm_temp, Operand(input_reg)); |
- __ ucomisd(xmm0, xmm_temp); |
- __ RecordComment("Deferred TaggedToI: lost precision"); |
- DeoptimizeIf(not_equal, instr->environment()); |
- __ RecordComment("Deferred TaggedToI: NaN"); |
- DeoptimizeIf(parity_even, instr->environment()); // NaN. |
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
- __ test(input_reg, Operand(input_reg)); |
- __ j(not_zero, &done); |
- __ movmskpd(input_reg, xmm0); |
- __ and_(input_reg, 1); |
- __ RecordComment("Deferred TaggedToI: minus zero"); |
- DeoptimizeIf(not_zero, instr->environment()); |
- } |
+ __ TruncateHeapNumberToI(input_reg, input_reg); |
} else { |
- UNREACHABLE(); |
+ Label bailout; |
+ XMMRegister scratch = (instr->temp() != NULL) |
+ ? ToDoubleRegister(instr->temp()) |
+ : no_xmm_reg; |
+ __ TaggedToI(input_reg, input_reg, scratch, |
+ instr->hydrogen()->GetMinusZeroMode(), &bailout); |
+ __ jmp(done); |
+ __ bind(&bailout); |
+ DeoptimizeIf(no_condition, instr->environment()); |
} |
- __ bind(&done); |
} |
@@ -5370,7 +5316,7 @@ void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
: LDeferredCode(codegen), instr_(instr) { } |
virtual void Generate() V8_OVERRIDE { |
- codegen()->DoDeferredTaggedToI(instr_); |
+ codegen()->DoDeferredTaggedToI(instr_, done()); |
} |
virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
private: |
@@ -5390,169 +5336,6 @@ void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
} |
-void LCodeGen::DoDeferredTaggedToINoSSE2(LTaggedToINoSSE2* instr) { |
- Label done, heap_number; |
- Register result_reg = ToRegister(instr->result()); |
- Register input_reg = ToRegister(instr->value()); |
- |
- // Heap number map check. |
- __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
- factory()->heap_number_map()); |
- if (instr->truncating()) { |
- __ j(equal, &heap_number, Label::kNear); |
- // Check for undefined. Undefined is converted to zero for truncating |
- // conversions. |
- __ cmp(input_reg, factory()->undefined_value()); |
- __ RecordComment("Deferred TaggedToI: cannot truncate"); |
- DeoptimizeIf(not_equal, instr->environment()); |
- __ xor_(result_reg, result_reg); |
- __ jmp(&done, Label::kFar); |
- __ bind(&heap_number); |
- } else { |
- // Deoptimize if we don't have a heap number. |
- DeoptimizeIf(not_equal, instr->environment()); |
- } |
- |
- // Surprisingly, all of this crazy bit manipulation is considerably |
- // faster than using the built-in x86 CPU conversion functions (about 6x). |
- Label right_exponent, adjust_bias, zero_result; |
- Register scratch = ToRegister(instr->scratch()); |
- Register scratch2 = ToRegister(instr->scratch2()); |
- // Get exponent word. |
- __ mov(scratch, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
- // Get exponent alone in scratch2. |
- __ mov(scratch2, scratch); |
- __ and_(scratch2, HeapNumber::kExponentMask); |
- __ shr(scratch2, HeapNumber::kExponentShift); |
- if (instr->truncating()) { |
- __ j(zero, &zero_result); |
- } else { |
- __ j(not_zero, &adjust_bias); |
- __ test(scratch, Immediate(HeapNumber::kMantissaMask)); |
- DeoptimizeIf(not_zero, instr->environment()); |
- __ cmp(FieldOperand(input_reg, HeapNumber::kMantissaOffset), Immediate(0)); |
- DeoptimizeIf(not_equal, instr->environment()); |
- __ bind(&adjust_bias); |
- } |
- __ sub(scratch2, Immediate(HeapNumber::kExponentBias)); |
- if (!instr->truncating()) { |
- DeoptimizeIf(negative, instr->environment()); |
- } else { |
- __ j(negative, &zero_result); |
- } |
- |
- // Get the second half of the double. For some exponents we don't |
- // actually need this because the bits get shifted out again, but |
- // it's probably slower to test than just to do it. |
- Register scratch3 = ToRegister(instr->scratch3()); |
- __ mov(scratch3, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); |
- __ xor_(result_reg, result_reg); |
- |
- const uint32_t non_int32_exponent = 31; |
- __ cmp(scratch2, Immediate(non_int32_exponent)); |
- // If we have a match of the int32 exponent then skip some logic. |
- __ j(equal, &right_exponent, Label::kNear); |
- // If the number doesn't find in an int32, deopt. |
- DeoptimizeIf(greater, instr->environment()); |
- |
- // Exponent word in scratch, exponent in scratch2. We know that 0 <= exponent |
- // < 31. |
- __ mov(result_reg, Immediate(31)); |
- __ sub(result_reg, scratch2); |
- |
- __ bind(&right_exponent); |
- |
- // Save off exponent for negative check later. |
- __ mov(scratch2, scratch); |
- |
- // Here result_reg is the shift, scratch is the exponent word. |
- // Get the top bits of the mantissa. |
- __ and_(scratch, HeapNumber::kMantissaMask); |
- // Put back the implicit 1. |
- __ or_(scratch, 1 << HeapNumber::kExponentShift); |
- // Shift up the mantissa bits to take up the space the exponent used to |
- // take. We have kExponentShift + 1 significant bits int he low end of the |
- // word. Shift them to the top bits. |
- const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 1; |
- __ shl(scratch, shift_distance); |
- if (!instr->truncating()) { |
- // If not truncating, a non-zero value in the bottom 22 bits means a |
- // non-integral value --> trigger a deopt. |
- __ test(scratch3, Immediate((1 << (32 - shift_distance)) - 1)); |
- DeoptimizeIf(not_equal, instr->environment()); |
- } |
- // Shift down 22 bits to get the most significant 10 bits or the low |
- // mantissa word. |
- __ shr(scratch3, 32 - shift_distance); |
- __ or_(scratch3, scratch); |
- if (!instr->truncating()) { |
- // If truncating, a non-zero value in the bits that will be shifted away |
- // when adjusting the exponent means rounding --> deopt. |
- __ mov(scratch, 0x1); |
- ASSERT(result_reg.is(ecx)); |
- __ shl_cl(scratch); |
- __ dec(scratch); |
- __ test(scratch3, scratch); |
- DeoptimizeIf(not_equal, instr->environment()); |
- } |
- // Move down according to the exponent. |
- ASSERT(result_reg.is(ecx)); |
- __ shr_cl(scratch3); |
- // Now the unsigned 32-bit answer is in scratch3. We need to move it to |
- // result_reg and we may need to fix the sign. |
- Label negative_result; |
- __ xor_(result_reg, result_reg); |
- __ cmp(scratch2, result_reg); |
- __ j(less, &negative_result, Label::kNear); |
- __ cmp(scratch3, result_reg); |
- __ mov(result_reg, scratch3); |
- // If the result is > MAX_INT, result doesn't fit in signed 32-bit --> deopt. |
- DeoptimizeIf(less, instr->environment()); |
- __ jmp(&done, Label::kNear); |
- __ bind(&zero_result); |
- __ xor_(result_reg, result_reg); |
- __ jmp(&done, Label::kNear); |
- __ bind(&negative_result); |
- __ sub(result_reg, scratch3); |
- if (!instr->truncating()) { |
- // -0.0 triggers a deopt. |
- DeoptimizeIf(zero, instr->environment()); |
- } |
- // If the negative subtraction overflows into a positive number, there was an |
- // overflow --> deopt. |
- DeoptimizeIf(positive, instr->environment()); |
- __ bind(&done); |
-} |
- |
- |
-void LCodeGen::DoTaggedToINoSSE2(LTaggedToINoSSE2* instr) { |
- class DeferredTaggedToINoSSE2 V8_FINAL : public LDeferredCode { |
- public: |
- DeferredTaggedToINoSSE2(LCodeGen* codegen, LTaggedToINoSSE2* instr) |
- : LDeferredCode(codegen), instr_(instr) { } |
- virtual void Generate() V8_OVERRIDE { |
- codegen()->DoDeferredTaggedToINoSSE2(instr_); |
- } |
- virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
- private: |
- LTaggedToINoSSE2* instr_; |
- }; |
- |
- LOperand* input = instr->value(); |
- ASSERT(input->IsRegister()); |
- Register input_reg = ToRegister(input); |
- ASSERT(input_reg.is(ToRegister(instr->result()))); |
- |
- DeferredTaggedToINoSSE2* deferred = |
- new(zone()) DeferredTaggedToINoSSE2(this, instr); |
- |
- // Smi check. |
- __ JumpIfNotSmi(input_reg, deferred->entry()); |
- __ SmiUntag(input_reg); // Untag smi. |
- __ bind(deferred->exit()); |
-} |
- |
- |
void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
LOperand* input = instr->value(); |
ASSERT(input->IsRegister()); |
@@ -5599,73 +5382,33 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
ASSERT(result->IsRegister()); |
Register result_reg = ToRegister(result); |
- Label done; |
- if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
- CpuFeatureScope scope(masm(), SSE2); |
- |
- XMMRegister input_reg = ToDoubleRegister(input); |
- |
- __ cvttsd2si(result_reg, Operand(input_reg)); |
- |
- if (instr->truncating()) { |
- // Performs a truncating conversion of a floating point number as used by |
- // the JS bitwise operations. |
- Label fast_case_succeeded; |
- __ cmp(result_reg, 0x80000000u); |
- __ j(not_equal, &fast_case_succeeded); |
- __ sub(esp, Immediate(kDoubleSize)); |
- __ movdbl(MemOperand(esp, 0), input_reg); |
- DoubleToIStub stub(esp, result_reg, 0, true); |
- __ call(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); |
- __ add(esp, Immediate(kDoubleSize)); |
- __ bind(&fast_case_succeeded); |
+ if (instr->truncating()) { |
+ if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
+ CpuFeatureScope scope(masm(), SSE2); |
+ XMMRegister input_reg = ToDoubleRegister(input); |
+ __ TruncateDoubleToI(result_reg, input_reg); |
} else { |
- __ cvtsi2sd(xmm0, Operand(result_reg)); |
- __ ucomisd(xmm0, input_reg); |
- DeoptimizeIf(not_equal, instr->environment()); |
- DeoptimizeIf(parity_even, instr->environment()); // NaN. |
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
- // The integer converted back is equal to the original. We |
- // only have to test if we got -0 as an input. |
- __ test(result_reg, Operand(result_reg)); |
- __ j(not_zero, &done, Label::kNear); |
- __ movmskpd(result_reg, input_reg); |
- // Bit 0 contains the sign of the double in input_reg. |
- // If input was positive, we are ok and return 0, otherwise |
- // deoptimize. |
- __ and_(result_reg, 1); |
- DeoptimizeIf(not_zero, instr->environment()); |
- } |
- __ bind(&done); |
+ X87Register input_reg = ToX87Register(input); |
+ X87Fxch(input_reg); |
+ __ TruncateX87TOSToI(result_reg); |
} |
} else { |
- X87Register input_reg = ToX87Register(input); |
- __ push(result_reg); |
- X87Mov(Operand(esp, 0), input_reg, kX87IntOperand); |
- if (instr->truncating()) { |
- __ pop(result_reg); |
+ Label bailout, done; |
+ if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
+ CpuFeatureScope scope(masm(), SSE2); |
+ XMMRegister input_reg = ToDoubleRegister(input); |
+ __ DoubleToI(result_reg, input_reg, xmm0, |
+ instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); |
} else { |
+ X87Register input_reg = ToX87Register(input); |
X87Fxch(input_reg); |
- __ fld(0); |
- __ fild_s(Operand(esp, 0)); |
- __ pop(result_reg); |
- __ FCmp(); |
- DeoptimizeIf(not_equal, instr->environment()); |
- DeoptimizeIf(parity_even, instr->environment()); // NaN. |
- } |
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
- __ test(result_reg, Operand(result_reg)); |
- __ j(not_zero, &done, Label::kNear); |
- // To check for minus zero, we load the value again as float, and check |
- // if that is still 0. |
- X87Fxch(input_reg); |
- __ push(result_reg); |
- __ fst_s(Operand(esp, 0)); |
- __ pop(result_reg); |
- __ test(result_reg, Operand(result_reg)); |
- DeoptimizeIf(not_zero, instr->environment()); |
- __ bind(&done); |
+ __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), |
+ &bailout, Label::kNear); |
} |
+ __ jmp(&done, Label::kNear); |
+ __ bind(&bailout); |
+ DeoptimizeIf(no_condition, instr->environment()); |
+ __ bind(&done); |
} |
} |
@@ -5677,55 +5420,23 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { |
ASSERT(result->IsRegister()); |
Register result_reg = ToRegister(result); |
- Label done; |
+ Label bailout, done; |
if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
CpuFeatureScope scope(masm(), SSE2); |
- |
XMMRegister input_reg = ToDoubleRegister(input); |
- |
- __ cvttsd2si(result_reg, Operand(input_reg)); |
- __ cvtsi2sd(xmm0, Operand(result_reg)); |
- __ ucomisd(xmm0, input_reg); |
- DeoptimizeIf(not_equal, instr->environment()); |
- DeoptimizeIf(parity_even, instr->environment()); // NaN. |
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
- // The integer converted back is equal to the original. We |
- // only have to test if we got -0 as an input. |
- __ test(result_reg, Operand(result_reg)); |
- __ j(not_zero, &done, Label::kNear); |
- __ movmskpd(result_reg, input_reg); |
- // Bit 0 contains the sign of the double in input_reg. |
- // If input was positive, we are ok and return 0, otherwise |
- // deoptimize. |
- __ and_(result_reg, 1); |
- DeoptimizeIf(not_zero, instr->environment()); |
- __ bind(&done); |
- } |
+ __ DoubleToI(result_reg, input_reg, xmm0, |
+ instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); |
} else { |
X87Register input_reg = ToX87Register(input); |
X87Fxch(input_reg); |
- __ push(result_reg); |
- X87Mov(Operand(esp, 0), input_reg, kX87IntOperand); |
- __ fld(0); |
- __ fild_s(Operand(esp, 0)); |
- __ pop(result_reg); |
- __ FCmp(); |
- DeoptimizeIf(not_equal, instr->environment()); |
- DeoptimizeIf(parity_even, instr->environment()); // NaN. |
- |
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
- __ test(result_reg, Operand(result_reg)); |
- __ j(not_zero, &done, Label::kNear); |
- // To check for minus zero, we load the value again as float, and check |
- // if that is still 0. |
- __ push(result_reg); |
- __ fst_s(Operand(esp, 0)); |
- __ pop(result_reg); |
- __ test(result_reg, Operand(result_reg)); |
- DeoptimizeIf(not_zero, instr->environment()); |
- __ bind(&done); |
- } |
+ __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), |
+ &bailout, Label::kNear); |
} |
+ __ jmp(&done, Label::kNear); |
+ __ bind(&bailout); |
+ DeoptimizeIf(no_condition, instr->environment()); |
+ __ bind(&done); |
+ |
__ SmiTag(result_reg); |
DeoptimizeIf(overflow, instr->environment()); |
} |