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