LCOV - code coverage report
Current view: top level - src/compiler - code-generator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 412 441 93.4 %
Date: 2017-10-20 Functions: 33 36 91.7 %

          Line data    Source code
       1             : // Copyright 2013 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/code-generator.h"
       6             : 
       7             : #include "src/address-map.h"
       8             : #include "src/assembler-inl.h"
       9             : #include "src/base/adapters.h"
      10             : #include "src/compilation-info.h"
      11             : #include "src/compiler/code-generator-impl.h"
      12             : #include "src/compiler/linkage.h"
      13             : #include "src/compiler/pipeline.h"
      14             : #include "src/eh-frame.h"
      15             : #include "src/frames.h"
      16             : #include "src/macro-assembler-inl.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : namespace compiler {
      21             : 
      22             : class CodeGenerator::JumpTable final : public ZoneObject {
      23             :  public:
      24             :   JumpTable(JumpTable* next, Label** targets, size_t target_count)
      25        7807 :       : next_(next), targets_(targets), target_count_(target_count) {}
      26             : 
      27             :   Label* label() { return &label_; }
      28             :   JumpTable* next() const { return next_; }
      29             :   Label** targets() const { return targets_; }
      30             :   size_t target_count() const { return target_count_; }
      31             : 
      32             :  private:
      33             :   Label label_;
      34             :   JumpTable* const next_;
      35             :   Label** const targets_;
      36             :   size_t const target_count_;
      37             : };
      38             : 
      39     1301551 : CodeGenerator::CodeGenerator(Zone* codegen_zone, Frame* frame, Linkage* linkage,
      40    16948857 :                              InstructionSequence* code, CompilationInfo* info,
      41             :                              base::Optional<OsrHelper> osr_helper,
      42             :                              int start_source_position,
      43     9110730 :                              JumpOptimizationInfo* jump_opt)
      44             :     : zone_(codegen_zone),
      45             :       frame_access_state_(nullptr),
      46             :       linkage_(linkage),
      47             :       code_(code),
      48             :       unwinding_info_writer_(zone()),
      49             :       info_(info),
      50     1301489 :       labels_(zone()->NewArray<Label>(code->InstructionBlockCount())),
      51             :       current_block_(RpoNumber::Invalid()),
      52             :       start_source_position_(start_source_position),
      53             :       current_source_position_(SourcePosition::Unknown()),
      54             :       tasm_(info->isolate(), nullptr, 0, CodeObjectRequired::kNo),
      55             :       resolver_(this),
      56             :       safepoints_(zone()),
      57             :       handlers_(zone()),
      58             :       deoptimization_exits_(zone()),
      59             :       deoptimization_states_(zone()),
      60             :       deoptimization_literals_(zone()),
      61             :       inlined_function_count_(0),
      62             :       translations_(zone()),
      63             :       last_lazy_deopt_pc_(0),
      64             :       caller_registers_saved_(false),
      65             :       jump_tables_(nullptr),
      66             :       ools_(nullptr),
      67             :       osr_helper_(osr_helper),
      68             :       osr_pc_offset_(-1),
      69             :       optimized_out_literal_id_(-1),
      70             :       source_position_table_builder_(zone(),
      71             :                                      info->SourcePositionRecordingMode()),
      72    14316878 :       result_(kSuccess) {
      73    28691692 :   for (int i = 0; i < code->InstructionBlockCount(); ++i) {
      74    13044302 :     new (&labels_[i]) Label;
      75             :   }
      76     1301544 :   CreateFrameAccessState(frame);
      77     1301515 :   CHECK_EQ(info->is_osr(), osr_helper_.has_value());
      78             :   tasm_.set_jump_optimization_info(jump_opt);
      79     1301515 : }
      80             : 
      81    17405244 : Isolate* CodeGenerator::isolate() const { return info_->isolate(); }
      82             : 
      83     2603104 : void CodeGenerator::CreateFrameAccessState(Frame* frame) {
      84     1301555 :   FinishFrame(frame);
      85     1301552 :   frame_access_state_ = new (zone()) FrameAccessState(frame);
      86     1301552 : }
      87             : 
      88     3087686 : CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
      89     3087701 :     int deoptimization_id, SourcePosition pos) {
      90     3087686 :   DeoptimizeKind deopt_kind = GetDeoptimizationKind(deoptimization_id);
      91             :   Deoptimizer::BailoutType bailout_type;
      92     3087686 :   switch (deopt_kind) {
      93             :     case DeoptimizeKind::kSoft: {
      94             :       bailout_type = Deoptimizer::SOFT;
      95             :       break;
      96             :     }
      97             :     case DeoptimizeKind::kEager: {
      98             :       bailout_type = Deoptimizer::EAGER;
      99      315586 :       break;
     100             :     }
     101             :     case DeoptimizeKind::kLazy: {
     102             :       bailout_type = Deoptimizer::LAZY;
     103     2733716 :       break;
     104             :     }
     105           0 :     default: { UNREACHABLE(); }
     106             :   }
     107             :   DeoptimizeReason deoptimization_reason =
     108     3087686 :       GetDeoptimizationReason(deoptimization_id);
     109             :   Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
     110     3087690 :       tasm()->isolate(), deoptimization_id, bailout_type);
     111     3087697 :   if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
     112     3087701 :   if (info()->is_source_positions_enabled()) {
     113      236611 :     tasm()->RecordDeoptReason(deoptimization_reason, pos, deoptimization_id);
     114             :   }
     115             :   tasm()->CallForDeoptimization(deopt_entry, RelocInfo::RUNTIME_ENTRY);
     116     3087701 :   return kSuccess;
     117             : }
     118             : 
     119    35592148 : void CodeGenerator::AssembleCode() {
     120     1301537 :   CompilationInfo* info = this->info();
     121             : 
     122             :   // Open a frame scope to indicate that there is a frame on the stack.  The
     123             :   // MANUAL indicates that the scope shouldn't actually generate code to set up
     124             :   // the frame (that is done in AssemblePrologue).
     125     1301517 :   FrameScope frame_scope(tasm(), StackFrame::MANUAL);
     126             : 
     127     1301527 :   if (info->is_source_positions_enabled()) {
     128       21334 :     AssembleSourcePosition(start_source_position());
     129             :   }
     130             : 
     131             :   // Place function entry hook if requested to do so.
     132     1301544 :   if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) {
     133      619720 :     ProfileEntryHookStub::MaybeCallEntryHookDelayed(tasm(), zone());
     134             :   }
     135             : 
     136             :   // TODO(jupvfranco): This should be the first thing in the code,
     137             :   // or otherwise MaybeCallEntryHookDelayed may happen twice (for
     138             :   // optimized and deoptimized code).
     139             :   // We want to bailout only from JS functions, which are the only ones
     140             :   // that are optimized.
     141     1301537 :   if (info->IsOptimizing()) {
     142             :     DCHECK(linkage()->GetIncomingDescriptor()->IsJSFunctionCall());
     143      443353 :     BailoutIfDeoptimized();
     144             :   }
     145             : 
     146             :   // Define deoptimization literals for all inlined functions.
     147             :   DCHECK_EQ(0u, deoptimization_literals_.size());
     148     2664592 :   for (CompilationInfo::InlinedFunctionHolder& inlined :
     149             :        info->inlined_functions()) {
     150       61528 :     if (!inlined.shared_info.equals(info->shared_info())) {
     151             :       int index = DefineDeoptimizationLiteral(
     152       61472 :           DeoptimizationLiteral(inlined.shared_info));
     153             :       inlined.RegisterInlinedFunctionId(index);
     154             :     }
     155             :   }
     156     1301532 :   inlined_function_count_ = deoptimization_literals_.size();
     157             : 
     158             :   unwinding_info_writer_.SetNumberOfInstructionBlocks(
     159     1301532 :       code()->InstructionBlockCount());
     160             : 
     161             :   // Assemble all non-deferred blocks, followed by deferred ones.
     162     2603021 :   for (int deferred = 0; deferred < 2; ++deferred) {
     163    57383588 :     for (const InstructionBlock* block : code()->instruction_blocks()) {
     164    26088700 :       if (block->IsDeferred() == (deferred == 0)) {
     165             :         continue;
     166             :       }
     167             : 
     168             :       // Align loop headers on 16-byte boundaries.
     169    13044402 :       if (block->IsLoopHeader() && !tasm()->jump_optimization_info()) {
     170       50977 :         tasm()->Align(16);
     171             :       }
     172             :       // Bind a label for a block.
     173    13044404 :       current_block_ = block->rpo_number();
     174    26088808 :       unwinding_info_writer_.BeginInstructionBlock(tasm()->pc_offset(), block);
     175    13044410 :       if (FLAG_code_comments) {
     176             :         // TODO(titzer): these code comments are a giant memory leak.
     177             :         Vector<char> buffer = Vector<char>::New(200);
     178             :         char* buffer_start = buffer.start();
     179             : 
     180             :         int next = SNPrintF(
     181             :             buffer, "-- B%d start%s%s%s%s", block->rpo_number().ToInt(),
     182             :             block->IsDeferred() ? " (deferred)" : "",
     183             :             block->needs_frame() ? "" : " (no frame)",
     184             :             block->must_construct_frame() ? " (construct frame)" : "",
     185           0 :             block->must_deconstruct_frame() ? " (deconstruct frame)" : "");
     186             : 
     187           0 :         buffer = buffer.SubVector(next, buffer.length());
     188             : 
     189           0 :         if (block->IsLoopHeader()) {
     190             :           next =
     191           0 :               SNPrintF(buffer, " (loop up to %d)", block->loop_end().ToInt());
     192           0 :           buffer = buffer.SubVector(next, buffer.length());
     193             :         }
     194           0 :         if (block->loop_header().IsValid()) {
     195             :           next =
     196           0 :               SNPrintF(buffer, " (in loop %d)", block->loop_header().ToInt());
     197           0 :           buffer = buffer.SubVector(next, buffer.length());
     198             :         }
     199           0 :         SNPrintF(buffer, " --");
     200           0 :         tasm()->RecordComment(buffer_start);
     201             :       }
     202             : 
     203    26088820 :       frame_access_state()->MarkHasFrame(block->needs_frame());
     204             : 
     205    13044429 :       tasm()->bind(GetLabel(current_block_));
     206    13044448 :       if (block->must_construct_frame()) {
     207     1074666 :         AssembleConstructFrame();
     208             :         // We need to setup the root register after we assemble the prologue, to
     209             :         // avoid clobbering callee saved registers in case of C linkage and
     210             :         // using the roots.
     211             :         // TODO(mtrofin): investigate how we can avoid doing this repeatedly.
     212     1074671 :         if (linkage()->GetIncomingDescriptor()->InitializeRootRegister()) {
     213      205101 :           tasm()->InitializeRootRegister();
     214             :         }
     215             :       }
     216             : 
     217             :       if (FLAG_enable_embedded_constant_pool && !block->needs_frame()) {
     218             :         ConstantPoolUnavailableScope constant_pool_unavailable(tasm());
     219             :         result_ = AssembleBlock(block);
     220             :       } else {
     221    13044453 :         result_ = AssembleBlock(block);
     222             :       }
     223    14345875 :       if (result_ != kSuccess) return;
     224    13044461 :       unwinding_info_writer_.EndInstructionBlock(block);
     225             :     }
     226             :   }
     227             : 
     228             :   // Assemble all out-of-line code.
     229     1301552 :   if (ools_) {
     230      226661 :     tasm()->RecordComment("-- Out of line code --");
     231      872679 :     for (OutOfLineCode* ool = ools_; ool; ool = ool->next()) {
     232      646024 :       tasm()->bind(ool->entry());
     233      646064 :       ool->Generate();
     234      646063 :       if (ool->exit()->is_bound()) tasm()->jmp(ool->exit());
     235             :     }
     236             :   }
     237             : 
     238             :   // This nop operation is needed to ensure that the trampoline is not
     239             :   // confused with the pc of the call before deoptimization.
     240             :   // The test regress/regress-259 is an example of where we need it.
     241     1301546 :   tasm()->nop();
     242             : 
     243             :   // Assemble deoptimization exits.
     244             :   int last_updated = 0;
     245    10409303 :   for (DeoptimizationExit* exit : deoptimization_exits_) {
     246     3036024 :     tasm()->bind(exit->label());
     247     3036030 :     int trampoline_pc = tasm()->pc_offset();
     248             :     int deoptimization_id = exit->deoptimization_id();
     249     5769743 :     DeoptimizationState* ds = deoptimization_states_[deoptimization_id];
     250             : 
     251     3036029 :     if (ds->kind() == DeoptimizeKind::kLazy) {
     252             :       last_updated = safepoints()->UpdateDeoptimizationInfo(
     253     2733714 :           ds->pc_offset(), trampoline_pc, last_updated);
     254             :     }
     255     3036030 :     AssembleDeoptimizerCall(deoptimization_id, exit->pos());
     256             :   }
     257             : 
     258     1301225 :   FinishCode();
     259             : 
     260             :   // Emit the jump tables.
     261     1301316 :   if (jump_tables_) {
     262        4271 :     tasm()->Align(kPointerSize);
     263       19885 :     for (JumpTable* table = jump_tables_; table; table = table->next()) {
     264        7807 :       tasm()->bind(table->label());
     265        7807 :       AssembleJumpTable(table->targets(), table->target_count());
     266             :     }
     267             :   }
     268             : 
     269             :   // The PerfJitLogger logs code up until here, excluding the safepoint
     270             :   // table. Resolve the unwinding info now so it is aware of the same code size
     271             :   // as reported by perf.
     272     1301316 :   unwinding_info_writer_.Finish(tasm()->pc_offset());
     273             : 
     274     1301316 :   safepoints()->Emit(tasm(), frame()->GetTotalFrameSlotCount());
     275     1301387 :   result_ = kSuccess;
     276             : }
     277             : 
     278     3901633 : Handle<Code> CodeGenerator::FinalizeCode() {
     279     1300543 :   if (result_ != kSuccess) return Handle<Code>();
     280             : 
     281             :   // Allocate exception handler table.
     282     1300543 :   Handle<HandlerTable> table = HandlerTable::Empty(isolate());
     283     1623045 :   if (!handlers_.empty()) {
     284             :     table = Handle<HandlerTable>::cast(isolate()->factory()->NewFixedArray(
     285             :         HandlerTable::LengthForReturn(static_cast<int>(handlers_.size())),
     286       24184 :         TENURED));
     287      334594 :     for (size_t i = 0; i < handlers_.size(); ++i) {
     288      310410 :       table->SetReturnOffset(static_cast<int>(i), handlers_[i].pc_offset);
     289      310410 :       table->SetReturnHandler(static_cast<int>(i), handlers_[i].handler->pos());
     290             :     }
     291             :   }
     292             : 
     293             :   // Allocate the source position table.
     294             :   Handle<ByteArray> source_positions =
     295     1300543 :       source_position_table_builder_.ToSourcePositionTable(isolate());
     296             : 
     297             :   // Allocate deoptimization data.
     298     1300544 :   Handle<DeoptimizationData> deopt_data = GenerateDeoptimizationData();
     299             : 
     300             :   // Allocate and install the code.
     301             :   CodeDesc desc;
     302     1300545 :   tasm()->GetCode(isolate(), &desc);
     303     1300545 :   if (unwinding_info_writer_.eh_frame_writer()) {
     304          21 :     unwinding_info_writer_.eh_frame_writer()->GetEhFrame(&desc);
     305             :   }
     306             : 
     307             :   Handle<Code> result =
     308             :       isolate()->factory()->NewCode(desc, info()->code_kind(), Handle<Object>(),
     309     2601090 :                                     table, source_positions, deopt_data, false);
     310             :   isolate()->counters()->total_compiled_code_size()->Increment(
     311     1300545 :       result->instruction_size());
     312             :   result->set_is_turbofanned(true);
     313     2601090 :   result->set_stack_slots(frame()->GetTotalFrameSlotCount());
     314     2601090 :   result->set_safepoint_table_offset(safepoints()->GetCodeOffset());
     315             : 
     316     2601188 :   LOG_CODE_EVENT(isolate(),
     317             :                  CodeLinePosInfoRecordEvent(*Handle<AbstractCode>::cast(result),
     318             :                                             *source_positions));
     319             : 
     320     1300545 :   return result;
     321             : }
     322             : 
     323             : 
     324    10632484 : bool CodeGenerator::IsNextInAssemblyOrder(RpoNumber block) const {
     325             :   return code()
     326             :       ->InstructionBlockAt(current_block_)
     327    10632547 :       ->ao_number()
     328    21265043 :       .IsNext(code()->InstructionBlockAt(block)->ao_number());
     329             : }
     330             : 
     331             : 
     332     4710808 : void CodeGenerator::RecordSafepoint(ReferenceMap* references,
     333             :                                     Safepoint::Kind kind, int arguments,
     334    12215073 :                                     Safepoint::DeoptMode deopt_mode) {
     335             :   Safepoint safepoint =
     336     4710808 :       safepoints()->DefineSafepoint(tasm(), kind, arguments, deopt_mode);
     337             :   int stackSlotToSpillSlotDelta =
     338     4710437 :       frame()->GetTotalFrameSlotCount() - frame()->GetSpillSlotCount();
     339    67495959 :   for (const InstructionOperand& operand : references->reference_operands()) {
     340    58074627 :     if (operand.IsStackSlot()) {
     341             :       int index = LocationOperand::cast(operand).index();
     342             :       DCHECK_LE(0, index);
     343             :       // We might index values in the fixed part of the frame (i.e. the
     344             :       // closure pointer or the context pointer); these are not spill slots
     345             :       // and therefore don't work with the SafepointTable currently, but
     346             :       // we also don't need to worry about them, since the GC has special
     347             :       // knowledge about those fields anyway.
     348     7504834 :       if (index < stackSlotToSpillSlotDelta) continue;
     349     7504636 :       safepoint.DefinePointerSlot(index, zone());
     350    50569793 :     } else if (operand.IsRegister() && (kind & Safepoint::kWithRegisters)) {
     351           0 :       Register reg = LocationOperand::cast(operand).GetRegister();
     352           0 :       safepoint.DefinePointerRegister(reg, zone());
     353             :     }
     354             :   }
     355     4710895 : }
     356             : 
     357     5300829 : bool CodeGenerator::IsMaterializableFromRoot(
     358     5300829 :     Handle<HeapObject> object, Heap::RootListIndex* index_return) {
     359             :   const CallDescriptor* incoming_descriptor =
     360             :       linkage()->GetIncomingDescriptor();
     361     5300829 :   if (incoming_descriptor->flags() & CallDescriptor::kCanUseRoots) {
     362             :     Heap* heap = isolate()->heap();
     363     7017131 :     return heap->IsRootHandle(object, index_return) &&
     364     7017131 :            !heap->RootCanBeWrittenAfterInitialization(*index_return);
     365             :   }
     366             :   return false;
     367             : }
     368             : 
     369    13044381 : CodeGenerator::CodeGenResult CodeGenerator::AssembleBlock(
     370   115520295 :     const InstructionBlock* block) {
     371   115520300 :   for (int i = block->code_start(); i < block->code_end(); ++i) {
     372             :     Instruction* instr = code()->InstructionAt(i);
     373    44716017 :     CodeGenResult result = AssembleInstruction(instr, block);
     374    44715696 :     if (result != kSuccess) return result;
     375             :   }
     376             :   return kSuccess;
     377             : }
     378             : 
     379       44226 : bool CodeGenerator::IsValidPush(InstructionOperand source,
     380             :                                 CodeGenerator::PushTypeFlags push_type) {
     381       44226 :   if (source.IsImmediate() &&
     382             :       ((push_type & CodeGenerator::kImmediatePush) != 0)) {
     383             :     return true;
     384             :   }
     385       77736 :   if (source.IsRegister() &&
     386             :       ((push_type & CodeGenerator::kRegisterPush) != 0)) {
     387             :     return true;
     388             :   }
     389       21302 :   if (source.IsStackSlot() &&
     390             :       ((push_type & CodeGenerator::kStackSlotPush) != 0)) {
     391             :     return true;
     392             :   }
     393         130 :   return false;
     394             : }
     395             : 
     396      186607 : void CodeGenerator::GetPushCompatibleMoves(Instruction* instr,
     397             :                                            PushTypeFlags push_type,
     398             :                                            ZoneVector<MoveOperands*>* pushes) {
     399      264761 :   pushes->clear();
     400      539745 :   for (int i = Instruction::FIRST_GAP_POSITION;
     401             :        i <= Instruction::LAST_GAP_POSITION; ++i) {
     402             :     Instruction::GapPosition inner_pos =
     403             :         static_cast<Instruction::GapPosition>(i);
     404             :     ParallelMove* parallel_move = instr->GetParallelMove(inner_pos);
     405      363176 :     if (parallel_move != nullptr) {
     406      957223 :       for (auto move : *parallel_move) {
     407      297819 :         InstructionOperand source = move->source();
     408      297819 :         InstructionOperand destination = move->destination();
     409             :         int first_push_compatible_index =
     410             :             V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK ? 1 : 0;
     411             :         // If there are any moves from slots that will be overridden by pushes,
     412             :         // then the full gap resolver must be used since optimization with
     413             :         // pushes don't participate in the parallel move and might clobber
     414             :         // values needed for the gap resolve.
     415      318815 :         if (source.IsStackSlot() &&
     416             :             LocationOperand::cast(source).index() >=
     417             :                 first_push_compatible_index) {
     418             :           pushes->clear();
     419      186607 :           return;
     420             :         }
     421             :         // TODO(danno): Right now, only consider moves from the FIRST gap for
     422             :         // pushes. Theoretically, we could extract pushes for both gaps (there
     423             :         // are cases where this happens), but the logic for that would also have
     424             :         // to check to make sure that non-memory inputs to the pushes from the
     425             :         // LAST gap don't get clobbered in the FIRST gap.
     426      287781 :         if (i == Instruction::FIRST_GAP_POSITION) {
     427      346302 :           if (destination.IsStackSlot() &&
     428             :               LocationOperand::cast(destination).index() >=
     429             :                   first_push_compatible_index) {
     430             :             int index = LocationOperand::cast(destination).index();
     431       44226 :             if (IsValidPush(source, push_type)) {
     432       44096 :               if (index >= static_cast<int>(pushes->size())) {
     433       43724 :                 pushes->resize(index + 1);
     434             :               }
     435       88192 :               (*pushes)[index] = move;
     436             :             }
     437             :           }
     438             :         }
     439             :       }
     440             :     }
     441             :   }
     442             : 
     443             :   // For now, only support a set of continuous pushes at the end of the list.
     444             :   size_t push_count_upper_bound = pushes->size();
     445             :   size_t push_begin = push_count_upper_bound;
     446      267317 :   for (auto move : base::Reversed(*pushes)) {
     447       50658 :     if (move == nullptr) break;
     448       40090 :     push_begin--;
     449             :   }
     450      176569 :   size_t push_count = pushes->size() - push_begin;
     451             :   std::copy(pushes->begin() + push_begin,
     452             :             pushes->begin() + push_begin + push_count, pushes->begin());
     453      176569 :   pushes->resize(push_count);
     454             : }
     455             : 
     456    44715984 : CodeGenerator::CodeGenResult CodeGenerator::AssembleInstruction(
     457   103654050 :     Instruction* instr, const InstructionBlock* block) {
     458             :   int first_unused_stack_slot;
     459    44715984 :   FlagsMode mode = FlagsModeField::decode(instr->opcode());
     460    44715984 :   if (mode != kFlags_trap) {
     461    44518425 :     AssembleSourcePosition(instr);
     462             :   }
     463             :   bool adjust_stack =
     464    44716041 :       GetSlotAboveSPBeforeTailCall(instr, &first_unused_stack_slot);
     465    44716150 :   if (adjust_stack) AssembleTailCallBeforeGap(instr, first_unused_stack_slot);
     466    44716150 :   AssembleGaps(instr);
     467    44716138 :   if (adjust_stack) AssembleTailCallAfterGap(instr, first_unused_stack_slot);
     468             :   DCHECK_IMPLIES(
     469             :       block->must_deconstruct_frame(),
     470             :       instr != code()->InstructionAt(block->last_instruction_index()) ||
     471             :           instr->IsRet() || instr->IsJump());
     472    48107339 :   if (instr->IsJump() && block->must_deconstruct_frame()) {
     473       43927 :     AssembleDeconstructFrame();
     474             :   }
     475             :   // Assemble architecture-specific code for the instruction.
     476    44716172 :   CodeGenResult result = AssembleArchInstruction(instr);
     477    44715622 :   if (result != kSuccess) return result;
     478             : 
     479    44715715 :   FlagsCondition condition = FlagsConditionField::decode(instr->opcode());
     480    44715715 :   switch (mode) {
     481             :     case kFlags_branch: {
     482             :       // Assemble a branch after this instruction.
     483             :       InstructionOperandConverter i(this, instr);
     484     3610740 :       RpoNumber true_rpo = i.InputRpo(instr->InputCount() - 2);
     485     3610748 :       RpoNumber false_rpo = i.InputRpo(instr->InputCount() - 1);
     486             : 
     487     3610721 :       if (true_rpo == false_rpo) {
     488             :         // redundant branch.
     489        1052 :         if (!IsNextInAssemblyOrder(true_rpo)) {
     490         226 :           AssembleArchJump(true_rpo);
     491             :         }
     492        1052 :         return kSuccess;
     493             :       }
     494     3609669 :       if (IsNextInAssemblyOrder(true_rpo)) {
     495             :         // true block is next, can fall through if condition negated.
     496             :         std::swap(true_rpo, false_rpo);
     497             :         condition = NegateFlagsCondition(condition);
     498             :       }
     499             :       BranchInfo branch;
     500     3609697 :       branch.condition = condition;
     501     3609697 :       branch.true_label = GetLabel(true_rpo);
     502     3609697 :       branch.false_label = GetLabel(false_rpo);
     503     3609697 :       branch.fallthru = IsNextInAssemblyOrder(false_rpo);
     504             :       // Assemble architecture-specific branch.
     505     3609703 :       AssembleArchBranch(instr, &branch);
     506     3609654 :       break;
     507             :     }
     508             :     case kFlags_deoptimize: {
     509             :       // Assemble a conditional eager deoptimization after this instruction.
     510             :       InstructionOperandConverter i(this, instr);
     511      302307 :       size_t frame_state_offset = MiscField::decode(instr->opcode());
     512             :       DeoptimizationExit* const exit =
     513      302307 :           AddDeoptimizationExit(instr, frame_state_offset);
     514             :       Label continue_label;
     515             :       BranchInfo branch;
     516      302298 :       branch.condition = condition;
     517      302298 :       branch.true_label = exit->label();
     518      302298 :       branch.false_label = &continue_label;
     519      302298 :       branch.fallthru = true;
     520             :       // Assemble architecture-specific branch.
     521      302298 :       AssembleArchDeoptBranch(instr, &branch);
     522      302301 :       tasm()->bind(&continue_label);
     523             :       break;
     524             :     }
     525             :     case kFlags_set: {
     526             :       // Assemble a boolean materialization after this instruction.
     527      199916 :       AssembleArchBoolean(instr, condition);
     528      199917 :       break;
     529             :     }
     530             :     case kFlags_trap: {
     531      197684 :       AssembleArchTrap(instr, condition);
     532      197678 :       break;
     533             :     }
     534             :     case kFlags_none: {
     535             :       break;
     536             :     }
     537             :   }
     538             :   return kSuccess;
     539             : }
     540             : 
     541    72101208 : void CodeGenerator::AssembleSourcePosition(Instruction* instr) {
     542    44686458 :   SourcePosition source_position = SourcePosition::Unknown();
     543    85153073 :   if (instr->IsNop() && instr->AreMovesRedundant()) return;
     544    27414750 :   if (!code()->GetSourcePosition(instr, &source_position)) return;
     545     4219958 :   AssembleSourcePosition(source_position);
     546             : }
     547             : 
     548     4241234 : void CodeGenerator::AssembleSourcePosition(SourcePosition source_position) {
     549     4241234 :   if (source_position == current_source_position_) return;
     550     2540951 :   current_source_position_ = source_position;
     551     2540951 :   if (!source_position.IsKnown()) return;
     552     2540942 :   source_position_table_builder_.AddPosition(tasm()->pc_offset(),
     553     2540942 :                                              source_position, false);
     554     2541011 :   if (FLAG_code_comments) {
     555           0 :     CompilationInfo* info = this->info();
     556           0 :     if (info->IsStub()) return;
     557           0 :     std::ostringstream buffer;
     558           0 :     buffer << "-- ";
     559           0 :     if (FLAG_trace_turbo || FLAG_trace_turbo_graph ||
     560           0 :         tasm()->isolate()->concurrent_recompilation_enabled()) {
     561           0 :       buffer << source_position;
     562             :     } else {
     563             :       AllowHeapAllocation allocation;
     564             :       AllowHandleAllocation handles;
     565             :       AllowHandleDereference deref;
     566           0 :       buffer << source_position.InliningStack(info);
     567             :     }
     568           0 :     buffer << " --";
     569           0 :     tasm()->RecordComment(StrDup(buffer.str().c_str()));
     570             :   }
     571             : }
     572             : 
     573    44902720 : bool CodeGenerator::GetSlotAboveSPBeforeTailCall(Instruction* instr,
     574             :                                                  int* slot) {
     575    44716131 :   if (instr->IsTailCall()) {
     576             :     InstructionOperandConverter g(this, instr);
     577      186589 :     *slot = g.InputInt32(instr->InputCount() - 1);
     578             :     return true;
     579             :   } else {
     580             :     return false;
     581             :   }
     582             : }
     583             : 
     584    44715992 : void CodeGenerator::AssembleGaps(Instruction* instr) {
     585   134147913 :   for (int i = Instruction::FIRST_GAP_POSITION;
     586             :        i <= Instruction::LAST_GAP_POSITION; i++) {
     587             :     Instruction::GapPosition inner_pos =
     588             :         static_cast<Instruction::GapPosition>(i);
     589             :     ParallelMove* move = instr->GetParallelMove(inner_pos);
     590    89431780 :     if (move != nullptr) resolver()->Resolve(move);
     591             :   }
     592    44716133 : }
     593             : 
     594             : namespace {
     595             : 
     596      442528 : Handle<PodArray<InliningPosition>> CreateInliningPositions(
     597      442528 :     CompilationInfo* info) {
     598      517187 :   const CompilationInfo::InlinedFunctionList& inlined_functions =
     599             :       info->inlined_functions();
     600      442528 :   if (inlined_functions.size() == 0) {
     601             :     return Handle<PodArray<InliningPosition>>::cast(
     602             :         info->isolate()->factory()->empty_byte_array());
     603             :   }
     604             :   Handle<PodArray<InliningPosition>> inl_positions =
     605             :       PodArray<InliningPosition>::New(
     606       13474 :           info->isolate(), static_cast<int>(inlined_functions.size()), TENURED);
     607      149318 :   for (size_t i = 0; i < inlined_functions.size(); ++i) {
     608       61185 :     inl_positions->set(static_cast<int>(i), inlined_functions[i].position);
     609             :   }
     610       13474 :   return inl_positions;
     611             : }
     612             : 
     613             : }  // namespace
     614             : 
     615     1300545 : Handle<DeoptimizationData> CodeGenerator::GenerateDeoptimizationData() {
     616      442528 :   CompilationInfo* info = this->info();
     617     1300545 :   int deopt_count = static_cast<int>(deoptimization_states_.size());
     618     2158562 :   if (deopt_count == 0 && !info->is_osr()) {
     619      858017 :     return DeoptimizationData::Empty(isolate());
     620             :   }
     621             :   Handle<DeoptimizationData> data =
     622      442528 :       DeoptimizationData::New(isolate(), deopt_count, TENURED);
     623             : 
     624             :   Handle<ByteArray> translation_array =
     625      442528 :       translations_.CreateByteArray(isolate()->factory());
     626             : 
     627             :   data->SetTranslationByteArray(*translation_array);
     628             :   data->SetInlinedFunctionCount(
     629      442528 :       Smi::FromInt(static_cast<int>(inlined_function_count_)));
     630             :   data->SetOptimizationId(Smi::FromInt(info->optimization_id()));
     631             : 
     632      442528 :   if (info->has_shared_info()) {
     633             :     data->SetSharedFunctionInfo(*info->shared_info());
     634             :   } else {
     635             :     data->SetSharedFunctionInfo(Smi::kZero);
     636             :   }
     637             : 
     638             :   Handle<FixedArray> literals = isolate()->factory()->NewFixedArray(
     639      885056 :       static_cast<int>(deoptimization_literals_.size()), TENURED);
     640     3370912 :   for (unsigned i = 0; i < deoptimization_literals_.size(); i++) {
     641     1242928 :     Handle<Object> object = deoptimization_literals_[i].Reify(isolate());
     642     2485856 :     literals->set(i, *object);
     643             :   }
     644             :   data->SetLiteralArray(*literals);
     645             : 
     646      442528 :   Handle<PodArray<InliningPosition>> inl_pos = CreateInliningPositions(info);
     647             :   data->SetInliningPositions(*inl_pos);
     648             : 
     649      442528 :   if (info->is_osr()) {
     650             :     DCHECK_LE(0, osr_pc_offset_);
     651        5809 :     data->SetOsrBytecodeOffset(Smi::FromInt(info_->osr_offset().ToInt()));
     652        5809 :     data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_));
     653             :   } else {
     654             :     BailoutId osr_offset = BailoutId::None();
     655             :     data->SetOsrBytecodeOffset(Smi::FromInt(osr_offset.ToInt()));
     656             :     data->SetOsrPcOffset(Smi::FromInt(-1));
     657             :   }
     658             : 
     659             :   // Populate deoptimization entries.
     660     3077632 :   for (int i = 0; i < deopt_count; i++) {
     661     9232896 :     DeoptimizationState* deoptimization_state = deoptimization_states_[i];
     662             :     data->SetBytecodeOffset(i, deoptimization_state->bailout_id());
     663     3077632 :     CHECK(deoptimization_state);
     664             :     data->SetTranslationIndex(
     665     3077632 :         i, Smi::FromInt(deoptimization_state->translation_id()));
     666     3077632 :     data->SetPc(i, Smi::FromInt(deoptimization_state->pc_offset()));
     667             :   }
     668             : 
     669      442528 :   return data;
     670             : }
     671             : 
     672             : 
     673        7807 : Label* CodeGenerator::AddJumpTable(Label** targets, size_t target_count) {
     674       15614 :   jump_tables_ = new (zone()) JumpTable(jump_tables_, targets, target_count);
     675        7807 :   return jump_tables_->label();
     676             : }
     677             : 
     678             : 
     679    12130306 : void CodeGenerator::RecordCallPosition(Instruction* instr) {
     680     4542767 :   CallDescriptor::Flags flags(MiscField::decode(instr->opcode()));
     681             : 
     682     4542767 :   bool needs_frame_state = (flags & CallDescriptor::kNeedsFrameState);
     683             : 
     684             :   RecordSafepoint(
     685             :       instr->reference_map(), Safepoint::kSimple, 0,
     686     9085534 :       needs_frame_state ? Safepoint::kLazyDeopt : Safepoint::kNoLazyDeopt);
     687             : 
     688     4542822 :   if (flags & CallDescriptor::kHasExceptionHandler) {
     689             :     InstructionOperandConverter i(this, instr);
     690      155527 :     RpoNumber handler_rpo = i.InputRpo(instr->InputCount() - 1);
     691      466581 :     handlers_.push_back({GetLabel(handler_rpo), tasm()->pc_offset()});
     692             :   }
     693             : 
     694     4542822 :   if (needs_frame_state) {
     695             :     MarkLazyDeoptSite();
     696             :     // If the frame state is present, it starts at argument 1 (just after the
     697             :     // code address).
     698             :     size_t frame_state_offset = 1;
     699             :     FrameStateDescriptor* descriptor =
     700     2733724 :         GetDeoptimizationEntry(instr, frame_state_offset).descriptor();
     701     2733718 :     int pc_offset = tasm()->pc_offset();
     702             :     int deopt_state_id = BuildTranslation(instr, pc_offset, frame_state_offset,
     703     2733718 :                                           descriptor->state_combine());
     704             : 
     705             :     DeoptimizationExit* const exit = new (zone())
     706     5467436 :         DeoptimizationExit(deopt_state_id, current_source_position_);
     707     2733718 :     deoptimization_exits_.push_back(exit);
     708     2733718 :     safepoints()->RecordLazyDeoptimizationIndex(deopt_state_id);
     709             :   }
     710     4542815 : }
     711             : 
     712     6385081 : int CodeGenerator::DefineDeoptimizationLiteral(DeoptimizationLiteral literal) {
     713     6385081 :   int result = static_cast<int>(deoptimization_literals_.size());
     714    57825022 :   for (unsigned i = 0; i < deoptimization_literals_.size(); ++i) {
     715    27665931 :     if (deoptimization_literals_[i] == literal) return i;
     716             :   }
     717     1246582 :   deoptimization_literals_.push_back(literal);
     718     1246578 :   return result;
     719             : }
     720             : 
     721     5821395 : DeoptimizationEntry const& CodeGenerator::GetDeoptimizationEntry(
     722     5821409 :     Instruction* instr, size_t frame_state_offset) {
     723             :   InstructionOperandConverter i(this, instr);
     724     5821395 :   int const state_id = i.InputInt32(frame_state_offset);
     725     5821409 :   return code()->GetDeoptimizationEntry(state_id);
     726             : }
     727             : 
     728     3087686 : DeoptimizeKind CodeGenerator::GetDeoptimizationKind(
     729             :     int deoptimization_id) const {
     730             :   size_t const index = static_cast<size_t>(deoptimization_id);
     731             :   DCHECK_LT(index, deoptimization_states_.size());
     732     3087686 :   return deoptimization_states_[index]->kind();
     733             : }
     734             : 
     735     3087683 : DeoptimizeReason CodeGenerator::GetDeoptimizationReason(
     736             :     int deoptimization_id) const {
     737             :   size_t const index = static_cast<size_t>(deoptimization_id);
     738             :   DCHECK_LT(index, deoptimization_states_.size());
     739     3087691 :   return deoptimization_states_[index]->reason();
     740             : }
     741             : 
     742    47795618 : void CodeGenerator::TranslateStateValueDescriptor(
     743    47825687 :     StateValueDescriptor* desc, StateValueList* nested,
     744             :     Translation* translation, InstructionOperandIterator* iter) {
     745             :   // Note:
     746             :   // If translation is null, we just skip the relevant instruction operands.
     747    47795618 :   if (desc->IsNested()) {
     748       57130 :     if (translation != nullptr) {
     749       57128 :       translation->BeginCapturedObject(static_cast<int>(nested->size()));
     750             :     }
     751      394815 :     for (auto field : *nested) {
     752             :       TranslateStateValueDescriptor(field.desc, field.nested, translation,
     753      280555 :                                     iter);
     754             :     }
     755    47738488 :   } else if (desc->IsArgumentsElements()) {
     756        8973 :     if (translation != nullptr) {
     757        8973 :       translation->ArgumentsElements(desc->arguments_type());
     758             :     }
     759    47729515 :   } else if (desc->IsArgumentsLength()) {
     760        9276 :     if (translation != nullptr) {
     761        9276 :       translation->ArgumentsLength(desc->arguments_type());
     762             :     }
     763    47720239 :   } else if (desc->IsDuplicate()) {
     764       11820 :     if (translation != nullptr) {
     765       11820 :       translation->DuplicateObject(static_cast<int>(desc->id()));
     766             :     }
     767    47708419 :   } else if (desc->IsPlain()) {
     768    20713945 :     InstructionOperand* op = iter->Advance();
     769    20713945 :     if (translation != nullptr) {
     770             :       AddTranslationForOperand(translation, iter->instruction(), op,
     771    20677414 :                                desc->type());
     772             :     }
     773             :   } else {
     774             :     DCHECK(desc->IsOptimizedOut());
     775    26994474 :     if (translation != nullptr) {
     776    25400881 :       if (optimized_out_literal_id_ == -1) {
     777             :         optimized_out_literal_id_ = DefineDeoptimizationLiteral(
     778      441564 :             DeoptimizationLiteral(isolate()->factory()->optimized_out()));
     779             :       }
     780    25400881 :       translation->StoreLiteral(optimized_out_literal_id_);
     781             :     }
     782             :   }
     783    47795507 : }
     784             : 
     785             : 
     786     3360451 : void CodeGenerator::TranslateFrameStateDescriptorOperands(
     787     3454228 :     FrameStateDescriptor* desc, InstructionOperandIterator* iter,
     788             :     OutputFrameStateCombine combine, Translation* translation) {
     789             :   size_t index = 0;
     790             :   StateValueList* values = desc->GetStateValueDescriptors();
     791   101750324 :   for (StateValueList::iterator it = values->begin(); it != values->end();
     792             :        ++it, ++index) {
     793             :     StateValueDescriptor* value_desc = (*it).desc;
     794    47514781 :     if (!combine.IsOutputIgnored()) {
     795             :       // The result of the call should be placed at position
     796             :       // [index_from_top] in the stack (overwriting whatever was
     797             :       // previously there).
     798    26319106 :       size_t index_from_top = desc->GetSize() - 1 - combine.GetOffsetToPokeAt();
     799    28143206 :       if (index >= index_from_top &&
     800     3648188 :           index < index_from_top + iter->instruction()->OutputCount()) {
     801             :         DCHECK_NOT_NULL(translation);
     802             :         AddTranslationForOperand(
     803             :             translation, iter->instruction(),
     804             :             iter->instruction()->OutputAt(index - index_from_top),
     805     3260268 :             MachineType::AnyTagged());
     806             :         // Skip the instruction operands.
     807     1630134 :         TranslateStateValueDescriptor(value_desc, (*it).nested, nullptr, iter);
     808     1630134 :         continue;
     809             :       }
     810             :     }
     811    45884653 :     TranslateStateValueDescriptor(value_desc, (*it).nested, translation, iter);
     812             :   }
     813             :   DCHECK_EQ(desc->GetSize(), index);
     814     3360381 : }
     815             : 
     816             : 
     817     3360352 : void CodeGenerator::BuildTranslationForFrameStateDescriptor(
     818    10075749 :     FrameStateDescriptor* descriptor, InstructionOperandIterator* iter,
     819        1299 :     Translation* translation, OutputFrameStateCombine state_combine) {
     820             :   // Outer-most state must be added to translation first.
     821     3360352 :   if (descriptor->outer_state() != nullptr) {
     822             :     BuildTranslationForFrameStateDescriptor(descriptor->outer_state(), iter,
     823             :                                             translation,
     824      272676 :                                             OutputFrameStateCombine::Ignore());
     825             :   }
     826             : 
     827             :   Handle<SharedFunctionInfo> shared_info;
     828     3360354 :   if (!descriptor->shared_info().ToHandle(&shared_info)) {
     829        1299 :     if (!info()->has_shared_info()) {
     830     3360383 :       return;  // Stub with no SharedFunctionInfo.
     831             :     }
     832             :     shared_info = info()->shared_info();
     833             :   }
     834             :   int shared_info_id =
     835     3360354 :       DefineDeoptimizationLiteral(DeoptimizationLiteral(shared_info));
     836             : 
     837     3360353 :   switch (descriptor->type()) {
     838             :     case FrameStateType::kInterpretedFunction:
     839             :       translation->BeginInterpretedFrame(
     840             :           descriptor->bailout_id(), shared_info_id,
     841     3258489 :           static_cast<unsigned int>(descriptor->locals_count() + 1));
     842     3258513 :       break;
     843             :     case FrameStateType::kArgumentsAdaptor:
     844             :       translation->BeginArgumentsAdaptorFrame(
     845             :           shared_info_id,
     846       61562 :           static_cast<unsigned int>(descriptor->parameters_count()));
     847       61562 :       break;
     848             :     case FrameStateType::kConstructStub:
     849             :       DCHECK(descriptor->bailout_id().IsValidForConstructStub());
     850             :       translation->BeginConstructStubFrame(
     851             :           descriptor->bailout_id(), shared_info_id,
     852       32279 :           static_cast<unsigned int>(descriptor->parameters_count()));
     853       32279 :       break;
     854             :     case FrameStateType::kBuiltinContinuation: {
     855        1299 :       BailoutId bailout_id = descriptor->bailout_id();
     856             :       int parameter_count =
     857             :           static_cast<unsigned int>(descriptor->parameters_count());
     858             :       translation->BeginBuiltinContinuationFrame(bailout_id, shared_info_id,
     859        1299 :                                                  parameter_count);
     860             :       break;
     861             :     }
     862             :     case FrameStateType::kJavaScriptBuiltinContinuation: {
     863        1415 :       BailoutId bailout_id = descriptor->bailout_id();
     864             :       int parameter_count =
     865             :           static_cast<unsigned int>(descriptor->parameters_count());
     866             :       translation->BeginJavaScriptBuiltinContinuationFrame(
     867        1415 :           bailout_id, shared_info_id, parameter_count);
     868             :       break;
     869             :     }
     870             :     case FrameStateType::kGetterStub:
     871        2979 :       translation->BeginGetterStubFrame(shared_info_id);
     872        2979 :       break;
     873             :     case FrameStateType::kSetterStub:
     874        2329 :       translation->BeginSetterStubFrame(shared_info_id);
     875        2329 :       break;
     876             :   }
     877             : 
     878             :   TranslateFrameStateDescriptorOperands(descriptor, iter, state_combine,
     879     3360377 :                                         translation);
     880             : }
     881             : 
     882             : 
     883     3087678 : int CodeGenerator::BuildTranslation(Instruction* instr, int pc_offset,
     884             :                                     size_t frame_state_offset,
     885     6175400 :                                     OutputFrameStateCombine state_combine) {
     886     6175400 :   DeoptimizationEntry const& entry =
     887     3087678 :       GetDeoptimizationEntry(instr, frame_state_offset);
     888             :   FrameStateDescriptor* const descriptor = entry.descriptor();
     889     3087692 :   frame_state_offset++;
     890             : 
     891             :   Translation translation(
     892     3087701 :       &translations_, static_cast<int>(descriptor->GetFrameCount()),
     893     6175389 :       static_cast<int>(descriptor->GetJSFrameCount()), zone());
     894             :   InstructionOperandIterator iter(instr, frame_state_offset);
     895             :   BuildTranslationForFrameStateDescriptor(descriptor, &iter, &translation,
     896     3087693 :                                           state_combine);
     897             : 
     898     3087708 :   int deoptimization_id = static_cast<int>(deoptimization_states_.size());
     899             : 
     900             :   deoptimization_states_.push_back(new (zone()) DeoptimizationState(
     901     3087708 :       descriptor->bailout_id(), translation.index(), pc_offset, entry.kind(),
     902     6175384 :       entry.reason()));
     903             : 
     904     3087681 :   return deoptimization_id;
     905             : }
     906             : 
     907    22307625 : void CodeGenerator::AddTranslationForOperand(Translation* translation,
     908             :                                              Instruction* instr,
     909             :                                              InstructionOperand* op,
     910     5511215 :                                              MachineType type) {
     911    22307625 :   if (op->IsStackSlot()) {
     912    14360151 :     if (type.representation() == MachineRepresentation::kBit) {
     913       23961 :       translation->StoreBoolStackSlot(LocationOperand::cast(op)->index());
     914    43008053 :     } else if (type == MachineType::Int8() || type == MachineType::Int16() ||
     915             :                type == MachineType::Int32()) {
     916      239055 :       translation->StoreInt32StackSlot(LocationOperand::cast(op)->index());
     917    42291386 :     } else if (type == MachineType::Uint8() || type == MachineType::Uint16() ||
     918             :                type == MachineType::Uint32()) {
     919         969 :       translation->StoreUint32StackSlot(LocationOperand::cast(op)->index());
     920             :     } else {
     921    14096166 :       CHECK_EQ(MachineRepresentation::kTagged, type.representation());
     922    14096166 :       translation->StoreStackSlot(LocationOperand::cast(op)->index());
     923             :     }
     924     7947474 :   } else if (op->IsFPStackSlot()) {
     925      188096 :     if (type.representation() == MachineRepresentation::kFloat64) {
     926      187771 :       translation->StoreDoubleStackSlot(LocationOperand::cast(op)->index());
     927             :     } else {
     928         325 :       CHECK_EQ(MachineRepresentation::kFloat32, type.representation());
     929         325 :       translation->StoreFloatStackSlot(LocationOperand::cast(op)->index());
     930             :     }
     931     7759378 :   } else if (op->IsRegister()) {
     932             :     InstructionOperandConverter converter(this, instr);
     933     2179034 :     if (type.representation() == MachineRepresentation::kBit) {
     934        2732 :       translation->StoreBoolRegister(converter.ToRegister(op));
     935     6527637 :     } else if (type == MachineType::Int8() || type == MachineType::Int16() ||
     936             :                type == MachineType::Int32()) {
     937       53795 :       translation->StoreInt32Register(converter.ToRegister(op));
     938     6367519 :     } else if (type == MachineType::Uint8() || type == MachineType::Uint16() ||
     939             :                type == MachineType::Uint32()) {
     940        1473 :       translation->StoreUint32Register(converter.ToRegister(op));
     941             :     } else {
     942     2121034 :       CHECK_EQ(MachineRepresentation::kTagged, type.representation());
     943     2121034 :       translation->StoreRegister(converter.ToRegister(op));
     944             :     }
     945     5580344 :   } else if (op->IsFPRegister()) {
     946             :     InstructionOperandConverter converter(this, instr);
     947       69134 :     if (type.representation() == MachineRepresentation::kFloat64) {
     948       68907 :       translation->StoreDoubleRegister(converter.ToDoubleRegister(op));
     949             :     } else {
     950         227 :       CHECK_EQ(MachineRepresentation::kFloat32, type.representation());
     951         227 :       translation->StoreFloatRegister(converter.ToFloatRegister(op));
     952             :     }
     953             :   } else {
     954     5511210 :     CHECK(op->IsImmediate());
     955             :     InstructionOperandConverter converter(this, instr);
     956     5511210 :     Constant constant = converter.ToConstant(op);
     957             :     DeoptimizationLiteral literal;
     958     5511216 :     switch (constant.type()) {
     959             :       case Constant::kInt32:
     960       11777 :         if (type.representation() == MachineRepresentation::kTagged) {
     961             :           // When pointers are 4 bytes, we can use int32 constants to represent
     962             :           // Smis.
     963             :           DCHECK_EQ(4, kPointerSize);
     964          12 :           Smi* smi = reinterpret_cast<Smi*>(constant.ToInt32());
     965             :           DCHECK(smi->IsSmi());
     966           6 :           literal = DeoptimizationLiteral(smi->value());
     967       11771 :         } else if (type.representation() == MachineRepresentation::kBit) {
     968         162 :           if (constant.ToInt32() == 0) {
     969             :             literal =
     970          48 :                 DeoptimizationLiteral(isolate()->factory()->false_value());
     971             :           } else {
     972             :             DCHECK_EQ(1, constant.ToInt32());
     973          33 :             literal = DeoptimizationLiteral(isolate()->factory()->true_value());
     974             :           }
     975             :         } else {
     976             :           // TODO(jarin,bmeurer): We currently pass in raw pointers to the
     977             :           // JSFunction::entry here. We should really consider fixing this.
     978             :           DCHECK(type == MachineType::Int32() ||
     979             :                  type == MachineType::Uint32() ||
     980             :                  type.representation() == MachineRepresentation::kWord32 ||
     981             :                  type.representation() == MachineRepresentation::kNone);
     982             :           DCHECK(type.representation() != MachineRepresentation::kNone ||
     983             :                  constant.ToInt32() == FrameStateDescriptor::kImpossibleValue);
     984       11690 :           if (type == MachineType::Uint32()) {
     985             :             literal = DeoptimizationLiteral(
     986        1028 :                 static_cast<uint32_t>(constant.ToInt32()));
     987             :           } else {
     988       22352 :             literal = DeoptimizationLiteral(constant.ToInt32());
     989             :           }
     990             :         }
     991             :         break;
     992             :       case Constant::kInt64:
     993             :         // When pointers are 8 bytes, we can use int64 constants to represent
     994             :         // Smis.
     995             :         // TODO(jarin,bmeurer): We currently pass in raw pointers to the
     996             :         // JSFunction::entry here. We should really consider fixing this.
     997             :         DCHECK(type.representation() == MachineRepresentation::kWord64 ||
     998             :                type.representation() == MachineRepresentation::kTagged);
     999             :         DCHECK_EQ(8, kPointerSize);
    1000             :         {
    1001             :           Smi* smi = reinterpret_cast<Smi*>(constant.ToInt64());
    1002             :           DCHECK(smi->IsSmi());
    1003           0 :           literal = DeoptimizationLiteral(smi->value());
    1004             :         }
    1005           0 :         break;
    1006             :       case Constant::kFloat32:
    1007             :         DCHECK(type.representation() == MachineRepresentation::kFloat32 ||
    1008             :                type.representation() == MachineRepresentation::kTagged);
    1009          50 :         literal = DeoptimizationLiteral(constant.ToFloat32());
    1010          25 :         break;
    1011             :       case Constant::kFloat64:
    1012             :         DCHECK(type.representation() == MachineRepresentation::kFloat64 ||
    1013             :                type.representation() == MachineRepresentation::kTagged);
    1014      724959 :         literal = DeoptimizationLiteral(constant.ToFloat64().value());
    1015      724959 :         break;
    1016             :       case Constant::kHeapObject:
    1017             :         DCHECK_EQ(MachineRepresentation::kTagged, type.representation());
    1018     4774455 :         literal = DeoptimizationLiteral(constant.ToHeapObject());
    1019     4774454 :         break;
    1020             :       default:
    1021           0 :         UNREACHABLE();
    1022             :     }
    1023     5511215 :     if (literal.object().equals(info()->closure())) {
    1024     2989488 :       translation->StoreJSFrameFunction();
    1025             :     } else {
    1026     2521727 :       int literal_id = DefineDeoptimizationLiteral(literal);
    1027     2521724 :       translation->StoreLiteral(literal_id);
    1028             :     }
    1029             :   }
    1030    22307624 : }
    1031             : 
    1032           0 : void CodeGenerator::MarkLazyDeoptSite() {
    1033     5467448 :   last_lazy_deopt_pc_ = tasm()->pc_offset();
    1034           0 : }
    1035             : 
    1036      302295 : DeoptimizationExit* CodeGenerator::AddDeoptimizationExit(
    1037      302293 :     Instruction* instr, size_t frame_state_offset) {
    1038             :   int const deoptimization_id = BuildTranslation(
    1039      302295 :       instr, -1, frame_state_offset, OutputFrameStateCombine::Ignore());
    1040             : 
    1041             :   DeoptimizationExit* const exit = new (zone())
    1042      604589 :       DeoptimizationExit(deoptimization_id, current_source_position_);
    1043      302296 :   deoptimization_exits_.push_back(exit);
    1044      302298 :   return exit;
    1045             : }
    1046             : 
    1047     1291998 : OutOfLineCode::OutOfLineCode(CodeGenerator* gen)
    1048     1291998 :     : frame_(gen->frame()), tasm_(gen->tasm()), next_(gen->ools_) {
    1049      645999 :   gen->ools_ = this;
    1050      645999 : }
    1051             : 
    1052           0 : OutOfLineCode::~OutOfLineCode() {}
    1053             : 
    1054     1242928 : Handle<Object> DeoptimizationLiteral::Reify(Isolate* isolate) const {
    1055     1242928 :   return object_.is_null() ? isolate->factory()->NewNumber(number_) : object_;
    1056             : }
    1057             : 
    1058             : }  // namespace compiler
    1059             : }  // namespace internal
    1060             : }  // namespace v8

Generated by: LCOV version 1.10