Chromium Code Reviews| 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..358103459b5f9ae0b6fab07cdc0348a9fa4c7562 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,37 @@ 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; |
| + __ TaggedToI(input_reg, input_reg, |
| + (instr->temp() != NULL) ? ToDoubleRegister(instr->temp()) : no_xmm_reg, |
|
danno
2013/08/20 16:14:28
nit: factor this out into a variable that is passe
oliv
2013/08/20 16:56:23
Done.
|
| + !instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero), &bailout); |
| + __ jmp(done); |
| + __ bind(&bailout); |
| + DeoptimizeIf(no_condition, instr->environment()); |
| } |
| - __ bind(&done); |
| } |
| @@ -5370,7 +5314,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 +5334,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 +5380,35 @@ 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(input_reg, result_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(input_reg, result_reg, xmm0, |
| + !instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero), |
| + &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()->CheckFlag(HValue::kBailoutOnMinusZero), |
| + &bailout, Label::kNear); |
| } |
| + __ jmp(&done, Label::kNear); |
| + __ bind(&bailout); |
| + DeoptimizeIf(no_condition, instr->environment()); |
| + __ bind(&done); |
| } |
| } |
| @@ -5677,55 +5420,25 @@ 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(input_reg, result_reg, xmm0, |
| + !instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero), |
| + &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()->CheckFlag(HValue::kBailoutOnMinusZero), |
| + &bailout, Label::kNear); |
| } |
| + __ jmp(&done, Label::kNear); |
| + __ bind(&bailout); |
| + DeoptimizeIf(no_condition, instr->environment()); |
| + __ bind(&done); |
| + |
| __ SmiTag(result_reg); |
| DeoptimizeIf(overflow, instr->environment()); |
| } |