diff --git a/src/compiler/x87/code-generator-x87.cc b/src/compiler/x87/code-generator-x87.cc index 15755703e0..31e4e71fa1 100644 --- a/src/compiler/x87/code-generator-x87.cc +++ b/src/compiler/x87/code-generator-x87.cc @@ -1610,8 +1610,16 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { X87OperandConverter i(this, instr); Label::Distance flabel_distance = branch->fallthru ? Label::kNear : Label::kFar; - Label* tlabel = branch->true_label; - Label* flabel = branch->false_label; + + Label done; + Label tlabel_tmp; + Label flabel_tmp; + Label* tlabel = &tlabel_tmp; + Label* flabel = &flabel_tmp; + + Label* tlabel_dst = branch->true_label; + Label* flabel_dst = branch->false_label; + switch (branch->condition) { case kUnorderedEqual: __ j(parity_even, flabel, flabel_distance); @@ -1661,6 +1669,34 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { } // Add a jump if not falling through to the next block. if (!branch->fallthru) __ jmp(flabel); + + __ jmp(&done); + __ bind(&tlabel_tmp); + FlagsMode mode = FlagsModeField::decode(instr->opcode()); + if (mode == kFlags_deoptimize) { + int double_register_param_count = 0; + int x87_layout = 0; + for (size_t i = 0; i < instr->InputCount(); i++) { + if (instr->InputAt(i)->IsDoubleRegister()) { + double_register_param_count++; + } + } + // Currently we use only one X87 register. If double_register_param_count + // is bigger than 1, it means duplicated double register is added to input + // of this instruction. + if (double_register_param_count > 0) { + x87_layout = (0 << 3) | 1; + } + // The layout of x87 register stack is loaded on the top of FPU register + // stack for deoptimization. + __ push(Immediate(x87_layout)); + __ fild_s(MemOperand(esp, 0)); + __ lea(esp, Operand(esp, kPointerSize)); + } + __ jmp(tlabel_dst); + __ bind(&flabel_tmp); + __ jmp(flabel_dst); + __ bind(&done); } diff --git a/src/compiler/x87/instruction-selector-x87.cc b/src/compiler/x87/instruction-selector-x87.cc index 079d5d2026..90f0f61e17 100644 --- a/src/compiler/x87/instruction-selector-x87.cc +++ b/src/compiler/x87/instruction-selector-x87.cc @@ -365,10 +365,11 @@ void InstructionSelector::VisitCheckedStore(Node* node) { } } +namespace { // Shared routine for multiple binary operations. -static void VisitBinop(InstructionSelector* selector, Node* node, - InstructionCode opcode, FlagsContinuation* cont) { +void VisitBinop(InstructionSelector* selector, Node* node, + InstructionCode opcode, FlagsContinuation* cont) { X87OperandGenerator g(selector); Int32BinopMatcher m(node); Node* left = m.left().node(); @@ -417,18 +418,24 @@ static void VisitBinop(InstructionSelector* selector, Node* node, DCHECK_GE(arraysize(inputs), input_count); DCHECK_GE(arraysize(outputs), output_count); - selector->Emit(cont->Encode(opcode), output_count, outputs, input_count, - inputs); + opcode = cont->Encode(opcode); + if (cont->IsDeoptimize()) { + selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, + cont->frame_state()); + } else { + selector->Emit(opcode, output_count, outputs, input_count, inputs); + } } // Shared routine for multiple binary operations. -static void VisitBinop(InstructionSelector* selector, Node* node, - InstructionCode opcode) { +void VisitBinop(InstructionSelector* selector, Node* node, + InstructionCode opcode) { FlagsContinuation cont; VisitBinop(selector, node, opcode, &cont); } +} // namespace void InstructionSelector::VisitWord32And(Node* node) { VisitBinop(this, node, kX87And); @@ -1011,6 +1018,9 @@ void VisitCompareWithMemoryOperand(InstructionSelector* selector, inputs[input_count++] = g.Label(cont->true_block()); inputs[input_count++] = g.Label(cont->false_block()); selector->Emit(opcode, 0, nullptr, input_count, inputs); + } else if (cont->IsDeoptimize()) { + selector->EmitDeoptimize(opcode, 0, nullptr, input_count, inputs, + cont->frame_state()); } else { DCHECK(cont->IsSet()); InstructionOperand output = g.DefineAsRegister(cont->result()); @@ -1038,13 +1048,16 @@ void VisitCompare(InstructionSelector* selector, InstructionCode opcode, InstructionOperand left, InstructionOperand right, FlagsContinuation* cont) { X87OperandGenerator g(selector); + opcode = cont->Encode(opcode); if (cont->IsBranch()) { - selector->Emit(cont->Encode(opcode), g.NoOutput(), left, right, + selector->Emit(opcode, g.NoOutput(), left, right, g.Label(cont->true_block()), g.Label(cont->false_block())); + } else if (cont->IsDeoptimize()) { + selector->EmitDeoptimize(opcode, g.NoOutput(), left, right, + cont->frame_state()); } else { DCHECK(cont->IsSet()); - selector->Emit(cont->Encode(opcode), g.DefineAsByteRegister(cont->result()), - left, right); + selector->Emit(opcode, g.DefineAsByteRegister(cont->result()), left, right); } } @@ -1070,6 +1083,10 @@ void VisitFloat32Compare(InstructionSelector* selector, Node* node, if (cont->IsBranch()) { selector->Emit(cont->Encode(kX87Float32Cmp), g.NoOutput(), g.Label(cont->true_block()), g.Label(cont->false_block())); + } else if (cont->IsDeoptimize()) { + selector->EmitDeoptimize(cont->Encode(kX87Float32Cmp), g.NoOutput(), + g.Use(node->InputAt(0)), g.Use(node->InputAt(1)), + cont->frame_state()); } else { DCHECK(cont->IsSet()); selector->Emit(cont->Encode(kX87Float32Cmp), @@ -1087,6 +1104,10 @@ void VisitFloat64Compare(InstructionSelector* selector, Node* node, if (cont->IsBranch()) { selector->Emit(cont->Encode(kX87Float64Cmp), g.NoOutput(), g.Label(cont->true_block()), g.Label(cont->false_block())); + } else if (cont->IsDeoptimize()) { + selector->EmitDeoptimize(cont->Encode(kX87Float64Cmp), g.NoOutput(), + g.Use(node->InputAt(0)), g.Use(node->InputAt(1)), + cont->frame_state()); } else { DCHECK(cont->IsSet()); selector->Emit(cont->Encode(kX87Float64Cmp), @@ -1145,6 +1166,9 @@ void VisitWordCompare(InstructionSelector* selector, Node* node, if (cont->IsBranch()) { selector->Emit(opcode, g.NoOutput(), g.Label(cont->true_block()), g.Label(cont->false_block())); + } else if (cont->IsDeoptimize()) { + selector->EmitDeoptimize(opcode, 0, nullptr, 0, nullptr, + cont->frame_state()); } else { DCHECK(cont->IsSet()); selector->Emit(opcode, g.DefineAsRegister(cont->result())); @@ -1254,6 +1278,17 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, VisitWordCompareZero(this, branch, branch->InputAt(0), &cont); } +void InstructionSelector::VisitDeoptimizeIf(Node* node) { + FlagsContinuation cont = + FlagsContinuation::ForDeoptimize(kNotEqual, node->InputAt(1)); + VisitWordCompareZero(this, node, node->InputAt(0), &cont); +} + +void InstructionSelector::VisitDeoptimizeUnless(Node* node) { + FlagsContinuation cont = + FlagsContinuation::ForDeoptimize(kEqual, node->InputAt(1)); + VisitWordCompareZero(this, node, node->InputAt(0), &cont); +} void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { X87OperandGenerator g(this); @@ -1284,7 +1319,7 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { void InstructionSelector::VisitWord32Equal(Node* const node) { - FlagsContinuation cont(kEqual, node); + FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node); Int32BinopMatcher m(node); if (m.right().Is(0)) { return VisitWordCompareZero(this, m.node(), m.left().node(), &cont); @@ -1294,32 +1329,34 @@ void InstructionSelector::VisitWord32Equal(Node* const node) { void InstructionSelector::VisitInt32LessThan(Node* node) { - FlagsContinuation cont(kSignedLessThan, node); + FlagsContinuation cont = FlagsContinuation::ForSet(kSignedLessThan, node); VisitWordCompare(this, node, &cont); } void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) { - FlagsContinuation cont(kSignedLessThanOrEqual, node); + FlagsContinuation cont = + FlagsContinuation::ForSet(kSignedLessThanOrEqual, node); VisitWordCompare(this, node, &cont); } void InstructionSelector::VisitUint32LessThan(Node* node) { - FlagsContinuation cont(kUnsignedLessThan, node); + FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node); VisitWordCompare(this, node, &cont); } void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) { - FlagsContinuation cont(kUnsignedLessThanOrEqual, node); + FlagsContinuation cont = + FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node); VisitWordCompare(this, node, &cont); } void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { if (Node* ovf = NodeProperties::FindProjection(node, 1)) { - FlagsContinuation cont(kOverflow, ovf); + FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); return VisitBinop(this, node, kX87Add, &cont); } FlagsContinuation cont; @@ -1329,7 +1366,7 @@ void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { if (Node* ovf = NodeProperties::FindProjection(node, 1)) { - FlagsContinuation cont(kOverflow, ovf); + FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); return VisitBinop(this, node, kX87Sub, &cont); } FlagsContinuation cont; @@ -1338,37 +1375,41 @@ void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { void InstructionSelector::VisitFloat32Equal(Node* node) { - FlagsContinuation cont(kUnorderedEqual, node); + FlagsContinuation cont = FlagsContinuation::ForSet(kUnorderedEqual, node); VisitFloat32Compare(this, node, &cont); } void InstructionSelector::VisitFloat32LessThan(Node* node) { - FlagsContinuation cont(kUnsignedGreaterThan, node); + FlagsContinuation cont = + FlagsContinuation::ForSet(kUnsignedGreaterThan, node); VisitFloat32Compare(this, node, &cont); } void InstructionSelector::VisitFloat32LessThanOrEqual(Node* node) { - FlagsContinuation cont(kUnsignedGreaterThanOrEqual, node); + FlagsContinuation cont = + FlagsContinuation::ForSet(kUnsignedGreaterThanOrEqual, node); VisitFloat32Compare(this, node, &cont); } void InstructionSelector::VisitFloat64Equal(Node* node) { - FlagsContinuation cont(kUnorderedEqual, node); + FlagsContinuation cont = FlagsContinuation::ForSet(kUnorderedEqual, node); VisitFloat64Compare(this, node, &cont); } void InstructionSelector::VisitFloat64LessThan(Node* node) { - FlagsContinuation cont(kUnsignedGreaterThan, node); + FlagsContinuation cont = + FlagsContinuation::ForSet(kUnsignedGreaterThan, node); VisitFloat64Compare(this, node, &cont); } void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { - FlagsContinuation cont(kUnsignedGreaterThanOrEqual, node); + FlagsContinuation cont = + FlagsContinuation::ForSet(kUnsignedGreaterThanOrEqual, node); VisitFloat64Compare(this, node, &cont); }