| Index: src/compiler/code-generator.cc
|
| diff --git a/src/compiler/code-generator.cc b/src/compiler/code-generator.cc
|
| index 712cfe0b2da9407cfb3109bde003add32ad8977d..d1957336f2c4a6df106056273a7673ebedec395a 100644
|
| --- a/src/compiler/code-generator.cc
|
| +++ b/src/compiler/code-generator.cc
|
| @@ -31,7 +31,6 @@ class CodeGenerator::JumpTable final : public ZoneObject {
|
| size_t const target_count_;
|
| };
|
|
|
| -
|
| CodeGenerator::CodeGenerator(Frame* frame, Linkage* linkage,
|
| InstructionSequence* code, CompilationInfo* info)
|
| : frame_access_state_(new (code->zone()) FrameAccessState(frame)),
|
| @@ -45,6 +44,7 @@ CodeGenerator::CodeGenerator(Frame* frame, Linkage* linkage,
|
| resolver_(this),
|
| safepoints_(code->zone()),
|
| handlers_(code->zone()),
|
| + deoptimization_exits_(code->zone()),
|
| deoptimization_states_(code->zone()),
|
| deoptimization_literals_(code->zone()),
|
| inlined_function_count_(0),
|
| @@ -158,6 +158,12 @@ Handle<Code> CodeGenerator::GenerateCode() {
|
| }
|
| }
|
|
|
| + // Assemble all eager deoptimization exits.
|
| + for (DeoptimizationExit* exit : deoptimization_exits_) {
|
| + masm()->bind(exit->label());
|
| + AssembleDeoptimizerCall(exit->deoptimization_id(), Deoptimizer::EAGER);
|
| + }
|
| +
|
| // Ensure there is space for lazy deoptimization in the code.
|
| if (info->ShouldEnsureSpaceForLazyDeopt()) {
|
| int target_offset = masm()->pc_offset() + Deoptimizer::patch_size();
|
| @@ -291,34 +297,59 @@ void CodeGenerator::AssembleInstruction(Instruction* instr) {
|
|
|
| FlagsMode mode = FlagsModeField::decode(instr->opcode());
|
| FlagsCondition condition = FlagsConditionField::decode(instr->opcode());
|
| - if (mode == kFlags_branch) {
|
| - // Assemble a branch after this instruction.
|
| - InstructionOperandConverter i(this, instr);
|
| - RpoNumber true_rpo = i.InputRpo(instr->InputCount() - 2);
|
| - RpoNumber false_rpo = i.InputRpo(instr->InputCount() - 1);
|
| -
|
| - if (true_rpo == false_rpo) {
|
| - // redundant branch.
|
| - if (!IsNextInAssemblyOrder(true_rpo)) {
|
| - AssembleArchJump(true_rpo);
|
| + switch (mode) {
|
| + case kFlags_branch: {
|
| + // Assemble a branch after this instruction.
|
| + InstructionOperandConverter i(this, instr);
|
| + RpoNumber true_rpo = i.InputRpo(instr->InputCount() - 2);
|
| + RpoNumber false_rpo = i.InputRpo(instr->InputCount() - 1);
|
| +
|
| + if (true_rpo == false_rpo) {
|
| + // redundant branch.
|
| + if (!IsNextInAssemblyOrder(true_rpo)) {
|
| + AssembleArchJump(true_rpo);
|
| + }
|
| + return;
|
| }
|
| - return;
|
| + if (IsNextInAssemblyOrder(true_rpo)) {
|
| + // true block is next, can fall through if condition negated.
|
| + std::swap(true_rpo, false_rpo);
|
| + condition = NegateFlagsCondition(condition);
|
| + }
|
| + BranchInfo branch;
|
| + branch.condition = condition;
|
| + branch.true_label = GetLabel(true_rpo);
|
| + branch.false_label = GetLabel(false_rpo);
|
| + branch.fallthru = IsNextInAssemblyOrder(false_rpo);
|
| + // Assemble architecture-specific branch.
|
| + AssembleArchBranch(instr, &branch);
|
| + break;
|
| }
|
| - if (IsNextInAssemblyOrder(true_rpo)) {
|
| - // true block is next, can fall through if condition negated.
|
| - std::swap(true_rpo, false_rpo);
|
| - condition = NegateFlagsCondition(condition);
|
| + case kFlags_deoptimize: {
|
| + // Assemble a conditional eager deoptimization after this instruction.
|
| + InstructionOperandConverter i(this, instr);
|
| + size_t frame_state_offset = MiscField::decode(instr->opcode());
|
| + DeoptimizationExit* const exit =
|
| + AddDeoptimizationExit(instr, frame_state_offset);
|
| + Label continue_label;
|
| + BranchInfo branch;
|
| + branch.condition = condition;
|
| + branch.true_label = exit->label();
|
| + branch.false_label = &continue_label;
|
| + branch.fallthru = true;
|
| + // Assemble architecture-specific branch.
|
| + AssembleArchBranch(instr, &branch);
|
| + masm()->bind(&continue_label);
|
| + break;
|
| + }
|
| + case kFlags_set: {
|
| + // Assemble a boolean materialization after this instruction.
|
| + AssembleArchBoolean(instr, condition);
|
| + break;
|
| + }
|
| + case kFlags_none: {
|
| + break;
|
| }
|
| - BranchInfo branch;
|
| - branch.condition = condition;
|
| - branch.true_label = GetLabel(true_rpo);
|
| - branch.false_label = GetLabel(false_rpo);
|
| - branch.fallthru = IsNextInAssemblyOrder(false_rpo);
|
| - // Assemble architecture-specific branch.
|
| - AssembleArchBranch(instr, &branch);
|
| - } else if (mode == kFlags_set) {
|
| - // Assemble a boolean materialization after this instruction.
|
| - AssembleArchBoolean(instr, condition);
|
| }
|
| }
|
|
|
| @@ -714,6 +745,15 @@ void CodeGenerator::MarkLazyDeoptSite() {
|
| last_lazy_deopt_pc_ = masm()->pc_offset();
|
| }
|
|
|
| +DeoptimizationExit* CodeGenerator::AddDeoptimizationExit(
|
| + Instruction* instr, size_t frame_state_offset) {
|
| + int const deoptimization_id = BuildTranslation(
|
| + instr, -1, frame_state_offset, OutputFrameStateCombine::Ignore());
|
| + DeoptimizationExit* const exit =
|
| + new (zone()) DeoptimizationExit(deoptimization_id);
|
| + deoptimization_exits_.push_back(exit);
|
| + return exit;
|
| +}
|
|
|
| int CodeGenerator::TailCallFrameStackSlotDelta(int stack_param_delta) {
|
| CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
|
|
|