Commit 383a1672 authored by olivf@chromium.org's avatar olivf@chromium.org

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
parent 1bff3fd5
...@@ -1641,6 +1641,13 @@ void Assembler::fstp_s(const Operand& adr) { ...@@ -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) { void Assembler::fstp_d(const Operand& adr) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
EMIT(0xDD); EMIT(0xDD);
......
...@@ -929,6 +929,7 @@ class Assembler : public AssemblerBase { ...@@ -929,6 +929,7 @@ class Assembler : public AssemblerBase {
void fld_d(const Operand& adr); void fld_d(const Operand& adr);
void fstp_s(const Operand& adr); void fstp_s(const Operand& adr);
void fst_s(const Operand& adr);
void fstp_d(const Operand& adr); void fstp_d(const Operand& adr);
void fst_d(const Operand& adr); void fst_d(const Operand& adr);
......
...@@ -359,10 +359,9 @@ bool LCodeGen::GenerateBody() { ...@@ -359,10 +359,9 @@ bool LCodeGen::GenerateBody() {
instr->CompileToNative(this); instr->CompileToNative(this);
if (!CpuFeatures::IsSupported(SSE2)) { if (!CpuFeatures::IsSupported(SSE2) &&
if (FLAG_debug_code && FLAG_enable_slow_asserts) { FLAG_debug_code && FLAG_enable_slow_asserts) {
__ VerifyX87StackDepth(x87_stack_depth_); __ VerifyX87StackDepth(x87_stack_.depth());
}
} }
} }
EnsureSpaceForLazyDeopt(); EnsureSpaceForLazyDeopt();
...@@ -497,21 +496,21 @@ XMMRegister LCodeGen::ToDoubleRegister(int index) const { ...@@ -497,21 +496,21 @@ XMMRegister LCodeGen::ToDoubleRegister(int index) const {
void LCodeGen::X87LoadForUsage(X87Register reg) { void LCodeGen::X87LoadForUsage(X87Register reg) {
ASSERT(X87StackContains(reg)); ASSERT(x87_stack_.Contains(reg));
X87Fxch(reg); x87_stack_.Fxch(reg);
x87_stack_depth_--; x87_stack_.pop();
} }
void LCodeGen::X87Fxch(X87Register reg, int other_slot) { void LCodeGen::X87Stack::Fxch(X87Register reg, int other_slot) {
ASSERT(X87StackContains(reg) && x87_stack_depth_ > other_slot); ASSERT(Contains(reg) && stack_depth_ > other_slot);
int i = X87ArrayIndex(reg); int i = ArrayIndex(reg);
int st = x87_st2idx(i); int st = st2idx(i);
if (st != other_slot) { if (st != other_slot) {
int other_i = x87_st2idx(other_slot); int other_i = st2idx(other_slot);
X87Register other = x87_stack_[other_i]; X87Register other = stack_[other_i];
x87_stack_[other_i] = reg; stack_[other_i] = reg;
x87_stack_[i] = other; stack_[i] = other;
if (st == 0) { if (st == 0) {
__ fxch(other_slot); __ fxch(other_slot);
} else if (other_slot == 0) { } else if (other_slot == 0) {
...@@ -525,88 +524,101 @@ void LCodeGen::X87Fxch(X87Register reg, int other_slot) { ...@@ -525,88 +524,101 @@ void LCodeGen::X87Fxch(X87Register reg, int other_slot) {
} }
int LCodeGen::x87_st2idx(int pos) { int LCodeGen::X87Stack::st2idx(int pos) {
return x87_stack_depth_ - pos - 1; return stack_depth_ - pos - 1;
} }
int LCodeGen::X87ArrayIndex(X87Register reg) { int LCodeGen::X87Stack::ArrayIndex(X87Register reg) {
for (int i = 0; i < x87_stack_depth_; i++) { for (int i = 0; i < stack_depth_; i++) {
if (x87_stack_[i].is(reg)) return i; if (stack_[i].is(reg)) return i;
} }
UNREACHABLE(); UNREACHABLE();
return -1; return -1;
} }
bool LCodeGen::X87StackContains(X87Register reg) { bool LCodeGen::X87Stack::Contains(X87Register reg) {
for (int i = 0; i < x87_stack_depth_; i++) { for (int i = 0; i < stack_depth_; i++) {
if (x87_stack_[i].is(reg)) return true; if (stack_[i].is(reg)) return true;
} }
return false; return false;
} }
void LCodeGen::X87Free(X87Register reg) { void LCodeGen::X87Stack::Free(X87Register reg) {
ASSERT(X87StackContains(reg)); ASSERT(Contains(reg));
int i = X87ArrayIndex(reg); int i = ArrayIndex(reg);
int st = x87_st2idx(i); int st = st2idx(i);
if (st > 0) { if (st > 0) {
// keep track of how fstp(i) changes the order of elements // keep track of how fstp(i) changes the order of elements
int tos_i = x87_st2idx(0); int tos_i = st2idx(0);
x87_stack_[i] = x87_stack_[tos_i]; stack_[i] = stack_[tos_i];
} }
x87_stack_depth_--; pop();
__ fstp(st); __ fstp(st);
} }
void LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) { void LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) {
if (X87StackContains(dst)) { if (x87_stack_.Contains(dst)) {
X87Fxch(dst); x87_stack_.Fxch(dst);
__ fstp(0); __ fstp(0);
} else { } else {
ASSERT(x87_stack_depth_ < X87Register::kNumAllocatableRegisters); x87_stack_.push(dst);
x87_stack_[x87_stack_depth_] = dst;
x87_stack_depth_++;
} }
X87Fld(src, opts); X87Fld(src, opts);
} }
void LCodeGen::X87Fld(Operand src, X87OperandType opts) { void LCodeGen::X87Fld(Operand src, X87OperandType opts) {
if (opts == kX87DoubleOperand) { ASSERT(!src.is_reg_only());
switch (opts) {
case kX87DoubleOperand:
__ fld_d(src); __ fld_d(src);
} else if (opts == kX87FloatOperand) { break;
case kX87FloatOperand:
__ fld_s(src); __ fld_s(src);
} else if (opts == kX87IntOperand) { break;
case kX87IntOperand:
__ fild_s(src); __ fild_s(src);
} else { break;
default:
UNREACHABLE(); UNREACHABLE();
} }
} }
void LCodeGen::X87Mov(Operand dst, X87Register src) { void LCodeGen::X87Mov(Operand dst, X87Register src, X87OperandType opts) {
X87Fxch(src); ASSERT(!dst.is_reg_only());
x87_stack_.Fxch(src);
switch (opts) {
case kX87DoubleOperand:
__ fst_d(dst); __ fst_d(dst);
break;
case kX87IntOperand:
__ fist_s(dst);
break;
default:
UNREACHABLE();
}
} }
void LCodeGen::X87PrepareToWrite(X87Register reg) { void LCodeGen::X87Stack::PrepareToWrite(X87Register reg) {
if (X87StackContains(reg)) { if (Contains(reg)) {
X87Free(reg); Free(reg);
} }
// Mark this register as the next register to write to // 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 the reg is prepared to write, but not on the virtual stack yet
ASSERT(!X87StackContains(reg) && x87_stack_[x87_stack_depth_].is(reg) && ASSERT(!Contains(reg) && stack_[stack_depth_].is(reg) &&
x87_stack_depth_ < X87Register::kNumAllocatableRegisters); stack_depth_ < X87Register::kNumAllocatableRegisters);
x87_stack_depth_++; stack_depth_++;
} }
...@@ -614,38 +626,47 @@ void LCodeGen::X87PrepareBinaryOp( ...@@ -614,38 +626,47 @@ void LCodeGen::X87PrepareBinaryOp(
X87Register left, X87Register right, X87Register result) { X87Register left, X87Register right, X87Register result) {
// You need to use DefineSameAsFirst for x87 instructions // You need to use DefineSameAsFirst for x87 instructions
ASSERT(result.is(left)); ASSERT(result.is(left));
X87Fxch(right, 1); x87_stack_.Fxch(right, 1);
X87Fxch(left); x87_stack_.Fxch(left);
} }
void LCodeGen::FlushX87StackIfNecessary(LInstruction* instr) { void LCodeGen::X87Stack::FlushIfNecessary(LInstruction* instr, LCodeGen* cgen) {
if (x87_stack_depth_ > 0 && instr->ClobbersDoubleRegisters()) { if (stack_depth_ > 0 && instr->ClobbersDoubleRegisters()) {
bool double_inputs = instr->HasDoubleRegisterInput(); bool double_inputs = instr->HasDoubleRegisterInput();
// Flush stack from tos down, since FreeX87() will mess with tos // Flush stack from tos down, since FreeX87() will mess with tos
for (int i = x87_stack_depth_-1; i >= 0; i--) { for (int i = stack_depth_-1; i >= 0; i--) {
X87Register reg = x87_stack_[i]; X87Register reg = stack_[i];
// Skip registers which contain the inputs for the next instruction // Skip registers which contain the inputs for the next instruction
// when flushing the stack // when flushing the stack
if (double_inputs && instr->IsDoubleInput(reg, this)) { if (double_inputs && instr->IsDoubleInput(reg, cgen)) {
continue; continue;
} }
X87Free(reg); Free(reg);
if (i < x87_stack_depth_-1) i++; if (i < stack_depth_-1) i++;
} }
} }
if (instr->IsReturn()) { if (instr->IsReturn()) {
while (x87_stack_depth_ > 0) { while (stack_depth_ > 0) {
__ fstp(0); __ fstp(0);
x87_stack_depth_--; stack_depth_--;
} }
} }
} }
void LCodeGen::EmitFlushX87ForDeopt() { 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, ...@@ -1003,7 +1024,7 @@ void LCodeGen::DeoptimizeIf(Condition cc,
// we can have inputs or outputs of the current instruction on the stack, // 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 // thus we need to flush them here from the physical stack to leave it in a
// consistent state. // consistent state.
if (x87_stack_depth_ > 0) { if (x87_stack_.depth() > 0) {
Label done; Label done;
if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear); if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
EmitFlushX87ForDeopt(); EmitFlushX87ForDeopt();
...@@ -1865,15 +1886,16 @@ void LCodeGen::DoConstantD(LConstantD* instr) { ...@@ -1865,15 +1886,16 @@ void LCodeGen::DoConstantD(LConstantD* instr) {
uint64_t int_val = BitCast<uint64_t, double>(v); uint64_t int_val = BitCast<uint64_t, double>(v);
int32_t lower = static_cast<int32_t>(int_val); int32_t lower = static_cast<int32_t>(int_val);
int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
ASSERT(instr->result()->IsDoubleRegister());
if (!CpuFeatures::IsSafeForSnapshot(SSE2)) { if (!CpuFeatures::IsSafeForSnapshot(SSE2)) {
__ push(Immediate(upper)); __ push(Immediate(upper));
__ push(Immediate(lower)); __ 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)); __ add(Operand(esp), Immediate(kDoubleSize));
} else { } else {
CpuFeatureScope scope1(masm(), SSE2); CpuFeatureScope scope1(masm(), SSE2);
ASSERT(instr->result()->IsDoubleRegister());
XMMRegister res = ToDoubleRegister(instr->result()); XMMRegister res = ToDoubleRegister(instr->result());
if (int_val == 0) { if (int_val == 0) {
__ xorps(res, res); __ xorps(res, res);
...@@ -2266,7 +2288,6 @@ void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) { ...@@ -2266,7 +2288,6 @@ void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) {
void LCodeGen::DoBranch(LBranch* instr) { void LCodeGen::DoBranch(LBranch* instr) {
Representation r = instr->hydrogen()->value()->representation(); Representation r = instr->hydrogen()->value()->representation();
if (r.IsSmiOrInteger32()) { if (r.IsSmiOrInteger32()) {
ASSERT(!info()->IsStub());
Register reg = ToRegister(instr->value()); Register reg = ToRegister(instr->value());
__ test(reg, Operand(reg)); __ test(reg, Operand(reg));
EmitBranch(instr, not_zero); EmitBranch(instr, not_zero);
...@@ -4874,15 +4895,20 @@ void LCodeGen::DoStringAdd(LStringAdd* instr) { ...@@ -4874,15 +4895,20 @@ void LCodeGen::DoStringAdd(LStringAdd* instr) {
void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatureScope scope(masm(), SSE2);
LOperand* input = instr->value(); LOperand* input = instr->value();
ASSERT(input->IsRegister() || input->IsStackSlot());
LOperand* output = instr->result(); LOperand* output = instr->result();
ASSERT(input->IsRegister() || input->IsStackSlot());
ASSERT(output->IsDoubleRegister()); ASSERT(output->IsDoubleRegister());
if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatureScope scope(masm(), SSE2);
__ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); __ 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 { } else {
UNREACHABLE(); X87Mov(ToX87Register(output), ToOperand(input), kX87IntOperand);
} }
} }
...@@ -5570,10 +5596,13 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) { ...@@ -5570,10 +5596,13 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
ASSERT(input->IsDoubleRegister()); ASSERT(input->IsDoubleRegister());
LOperand* result = instr->result(); LOperand* result = instr->result();
ASSERT(result->IsRegister()); ASSERT(result->IsRegister());
Register result_reg = ToRegister(result);
Label done;
if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
CpuFeatureScope scope(masm(), SSE2); CpuFeatureScope scope(masm(), SSE2);
XMMRegister input_reg = ToDoubleRegister(input); XMMRegister input_reg = ToDoubleRegister(input);
Register result_reg = ToRegister(result);
__ cvttsd2si(result_reg, Operand(input_reg)); __ cvttsd2si(result_reg, Operand(input_reg));
...@@ -5590,7 +5619,6 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) { ...@@ -5590,7 +5619,6 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
__ add(esp, Immediate(kDoubleSize)); __ add(esp, Immediate(kDoubleSize));
__ bind(&fast_case_succeeded); __ bind(&fast_case_succeeded);
} else { } else {
Label done;
__ cvtsi2sd(xmm0, Operand(result_reg)); __ cvtsi2sd(xmm0, Operand(result_reg));
__ ucomisd(xmm0, input_reg); __ ucomisd(xmm0, input_reg);
DeoptimizeIf(not_equal, instr->environment()); DeoptimizeIf(not_equal, instr->environment());
...@@ -5609,6 +5637,35 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) { ...@@ -5609,6 +5637,35 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
} }
__ bind(&done); __ bind(&done);
} }
} else {
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)) {
__ 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);
}
}
} }
...@@ -5617,18 +5674,19 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { ...@@ -5617,18 +5674,19 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
ASSERT(input->IsDoubleRegister()); ASSERT(input->IsDoubleRegister());
LOperand* result = instr->result(); LOperand* result = instr->result();
ASSERT(result->IsRegister()); ASSERT(result->IsRegister());
Register result_reg = ToRegister(result);
Label done;
if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
CpuFeatureScope scope(masm(), SSE2); CpuFeatureScope scope(masm(), SSE2);
XMMRegister input_reg = ToDoubleRegister(input); XMMRegister input_reg = ToDoubleRegister(input);
Register result_reg = ToRegister(result);
Label done;
__ cvttsd2si(result_reg, Operand(input_reg)); __ cvttsd2si(result_reg, Operand(input_reg));
__ cvtsi2sd(xmm0, Operand(result_reg)); __ cvtsi2sd(xmm0, Operand(result_reg));
__ ucomisd(xmm0, input_reg); __ ucomisd(xmm0, input_reg);
DeoptimizeIf(not_equal, instr->environment()); DeoptimizeIf(not_equal, instr->environment());
DeoptimizeIf(parity_even, instr->environment()); // NaN. DeoptimizeIf(parity_even, instr->environment()); // NaN.
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
// The integer converted back is equal to the original. We // The integer converted back is equal to the original. We
// only have to test if we got -0 as an input. // only have to test if we got -0 as an input.
...@@ -5642,6 +5700,31 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { ...@@ -5642,6 +5700,31 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
DeoptimizeIf(not_zero, instr->environment()); DeoptimizeIf(not_zero, instr->environment());
__ bind(&done); __ 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); __ SmiTag(result_reg);
DeoptimizeIf(overflow, instr->environment()); DeoptimizeIf(overflow, instr->environment());
} }
......
...@@ -68,7 +68,7 @@ class LCodeGen V8_FINAL BASE_EMBEDDED { ...@@ -68,7 +68,7 @@ class LCodeGen V8_FINAL BASE_EMBEDDED {
osr_pc_offset_(-1), osr_pc_offset_(-1),
last_lazy_deopt_pc_(0), last_lazy_deopt_pc_(0),
frame_is_built_(false), frame_is_built_(false),
x87_stack_depth_(0), x87_stack_(assembler),
safepoints_(info->zone()), safepoints_(info->zone()),
resolver_(this), resolver_(this),
expected_safepoint_kind_(Safepoint::kSimple), expected_safepoint_kind_(Safepoint::kSimple),
...@@ -122,14 +122,23 @@ class LCodeGen V8_FINAL BASE_EMBEDDED { ...@@ -122,14 +122,23 @@ class LCodeGen V8_FINAL BASE_EMBEDDED {
void X87Mov(X87Register reg, Operand src, void X87Mov(X87Register reg, Operand src,
X87OperandType operand = kX87DoubleOperand); X87OperandType operand = kX87DoubleOperand);
void X87Mov(Operand src, X87Register reg); void X87Mov(Operand src, X87Register reg,
X87OperandType operand = kX87DoubleOperand);
void X87PrepareBinaryOp( void X87PrepareBinaryOp(
X87Register left, X87Register right, X87Register result); X87Register left, X87Register right, X87Register result);
void X87LoadForUsage(X87Register reg); void X87LoadForUsage(X87Register reg);
void X87PrepareToWrite(X87Register reg); void X87PrepareToWrite(X87Register reg) { x87_stack_.PrepareToWrite(reg); }
void X87CommitWrite(X87Register 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<Object> ToHandle(LConstantOperand* op) const; Handle<Object> ToHandle(LConstantOperand* op) const;
...@@ -399,15 +408,13 @@ class LCodeGen V8_FINAL BASE_EMBEDDED { ...@@ -399,15 +408,13 @@ class LCodeGen V8_FINAL BASE_EMBEDDED {
// register, or a stack slot operand. // register, or a stack slot operand.
void EmitPushTaggedOperand(LOperand* operand); void EmitPushTaggedOperand(LOperand* operand);
void X87Fxch(X87Register reg, int other_slot = 0);
void X87Fld(Operand src, X87OperandType opts); void X87Fld(Operand src, X87OperandType opts);
void X87Free(X87Register reg);
void FlushX87StackIfNecessary(LInstruction* instr);
void EmitFlushX87ForDeopt(); void EmitFlushX87ForDeopt();
bool X87StackContains(X87Register reg); void FlushX87StackIfNecessary(LInstruction* instr) {
int X87ArrayIndex(X87Register reg); x87_stack_.FlushIfNecessary(instr, this);
int x87_st2idx(int pos); }
friend class LGapResolver;
#ifdef _MSC_VER #ifdef _MSC_VER
// On windows, you may not access the stack more than one page below // On windows, you may not access the stack more than one page below
...@@ -438,8 +445,48 @@ class LCodeGen V8_FINAL BASE_EMBEDDED { ...@@ -438,8 +445,48 @@ class LCodeGen V8_FINAL BASE_EMBEDDED {
int osr_pc_offset_; int osr_pc_offset_;
int last_lazy_deopt_pc_; int last_lazy_deopt_pc_;
bool frame_is_built_; 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 // Builder that keeps track of safepoints in the code. The table
// itself is emitted at the end of the generated code. // itself is emitted at the end of the generated code.
......
...@@ -277,10 +277,9 @@ class LInstruction : public ZoneObject { ...@@ -277,10 +277,9 @@ class LInstruction : public ZoneObject {
bool ClobbersRegisters() const { return IsCall(); } bool ClobbersRegisters() const { return IsCall(); }
virtual bool ClobbersDoubleRegisters() const { virtual bool ClobbersDoubleRegisters() const {
return IsCall() || return IsCall() ||
(!CpuFeatures::IsSupported(SSE2) &&
// We only have rudimentary X87Stack tracking, thus in general // We only have rudimentary X87Stack tracking, thus in general
// cannot handle deoptimization nor phi-nodes. // cannot handle phi-nodes.
(HasEnvironment() || IsControl())); (!CpuFeatures::IsSafeForSnapshot(SSE2) && IsControl());
} }
virtual bool HasResult() const = 0; virtual bool HasResult() const = 0;
...@@ -1542,11 +1541,6 @@ class LLoadNamedField V8_FINAL : public LTemplateInstruction<1, 1, 0> { ...@@ -1542,11 +1541,6 @@ class LLoadNamedField V8_FINAL : public LTemplateInstruction<1, 1, 0> {
inputs_[0] = object; inputs_[0] = object;
} }
virtual bool ClobbersDoubleRegisters() const {
return !CpuFeatures::IsSupported(SSE2) &&
!hydrogen()->representation().IsDouble();
}
LOperand* object() { return inputs_[0]; } LOperand* object() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field") DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field")
...@@ -2206,8 +2200,6 @@ class LNumberUntagD V8_FINAL : public LTemplateInstruction<1, 1, 1> { ...@@ -2206,8 +2200,6 @@ class LNumberUntagD V8_FINAL : public LTemplateInstruction<1, 1, 1> {
LOperand* value() { return inputs_[0]; } LOperand* value() { return inputs_[0]; }
LOperand* temp() { return temps_[0]; } LOperand* temp() { return temps_[0]; }
virtual bool ClobbersDoubleRegisters() const V8_OVERRIDE { return false; }
DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag") DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
DECLARE_HYDROGEN_ACCESSOR(Change); DECLARE_HYDROGEN_ACCESSOR(Change);
}; };
......
// 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment