| Index: src/compiler/x87/code-generator-x87.cc
|
| diff --git a/src/compiler/x87/code-generator-x87.cc b/src/compiler/x87/code-generator-x87.cc
|
| index 4a8d06b10c4ff85800a0e85ad61e623aaf3f90fd..19ba68ec87b855acc5a84333896f62e5894bc33e 100644
|
| --- a/src/compiler/x87/code-generator-x87.cc
|
| +++ b/src/compiler/x87/code-generator-x87.cc
|
| @@ -2028,69 +2028,74 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
| return kSuccess;
|
| } // NOLINT(readability/fn_size)
|
|
|
| -
|
| -// Assembles a branch after an instruction.
|
| -void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
| - X87OperandConverter i(this, instr);
|
| - Label::Distance flabel_distance =
|
| - branch->fallthru ? Label::kNear : Label::kFar;
|
| -
|
| - 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) {
|
| +static Condition FlagsConditionToCondition(FlagsCondition condition) {
|
| + switch (condition) {
|
| case kUnorderedEqual:
|
| - __ j(parity_even, flabel, flabel_distance);
|
| - // Fall through.
|
| case kEqual:
|
| - __ j(equal, tlabel);
|
| + return equal;
|
| break;
|
| case kUnorderedNotEqual:
|
| - __ j(parity_even, tlabel);
|
| - // Fall through.
|
| case kNotEqual:
|
| - __ j(not_equal, tlabel);
|
| + return not_equal;
|
| break;
|
| case kSignedLessThan:
|
| - __ j(less, tlabel);
|
| + return less;
|
| break;
|
| case kSignedGreaterThanOrEqual:
|
| - __ j(greater_equal, tlabel);
|
| + return greater_equal;
|
| break;
|
| case kSignedLessThanOrEqual:
|
| - __ j(less_equal, tlabel);
|
| + return less_equal;
|
| break;
|
| case kSignedGreaterThan:
|
| - __ j(greater, tlabel);
|
| + return greater;
|
| break;
|
| case kUnsignedLessThan:
|
| - __ j(below, tlabel);
|
| + return below;
|
| break;
|
| case kUnsignedGreaterThanOrEqual:
|
| - __ j(above_equal, tlabel);
|
| + return above_equal;
|
| break;
|
| case kUnsignedLessThanOrEqual:
|
| - __ j(below_equal, tlabel);
|
| + return below_equal;
|
| break;
|
| case kUnsignedGreaterThan:
|
| - __ j(above, tlabel);
|
| + return above;
|
| break;
|
| case kOverflow:
|
| - __ j(overflow, tlabel);
|
| + return overflow;
|
| break;
|
| case kNotOverflow:
|
| - __ j(no_overflow, tlabel);
|
| + return no_overflow;
|
| break;
|
| default:
|
| UNREACHABLE();
|
| + return no_condition;
|
| break;
|
| }
|
| +}
|
| +
|
| +// Assembles a branch after an instruction.
|
| +void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
| + Label::Distance flabel_distance =
|
| + branch->fallthru ? Label::kNear : Label::kFar;
|
| +
|
| + 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;
|
| +
|
| + if (branch->condition == kUnorderedEqual) {
|
| + __ j(parity_even, flabel, flabel_distance);
|
| + } else if (branch->condition == kUnorderedNotEqual) {
|
| + __ j(parity_even, tlabel);
|
| + }
|
| + __ j(FlagsConditionToCondition(branch->condition), tlabel);
|
| +
|
| // Add a jump if not falling through to the next block.
|
| if (!branch->fallthru) __ jmp(flabel);
|
|
|
| @@ -2130,7 +2135,68 @@ void CodeGenerator::AssembleArchJump(RpoNumber target) {
|
|
|
| void CodeGenerator::AssembleArchTrap(Instruction* instr,
|
| FlagsCondition condition) {
|
| - UNREACHABLE();
|
| + 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 {
|
| + X87OperandConverter 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_) {
|
| + ReferenceMap* reference_map =
|
| + new (gen_->zone()) ReferenceMap(gen_->zone());
|
| + gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0,
|
| + Safepoint::kNoLazyDeopt);
|
| + __ 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, esi);
|
| + __ CallCFunction(
|
| + ExternalReference::wasm_call_trap_callback_for_testing(isolate()),
|
| + 0);
|
| + } else {
|
| + __ Move(esi, isolate()->native_context());
|
| + gen_->AssembleSourcePosition(instr_);
|
| + __ CallRuntime(trap_id);
|
| + }
|
| + }
|
| +
|
| + 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 an instruction.
|
| @@ -2144,58 +2210,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);
|
| - __ Move(reg, Immediate(0));
|
| - __ jmp(&done, Label::kNear);
|
| - // Fall through.
|
| - case kEqual:
|
| - cc = equal;
|
| - break;
|
| - case kUnorderedNotEqual:
|
| - __ j(parity_odd, &check, Label::kNear);
|
| - __ mov(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);
|
| + __ Move(reg, Immediate(0));
|
| + __ jmp(&done, Label::kNear);
|
| + } else if (condition == kUnorderedNotEqual) {
|
| + __ j(parity_odd, &check, Label::kNear);
|
| + __ mov(reg, Immediate(1));
|
| + __ jmp(&done, Label::kNear);
|
| }
|
| + Condition cc = FlagsConditionToCondition(condition);
|
| +
|
| __ bind(&check);
|
| if (reg.is_byte_register()) {
|
| // setcc for byte registers (al, bl, cl, dl).
|
|
|