Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(684)

Unified Diff: src/x87/lithium-codegen-x87.cc

Issue 579713002: X87: enable the crankshaft compiler for X87 port. (Closed) Base URL: https://chromium.googlesource.com/external/v8.git@bleeding_edge
Patch Set: rebase code Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/x87/lithium-codegen-x87.h ('k') | src/x87/lithium-gap-resolver-x87.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/x87/lithium-codegen-x87.cc
diff --git a/src/x87/lithium-codegen-x87.cc b/src/x87/lithium-codegen-x87.cc
index ded2cd94ae6e08cd7865f075fe18b61e7e594ad3..63feb425b8467fcf0f53bcfddfcdaf046f598eed 100644
--- a/src/x87/lithium-codegen-x87.cc
+++ b/src/x87/lithium-codegen-x87.cc
@@ -257,7 +257,8 @@ bool LCodeGen::GeneratePrologue() {
__ RecordWriteContextSlot(esi,
context_offset,
eax,
- ebx);
+ ebx,
+ kDontSaveFPRegs);
} else if (FLAG_debug_code) {
Label done;
__ JumpIfInNewSpace(esi, eax, &done, Label::kNear);
@@ -269,6 +270,8 @@ bool LCodeGen::GeneratePrologue() {
Comment(";;; End allocate local context");
}
+ // Initailize FPU state.
+ __ fninit();
// Trace the call.
if (FLAG_trace && info()->IsOptimizing()) {
// We have not executed any compiled code yet, so esi still holds the
@@ -327,6 +330,9 @@ void LCodeGen::GenerateOsrPrologue() {
int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots();
DCHECK(slots >= 1);
__ sub(esp, Immediate((slots - 1) * kPointerSize));
+
+ // Initailize FPU state.
+ __ fninit();
}
@@ -342,8 +348,21 @@ void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) {
void LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) {
+ // When return from function call, FPU should be initialized again.
+ if (instr->IsCall() && instr->ClobbersDoubleRegisters(isolate())) {
+ bool double_result = instr->HasDoubleRegisterResult();
+ if (double_result) {
+ __ lea(esp, Operand(esp, -kDoubleSize));
+ __ fstp_d(Operand(esp, 0));
+ }
+ __ fninit();
+ if (double_result) {
+ __ fld_d(Operand(esp, 0));
+ __ lea(esp, Operand(esp, kDoubleSize));
+ }
+ }
if (instr->IsGoto()) {
- x87_stack_.LeavingBlock(current_block_, LGoto::cast(instr));
+ x87_stack_.LeavingBlock(current_block_, LGoto::cast(instr), this);
} else if (FLAG_debug_code && FLAG_enable_slow_asserts &&
!instr->IsGap() && !instr->IsReturn()) {
if (instr->ClobbersDoubleRegisters(isolate())) {
@@ -494,10 +513,27 @@ void LCodeGen::X87LoadForUsage(X87Register reg) {
void LCodeGen::X87LoadForUsage(X87Register reg1, X87Register reg2) {
DCHECK(x87_stack_.Contains(reg1));
DCHECK(x87_stack_.Contains(reg2));
- x87_stack_.Fxch(reg1, 1);
- x87_stack_.Fxch(reg2);
- x87_stack_.pop();
- x87_stack_.pop();
+ if (reg1.is(reg2) && x87_stack_.depth() == 1) {
+ __ fld(x87_stack_.st(reg1));
+ x87_stack_.push(reg1);
+ x87_stack_.pop();
+ x87_stack_.pop();
+ } else {
+ x87_stack_.Fxch(reg1, 1);
+ x87_stack_.Fxch(reg2);
+ x87_stack_.pop();
+ x87_stack_.pop();
+ }
+}
+
+
+int LCodeGen::X87Stack::GetLayout() {
+ int layout = stack_depth_;
+ for (int i = 0; i < stack_depth_; i++) {
+ layout |= (stack_[stack_depth_ - 1 - i].code() << ((i + 1) * 3));
+ }
+
+ return layout;
}
@@ -572,6 +608,22 @@ void LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) {
}
+void LCodeGen::X87Mov(X87Register dst, X87Register src, X87OperandType opts) {
+ if (x87_stack_.Contains(dst)) {
+ x87_stack_.Fxch(dst);
+ __ fstp(0);
+ x87_stack_.pop();
+ // Push ST(i) onto the FPU register stack
+ __ fld(x87_stack_.st(src));
+ x87_stack_.push(dst);
+ } else {
+ // Push ST(i) onto the FPU register stack
+ __ fld(x87_stack_.st(src));
+ x87_stack_.push(dst);
+ }
+}
+
+
void LCodeGen::X87Fld(Operand src, X87OperandType opts) {
DCHECK(!src.is_reg_only());
switch (opts) {
@@ -597,6 +649,9 @@ void LCodeGen::X87Mov(Operand dst, X87Register src, X87OperandType opts) {
case kX87DoubleOperand:
__ fst_d(dst);
break;
+ case kX87FloatOperand:
+ __ fst_s(dst);
+ break;
case kX87IntOperand:
__ fist_s(dst);
break;
@@ -660,15 +715,39 @@ void LCodeGen::X87Stack::FlushIfNecessary(LInstruction* instr, LCodeGen* cgen) {
}
-void LCodeGen::X87Stack::LeavingBlock(int current_block_id, LGoto* goto_instr) {
- DCHECK(stack_depth_ <= 1);
- // If ever used for new stubs producing two pairs of doubles joined into two
- // phis this assert hits. That situation is not handled, since the two stacks
- // might have st0 and st1 swapped.
- if (current_block_id + 1 != goto_instr->block_id()) {
+void LCodeGen::X87Stack::LeavingBlock(int current_block_id,
+ LGoto* goto_instr,
+ LCodeGen* cgen) {
+ // For going to a joined block, an explicit LClobberDoubles is inserted before
+ // LGoto. Because all used x87 registers are spilled to stack slots. The
+ // ResolvePhis phase of register allocator could guarantee the two input's x87
+ // stacks have the same layout. So don't check stack_depth_ <= 1 here.
+ int goto_block_id = goto_instr->block_id();
+ if (current_block_id + 1 != goto_block_id) {
// If we have a value on the x87 stack on leaving a block, it must be a
// phi input. If the next block we compile is not the join block, we have
// to discard the stack state.
+ // Before discarding the stack state, we need to save it if the "goto block"
+ // has unreachable last predecessor when FLAG_unreachable_code_elimination.
+ if (FLAG_unreachable_code_elimination) {
+ int length = goto_instr->block()->predecessors()->length();
+ bool has_unreachable_last_predecessor = false;
+ for (int i = 0; i < length; i ++) {
+ HBasicBlock* block = goto_instr->block()->predecessors()->at(i);
+ if (block->IsUnreachable() && (block->block_id()+ 1) == goto_block_id) {
+ has_unreachable_last_predecessor = true;
+ }
+ }
+ if (has_unreachable_last_predecessor) {
+ if (cgen->x87_stack_map_.find(goto_block_id) ==
+ cgen->x87_stack_map_.end()) {
+ X87Stack* stack = new(cgen->zone()) X87Stack(*this);
+ cgen->x87_stack_map_.insert(std::make_pair(goto_block_id, stack));
+ }
+ }
+ }
+
+ // Discard the stack state.
stack_depth_ = 0;
}
}
@@ -678,13 +757,14 @@ void LCodeGen::EmitFlushX87ForDeopt() {
// 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.
- DCHECK(info()->IsStub());
+ // DCHECK(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);
+
+ // Flush X87 stack in the deoptimizer entry.
}
@@ -891,6 +971,9 @@ void LCodeGen::AddToTranslation(LEnvironment* environment,
} else {
translation->StoreInt32Register(reg);
}
+ } else if (op->IsDoubleRegister()) {
+ X87Register reg = ToX87Register(op);
+ translation->StoreDoubleRegister(reg);
} else if (op->IsConstantOperand()) {
HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
int src_index = DefineDeoptimizationLiteral(constant->handle(isolate()));
@@ -927,11 +1010,12 @@ void LCodeGen::CallCode(Handle<Code> code,
void LCodeGen::CallRuntime(const Runtime::Function* fun,
int argc,
- LInstruction* instr) {
+ LInstruction* instr,
+ SaveFPRegsMode save_doubles) {
DCHECK(instr != NULL);
DCHECK(instr->HasPointerMap());
- __ CallRuntime(fun, argc);
+ __ CallRuntime(fun, argc, save_doubles);
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
@@ -961,7 +1045,7 @@ void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
LOperand* context) {
LoadContextFromDeferred(context);
- __ CallRuntime(id);
+ __ CallRuntimeSaveDoubles(id);
RecordSafepointWithRegisters(
instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
@@ -1035,6 +1119,12 @@ void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
__ pop(eax);
__ popfd();
DCHECK(frame_is_built_);
+ // Put the x87 stack layout in TOS.
+ if (x87_stack_.depth() > 0) EmitFlushX87ForDeopt();
+ __ push(Immediate(x87_stack_.GetLayout()));
+ __ fild_s(MemOperand(esp, 0));
+ // Don't touch eflags.
+ __ lea(esp, Operand(esp, kPointerSize));
__ call(entry, RelocInfo::RUNTIME_ENTRY);
__ bind(&no_deopt);
__ mov(Operand::StaticVariable(count), eax);
@@ -1042,14 +1132,18 @@ void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
__ popfd();
}
- // Before Instructions which can deopt, we normally flush the x87 stack. But
- // 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) {
+ // Put the x87 stack layout in TOS, so that we can save x87 fp registers in
+ // the correct location.
+ {
Label done;
if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
- EmitFlushX87ForDeopt();
+ if (x87_stack_.depth() > 0) EmitFlushX87ForDeopt();
+
+ int x87_stack_layout = x87_stack_.GetLayout();
+ __ push(Immediate(x87_stack_layout));
+ __ fild_s(MemOperand(esp, 0));
+ // Don't touch eflags.
+ __ lea(esp, Operand(esp, kPointerSize));
__ bind(&done);
}
@@ -1236,6 +1330,16 @@ void LCodeGen::DoLabel(LLabel* label) {
LabelType(label));
__ bind(label->label());
current_block_ = label->block_id();
+ if (label->block()->predecessors()->length() > 1) {
+ // A join block's x87 stack is that of its last visited predecessor.
+ // If the last visited predecessor block is unreachable, the stack state
+ // will be wrong. In such case, use the x87 stack of reachable predecessor.
+ X87StackMap::const_iterator it = x87_stack_map_.find(current_block_);
+ // Restore x87 stack.
+ if (it != x87_stack_map_.end()) {
+ x87_stack_ = *(it->second);
+ }
+ }
DoGap(label);
}
@@ -1737,7 +1841,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
// Bail out if the result is supposed to be negative zero.
Label done;
__ test(left, Operand(left));
- __ j(not_zero, &done, Label::kNear);
+ __ j(not_zero, &done);
if (right->IsConstantOperand()) {
if (ToInteger32(LConstantOperand::cast(right)) < 0) {
DeoptimizeIf(no_condition, instr);
@@ -2118,8 +2222,58 @@ void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
}
__ bind(&return_left);
} else {
- // TODO(weiliang) use X87 for double representation.
- UNIMPLEMENTED();
+ DCHECK(instr->hydrogen()->representation().IsDouble());
+ Label check_nan_left, check_zero, return_left, return_right;
+ Condition condition = (operation == HMathMinMax::kMathMin) ? below : above;
+ X87Register left_reg = ToX87Register(left);
+ X87Register right_reg = ToX87Register(right);
+
+ X87PrepareBinaryOp(left_reg, right_reg, ToX87Register(instr->result()));
+ __ fld(1);
+ __ fld(1);
+ __ FCmp();
+ __ j(parity_even, &check_nan_left, Label::kNear); // At least one NaN.
+ __ j(equal, &check_zero, Label::kNear); // left == right.
+ __ j(condition, &return_left, Label::kNear);
+ __ jmp(&return_right, Label::kNear);
+
+ __ bind(&check_zero);
+ __ fld(0);
+ __ fldz();
+ __ FCmp();
+ __ j(not_equal, &return_left, Label::kNear); // left == right != 0.
+ // At this point, both left and right are either 0 or -0.
+ if (operation == HMathMinMax::kMathMin) {
+ // Push st0 and st1 to stack, then pop them to temp registers and OR them,
+ // load it to left.
+ Register scratch_reg = ToRegister(instr->temp());
+ __ fld(1);
+ __ fld(1);
+ __ sub(esp, Immediate(2*kPointerSize));
+ __ fstp_s(MemOperand(esp, 0));
+ __ fstp_s(MemOperand(esp, kPointerSize));
+ __ pop(scratch_reg);
+ __ xor_(MemOperand(esp, 0), scratch_reg);
+ X87Mov(left_reg, MemOperand(esp, 0), kX87FloatOperand);
+ __ pop(scratch_reg); // restore esp
+ } else {
+ // Since we operate on +0 and/or -0, addsd and andsd have the same effect.
+ X87Fxch(left_reg);
+ __ fadd(1);
+ }
+ __ jmp(&return_left, Label::kNear);
+
+ __ bind(&check_nan_left);
+ __ fld(0);
+ __ fld(0);
+ __ FCmp(); // NaN check.
+ __ j(parity_even, &return_left, Label::kNear); // left == NaN.
+
+ __ bind(&return_right);
+ X87Fxch(left_reg);
+ X87Mov(left_reg, right_reg);
+
+ __ bind(&return_left);
}
}
@@ -2164,6 +2318,13 @@ void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
UNREACHABLE();
break;
}
+
+ // Only always explicitly storing to memory to force the round-down for double
+ // arithmetic.
+ __ lea(esp, Operand(esp, -kDoubleSize));
+ __ fstp_d(Operand(esp, 0));
+ __ fld_d(Operand(esp, 0));
+ __ lea(esp, Operand(esp, kDoubleSize));
}
@@ -2217,7 +2378,11 @@ void LCodeGen::DoBranch(LBranch* instr) {
__ test(reg, Operand(reg));
EmitBranch(instr, not_zero);
} else if (r.IsDouble()) {
- UNREACHABLE();
+ X87Register reg = ToX87Register(instr->value());
+ X87LoadForUsage(reg);
+ __ fldz();
+ __ FCmp();
+ EmitBranch(instr, not_zero);
} else {
DCHECK(r.IsTagged());
Register reg = ToRegister(instr->value());
@@ -2473,7 +2638,10 @@ void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
DCHECK(!rep.IsInteger32());
if (rep.IsDouble()) {
- UNREACHABLE();
+ X87Register input = ToX87Register(instr->value());
+ X87LoadForUsage(input);
+ __ FXamMinusZero();
+ EmitBranch(instr, equal);
} else {
Register value = ToRegister(instr->value());
Handle<Map> map = masm()->isolate()->factory()->heap_number_map();
@@ -3062,6 +3230,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
offset,
value,
temp,
+ kSaveFPRegs,
EMIT_REMEMBERED_SET,
check_needed);
}
@@ -3732,7 +3901,9 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) {
Representation r = instr->hydrogen()->value()->representation();
if (r.IsDouble()) {
- UNIMPLEMENTED();
+ X87Register value = ToX87Register(instr->value());
+ X87Fxch(value);
+ __ fabs();
} else if (r.IsSmiOrInteger32()) {
EmitIntegerMathAbs(instr);
} else { // Tagged case.
@@ -3748,47 +3919,351 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) {
void LCodeGen::DoMathFloor(LMathFloor* instr) {
- UNIMPLEMENTED();
+ Register output_reg = ToRegister(instr->result());
+ X87Register input_reg = ToX87Register(instr->value());
+ X87Fxch(input_reg);
+
+ Label not_minus_zero, done;
+ // Deoptimize on unordered.
+ __ fldz();
+ __ fld(1);
+ __ FCmp();
+ DeoptimizeIf(parity_even, instr);
+ __ j(below, &not_minus_zero, Label::kNear);
+
+ if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ // Check for negative zero.
+ __ j(not_equal, &not_minus_zero, Label::kNear);
+ // +- 0.0.
+ __ fld(0);
+ __ FXamSign();
+ DeoptimizeIf(not_zero, instr);
+ __ Move(output_reg, Immediate(0));
+ __ jmp(&done, Label::kFar);
+ }
+
+ // Positive input.
+ // rc=01B, round down.
+ __ bind(&not_minus_zero);
+ __ fnclex();
+ __ X87SetRC(0x0400);
+ __ sub(esp, Immediate(kPointerSize));
+ __ fist_s(Operand(esp, 0));
+ __ pop(output_reg);
+ __ X87CheckIA();
+ DeoptimizeIf(equal, instr);
+ __ fnclex();
+ __ X87SetRC(0x0000);
+ __ bind(&done);
}
void LCodeGen::DoMathRound(LMathRound* instr) {
- UNIMPLEMENTED();
+ X87Register input_reg = ToX87Register(instr->value());
+ Register result = ToRegister(instr->result());
+ X87Fxch(input_reg);
+ Label below_one_half, below_minus_one_half, done;
+
+ ExternalReference one_half = ExternalReference::address_of_one_half();
+ ExternalReference minus_one_half =
+ ExternalReference::address_of_minus_one_half();
+
+ __ fld_d(Operand::StaticVariable(one_half));
+ __ fld(1);
+ __ FCmp();
+ __ j(carry, &below_one_half);
+
+ // Use rounds towards zero, since 0.5 <= x, we use floor(0.5 + x)
+ __ fld(0);
+ __ fadd_d(Operand::StaticVariable(one_half));
+ // rc=11B, round toward zero.
+ __ X87SetRC(0x0c00);
+ __ sub(esp, Immediate(kPointerSize));
+ // Clear exception bits.
+ __ fnclex();
+ __ fistp_s(MemOperand(esp, 0));
+ // Check overflow.
+ __ X87CheckIA();
+ __ RecordComment("D2I conversion overflow");
+ __ pop(result);
+ DeoptimizeIf(equal, instr);
+ __ fnclex();
+ // Restore round mode.
+ __ X87SetRC(0x0000);
+ __ jmp(&done);
+
+ __ bind(&below_one_half);
+ __ fld_d(Operand::StaticVariable(minus_one_half));
+ __ fld(1);
+ __ FCmp();
+ __ j(carry, &below_minus_one_half);
+ // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
+ // we can ignore the difference between a result of -0 and +0.
+ if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ // If the sign is positive, we return +0.
+ __ fld(0);
+ __ FXamSign();
+ __ RecordComment("Minus zero");
+ DeoptimizeIf(not_zero, instr);
+ }
+ __ Move(result, Immediate(0));
+ __ jmp(&done);
+
+ __ bind(&below_minus_one_half);
+ __ fld(0);
+ __ fadd_d(Operand::StaticVariable(one_half));
+ // rc=01B, round down.
+ __ X87SetRC(0x0400);
+ __ sub(esp, Immediate(kPointerSize));
+ // Clear exception bits.
+ __ fnclex();
+ __ fistp_s(MemOperand(esp, 0));
+ // Check overflow.
+ __ X87CheckIA();
+ __ RecordComment("D2I conversion overflow");
+ __ pop(result);
+ DeoptimizeIf(equal, instr);
+ __ fnclex();
+ // Restore round mode.
+ __ X87SetRC(0x0000);
+
+ __ bind(&done);
}
void LCodeGen::DoMathFround(LMathFround* instr) {
- UNIMPLEMENTED();
+ X87Register input_reg = ToX87Register(instr->value());
+ X87Fxch(input_reg);
+ __ sub(esp, Immediate(kPointerSize));
+ __ fstp_s(MemOperand(esp, 0));
+ X87Fld(MemOperand(esp, 0), kX87FloatOperand);
+ __ add(esp, Immediate(kPointerSize));
}
void LCodeGen::DoMathSqrt(LMathSqrt* instr) {
- UNIMPLEMENTED();
+ X87Register input_reg = ToX87Register(instr->value());
+ X87Register output_reg = ToX87Register(instr->result());
+ DCHECK(output_reg.is(input_reg));
+ USE(output_reg);
+ X87Fxch(input_reg);
+ __ fsqrt();
}
void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
- UNIMPLEMENTED();
+ X87Register input_reg = ToX87Register(instr->value());
+ DCHECK(ToX87Register(instr->result()).is(input_reg));
+ X87Fxch(input_reg);
+ // Note that according to ECMA-262 15.8.2.13:
+ // Math.pow(-Infinity, 0.5) == Infinity
+ // Math.sqrt(-Infinity) == NaN
+ Label done, sqrt;
+ // Check base for -Infinity. C3 == 0, C2 == 1, C1 == 1 and C0 == 1
+ __ fxam();
+ __ push(eax);
+ __ fnstsw_ax();
+ __ and_(eax, Immediate(0x4700));
+ __ cmp(eax, Immediate(0x0700));
+ __ j(not_equal, &sqrt, Label::kNear);
+ // If input is -Infinity, return Infinity.
+ __ fchs();
+ __ jmp(&done, Label::kNear);
+
+ // Square root.
+ __ bind(&sqrt);
+ __ fldz();
+ __ faddp(); // Convert -0 to +0.
+ __ fsqrt();
+ __ bind(&done);
+ __ pop(eax);
}
void LCodeGen::DoPower(LPower* instr) {
- UNIMPLEMENTED();
+ Representation exponent_type = instr->hydrogen()->right()->representation();
+ X87Register result = ToX87Register(instr->result());
+ // Having marked this as a call, we can use any registers.
+ X87Register base = ToX87Register(instr->left());
+ ExternalReference one_half = ExternalReference::address_of_one_half();
+
+ if (exponent_type.IsSmi()) {
+ Register exponent = ToRegister(instr->right());
+ X87LoadForUsage(base);
+ __ SmiUntag(exponent);
+ __ push(exponent);
+ __ fild_s(MemOperand(esp, 0));
+ __ pop(exponent);
+ } else if (exponent_type.IsTagged()) {
+ Register exponent = ToRegister(instr->right());
+ Register temp = exponent.is(ecx) ? eax : ecx;
+ Label no_deopt, done;
+ X87LoadForUsage(base);
+ __ JumpIfSmi(exponent, &no_deopt);
+ __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, temp);
+ DeoptimizeIf(not_equal, instr);
+ // Heap number(double)
+ __ fld_d(FieldOperand(exponent, HeapNumber::kValueOffset));
+ __ jmp(&done);
+ // SMI
+ __ bind(&no_deopt);
+ __ SmiUntag(exponent);
+ __ push(exponent);
+ __ fild_s(MemOperand(esp, 0));
+ __ pop(exponent);
+ __ bind(&done);
+ } else if (exponent_type.IsInteger32()) {
+ Register exponent = ToRegister(instr->right());
+ X87LoadForUsage(base);
+ __ push(exponent);
+ __ fild_s(MemOperand(esp, 0));
+ __ pop(exponent);
+ } else {
+ DCHECK(exponent_type.IsDouble());
+ X87Register exponent_double = ToX87Register(instr->right());
+ X87LoadForUsage(base, exponent_double);
+ }
+
+ // FP data stack {base, exponent(TOS)}.
+ // Handle (exponent==+-0.5 && base == -0).
+ Label not_plus_0;
+ __ fld(0);
+ __ fabs();
+ X87Fld(Operand::StaticVariable(one_half), kX87DoubleOperand);
+ __ FCmp();
+ __ j(parity_even, &not_plus_0, Label::kNear); // NaN.
+ __ j(not_equal, &not_plus_0, Label::kNear);
+ __ fldz();
+ // FP data stack {base, exponent(TOS), zero}.
+ __ faddp(2);
+ __ bind(&not_plus_0);
+
+ {
+ __ PrepareCallCFunction(4, eax);
+ __ fstp_d(MemOperand(esp, kDoubleSize)); // Exponent value.
+ __ fstp_d(MemOperand(esp, 0)); // Base value.
+ X87PrepareToWrite(result);
+ __ CallCFunction(
+ ExternalReference::power_double_double_function(isolate()), 4);
+ // Return value is in st(0) on ia32.
+ X87CommitWrite(result);
+ }
}
void LCodeGen::DoMathLog(LMathLog* instr) {
- UNIMPLEMENTED();
+ DCHECK(instr->value()->Equals(instr->result()));
+ X87Register input_reg = ToX87Register(instr->value());
+ X87Fxch(input_reg);
+
+ Label positive, done, zero, nan_result;
+ __ fldz();
+ __ fld(1);
+ __ FCmp();
+ __ j(below, &nan_result, Label::kNear);
+ __ j(equal, &zero, Label::kNear);
+ // Positive input.
+ // {input, ln2}.
+ __ fldln2();
+ // {ln2, input}.
+ __ fxch();
+ // {result}.
+ __ fyl2x();
+ __ jmp(&done, Label::kNear);
+
+ __ bind(&nan_result);
+ ExternalReference nan =
+ ExternalReference::address_of_canonical_non_hole_nan();
+ X87PrepareToWrite(input_reg);
+ __ fld_d(Operand::StaticVariable(nan));
+ X87CommitWrite(input_reg);
+ __ jmp(&done, Label::kNear);
+
+ __ bind(&zero);
+ ExternalReference ninf =
+ ExternalReference::address_of_negative_infinity();
+ X87PrepareToWrite(input_reg);
+ __ fld_d(Operand::StaticVariable(ninf));
+ X87CommitWrite(input_reg);
+
+ __ bind(&done);
}
void LCodeGen::DoMathClz32(LMathClz32* instr) {
- UNIMPLEMENTED();
+ Register input = ToRegister(instr->value());
+ Register result = ToRegister(instr->result());
+ Label not_zero_input;
+ __ bsr(result, input);
+
+ __ j(not_zero, &not_zero_input);
+ __ Move(result, Immediate(63)); // 63^31 == 32
+
+ __ bind(&not_zero_input);
+ __ xor_(result, Immediate(31)); // for x in [0..31], 31^x == 31-x.
}
void LCodeGen::DoMathExp(LMathExp* instr) {
- UNIMPLEMENTED();
+ X87Register input = ToX87Register(instr->value());
+ X87Register result_reg = ToX87Register(instr->result());
+ Register temp_result = ToRegister(instr->temp1());
+ Register temp = ToRegister(instr->temp2());
+ Label slow, done, smi, finish;
+ DCHECK(result_reg.is(input));
+
+ // Store input into Heap number and call runtime function kMathExpRT.
+ if (FLAG_inline_new) {
+ __ AllocateHeapNumber(temp_result, temp, no_reg, &slow);
+ __ jmp(&done, Label::kNear);
+ }
+
+ // Slow case: Call the runtime system to do the number allocation.
+ __ bind(&slow);
+ {
+ // TODO(3095996): Put a valid pointer value in the stack slot where the
+ // result register is stored, as this register is in the pointer map, but
+ // contains an integer value.
+ __ Move(temp_result, Immediate(0));
+
+ // Preserve the value of all registers.
+ PushSafepointRegistersScope scope(this);
+
+ __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+ __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
+ RecordSafepointWithRegisters(
+ instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
+ __ StoreToSafepointRegisterSlot(temp_result, eax);
+ }
+ __ bind(&done);
+ X87LoadForUsage(input);
+ __ fstp_d(FieldOperand(temp_result, HeapNumber::kValueOffset));
+
+ {
+ // Preserve the value of all registers.
+ PushSafepointRegistersScope scope(this);
+
+ __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+ __ push(temp_result);
+ __ CallRuntimeSaveDoubles(Runtime::kMathExpRT);
+ RecordSafepointWithRegisters(
+ instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
+ __ StoreToSafepointRegisterSlot(temp_result, eax);
+ }
+ X87PrepareToWrite(result_reg);
+ // return value of MathExpRT is Smi or Heap Number.
+ __ JumpIfSmi(temp_result, &smi);
+ // Heap number(double)
+ __ fld_d(FieldOperand(temp_result, HeapNumber::kValueOffset));
+ __ jmp(&finish);
+ // SMI
+ __ bind(&smi);
+ __ SmiUntag(temp_result);
+ __ push(temp_result);
+ __ fild_s(MemOperand(esp, 0));
+ __ pop(temp_result);
+ __ bind(&finish);
+ X87CommitWrite(result_reg);
}
@@ -3885,7 +4360,7 @@ void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
DCHECK(ToRegister(instr->context()).is(esi));
- CallRuntime(instr->function(), instr->arity(), instr);
+ CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles());
}
@@ -3956,7 +4431,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
__ mov(temp_map, transition);
__ mov(FieldOperand(object, HeapObject::kMapOffset), temp_map);
// Update the write barrier for the map field.
- __ RecordWriteForMap(object, transition, temp_map, temp);
+ __ RecordWriteForMap(object, transition, temp_map, temp, kSaveFPRegs);
}
}
@@ -3995,6 +4470,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
offset,
value,
temp,
+ kSaveFPRegs,
EMIT_REMEMBERED_SET,
instr->hydrogen()->SmiCheckForWriteBarrier(),
instr->hydrogen()->PointersToHereCheckForValue());
@@ -4054,8 +4530,7 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
instr->base_offset()));
if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
elements_kind == FLOAT32_ELEMENTS) {
- __ fld(0);
- __ fstp_s(operand);
+ X87Mov(operand, ToX87Register(instr->value()), kX87FloatOperand);
} else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
elements_kind == FLOAT64_ELEMENTS) {
X87Mov(operand, ToX87Register(instr->value()));
@@ -4194,6 +4669,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
__ RecordWrite(elements,
key,
value,
+ kSaveFPRegs,
EMIT_REMEMBERED_SET,
check_needed,
instr->hydrogen()->PointersToHereCheckForValue());
@@ -4257,7 +4733,8 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
// Write barrier.
DCHECK_NE(instr->temp(), NULL);
__ RecordWriteForMap(object_reg, to_map, new_map_reg,
- ToRegister(instr->temp()));
+ ToRegister(instr->temp()),
+ kDontSaveFPRegs);
} else {
DCHECK(ToRegister(instr->context()).is(esi));
DCHECK(object_reg.is(eax));
@@ -4527,7 +5004,7 @@ void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr,
// The corresponding HChange instructions are added in a phase that does
// not have easy access to the local context.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
- __ CallRuntime(Runtime::kAllocateHeapNumber);
+ __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
RecordSafepointWithRegisters(
instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
__ StoreToSafepointRegisterSlot(reg, eax);
@@ -4557,7 +5034,9 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
// Put the value to the top of stack
X87Register src = ToX87Register(instr->value());
- X87LoadForUsage(src);
+ // Don't use X87LoadForUsage here, which is only used by Instruction which
+ // clobbers fp registers.
+ x87_stack_.Fxch(src);
DeferredNumberTagD* deferred =
new(zone()) DeferredNumberTagD(this, instr, x87_stack_);
@@ -4568,7 +5047,7 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
__ jmp(deferred->entry());
}
__ bind(deferred->exit());
- __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset));
+ __ fst_d(FieldOperand(reg, HeapNumber::kValueOffset));
}
@@ -4586,7 +5065,7 @@ void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
// The corresponding HChange instructions are added in a phase that does
// not have easy access to the local context.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
- __ CallRuntime(Runtime::kAllocateHeapNumber);
+ __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
RecordSafepointWithRegisters(
instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
__ StoreToSafepointRegisterSlot(reg, eax);
@@ -4635,7 +5114,7 @@ void LCodeGen::EmitNumberUntagDNoSSE2(LNumberUntagD* instr, Register input_reg,
X87PrepareToWrite(res_reg);
if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
// Smi check.
- __ JumpIfSmi(input_reg, &load_smi, Label::kNear);
+ __ JumpIfSmi(input_reg, &load_smi);
// Heap number map check.
__ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
@@ -4644,7 +5123,7 @@ void LCodeGen::EmitNumberUntagDNoSSE2(LNumberUntagD* instr, Register input_reg,
DeoptimizeIf(not_equal, instr);
} else {
Label heap_number, convert;
- __ j(equal, &heap_number, Label::kNear);
+ __ j(equal, &heap_number);
// Convert undefined (or hole) to NaN.
__ cmp(input_reg, factory()->undefined_value());
@@ -4973,7 +5452,7 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
PushSafepointRegistersScope scope(this);
__ push(object);
__ xor_(esi, esi);
- __ CallRuntime(Runtime::kTryMigrateInstance);
+ __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
RecordSafepointWithRegisters(
instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
@@ -5043,7 +5522,10 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
- UNREACHABLE();
+ X87Register value_reg = ToX87Register(instr->unclamped());
+ Register result_reg = ToRegister(instr->result());
+ X87Fxch(value_reg);
+ __ ClampTOSToUint8(result_reg);
}
@@ -5177,12 +5659,32 @@ void LCodeGen::DoClampTToUint8NoSSE2(LClampTToUint8NoSSE2* instr) {
void LCodeGen::DoDoubleBits(LDoubleBits* instr) {
- UNREACHABLE();
+ X87Register value_reg = ToX87Register(instr->value());
+ Register result_reg = ToRegister(instr->result());
+ X87Fxch(value_reg);
+ __ sub(esp, Immediate(kDoubleSize));
+ __ fst_d(Operand(esp, 0));
+ if (instr->hydrogen()->bits() == HDoubleBits::HIGH) {
+ __ mov(result_reg, Operand(esp, kPointerSize));
+ } else {
+ __ mov(result_reg, Operand(esp, 0));
+ }
+ __ add(esp, Immediate(kDoubleSize));
}
void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
- UNREACHABLE();
+ Register hi_reg = ToRegister(instr->hi());
+ Register lo_reg = ToRegister(instr->lo());
+ X87Register result_reg = ToX87Register(instr->result());
+ // Follow below pattern to write a x87 fp register.
+ X87PrepareToWrite(result_reg);
+ __ sub(esp, Immediate(kDoubleSize));
+ __ mov(Operand(esp, 0), lo_reg);
+ __ mov(Operand(esp, kPointerSize), hi_reg);
+ __ fld_d(Operand(esp, 0));
+ __ add(esp, Immediate(kDoubleSize));
+ X87CommitWrite(result_reg);
}
@@ -5546,7 +6048,7 @@ void LCodeGen::DoDummyUse(LDummyUse* instr) {
void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
PushSafepointRegistersScope scope(this);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
- __ CallRuntime(Runtime::kStackGuard);
+ __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
RecordSafepointWithLazyDeopt(
instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
DCHECK(instr->HasEnvironment());
@@ -5693,7 +6195,7 @@ void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
__ push(object);
__ push(index);
__ xor_(esi, esi);
- __ CallRuntime(Runtime::kLoadMutableDouble);
+ __ CallRuntimeSaveDoubles(Runtime::kLoadMutableDouble);
RecordSafepointWithRegisters(
instr->pointer_map(), 2, Safepoint::kNoLazyDeopt);
__ StoreToSafepointRegisterSlot(object, eax);
« no previous file with comments | « src/x87/lithium-codegen-x87.h ('k') | src/x87/lithium-gap-resolver-x87.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698