Index: src/compiler/x64/code-generator-x64.cc |
diff --git a/src/compiler/x64/code-generator-x64.cc b/src/compiler/x64/code-generator-x64.cc |
index 0a14781921a660bec6dead9866d0e3e67a7cf326..710cbdbc4e89d927d11b1cb222e35f8fcd4b8bb4 100644 |
--- a/src/compiler/x64/code-generator-x64.cc |
+++ b/src/compiler/x64/code-generator-x64.cc |
@@ -2226,61 +2226,59 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
return kSuccess; |
} // NOLINT(readability/fn_size) |
+namespace { |
-// Assembles branches after this instruction. |
-void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
- X64OperandConverter i(this, instr); |
- Label::Distance flabel_distance = |
- branch->fallthru ? Label::kNear : Label::kFar; |
- Label* tlabel = branch->true_label; |
- Label* flabel = branch->false_label; |
- switch (branch->condition) { |
+Condition FlagsConditionToCondition(FlagsCondition condition) { |
+ switch (condition) { |
case kUnorderedEqual: |
- __ j(parity_even, flabel, flabel_distance); |
- // Fall through. |
case kEqual: |
- __ j(equal, tlabel); |
- break; |
+ return equal; |
case kUnorderedNotEqual: |
- __ j(parity_even, tlabel); |
- // Fall through. |
case kNotEqual: |
- __ j(not_equal, tlabel); |
- break; |
+ return not_equal; |
case kSignedLessThan: |
- __ j(less, tlabel); |
- break; |
+ return less; |
case kSignedGreaterThanOrEqual: |
- __ j(greater_equal, tlabel); |
- break; |
+ return greater_equal; |
case kSignedLessThanOrEqual: |
- __ j(less_equal, tlabel); |
- break; |
+ return less_equal; |
case kSignedGreaterThan: |
- __ j(greater, tlabel); |
- break; |
+ return greater; |
case kUnsignedLessThan: |
- __ j(below, tlabel); |
- break; |
+ return below; |
case kUnsignedGreaterThanOrEqual: |
- __ j(above_equal, tlabel); |
- break; |
+ return above_equal; |
case kUnsignedLessThanOrEqual: |
- __ j(below_equal, tlabel); |
- break; |
+ return below_equal; |
case kUnsignedGreaterThan: |
- __ j(above, tlabel); |
- break; |
+ return above; |
case kOverflow: |
- __ j(overflow, tlabel); |
- break; |
+ return overflow; |
case kNotOverflow: |
- __ j(no_overflow, tlabel); |
- break; |
+ return no_overflow; |
default: |
- UNREACHABLE(); |
break; |
} |
+ UNREACHABLE(); |
+ return no_condition; |
+} |
+ |
+} // namespace |
+ |
+// Assembles branches after this instruction. |
+void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
+ X64OperandConverter i(this, instr); |
+ Label::Distance flabel_distance = |
+ branch->fallthru ? Label::kNear : Label::kFar; |
+ Label* tlabel = branch->true_label; |
+ Label* flabel = branch->false_label; |
+ if (branch->condition == kUnorderedEqual) { |
+ __ j(parity_even, flabel, flabel_distance); |
+ } else if (branch->condition == kUnorderedNotEqual) { |
+ __ j(parity_even, tlabel); |
+ } |
+ __ j(FlagsConditionToCondition(branch->condition), tlabel); |
+ |
if (!branch->fallthru) __ jmp(flabel, flabel_distance); |
} |
@@ -2289,6 +2287,71 @@ void CodeGenerator::AssembleArchJump(RpoNumber target) { |
if (!IsNextInAssemblyOrder(target)) __ jmp(GetLabel(target)); |
} |
+void CodeGenerator::AssembleArchTrap(Instruction* instr, |
+ FlagsCondition condition) { |
+ class OutOfLineTrap final : public OutOfLineCode { |
+ public: |
+ OutOfLineTrap(CodeGenerator* gen, bool frame_elided, Instruction* instr) |
+ : OutOfLineCode(gen), |
+ frame_elided_(frame_elided), |
+ instr_(instr), |
+ gen_(gen) {} |
+ |
+ void Generate() final { |
+ X64OperandConverter i(gen_, instr_); |
+ |
+ Runtime::FunctionId trap_id = static_cast<Runtime::FunctionId>( |
+ i.InputInt32(instr_->InputCount() - 1)); |
+ bool old_has_frame = __ has_frame(); |
+ if (frame_elided_) { |
+ __ set_has_frame(true); |
+ __ EnterFrame(StackFrame::WASM); |
+ } |
+ GenerateCallToTrap(trap_id); |
+ if (frame_elided_) { |
+ __ set_has_frame(old_has_frame); |
+ } |
+ if (FLAG_debug_code) { |
+ __ ud2(); |
+ } |
+ } |
+ |
+ private: |
+ void GenerateCallToTrap(Runtime::FunctionId trap_id) { |
+ if (trap_id == Runtime::kNumFunctions) { |
+ // We cannot test calls to the runtime in cctest/test-run-wasm. |
+ // Therefore we emit a call to C here instead of a call to the runtime. |
+ __ PrepareCallCFunction(0); |
+ __ CallCFunction( |
+ ExternalReference::wasm_call_trap_callback_for_testing(isolate()), |
+ 0); |
+ } else { |
+ __ Move(rsi, isolate()->native_context()); |
+ gen_->AssembleSourcePosition(instr_); |
+ __ CallRuntime(trap_id); |
+ } |
+ ReferenceMap* reference_map = |
+ new (gen_->zone()) ReferenceMap(gen_->zone()); |
+ gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0, |
+ Safepoint::kNoLazyDeopt); |
+ } |
+ |
+ bool frame_elided_; |
+ Instruction* instr_; |
+ CodeGenerator* gen_; |
+ }; |
+ bool frame_elided = !frame_access_state()->has_frame(); |
+ auto ool = new (zone()) OutOfLineTrap(this, frame_elided, instr); |
+ Label* tlabel = ool->entry(); |
+ Label end; |
+ if (condition == kUnorderedEqual) { |
+ __ j(parity_even, &end); |
+ } else if (condition == kUnorderedNotEqual) { |
+ __ j(parity_even, tlabel); |
+ } |
+ __ j(FlagsConditionToCondition(condition), tlabel); |
+ __ bind(&end); |
+} |
// Assembles boolean materializations after this instruction. |
void CodeGenerator::AssembleArchBoolean(Instruction* instr, |
@@ -2301,60 +2364,17 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr, |
Label check; |
DCHECK_NE(0u, instr->OutputCount()); |
Register reg = i.OutputRegister(instr->OutputCount() - 1); |
- Condition cc = no_condition; |
- switch (condition) { |
- case kUnorderedEqual: |
- __ j(parity_odd, &check, Label::kNear); |
- __ movl(reg, Immediate(0)); |
- __ jmp(&done, Label::kNear); |
- // Fall through. |
- case kEqual: |
- cc = equal; |
- break; |
- case kUnorderedNotEqual: |
- __ j(parity_odd, &check, Label::kNear); |
- __ movl(reg, Immediate(1)); |
- __ jmp(&done, Label::kNear); |
- // Fall through. |
- case kNotEqual: |
- cc = not_equal; |
- break; |
- case kSignedLessThan: |
- cc = less; |
- break; |
- case kSignedGreaterThanOrEqual: |
- cc = greater_equal; |
- break; |
- case kSignedLessThanOrEqual: |
- cc = less_equal; |
- break; |
- case kSignedGreaterThan: |
- cc = greater; |
- break; |
- case kUnsignedLessThan: |
- cc = below; |
- break; |
- case kUnsignedGreaterThanOrEqual: |
- cc = above_equal; |
- break; |
- case kUnsignedLessThanOrEqual: |
- cc = below_equal; |
- break; |
- case kUnsignedGreaterThan: |
- cc = above; |
- break; |
- case kOverflow: |
- cc = overflow; |
- break; |
- case kNotOverflow: |
- cc = no_overflow; |
- break; |
- default: |
- UNREACHABLE(); |
- break; |
+ if (condition == kUnorderedEqual) { |
+ __ j(parity_odd, &check, Label::kNear); |
+ __ movl(reg, Immediate(0)); |
+ __ jmp(&done, Label::kNear); |
+ } else if (condition == kUnorderedNotEqual) { |
+ __ j(parity_odd, &check, Label::kNear); |
+ __ movl(reg, Immediate(1)); |
+ __ jmp(&done, Label::kNear); |
} |
__ bind(&check); |
- __ setcc(cc, reg); |
+ __ setcc(FlagsConditionToCondition(condition), reg); |
__ movzxbl(reg, reg); |
__ bind(&done); |
} |