[x87] Keep x87 FPU stack empty when calling or return to natvie C++ function.
X87 TurboFan code generation convention assumes that there is always a value at the top of the X87 FPU stack for each TurboFan's float operation. But native C++ function assumes there are 8 FPU stack slots can be used when it's called. This will lead to FPU stack overflow when TurboFan x87 code calls or returns back to native C++ function. as there are only 7 FPU stack slots remained for this native C++ function. This CL does: 1. Make sure X87 FPU stack depth always 1 before each TurboFan's float operation 2. Remove the top value in X87 FPU stack required by TurboFan when calling or returning from TurboFan Functions to other TurboFan or Non-TurboFan Functions. 3. Add the strict X87 FPU stack depth check for TurboFan debug code. 4. Re-initialize the X87 FPU stack and push a value at the top of the X87 FPU stack to satify the X87 TurboFan code generation convention for float operation at the entries where the TurboFan code will be called such as: exception handler, CallCFunctions in tests,..etc BUG= Review URL: https://codereview.chromium.org/1636353002 Cr-Commit-Position: refs/heads/master@{#33573}
This commit is contained in:
parent
f8ece9a013
commit
17bf607ddc
@ -195,6 +195,9 @@ class OutOfLineLoadFloat final : public OutOfLineCode {
|
||||
void Generate() final {
|
||||
DCHECK(result_.code() == 0);
|
||||
USE(result_);
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
__ push(Immediate(0xffffffff));
|
||||
__ push(Immediate(0x7fffffff));
|
||||
@ -364,6 +367,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
|
||||
switch (ArchOpcodeField::decode(instr->opcode())) {
|
||||
case kArchCallCodeObject: {
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
EnsureSpaceForLazyDeopt();
|
||||
if (HasImmediateInput(instr, 0)) {
|
||||
Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
|
||||
@ -391,6 +398,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
break;
|
||||
}
|
||||
case kArchTailCallCodeObject: {
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
|
||||
AssembleDeconstructActivationRecord(stack_param_delta);
|
||||
if (HasImmediateInput(instr, 0)) {
|
||||
@ -412,6 +423,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
__ cmp(esi, FieldOperand(func, JSFunction::kContextOffset));
|
||||
__ Assert(equal, kWrongFunctionContext);
|
||||
}
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
__ call(FieldOperand(func, JSFunction::kCodeEntryOffset));
|
||||
RecordCallPosition(instr);
|
||||
bool double_result =
|
||||
@ -437,6 +452,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
__ cmp(esi, FieldOperand(func, JSFunction::kContextOffset));
|
||||
__ Assert(equal, kWrongFunctionContext);
|
||||
}
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
|
||||
AssembleDeconstructActivationRecord(stack_param_delta);
|
||||
__ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset));
|
||||
@ -446,6 +465,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
case kArchLazyBailout: {
|
||||
EnsureSpaceForLazyDeopt();
|
||||
RecordCallPosition(instr);
|
||||
// Lazy Bailout entry, need to re-initialize FPU state.
|
||||
__ fninit();
|
||||
__ fld1();
|
||||
break;
|
||||
}
|
||||
case kArchPrepareCallCFunction: {
|
||||
@ -459,6 +481,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1));
|
||||
break;
|
||||
case kArchCallCFunction: {
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
int const num_parameters = MiscField::decode(instr->opcode());
|
||||
if (HasImmediateInput(instr, 0)) {
|
||||
ExternalReference ref = i.InputExternalReference(0);
|
||||
@ -467,6 +493,19 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
Register func = i.InputRegister(0);
|
||||
__ CallCFunction(func, num_parameters);
|
||||
}
|
||||
bool double_result =
|
||||
instr->HasOutput() && instr->Output()->IsDoubleRegister();
|
||||
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));
|
||||
} else {
|
||||
__ fld1();
|
||||
}
|
||||
frame_access_state()->SetFrameAccessToDefault();
|
||||
frame_access_state()->ClearSPDelta();
|
||||
break;
|
||||
@ -689,6 +728,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
break;
|
||||
}
|
||||
case kX87Float32Add: {
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ X87SetFPUCW(0x027F);
|
||||
__ fstp(0);
|
||||
__ fld_s(MemOperand(esp, 0));
|
||||
@ -701,6 +743,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
break;
|
||||
}
|
||||
case kX87Float32Sub: {
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ X87SetFPUCW(0x027F);
|
||||
__ fstp(0);
|
||||
__ fld_s(MemOperand(esp, kFloatSize));
|
||||
@ -713,6 +758,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
break;
|
||||
}
|
||||
case kX87Float32Mul: {
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ X87SetFPUCW(0x027F);
|
||||
__ fstp(0);
|
||||
__ fld_s(MemOperand(esp, kFloatSize));
|
||||
@ -725,6 +773,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
break;
|
||||
}
|
||||
case kX87Float32Div: {
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ X87SetFPUCW(0x027F);
|
||||
__ fstp(0);
|
||||
__ fld_s(MemOperand(esp, kFloatSize));
|
||||
@ -739,6 +790,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
case kX87Float32Max: {
|
||||
Label check_nan_left, check_zero, return_left, return_right;
|
||||
Condition condition = below;
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
__ fld_s(MemOperand(esp, kFloatSize));
|
||||
__ fld_s(MemOperand(esp, 0));
|
||||
@ -773,6 +827,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
case kX87Float32Min: {
|
||||
Label check_nan_left, check_zero, return_left, return_right;
|
||||
Condition condition = above;
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
__ fld_s(MemOperand(esp, kFloatSize));
|
||||
__ fld_s(MemOperand(esp, 0));
|
||||
@ -818,6 +875,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
break;
|
||||
}
|
||||
case kX87Float32Sqrt: {
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
__ fld_s(MemOperand(esp, 0));
|
||||
__ fsqrt();
|
||||
@ -825,6 +885,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
break;
|
||||
}
|
||||
case kX87Float32Abs: {
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
__ fld_s(MemOperand(esp, 0));
|
||||
__ fabs();
|
||||
@ -841,6 +904,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
InstructionOperand* input = instr->InputAt(0);
|
||||
USE(input);
|
||||
DCHECK(input->IsDoubleStackSlot());
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
__ fld_s(i.InputOperand(0));
|
||||
}
|
||||
@ -849,6 +915,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
break;
|
||||
}
|
||||
case kX87Float64Add: {
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ X87SetFPUCW(0x027F);
|
||||
__ fstp(0);
|
||||
__ fld_d(MemOperand(esp, 0));
|
||||
@ -861,6 +930,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
break;
|
||||
}
|
||||
case kX87Float64Sub: {
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ X87SetFPUCW(0x027F);
|
||||
__ fstp(0);
|
||||
__ fld_d(MemOperand(esp, kDoubleSize));
|
||||
@ -872,6 +944,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
break;
|
||||
}
|
||||
case kX87Float64Mul: {
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ X87SetFPUCW(0x027F);
|
||||
__ fstp(0);
|
||||
__ fld_d(MemOperand(esp, kDoubleSize));
|
||||
@ -883,6 +958,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
break;
|
||||
}
|
||||
case kX87Float64Div: {
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ X87SetFPUCW(0x027F);
|
||||
__ fstp(0);
|
||||
__ fld_d(MemOperand(esp, kDoubleSize));
|
||||
@ -895,6 +973,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
}
|
||||
case kX87Float64Mod: {
|
||||
FrameScope frame_scope(&masm_, StackFrame::MANUAL);
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ mov(eax, esp);
|
||||
__ PrepareCallCFunction(4, eax);
|
||||
__ fstp(0);
|
||||
@ -910,6 +991,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
case kX87Float64Max: {
|
||||
Label check_zero, return_left, return_right;
|
||||
Condition condition = below;
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
__ fld_d(MemOperand(esp, kDoubleSize));
|
||||
__ fld_d(MemOperand(esp, 0));
|
||||
@ -939,6 +1023,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
case kX87Float64Min: {
|
||||
Label check_zero, return_left, return_right;
|
||||
Condition condition = above;
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
__ fld_d(MemOperand(esp, kDoubleSize));
|
||||
__ fld_d(MemOperand(esp, 0));
|
||||
@ -966,6 +1053,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
break;
|
||||
}
|
||||
case kX87Float64Abs: {
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
__ fld_d(MemOperand(esp, 0));
|
||||
__ fabs();
|
||||
@ -975,6 +1065,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
case kX87Int32ToFloat32: {
|
||||
InstructionOperand* input = instr->InputAt(0);
|
||||
DCHECK(input->IsRegister() || input->IsStackSlot());
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
if (input->IsRegister()) {
|
||||
Register input_reg = i.InputRegister(0);
|
||||
@ -989,6 +1082,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
case kX87Int32ToFloat64: {
|
||||
InstructionOperand* input = instr->InputAt(0);
|
||||
DCHECK(input->IsRegister() || input->IsStackSlot());
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
if (input->IsRegister()) {
|
||||
Register input_reg = i.InputRegister(0);
|
||||
@ -1009,12 +1105,18 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
__ add(esp, Immediate(kDoubleSize));
|
||||
} else {
|
||||
DCHECK(input->IsDoubleStackSlot());
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
__ fld_s(i.InputOperand(0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kX87Uint32ToFloat64: {
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
__ LoadUint32NoSSE2(i.InputRegister(0));
|
||||
break;
|
||||
@ -1048,6 +1150,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
__ add(esp, Immediate(kDoubleSize));
|
||||
} else {
|
||||
DCHECK(input->IsDoubleStackSlot());
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
__ fld_d(i.InputOperand(0));
|
||||
__ sub(esp, Immediate(kDoubleSize));
|
||||
@ -1118,6 +1223,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
break;
|
||||
}
|
||||
case kX87Float64Sqrt: {
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ X87SetFPUCW(0x027F);
|
||||
__ fstp(0);
|
||||
__ fld_d(MemOperand(esp, 0));
|
||||
@ -1136,6 +1244,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
InstructionOperand* input = instr->InputAt(0);
|
||||
USE(input);
|
||||
DCHECK(input->IsDoubleStackSlot());
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
__ fld_d(i.InputOperand(0));
|
||||
}
|
||||
@ -1200,6 +1311,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
X87Register output = i.OutputDoubleRegister();
|
||||
USE(output);
|
||||
DCHECK(output.code() == 0);
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
__ fld_d(i.MemoryOperand());
|
||||
} else {
|
||||
@ -1214,6 +1328,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
X87Register output = i.OutputDoubleRegister();
|
||||
USE(output);
|
||||
DCHECK(output.code() == 0);
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
__ fld_s(i.MemoryOperand());
|
||||
} else {
|
||||
@ -1229,6 +1346,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
break;
|
||||
}
|
||||
case kX87BitcastIF: {
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
__ fstp(0);
|
||||
if (instr->InputAt(0)->IsRegister()) {
|
||||
__ lea(esp, Operand(esp, -kFloatSize));
|
||||
@ -1754,6 +1874,21 @@ void CodeGenerator::AssemblePrologue() {
|
||||
void CodeGenerator::AssembleReturn() {
|
||||
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
|
||||
|
||||
// Clear the FPU stack only if there is no return value in the stack.
|
||||
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
__ VerifyX87StackDepth(1);
|
||||
}
|
||||
bool clear_stack = true;
|
||||
for (int i = 0; i < descriptor->ReturnCount(); i++) {
|
||||
MachineRepresentation rep = descriptor->GetReturnType(i).representation();
|
||||
LinkageLocation loc = descriptor->GetReturnLocation(i);
|
||||
if (IsFloatingPoint(rep) && loc == LinkageLocation::ForRegister(0)) {
|
||||
clear_stack = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (clear_stack) __ fstp(0);
|
||||
|
||||
int pop_count = static_cast<int>(descriptor->StackParameterCount());
|
||||
const RegList saves = descriptor->CalleeSavedRegisters();
|
||||
// Restore registers.
|
||||
|
Loading…
Reference in New Issue
Block a user