Index: src/x64/lithium-codegen-x64.cc |
=================================================================== |
--- src/x64/lithium-codegen-x64.cc (revision 6635) |
+++ src/x64/lithium-codegen-x64.cc (working copy) |
@@ -1954,13 +1954,108 @@ |
} |
+class DeferredTaggedToI: public LDeferredCode { |
+ public: |
+ DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
+ : LDeferredCode(codegen), instr_(instr) { } |
+ virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
+ private: |
+ LTaggedToI* instr_; |
+}; |
+ |
+ |
void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
- Abort("Unimplemented: %s", "DoDeferredTaggedToI"); |
+ NearLabel done, heap_number; |
+ Register input_reg = ToRegister(instr->InputAt(0)); |
+ |
+ // Heap number map check. |
+ __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
+ Heap::kHeapNumberMapRootIndex); |
Lasse Reichstein
2011/02/04 12:57:55
indentation.
William Hesse
2011/02/04 13:16:39
Done.
|
+ |
+ if (instr->truncating()) { |
+ __ j(equal, &heap_number); |
+ // Check for undefined. Undefined is converted to zero for truncating |
+ // conversions. |
+ __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); |
+ DeoptimizeIf(not_equal, instr->environment()); |
+ __ movl(input_reg, Immediate(0)); |
+ __ jmp(&done); |
+ |
+ __ bind(&heap_number); |
+ if (CpuFeatures::IsSupported(SSE3)) { |
+ CpuFeatures::Scope scope(SSE3); |
Lasse Reichstein
2011/02/04 12:57:55
Fisttp isn't any "more powerful" than cvttsd2si in
William Hesse
2011/02/04 13:16:39
Done.
|
+ NearLabel 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. |
+ __ movl(input_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
+ __ andl(input_reg, Immediate(HeapNumber::kExponentMask)); |
+ const uint32_t kTooBigExponent = |
+ (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; |
+ __ cmpl(input_reg, Immediate(kTooBigExponent)); |
+ __ j(less, &convert); |
+ // Pop FPU stack before deoptimizing. |
+ __ ffree(0); |
+ __ fincstp(); |
Lasse Reichstein
2011/02/04 12:57:55
Use
__ fstp(0);
to drop the top of the FPU stack
William Hesse
2011/02/04 13:16:39
Entire block of code deleted.
On 2011/02/04 12:57:
|
+ DeoptimizeIf(no_condition, instr->environment()); |
+ |
+ // Reserve space for 64 bit answer. |
+ __ bind(&convert); |
+ __ subq(rsp, Immediate(kDoubleSize)); |
+ // Do conversion, which cannot fail because we checked the exponent. |
+ __ fisttp_d(Operand(rsp, 0)); |
+ __ movl(input_reg, Operand(rsp, 0)); // Low word of answer is the result. |
+ __ addq(rsp, Immediate(kDoubleSize)); |
+ } else { |
+ NearLabel deopt; |
+ XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); |
+ __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
+ __ cvttsd2si(input_reg, xmm0); |
Lasse Reichstein
2011/02/04 12:57:55
Use the 64-bit version and compare to 0x8000000000
William Hesse
2011/02/04 13:16:39
Done.
|
+ __ cmpl(input_reg, Immediate(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(); |
+ __ movq(kScratchRegister, min_int); |
+ __ movsd(xmm_temp, Operand(kScratchRegister, 0)); |
+ __ ucomisd(xmm_temp, xmm0); |
+ DeoptimizeIf(not_equal, instr->environment()); |
+ DeoptimizeIf(parity_even, instr->environment()); // NaN. |
+ } |
+ } else { |
+ // Deoptimize if we don't have a heap number. |
+ DeoptimizeIf(not_equal, instr->environment()); |
+ |
+ XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); |
+ __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
+ __ cvttsd2si(input_reg, xmm0); |
+ __ cvtlsi2sd(xmm_temp, input_reg); |
+ __ ucomisd(xmm0, xmm_temp); |
+ DeoptimizeIf(not_equal, instr->environment()); |
+ DeoptimizeIf(parity_even, instr->environment()); // NaN. |
+ if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
+ __ testl(input_reg, input_reg); |
+ __ j(not_zero, &done); |
+ __ movmskpd(input_reg, xmm0); |
+ __ andl(input_reg, Immediate(1)); |
+ DeoptimizeIf(not_zero, instr->environment()); |
+ } |
+ } |
+ __ bind(&done); |
} |
void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
- Abort("Unimplemented: %s", "DoTaggedToI"); |
+ LOperand* input = instr->InputAt(0); |
+ ASSERT(input->IsRegister()); |
+ ASSERT(input->Equals(instr->result())); |
+ |
+ Register input_reg = ToRegister(input); |
+ DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr); |
+ __ JumpIfNotSmi(input_reg, deferred->entry()); |
+ __ SmiToInteger32(input_reg, input_reg); |
+ __ bind(deferred->exit()); |
} |
@@ -2217,7 +2312,6 @@ |
void LCodeGen::DoStackCheck(LStackCheck* instr) { |
// Perform stack overflow check. |
NearLabel done; |
- ExternalReference stack_limit = ExternalReference::address_of_stack_limit(); |
__ CompareRoot(rsp, Heap::kStackLimitRootIndex); |
__ j(above_equal, &done); |