Index: src/ia32/lithium-codegen-ia32.cc |
=================================================================== |
--- src/ia32/lithium-codegen-ia32.cc (revision 8519) |
+++ src/ia32/lithium-codegen-ia32.cc (working copy) |
@@ -259,7 +259,6 @@ |
LDeferredCode* code = deferred_[i]; |
__ bind(code->entry()); |
code->Generate(); |
- __ jmp(code->exit()); |
} |
// Deferred code is the last part of the instruction sequence. Mark |
@@ -1465,6 +1464,17 @@ |
} |
+void LCodeGen::EmitPush(LOperand* operand) { |
+ if (operand->IsRegister()) { |
+ __ push(ToRegister(operand)); |
+ } else if (operand->IsConstantOperand()) { |
+ __ push(ToImmediate(operand)); |
+ } else { |
+ __ push(ToOperand(operand)); |
+ } |
+} |
+ |
+ |
void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { |
if (right->IsConstantOperand()) { |
__ cmp(ToOperand(left), ToImmediate(right)); |
@@ -1788,6 +1798,7 @@ |
: LDeferredCode(codegen), instr_(instr) { } |
virtual void Generate() { |
codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_); |
+ __ jmp(exit()); |
} |
Label* map_check() { return &map_check_; } |
@@ -2434,11 +2445,7 @@ |
void LCodeGen::DoPushArgument(LPushArgument* instr) { |
LOperand* argument = instr->InputAt(0); |
- if (argument->IsConstantOperand()) { |
- __ push(ToImmediate(argument)); |
- } else { |
- __ push(ToOperand(argument)); |
- } |
+ EmitPush(argument); |
} |
@@ -2596,6 +2603,7 @@ |
: LDeferredCode(codegen), instr_(instr) { } |
virtual void Generate() { |
codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
+ __ jmp(exit()); |
} |
private: |
LUnaryMathOperation* instr_; |
@@ -3073,7 +3081,10 @@ |
public: |
DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
: LDeferredCode(codegen), instr_(instr) { } |
- virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } |
+ virtual void Generate() { |
+ codegen()->DoDeferredStringCharCodeAt(instr_); |
+ __ jmp(exit()); |
+ } |
private: |
LStringCharCodeAt* instr_; |
}; |
@@ -3209,7 +3220,10 @@ |
public: |
DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) |
: LDeferredCode(codegen), instr_(instr) { } |
- virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } |
+ virtual void Generate() { |
+ codegen()->DoDeferredStringCharFromCode(instr_); |
+ __ jmp(exit()); |
+ } |
private: |
LStringCharFromCode* instr_; |
}; |
@@ -3259,16 +3273,8 @@ |
void LCodeGen::DoStringAdd(LStringAdd* instr) { |
- if (instr->left()->IsConstantOperand()) { |
- __ push(ToImmediate(instr->left())); |
- } else { |
- __ push(ToOperand(instr->left())); |
- } |
- if (instr->right()->IsConstantOperand()) { |
- __ push(ToImmediate(instr->right())); |
- } else { |
- __ push(ToOperand(instr->right())); |
- } |
+ EmitPush(instr->left()); |
+ EmitPush(instr->right()); |
StringAddStub stub(NO_STRING_CHECK_IN_STUB); |
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); |
} |
@@ -3288,7 +3294,10 @@ |
public: |
DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
: LDeferredCode(codegen), instr_(instr) { } |
- virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); } |
+ virtual void Generate() { |
+ codegen()->DoDeferredNumberTagI(instr_); |
+ __ jmp(exit()); |
+ } |
private: |
LNumberTagI* instr_; |
}; |
@@ -3348,7 +3357,10 @@ |
public: |
DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
: LDeferredCode(codegen), instr_(instr) { } |
- virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
+ virtual void Generate() { |
+ codegen()->DoDeferredNumberTagD(instr_); |
+ __ jmp(exit()); |
+ } |
private: |
LNumberTagD* instr_; |
}; |
@@ -3445,14 +3457,14 @@ |
public: |
DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
: LDeferredCode(codegen), instr_(instr) { } |
- virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
+ virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_, exit()); } |
private: |
LTaggedToI* instr_; |
}; |
-void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
- Label done, heap_number; |
+void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* exit) { |
+ Label deoptimize; |
Register input_reg = ToRegister(instr->InputAt(0)); |
// Heap number map check. |
@@ -3460,18 +3472,13 @@ |
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()); |
- DeoptimizeIf(not_equal, instr->environment()); |
- __ mov(input_reg, 0); |
- __ jmp(&done, Label::kNear); |
+ Label not_heap_number; |
- __ bind(&heap_number); |
+ __ j(not_equal, ¬_heap_number, Label::kNear); |
+ |
if (CpuFeatures::IsSupported(SSE3)) { |
CpuFeatures::Scope scope(SSE3); |
- Label convert; |
+ Label fix_fp_stack_and_deoptimize; |
// Use more powerful conversion when sse3 is available. |
// Load x87 register with heap number. |
__ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); |
@@ -3481,53 +3488,71 @@ |
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. |
- __ ffree(0); |
- __ fincstp(); |
- DeoptimizeIf(no_condition, instr->environment()); |
+ __ j(greater_equal, &fix_fp_stack_and_deoptimize, Label::kNear); |
// 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)); |
+ __ jmp(exit); |
+ |
+ __ bind(&fix_fp_stack_and_deoptimize); |
+ // Pop FPU stack before deoptimizing. |
+ __ ffree(0); |
+ __ fincstp(); |
+ __ jmp(&deoptimize, Label::kNear); |
+ |
} else { |
XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); |
__ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
__ cvttsd2si(input_reg, Operand(xmm0)); |
__ cmp(input_reg, 0x80000000u); |
- __ j(not_equal, &done); |
+ __ j(equal, exit, Label::kNear); |
// 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. |
+ __ j(not_equal, &deoptimize, Label::kNear); |
+ __ j(parity_even, &deoptimize, Label::kNear); // NaN. |
+ __ jmp(exit); |
} |
+ |
+ __ bind(¬_heap_number); |
+ // Check for undefined. Undefined is converted to zero for truncating |
+ // conversions. |
+ __ cmp(input_reg, factory()->undefined_value()); |
+ __ j(not_equal, &deoptimize, Label::kNear); |
+ __ Set(input_reg, Immediate(0)); |
+ __ jmp(exit); |
+ |
} else { |
// Deoptimize if we don't have a heap number. |
- DeoptimizeIf(not_equal, instr->environment()); |
+ __ j(not_equal, &deoptimize, Label::kNear); |
XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); |
__ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
__ cvttsd2si(input_reg, Operand(xmm0)); |
__ cvtsi2sd(xmm_temp, Operand(input_reg)); |
__ ucomisd(xmm0, xmm_temp); |
- DeoptimizeIf(not_equal, instr->environment()); |
- DeoptimizeIf(parity_even, instr->environment()); // NaN. |
+ __ j(not_equal, &deoptimize, Label::kNear); |
+ |
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
+ __ j(parity_even, &deoptimize, Label::kNear); // NaN. |
__ test(input_reg, Operand(input_reg)); |
- __ j(not_zero, &done); |
+ __ j(not_zero, exit); |
__ movmskpd(input_reg, xmm0); |
__ and_(input_reg, 1); |
- DeoptimizeIf(not_zero, instr->environment()); |
+ __ j(zero, exit); |
+ } else { |
+ __ j(parity_odd, exit); // Exit if not NaN, fall through if NaN. |
} |
} |
- __ bind(&done); |
+ |
+ __ bind(&deoptimize); |
+ DeoptimizeIf(no_condition, instr->environment()); |
} |
@@ -3691,7 +3716,11 @@ |
void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
LOperand* input = instr->InputAt(0); |
- __ test(ToOperand(input), Immediate(kSmiTagMask)); |
+ if (input->IsRegister()) { |
+ __ test(ToRegister(input), Immediate(kSmiTagMask)); |
+ } else { |
+ __ test(ToOperand(input), Immediate(kSmiTagMask)); |
+ } |
DeoptimizeIf(zero, instr->environment()); |
} |
@@ -3982,11 +4011,7 @@ |
void LCodeGen::DoTypeof(LTypeof* instr) { |
LOperand* input = instr->InputAt(0); |
- if (input->IsConstantOperand()) { |
- __ push(ToImmediate(input)); |
- } else { |
- __ push(ToOperand(input)); |
- } |
+ EmitPush(input); |
CallRuntime(Runtime::kTypeof, 1, instr, RESTORE_CONTEXT); |
} |
@@ -4113,12 +4138,8 @@ |
void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { |
LOperand* obj = instr->object(); |
LOperand* key = instr->key(); |
- __ push(ToOperand(obj)); |
- if (key->IsConstantOperand()) { |
- __ push(ToImmediate(key)); |
- } else { |
- __ push(ToOperand(key)); |
- } |
+ EmitPush(obj); |
+ EmitPush(key); |
ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); |
LPointerMap* pointers = instr->pointer_map(); |
LEnvironment* env = instr->deoptimization_environment(); |
@@ -4147,7 +4168,10 @@ |
public: |
DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) |
: LDeferredCode(codegen), instr_(instr) { } |
- virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } |
+ virtual void Generate() { |
+ codegen()->DoDeferredStackCheck(instr_); |
+ __ jmp(exit()); |
+ } |
private: |
LStackCheck* instr_; |
}; |
@@ -4198,16 +4222,8 @@ |
void LCodeGen::DoIn(LIn* instr) { |
LOperand* obj = instr->object(); |
LOperand* key = instr->key(); |
- if (key->IsConstantOperand()) { |
- __ push(ToImmediate(key)); |
- } else { |
- __ push(ToOperand(key)); |
- } |
- if (obj->IsConstantOperand()) { |
- __ push(ToImmediate(obj)); |
- } else { |
- __ push(ToOperand(obj)); |
- } |
+ EmitPush(key); |
+ EmitPush(obj); |
ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); |
LPointerMap* pointers = instr->pointer_map(); |
LEnvironment* env = instr->deoptimization_environment(); |