From: olivf@chromium.org Date: Tue, 20 Aug 2013 13:01:54 +0000 (+0000) Subject: Add X87 implementations for Integer32ToDouble, DoubleToI, DoubleToSmi X-Git-Tag: upstream/4.7.83~12901 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=383a167279c52d8f3aa66ca89895694b3b99f15d;p=platform%2Fupstream%2Fv8.git Add X87 implementations for Integer32ToDouble, DoubleToI, DoubleToSmi Additionally refactor the X87Stack tracking BUG= R=verwaest@chromium.org Review URL: https://codereview.chromium.org/20781007 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16246 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc index 7bea373..37218e5 100644 --- a/src/ia32/assembler-ia32.cc +++ b/src/ia32/assembler-ia32.cc @@ -1641,6 +1641,13 @@ void Assembler::fstp_s(const Operand& adr) { } +void Assembler::fst_s(const Operand& adr) { + EnsureSpace ensure_space(this); + EMIT(0xD9); + emit_operand(edx, adr); +} + + void Assembler::fstp_d(const Operand& adr) { EnsureSpace ensure_space(this); EMIT(0xDD); diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h index 8380897..c102937 100644 --- a/src/ia32/assembler-ia32.h +++ b/src/ia32/assembler-ia32.h @@ -929,6 +929,7 @@ class Assembler : public AssemblerBase { void fld_d(const Operand& adr); void fstp_s(const Operand& adr); + void fst_s(const Operand& adr); void fstp_d(const Operand& adr); void fst_d(const Operand& adr); diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 6dc0171..bffc062 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -359,10 +359,9 @@ bool LCodeGen::GenerateBody() { instr->CompileToNative(this); - if (!CpuFeatures::IsSupported(SSE2)) { - if (FLAG_debug_code && FLAG_enable_slow_asserts) { - __ VerifyX87StackDepth(x87_stack_depth_); - } + if (!CpuFeatures::IsSupported(SSE2) && + FLAG_debug_code && FLAG_enable_slow_asserts) { + __ VerifyX87StackDepth(x87_stack_.depth()); } } EnsureSpaceForLazyDeopt(); @@ -497,21 +496,21 @@ XMMRegister LCodeGen::ToDoubleRegister(int index) const { void LCodeGen::X87LoadForUsage(X87Register reg) { - ASSERT(X87StackContains(reg)); - X87Fxch(reg); - x87_stack_depth_--; + ASSERT(x87_stack_.Contains(reg)); + x87_stack_.Fxch(reg); + x87_stack_.pop(); } -void LCodeGen::X87Fxch(X87Register reg, int other_slot) { - ASSERT(X87StackContains(reg) && x87_stack_depth_ > other_slot); - int i = X87ArrayIndex(reg); - int st = x87_st2idx(i); +void LCodeGen::X87Stack::Fxch(X87Register reg, int other_slot) { + ASSERT(Contains(reg) && stack_depth_ > other_slot); + int i = ArrayIndex(reg); + int st = st2idx(i); if (st != other_slot) { - int other_i = x87_st2idx(other_slot); - X87Register other = x87_stack_[other_i]; - x87_stack_[other_i] = reg; - x87_stack_[i] = other; + int other_i = st2idx(other_slot); + X87Register other = stack_[other_i]; + stack_[other_i] = reg; + stack_[i] = other; if (st == 0) { __ fxch(other_slot); } else if (other_slot == 0) { @@ -525,88 +524,101 @@ void LCodeGen::X87Fxch(X87Register reg, int other_slot) { } -int LCodeGen::x87_st2idx(int pos) { - return x87_stack_depth_ - pos - 1; +int LCodeGen::X87Stack::st2idx(int pos) { + return stack_depth_ - pos - 1; } -int LCodeGen::X87ArrayIndex(X87Register reg) { - for (int i = 0; i < x87_stack_depth_; i++) { - if (x87_stack_[i].is(reg)) return i; +int LCodeGen::X87Stack::ArrayIndex(X87Register reg) { + for (int i = 0; i < stack_depth_; i++) { + if (stack_[i].is(reg)) return i; } UNREACHABLE(); return -1; } -bool LCodeGen::X87StackContains(X87Register reg) { - for (int i = 0; i < x87_stack_depth_; i++) { - if (x87_stack_[i].is(reg)) return true; +bool LCodeGen::X87Stack::Contains(X87Register reg) { + for (int i = 0; i < stack_depth_; i++) { + if (stack_[i].is(reg)) return true; } return false; } -void LCodeGen::X87Free(X87Register reg) { - ASSERT(X87StackContains(reg)); - int i = X87ArrayIndex(reg); - int st = x87_st2idx(i); +void LCodeGen::X87Stack::Free(X87Register reg) { + ASSERT(Contains(reg)); + int i = ArrayIndex(reg); + int st = st2idx(i); if (st > 0) { // keep track of how fstp(i) changes the order of elements - int tos_i = x87_st2idx(0); - x87_stack_[i] = x87_stack_[tos_i]; + int tos_i = st2idx(0); + stack_[i] = stack_[tos_i]; } - x87_stack_depth_--; + pop(); __ fstp(st); } void LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) { - if (X87StackContains(dst)) { - X87Fxch(dst); + if (x87_stack_.Contains(dst)) { + x87_stack_.Fxch(dst); __ fstp(0); } else { - ASSERT(x87_stack_depth_ < X87Register::kNumAllocatableRegisters); - x87_stack_[x87_stack_depth_] = dst; - x87_stack_depth_++; + x87_stack_.push(dst); } X87Fld(src, opts); } void LCodeGen::X87Fld(Operand src, X87OperandType opts) { - if (opts == kX87DoubleOperand) { - __ fld_d(src); - } else if (opts == kX87FloatOperand) { - __ fld_s(src); - } else if (opts == kX87IntOperand) { - __ fild_s(src); - } else { - UNREACHABLE(); + ASSERT(!src.is_reg_only()); + switch (opts) { + case kX87DoubleOperand: + __ fld_d(src); + break; + case kX87FloatOperand: + __ fld_s(src); + break; + case kX87IntOperand: + __ fild_s(src); + break; + default: + UNREACHABLE(); } } -void LCodeGen::X87Mov(Operand dst, X87Register src) { - X87Fxch(src); - __ fst_d(dst); +void LCodeGen::X87Mov(Operand dst, X87Register src, X87OperandType opts) { + ASSERT(!dst.is_reg_only()); + x87_stack_.Fxch(src); + switch (opts) { + case kX87DoubleOperand: + __ fst_d(dst); + break; + case kX87IntOperand: + __ fist_s(dst); + break; + default: + UNREACHABLE(); + } } -void LCodeGen::X87PrepareToWrite(X87Register reg) { - if (X87StackContains(reg)) { - X87Free(reg); +void LCodeGen::X87Stack::PrepareToWrite(X87Register reg) { + if (Contains(reg)) { + Free(reg); } // Mark this register as the next register to write to - x87_stack_[x87_stack_depth_] = reg; + stack_[stack_depth_] = reg; } -void LCodeGen::X87CommitWrite(X87Register reg) { +void LCodeGen::X87Stack::CommitWrite(X87Register reg) { // Assert the reg is prepared to write, but not on the virtual stack yet - ASSERT(!X87StackContains(reg) && x87_stack_[x87_stack_depth_].is(reg) && - x87_stack_depth_ < X87Register::kNumAllocatableRegisters); - x87_stack_depth_++; + ASSERT(!Contains(reg) && stack_[stack_depth_].is(reg) && + stack_depth_ < X87Register::kNumAllocatableRegisters); + stack_depth_++; } @@ -614,38 +626,47 @@ void LCodeGen::X87PrepareBinaryOp( X87Register left, X87Register right, X87Register result) { // You need to use DefineSameAsFirst for x87 instructions ASSERT(result.is(left)); - X87Fxch(right, 1); - X87Fxch(left); + x87_stack_.Fxch(right, 1); + x87_stack_.Fxch(left); } -void LCodeGen::FlushX87StackIfNecessary(LInstruction* instr) { - if (x87_stack_depth_ > 0 && instr->ClobbersDoubleRegisters()) { +void LCodeGen::X87Stack::FlushIfNecessary(LInstruction* instr, LCodeGen* cgen) { + if (stack_depth_ > 0 && instr->ClobbersDoubleRegisters()) { bool double_inputs = instr->HasDoubleRegisterInput(); // Flush stack from tos down, since FreeX87() will mess with tos - for (int i = x87_stack_depth_-1; i >= 0; i--) { - X87Register reg = x87_stack_[i]; + for (int i = stack_depth_-1; i >= 0; i--) { + X87Register reg = stack_[i]; // Skip registers which contain the inputs for the next instruction // when flushing the stack - if (double_inputs && instr->IsDoubleInput(reg, this)) { + if (double_inputs && instr->IsDoubleInput(reg, cgen)) { continue; } - X87Free(reg); - if (i < x87_stack_depth_-1) i++; + Free(reg); + if (i < stack_depth_-1) i++; } } if (instr->IsReturn()) { - while (x87_stack_depth_ > 0) { + while (stack_depth_ > 0) { __ fstp(0); - x87_stack_depth_--; + stack_depth_--; } } } void LCodeGen::EmitFlushX87ForDeopt() { - for (int i = 0; i < x87_stack_depth_; i++) __ fstp(0); + // The deoptimizer does not support X87 Registers. But as long as we + // deopt from a stub its not a problem, since we will re-materialize the + // original stub inputs, which can't be double registers. + ASSERT(info()->IsStub()); + if (FLAG_debug_code && FLAG_enable_slow_asserts) { + __ pushfd(); + __ VerifyX87StackDepth(x87_stack_.depth()); + __ popfd(); + } + for (int i = 0; i < x87_stack_.depth(); i++) __ fstp(0); } @@ -1003,7 +1024,7 @@ void LCodeGen::DeoptimizeIf(Condition cc, // we can have inputs or outputs of the current instruction on the stack, // thus we need to flush them here from the physical stack to leave it in a // consistent state. - if (x87_stack_depth_ > 0) { + if (x87_stack_.depth() > 0) { Label done; if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear); EmitFlushX87ForDeopt(); @@ -1865,15 +1886,16 @@ void LCodeGen::DoConstantD(LConstantD* instr) { uint64_t int_val = BitCast(v); int32_t lower = static_cast(int_val); int32_t upper = static_cast(int_val >> (kBitsPerInt)); + ASSERT(instr->result()->IsDoubleRegister()); if (!CpuFeatures::IsSafeForSnapshot(SSE2)) { __ push(Immediate(upper)); __ push(Immediate(lower)); - X87Mov(ToX87Register(instr->result()), Operand(esp, 0)); + X87Register reg = ToX87Register(instr->result()); + X87Mov(reg, Operand(esp, 0)); __ add(Operand(esp), Immediate(kDoubleSize)); } else { CpuFeatureScope scope1(masm(), SSE2); - ASSERT(instr->result()->IsDoubleRegister()); XMMRegister res = ToDoubleRegister(instr->result()); if (int_val == 0) { __ xorps(res, res); @@ -2266,7 +2288,6 @@ void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) { void LCodeGen::DoBranch(LBranch* instr) { Representation r = instr->hydrogen()->value()->representation(); if (r.IsSmiOrInteger32()) { - ASSERT(!info()->IsStub()); Register reg = ToRegister(instr->value()); __ test(reg, Operand(reg)); EmitBranch(instr, not_zero); @@ -4874,15 +4895,20 @@ void LCodeGen::DoStringAdd(LStringAdd* instr) { void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { + LOperand* input = instr->value(); + LOperand* output = instr->result(); + ASSERT(input->IsRegister() || input->IsStackSlot()); + ASSERT(output->IsDoubleRegister()); if (CpuFeatures::IsSupported(SSE2)) { CpuFeatureScope scope(masm(), SSE2); - LOperand* input = instr->value(); - ASSERT(input->IsRegister() || input->IsStackSlot()); - LOperand* output = instr->result(); - ASSERT(output->IsDoubleRegister()); __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); + } else if (input->IsRegister()) { + Register input_reg = ToRegister(input); + __ push(input_reg); + X87Mov(ToX87Register(output), Operand(esp, 0), kX87IntOperand); + __ pop(input_reg); } else { - UNREACHABLE(); + X87Mov(ToX87Register(output), ToOperand(input), kX87IntOperand); } } @@ -5570,44 +5596,75 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) { ASSERT(input->IsDoubleRegister()); LOperand* result = instr->result(); ASSERT(result->IsRegister()); - CpuFeatureScope scope(masm(), SSE2); - - XMMRegister input_reg = ToDoubleRegister(input); Register result_reg = ToRegister(result); - __ cvttsd2si(result_reg, Operand(input_reg)); + Label done; + if (CpuFeatures::IsSafeForSnapshot(SSE2)) { + CpuFeatureScope scope(masm(), SSE2); - 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); + 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); + } 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); + } } else { - Label done; - __ cvtsi2sd(xmm0, Operand(result_reg)); - __ ucomisd(xmm0, input_reg); - DeoptimizeIf(not_equal, instr->environment()); - DeoptimizeIf(parity_even, instr->environment()); // NaN. + X87Register input_reg = ToX87Register(input); + __ push(result_reg); + X87Mov(Operand(esp, 0), input_reg, kX87IntOperand); + if (instr->truncating()) { + __ pop(result_reg); + } else { + 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)) { - // 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); + // 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); } - __ bind(&done); } } @@ -5617,30 +5674,56 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { ASSERT(input->IsDoubleRegister()); LOperand* result = instr->result(); ASSERT(result->IsRegister()); - CpuFeatureScope scope(masm(), SSE2); - - XMMRegister input_reg = ToDoubleRegister(input); Register result_reg = ToRegister(result); Label done; - __ 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 (CpuFeatures::IsSafeForSnapshot(SSE2)) { + CpuFeatureScope scope(masm(), SSE2); - 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); + 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); + } + } 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); + } } __ SmiTag(result_reg); DeoptimizeIf(overflow, instr->environment()); diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h index e498f53..5a474b6 100644 --- a/src/ia32/lithium-codegen-ia32.h +++ b/src/ia32/lithium-codegen-ia32.h @@ -68,7 +68,7 @@ class LCodeGen V8_FINAL BASE_EMBEDDED { osr_pc_offset_(-1), last_lazy_deopt_pc_(0), frame_is_built_(false), - x87_stack_depth_(0), + x87_stack_(assembler), safepoints_(info->zone()), resolver_(this), expected_safepoint_kind_(Safepoint::kSimple), @@ -122,14 +122,23 @@ class LCodeGen V8_FINAL BASE_EMBEDDED { void X87Mov(X87Register reg, Operand src, X87OperandType operand = kX87DoubleOperand); - void X87Mov(Operand src, X87Register reg); + void X87Mov(Operand src, X87Register reg, + X87OperandType operand = kX87DoubleOperand); void X87PrepareBinaryOp( X87Register left, X87Register right, X87Register result); void X87LoadForUsage(X87Register reg); - void X87PrepareToWrite(X87Register reg); - void X87CommitWrite(X87Register reg); + void X87PrepareToWrite(X87Register reg) { x87_stack_.PrepareToWrite(reg); } + void X87CommitWrite(X87Register reg) { x87_stack_.CommitWrite(reg); } + + void X87Fxch(X87Register reg, int other_slot = 0) { + x87_stack_.Fxch(reg, other_slot); + } + + bool X87StackEmpty() { + return x87_stack_.depth() == 0; + } Handle ToHandle(LConstantOperand* op) const; @@ -399,15 +408,13 @@ class LCodeGen V8_FINAL BASE_EMBEDDED { // register, or a stack slot operand. void EmitPushTaggedOperand(LOperand* operand); - void X87Fxch(X87Register reg, int other_slot = 0); void X87Fld(Operand src, X87OperandType opts); - void X87Free(X87Register reg); - void FlushX87StackIfNecessary(LInstruction* instr); void EmitFlushX87ForDeopt(); - bool X87StackContains(X87Register reg); - int X87ArrayIndex(X87Register reg); - int x87_st2idx(int pos); + void FlushX87StackIfNecessary(LInstruction* instr) { + x87_stack_.FlushIfNecessary(instr, this); + } + friend class LGapResolver; #ifdef _MSC_VER // On windows, you may not access the stack more than one page below @@ -438,8 +445,48 @@ class LCodeGen V8_FINAL BASE_EMBEDDED { int osr_pc_offset_; int last_lazy_deopt_pc_; bool frame_is_built_; - X87Register x87_stack_[X87Register::kNumAllocatableRegisters]; - int x87_stack_depth_; + + class X87Stack { + public: + explicit X87Stack(MacroAssembler* masm) : stack_depth_(0), masm_(masm) { } + explicit X87Stack(const X87Stack& other) + : stack_depth_(0), masm_(other.masm_) { + stack_depth_ = other.stack_depth_; + for (int i = 0; i < stack_depth_; i++) { + stack_[i] = other.stack_[i]; + } + } + bool operator==(const X87Stack& other) const { + if (stack_depth_ != other.stack_depth_) return false; + for (int i = 0; i < stack_depth_; i++) { + if (!stack_[i].is(other.stack_[i])) return false; + } + return true; + } + bool Contains(X87Register reg); + void Fxch(X87Register reg, int other_slot = 0); + void Free(X87Register reg); + void PrepareToWrite(X87Register reg); + void CommitWrite(X87Register reg); + void FlushIfNecessary(LInstruction* instr, LCodeGen* cgen); + int depth() const { return stack_depth_; } + void pop() { stack_depth_--; } + void push(X87Register reg) { + ASSERT(stack_depth_ < X87Register::kNumAllocatableRegisters); + stack_[stack_depth_] = reg; + stack_depth_++; + } + + MacroAssembler* masm() const { return masm_; } + + private: + int ArrayIndex(X87Register reg); + int st2idx(int pos); + X87Register stack_[X87Register::kNumAllocatableRegisters]; + int stack_depth_; + MacroAssembler* const masm_; + }; + X87Stack x87_stack_; // Builder that keeps track of safepoints in the code. The table // itself is emitted at the end of the generated code. diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h index f35c777..a6a2526 100644 --- a/src/ia32/lithium-ia32.h +++ b/src/ia32/lithium-ia32.h @@ -277,10 +277,9 @@ class LInstruction : public ZoneObject { bool ClobbersRegisters() const { return IsCall(); } virtual bool ClobbersDoubleRegisters() const { return IsCall() || - (!CpuFeatures::IsSupported(SSE2) && - // We only have rudimentary X87Stack tracking, thus in general - // cannot handle deoptimization nor phi-nodes. - (HasEnvironment() || IsControl())); + // We only have rudimentary X87Stack tracking, thus in general + // cannot handle phi-nodes. + (!CpuFeatures::IsSafeForSnapshot(SSE2) && IsControl()); } virtual bool HasResult() const = 0; @@ -1542,11 +1541,6 @@ class LLoadNamedField V8_FINAL : public LTemplateInstruction<1, 1, 0> { inputs_[0] = object; } - virtual bool ClobbersDoubleRegisters() const { - return !CpuFeatures::IsSupported(SSE2) && - !hydrogen()->representation().IsDouble(); - } - LOperand* object() { return inputs_[0]; } DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field") @@ -2206,8 +2200,6 @@ class LNumberUntagD V8_FINAL : public LTemplateInstruction<1, 1, 1> { LOperand* value() { return inputs_[0]; } LOperand* temp() { return temps_[0]; } - virtual bool ClobbersDoubleRegisters() const V8_OVERRIDE { return false; } - DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag") DECLARE_HYDROGEN_ACCESSOR(Change); }; diff --git a/test/mjsunit/regress/regress-x87.js b/test/mjsunit/regress/regress-x87.js new file mode 100644 index 0000000..60380a8 --- /dev/null +++ b/test/mjsunit/regress/regress-x87.js @@ -0,0 +1,48 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --allow-natives-syntax --noenable-sse2 + +// Regression for register allocation. +var x; +var a = new Float32Array([1,2, 4, 6, 8, 11, NaN, 1/0, -3]) +var val = 2.1*a[1]*a[0]*a[1*2*3*0]*a[1*1]*1.0; +assertEquals(8.4, val); + +// Regression for double-phis +var a; +var t = true; +var res = [2.5, 2]; +for (var i = 0; i < 2; i++) { + if (t) { + a = 1.5; + } else { + a = true; + } + assertEquals(res[i], a+1); + t = false; +}