Home | History | Annotate | Download | only in interpreter
      1 // Copyright 2015 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/interpreter/bytecode-array-builder.h"
      6 
      7 #include "src/globals.h"
      8 #include "src/interpreter/bytecode-array-writer.h"
      9 #include "src/interpreter/bytecode-dead-code-optimizer.h"
     10 #include "src/interpreter/bytecode-label.h"
     11 #include "src/interpreter/bytecode-peephole-optimizer.h"
     12 #include "src/interpreter/bytecode-register-optimizer.h"
     13 #include "src/interpreter/interpreter-intrinsics.h"
     14 #include "src/objects-inl.h"
     15 
     16 namespace v8 {
     17 namespace internal {
     18 namespace interpreter {
     19 
     20 BytecodeArrayBuilder::BytecodeArrayBuilder(
     21     Isolate* isolate, Zone* zone, int parameter_count, int context_count,
     22     int locals_count, FunctionLiteral* literal,
     23     SourcePositionTableBuilder::RecordingMode source_position_mode)
     24     : zone_(zone),
     25       literal_(literal),
     26       bytecode_generated_(false),
     27       constant_array_builder_(zone),
     28       handler_table_builder_(zone),
     29       return_seen_in_block_(false),
     30       parameter_count_(parameter_count),
     31       local_register_count_(locals_count),
     32       context_register_count_(context_count),
     33       register_allocator_(fixed_register_count()),
     34       bytecode_array_writer_(zone, &constant_array_builder_,
     35                              source_position_mode),
     36       pipeline_(&bytecode_array_writer_),
     37       register_optimizer_(nullptr) {
     38   DCHECK_GE(parameter_count_, 0);
     39   DCHECK_GE(context_register_count_, 0);
     40   DCHECK_GE(local_register_count_, 0);
     41 
     42   if (FLAG_ignition_deadcode) {
     43     pipeline_ = new (zone) BytecodeDeadCodeOptimizer(pipeline_);
     44   }
     45 
     46   if (FLAG_ignition_peephole) {
     47     pipeline_ = new (zone) BytecodePeepholeOptimizer(pipeline_);
     48   }
     49 
     50   if (FLAG_ignition_reo) {
     51     register_optimizer_ = new (zone) BytecodeRegisterOptimizer(
     52         zone, &register_allocator_, fixed_register_count(), parameter_count,
     53         pipeline_);
     54   }
     55 
     56   return_position_ = literal ? literal->return_position() : kNoSourcePosition;
     57 }
     58 
     59 Register BytecodeArrayBuilder::first_context_register() const {
     60   DCHECK_GT(context_register_count_, 0);
     61   return Register(local_register_count_);
     62 }
     63 
     64 Register BytecodeArrayBuilder::last_context_register() const {
     65   DCHECK_GT(context_register_count_, 0);
     66   return Register(local_register_count_ + context_register_count_ - 1);
     67 }
     68 
     69 Register BytecodeArrayBuilder::Parameter(int parameter_index) const {
     70   DCHECK_GE(parameter_index, 0);
     71   return Register::FromParameterIndex(parameter_index, parameter_count());
     72 }
     73 
     74 Register BytecodeArrayBuilder::Local(int index) const {
     75   // TODO(marja): Make a DCHECK once crbug.com/706234 is fixed.
     76   CHECK_LT(index, locals_count());
     77   return Register(index);
     78 }
     79 
     80 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) {
     81   DCHECK(return_seen_in_block_);
     82   DCHECK(!bytecode_generated_);
     83   bytecode_generated_ = true;
     84 
     85   int register_count = total_register_count();
     86 
     87   if (register_optimizer_) {
     88     register_optimizer_->Flush();
     89     register_count = register_optimizer_->maxiumum_register_index() + 1;
     90   }
     91 
     92   Handle<FixedArray> handler_table =
     93       handler_table_builder()->ToHandlerTable(isolate);
     94   return pipeline_->ToBytecodeArray(isolate, register_count, parameter_count(),
     95                                     handler_table);
     96 }
     97 
     98 BytecodeSourceInfo BytecodeArrayBuilder::CurrentSourcePosition(
     99     Bytecode bytecode) {
    100   BytecodeSourceInfo source_position;
    101   if (latest_source_info_.is_valid()) {
    102     // Statement positions need to be emitted immediately.  Expression
    103     // positions can be pushed back until a bytecode is found that can
    104     // throw (if expression position filtering is turned on). We only
    105     // invalidate the existing source position information if it is used.
    106     if (latest_source_info_.is_statement() ||
    107         !FLAG_ignition_filter_expression_positions ||
    108         !Bytecodes::IsWithoutExternalSideEffects(bytecode)) {
    109       source_position = latest_source_info_;
    110       latest_source_info_.set_invalid();
    111     }
    112   }
    113   return source_position;
    114 }
    115 
    116 namespace {
    117 
    118 template <OperandTypeInfo type_info>
    119 class UnsignedOperandHelper {
    120  public:
    121   INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, size_t value)) {
    122     DCHECK(IsValid(value));
    123     return static_cast<uint32_t>(value);
    124   }
    125 
    126   INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, int value)) {
    127     DCHECK_GE(value, 0);
    128     return Convert(builder, static_cast<size_t>(value));
    129   }
    130 
    131  private:
    132   static bool IsValid(size_t value) {
    133     switch (type_info) {
    134       case OperandTypeInfo::kFixedUnsignedByte:
    135         return value <= kMaxUInt8;
    136       case OperandTypeInfo::kFixedUnsignedShort:
    137         return value <= kMaxUInt16;
    138       case OperandTypeInfo::kScalableUnsignedByte:
    139         return value <= kMaxUInt32;
    140       default:
    141         UNREACHABLE();
    142         return false;
    143     }
    144   }
    145 };
    146 
    147 template <OperandType>
    148 class OperandHelper {};
    149 
    150 #define DEFINE_UNSIGNED_OPERAND_HELPER(Name, Type) \
    151   template <>                                      \
    152   class OperandHelper<OperandType::k##Name>        \
    153       : public UnsignedOperandHelper<Type> {};
    154 UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
    155 UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
    156 #undef DEFINE_UNSIGNED_OPERAND_HELPER
    157 
    158 template <>
    159 class OperandHelper<OperandType::kImm> {
    160  public:
    161   INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, int value)) {
    162     return static_cast<uint32_t>(value);
    163   }
    164 };
    165 
    166 template <>
    167 class OperandHelper<OperandType::kReg> {
    168  public:
    169   INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, Register reg)) {
    170     return builder->GetInputRegisterOperand(reg);
    171   }
    172 };
    173 
    174 template <>
    175 class OperandHelper<OperandType::kRegList> {
    176  public:
    177   INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
    178                                  RegisterList reg_list)) {
    179     return builder->GetInputRegisterListOperand(reg_list);
    180   }
    181 };
    182 
    183 template <>
    184 class OperandHelper<OperandType::kRegPair> {
    185  public:
    186   INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
    187                                  RegisterList reg_list)) {
    188     DCHECK_EQ(reg_list.register_count(), 2);
    189     return builder->GetInputRegisterListOperand(reg_list);
    190   }
    191 };
    192 
    193 template <>
    194 class OperandHelper<OperandType::kRegOut> {
    195  public:
    196   INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, Register reg)) {
    197     return builder->GetOutputRegisterOperand(reg);
    198   }
    199 };
    200 
    201 template <>
    202 class OperandHelper<OperandType::kRegOutPair> {
    203  public:
    204   INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
    205                                  RegisterList reg_list)) {
    206     DCHECK_EQ(2, reg_list.register_count());
    207     return builder->GetOutputRegisterListOperand(reg_list);
    208   }
    209 };
    210 
    211 template <>
    212 class OperandHelper<OperandType::kRegOutTriple> {
    213  public:
    214   INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
    215                                  RegisterList reg_list)) {
    216     DCHECK_EQ(3, reg_list.register_count());
    217     return builder->GetOutputRegisterListOperand(reg_list);
    218   }
    219 };
    220 
    221 }  // namespace
    222 
    223 template <Bytecode bytecode, AccumulatorUse accumulator_use,
    224           OperandType... operand_types>
    225 class BytecodeNodeBuilder {
    226  public:
    227   template <typename... Operands>
    228   INLINE(static BytecodeNode Make(BytecodeArrayBuilder* builder,
    229                                   BytecodeSourceInfo source_info,
    230                                   Operands... operands)) {
    231     builder->PrepareToOutputBytecode<bytecode, accumulator_use>();
    232     // The "OperandHelper<operand_types>::Convert(builder, operands)..." will
    233     // expand both the OperandType... and Operands... parameter packs e.g. for:
    234     //   BytecodeNodeBuilder<OperandType::kReg, OperandType::kImm>::Make<
    235     //       Register, int>(..., Register reg, int immediate)
    236     // the code will expand into:
    237     //    OperandHelper<OperandType::kReg>::Convert(builder, reg),
    238     //    OperandHelper<OperandType::kImm>::Convert(builder, immediate),
    239     return BytecodeNode::Create<bytecode, accumulator_use, operand_types...>(
    240         source_info,
    241         OperandHelper<operand_types>::Convert(builder, operands)...);
    242   }
    243 };
    244 
    245 #define DEFINE_BYTECODE_OUTPUT(name, ...)                                \
    246   template <typename... Operands>                                        \
    247   void BytecodeArrayBuilder::Output##name(Operands... operands) {        \
    248     static_assert(sizeof...(Operands) <= Bytecodes::kMaxOperands,        \
    249                   "too many operands for bytecode");                     \
    250     BytecodeNode node(                                                   \
    251         BytecodeNodeBuilder<Bytecode::k##name, __VA_ARGS__>::Make<       \
    252             Operands...>(this, CurrentSourcePosition(Bytecode::k##name), \
    253                          operands...));                                  \
    254     pipeline()->Write(&node);                                            \
    255   }                                                                      \
    256                                                                          \
    257   template <typename... Operands>                                        \
    258   void BytecodeArrayBuilder::Output##name(BytecodeLabel* label,          \
    259                                           Operands... operands) {        \
    260     DCHECK(Bytecodes::IsJump(Bytecode::k##name));                        \
    261     BytecodeNode node(                                                   \
    262         BytecodeNodeBuilder<Bytecode::k##name, __VA_ARGS__>::Make<       \
    263             Operands...>(this, CurrentSourcePosition(Bytecode::k##name), \
    264                          operands...));                                  \
    265     pipeline()->WriteJump(&node, label);                                 \
    266     LeaveBasicBlock();                                                   \
    267   }
    268 BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT)
    269 #undef DEFINE_BYTECODE_OUTPUT
    270 
    271 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
    272                                                             Register reg,
    273                                                             int feedback_slot) {
    274   switch (op) {
    275     case Token::Value::ADD:
    276       OutputAdd(reg, feedback_slot);
    277       break;
    278     case Token::Value::SUB:
    279       OutputSub(reg, feedback_slot);
    280       break;
    281     case Token::Value::MUL:
    282       OutputMul(reg, feedback_slot);
    283       break;
    284     case Token::Value::DIV:
    285       OutputDiv(reg, feedback_slot);
    286       break;
    287     case Token::Value::MOD:
    288       OutputMod(reg, feedback_slot);
    289       break;
    290     case Token::Value::BIT_OR:
    291       OutputBitwiseOr(reg, feedback_slot);
    292       break;
    293     case Token::Value::BIT_XOR:
    294       OutputBitwiseXor(reg, feedback_slot);
    295       break;
    296     case Token::Value::BIT_AND:
    297       OutputBitwiseAnd(reg, feedback_slot);
    298       break;
    299     case Token::Value::SHL:
    300       OutputShiftLeft(reg, feedback_slot);
    301       break;
    302     case Token::Value::SAR:
    303       OutputShiftRight(reg, feedback_slot);
    304       break;
    305     case Token::Value::SHR:
    306       OutputShiftRightLogical(reg, feedback_slot);
    307       break;
    308     default:
    309       UNREACHABLE();
    310   }
    311   return *this;
    312 }
    313 
    314 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op,
    315                                                            int feedback_slot) {
    316   if (op == Token::Value::ADD) {
    317     OutputInc(feedback_slot);
    318   } else {
    319     DCHECK_EQ(op, Token::Value::SUB);
    320     OutputDec(feedback_slot);
    321   }
    322   return *this;
    323 }
    324 
    325 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() {
    326   OutputToBooleanLogicalNot();
    327   return *this;
    328 }
    329 
    330 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
    331   OutputTypeOf();
    332   return *this;
    333 }
    334 
    335 BytecodeArrayBuilder& BytecodeArrayBuilder::GetSuperConstructor(Register out) {
    336   OutputGetSuperConstructor(out);
    337   return *this;
    338 }
    339 
    340 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
    341     Token::Value op, Register reg, int feedback_slot) {
    342   switch (op) {
    343     case Token::Value::EQ:
    344       OutputTestEqual(reg, feedback_slot);
    345       break;
    346     case Token::Value::NE:
    347       OutputTestNotEqual(reg, feedback_slot);
    348       break;
    349     case Token::Value::EQ_STRICT:
    350       OutputTestEqualStrict(reg, feedback_slot);
    351       break;
    352     case Token::Value::LT:
    353       OutputTestLessThan(reg, feedback_slot);
    354       break;
    355     case Token::Value::GT:
    356       OutputTestGreaterThan(reg, feedback_slot);
    357       break;
    358     case Token::Value::LTE:
    359       OutputTestLessThanOrEqual(reg, feedback_slot);
    360       break;
    361     case Token::Value::GTE:
    362       OutputTestGreaterThanOrEqual(reg, feedback_slot);
    363       break;
    364     case Token::Value::INSTANCEOF:
    365       OutputTestInstanceOf(reg);
    366       break;
    367     case Token::Value::IN:
    368       OutputTestIn(reg);
    369       break;
    370     default:
    371       UNREACHABLE();
    372   }
    373   return *this;
    374 }
    375 
    376 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry(
    377     size_t entry) {
    378   OutputLdaConstant(entry);
    379   return *this;
    380 }
    381 
    382 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
    383     v8::internal::Smi* smi) {
    384   int32_t raw_smi = smi->value();
    385   if (raw_smi == 0) {
    386     OutputLdaZero();
    387   } else {
    388     OutputLdaSmi(raw_smi);
    389   }
    390   return *this;
    391 }
    392 
    393 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
    394     const AstRawString* raw_string) {
    395   size_t entry = GetConstantPoolEntry(raw_string);
    396   OutputLdaConstant(entry);
    397   return *this;
    398 }
    399 
    400 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(const Scope* scope) {
    401   size_t entry = GetConstantPoolEntry(scope);
    402   OutputLdaConstant(entry);
    403   return *this;
    404 }
    405 
    406 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
    407     const AstValue* ast_value) {
    408   if (ast_value->IsSmi()) {
    409     return LoadLiteral(ast_value->AsSmi());
    410   } else if (ast_value->IsUndefined()) {
    411     return LoadUndefined();
    412   } else if (ast_value->IsTrue()) {
    413     return LoadTrue();
    414   } else if (ast_value->IsFalse()) {
    415     return LoadFalse();
    416   } else if (ast_value->IsNull()) {
    417     return LoadNull();
    418   } else if (ast_value->IsTheHole()) {
    419     return LoadTheHole();
    420   } else if (ast_value->IsString()) {
    421     return LoadLiteral(ast_value->AsString());
    422   } else if (ast_value->IsHeapNumber()) {
    423     size_t entry = GetConstantPoolEntry(ast_value);
    424     OutputLdaConstant(entry);
    425     return *this;
    426   } else {
    427     // This should be the only ast value type left.
    428     DCHECK(ast_value->IsSymbol());
    429     size_t entry;
    430     switch (ast_value->AsSymbol()) {
    431       case AstSymbol::kHomeObjectSymbol:
    432         entry = HomeObjectSymbolConstantPoolEntry();
    433         break;
    434         // No default case so that we get a warning if AstSymbol changes
    435     }
    436     OutputLdaConstant(entry);
    437     return *this;
    438   }
    439 }
    440 
    441 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
    442   OutputLdaUndefined();
    443   return *this;
    444 }
    445 
    446 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() {
    447   OutputLdaNull();
    448   return *this;
    449 }
    450 
    451 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() {
    452   OutputLdaTheHole();
    453   return *this;
    454 }
    455 
    456 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() {
    457   OutputLdaTrue();
    458   return *this;
    459 }
    460 
    461 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
    462   OutputLdaFalse();
    463   return *this;
    464 }
    465 
    466 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
    467     Register reg) {
    468   if (register_optimizer_) {
    469     register_optimizer_->DoLdar(reg, CurrentSourcePosition(Bytecode::kLdar));
    470   } else {
    471     OutputLdar(reg);
    472   }
    473   return *this;
    474 }
    475 
    476 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
    477     Register reg) {
    478   if (register_optimizer_) {
    479     register_optimizer_->DoStar(reg, CurrentSourcePosition(Bytecode::kStar));
    480   } else {
    481     OutputStar(reg);
    482   }
    483   return *this;
    484 }
    485 
    486 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
    487                                                          Register to) {
    488   DCHECK(from != to);
    489   if (register_optimizer_) {
    490     register_optimizer_->DoMov(from, to, CurrentSourcePosition(Bytecode::kMov));
    491   } else {
    492     OutputMov(from, to);
    493   }
    494   return *this;
    495 }
    496 
    497 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(const AstRawString* name,
    498                                                        int feedback_slot,
    499                                                        TypeofMode typeof_mode) {
    500   size_t name_index = GetConstantPoolEntry(name);
    501   // Ensure that typeof mode is in sync with the IC slot kind if the function
    502   // literal is available (not a unit test case).
    503   // TODO(ishell): check only in debug mode.
    504   if (literal_) {
    505     FeedbackSlot slot = FeedbackVector::ToSlot(feedback_slot);
    506     CHECK_EQ(GetTypeofModeFromSlotKind(feedback_vector_spec()->GetKind(slot)),
    507              typeof_mode);
    508   }
    509   if (typeof_mode == INSIDE_TYPEOF) {
    510     OutputLdaGlobalInsideTypeof(name_index, feedback_slot);
    511   } else {
    512     DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
    513     OutputLdaGlobal(name_index, feedback_slot);
    514   }
    515   return *this;
    516 }
    517 
    518 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
    519     const AstRawString* name, int feedback_slot, LanguageMode language_mode) {
    520   size_t name_index = GetConstantPoolEntry(name);
    521   if (language_mode == SLOPPY) {
    522     OutputStaGlobalSloppy(name_index, feedback_slot);
    523   } else {
    524     DCHECK_EQ(language_mode, STRICT);
    525     OutputStaGlobalStrict(name_index, feedback_slot);
    526   }
    527   return *this;
    528 }
    529 
    530 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(
    531     Register context, int slot_index, int depth,
    532     ContextSlotMutability mutability) {
    533   if (context.is_current_context() && depth == 0) {
    534     if (mutability == kImmutableSlot) {
    535       OutputLdaImmutableCurrentContextSlot(slot_index);
    536     } else {
    537       DCHECK_EQ(kMutableSlot, mutability);
    538       OutputLdaCurrentContextSlot(slot_index);
    539     }
    540   } else if (mutability == kImmutableSlot) {
    541     OutputLdaImmutableContextSlot(context, slot_index, depth);
    542   } else {
    543     DCHECK_EQ(mutability, kMutableSlot);
    544     OutputLdaContextSlot(context, slot_index, depth);
    545   }
    546   return *this;
    547 }
    548 
    549 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
    550                                                              int slot_index,
    551                                                              int depth) {
    552   if (context.is_current_context() && depth == 0) {
    553     OutputStaCurrentContextSlot(slot_index);
    554   } else {
    555     OutputStaContextSlot(context, slot_index, depth);
    556   }
    557   return *this;
    558 }
    559 
    560 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
    561     const AstRawString* name, TypeofMode typeof_mode) {
    562   size_t name_index = GetConstantPoolEntry(name);
    563   if (typeof_mode == INSIDE_TYPEOF) {
    564     OutputLdaLookupSlotInsideTypeof(name_index);
    565   } else {
    566     DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
    567     OutputLdaLookupSlot(name_index);
    568   }
    569   return *this;
    570 }
    571 
    572 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot(
    573     const AstRawString* name, TypeofMode typeof_mode, int slot_index,
    574     int depth) {
    575   size_t name_index = GetConstantPoolEntry(name);
    576   if (typeof_mode == INSIDE_TYPEOF) {
    577     OutputLdaLookupContextSlotInsideTypeof(name_index, slot_index, depth);
    578   } else {
    579     DCHECK(typeof_mode == NOT_INSIDE_TYPEOF);
    580     OutputLdaLookupContextSlot(name_index, slot_index, depth);
    581   }
    582   return *this;
    583 }
    584 
    585 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot(
    586     const AstRawString* name, TypeofMode typeof_mode, int feedback_slot,
    587     int depth) {
    588   size_t name_index = GetConstantPoolEntry(name);
    589   if (typeof_mode == INSIDE_TYPEOF) {
    590     OutputLdaLookupGlobalSlotInsideTypeof(name_index, feedback_slot, depth);
    591   } else {
    592     DCHECK(typeof_mode == NOT_INSIDE_TYPEOF);
    593     OutputLdaLookupGlobalSlot(name_index, feedback_slot, depth);
    594   }
    595   return *this;
    596 }
    597 
    598 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot(
    599     const AstRawString* name, LanguageMode language_mode) {
    600   size_t name_index = GetConstantPoolEntry(name);
    601   if (language_mode == SLOPPY) {
    602     OutputStaLookupSlotSloppy(name_index);
    603   } else {
    604     DCHECK_EQ(language_mode, STRICT);
    605     OutputStaLookupSlotStrict(name_index);
    606   }
    607   return *this;
    608 }
    609 
    610 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
    611     Register object, const AstRawString* name, int feedback_slot) {
    612   size_t name_index = GetConstantPoolEntry(name);
    613   OutputLdaNamedProperty(object, name_index, feedback_slot);
    614   return *this;
    615 }
    616 
    617 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
    618     Register object, int feedback_slot) {
    619   OutputLdaKeyedProperty(object, feedback_slot);
    620   return *this;
    621 }
    622 
    623 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadIteratorProperty(
    624     Register object, int feedback_slot) {
    625   size_t name_index = IteratorSymbolConstantPoolEntry();
    626   OutputLdaNamedProperty(object, name_index, feedback_slot);
    627   return *this;
    628 }
    629 
    630 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAsyncIteratorProperty(
    631     Register object, int feedback_slot) {
    632   size_t name_index = AsyncIteratorSymbolConstantPoolEntry();
    633   OutputLdaNamedProperty(object, name_index, feedback_slot);
    634   return *this;
    635 }
    636 
    637 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreDataPropertyInLiteral(
    638     Register object, Register name, DataPropertyInLiteralFlags flags,
    639     int feedback_slot) {
    640   OutputStaDataPropertyInLiteral(object, name, flags, feedback_slot);
    641   return *this;
    642 }
    643 
    644 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
    645     Register object, size_t name_index, int feedback_slot,
    646     LanguageMode language_mode) {
    647   // Ensure that language mode is in sync with the IC slot kind if the function
    648   // literal is available (not a unit test case).
    649   // TODO(ishell): check only in debug mode.
    650   if (literal_) {
    651     FeedbackSlot slot = FeedbackVector::ToSlot(feedback_slot);
    652     CHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(slot)),
    653              language_mode);
    654   }
    655   if (language_mode == SLOPPY) {
    656     OutputStaNamedPropertySloppy(object, name_index, feedback_slot);
    657   } else {
    658     DCHECK_EQ(language_mode, STRICT);
    659     OutputStaNamedPropertyStrict(object, name_index, feedback_slot);
    660   }
    661   return *this;
    662 }
    663 
    664 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
    665     Register object, const AstRawString* name, int feedback_slot,
    666     LanguageMode language_mode) {
    667   size_t name_index = GetConstantPoolEntry(name);
    668   return StoreNamedProperty(object, name_index, feedback_slot, language_mode);
    669 }
    670 
    671 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedOwnProperty(
    672     Register object, const AstRawString* name, int feedback_slot) {
    673   size_t name_index = GetConstantPoolEntry(name);
    674   // Ensure that the store operation is in sync with the IC slot kind if
    675   // the function literal is available (not a unit test case).
    676   // TODO(ishell): check only in debug mode.
    677   if (literal_) {
    678     FeedbackSlot slot = FeedbackVector::ToSlot(feedback_slot);
    679     CHECK_EQ(FeedbackSlotKind::kStoreOwnNamed,
    680              feedback_vector_spec()->GetKind(slot));
    681   }
    682   OutputStaNamedOwnProperty(object, name_index, feedback_slot);
    683   return *this;
    684 }
    685 
    686 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty(
    687     Register object, Register key, int feedback_slot,
    688     LanguageMode language_mode) {
    689   // Ensure that language mode is in sync with the IC slot kind if the function
    690   // literal is available (not a unit test case).
    691   // TODO(ishell): check only in debug mode.
    692   if (literal_) {
    693     FeedbackSlot slot = FeedbackVector::ToSlot(feedback_slot);
    694     CHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(slot)),
    695              language_mode);
    696   }
    697   if (language_mode == SLOPPY) {
    698     OutputStaKeyedPropertySloppy(object, key, feedback_slot);
    699   } else {
    700     DCHECK_EQ(language_mode, STRICT);
    701     OutputStaKeyedPropertyStrict(object, key, feedback_slot);
    702   }
    703   return *this;
    704 }
    705 
    706 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreHomeObjectProperty(
    707     Register object, int feedback_slot, LanguageMode language_mode) {
    708   size_t name_index = HomeObjectSymbolConstantPoolEntry();
    709   return StoreNamedProperty(object, name_index, feedback_slot, language_mode);
    710 }
    711 
    712 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(
    713     size_t shared_function_info_entry, int slot, int flags) {
    714   OutputCreateClosure(shared_function_info_entry, slot, flags);
    715   return *this;
    716 }
    717 
    718 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateBlockContext(
    719     const Scope* scope) {
    720   size_t entry = GetConstantPoolEntry(scope);
    721   OutputCreateBlockContext(entry);
    722   return *this;
    723 }
    724 
    725 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateCatchContext(
    726     Register exception, const AstRawString* name, const Scope* scope) {
    727   size_t name_index = GetConstantPoolEntry(name);
    728   size_t scope_index = GetConstantPoolEntry(scope);
    729   OutputCreateCatchContext(exception, name_index, scope_index);
    730   return *this;
    731 }
    732 
    733 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(int slots) {
    734   OutputCreateFunctionContext(slots);
    735   return *this;
    736 }
    737 
    738 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEvalContext(int slots) {
    739   OutputCreateEvalContext(slots);
    740   return *this;
    741 }
    742 
    743 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext(
    744     Register object, const Scope* scope) {
    745   size_t scope_index = GetConstantPoolEntry(scope);
    746   OutputCreateWithContext(object, scope_index);
    747   return *this;
    748 }
    749 
    750 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
    751     CreateArgumentsType type) {
    752   switch (type) {
    753     case CreateArgumentsType::kMappedArguments:
    754       OutputCreateMappedArguments();
    755       break;
    756     case CreateArgumentsType::kUnmappedArguments:
    757       OutputCreateUnmappedArguments();
    758       break;
    759     case CreateArgumentsType::kRestParameter:
    760       OutputCreateRestParameter();
    761       break;
    762     default:
    763       UNREACHABLE();
    764   }
    765   return *this;
    766 }
    767 
    768 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
    769     const AstRawString* pattern, int literal_index, int flags) {
    770   size_t pattern_entry = GetConstantPoolEntry(pattern);
    771   OutputCreateRegExpLiteral(pattern_entry, literal_index, flags);
    772   return *this;
    773 }
    774 
    775 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
    776     size_t constant_elements_entry, int literal_index, int flags) {
    777   OutputCreateArrayLiteral(constant_elements_entry, literal_index, flags);
    778   return *this;
    779 }
    780 
    781 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
    782     size_t constant_properties_entry, int literal_index, int flags,
    783     Register output) {
    784   OutputCreateObjectLiteral(constant_properties_entry, literal_index, flags,
    785                             output);
    786   return *this;
    787 }
    788 
    789 BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) {
    790   OutputPushContext(context);
    791   return *this;
    792 }
    793 
    794 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) {
    795   OutputPopContext(context);
    796   return *this;
    797 }
    798 
    799 BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToObject(
    800     Register out) {
    801   OutputToObject(out);
    802   return *this;
    803 }
    804 
    805 BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToName(
    806     Register out) {
    807   OutputToName(out);
    808   return *this;
    809 }
    810 
    811 BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToNumber(
    812     Register out) {
    813   OutputToNumber(out);
    814   return *this;
    815 }
    816 
    817 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
    818   // Flush the register optimizer when binding a label to ensure all
    819   // expected registers are valid when jumping to this label.
    820   if (register_optimizer_) register_optimizer_->Flush();
    821   pipeline_->BindLabel(label);
    822   LeaveBasicBlock();
    823   return *this;
    824 }
    825 
    826 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target,
    827                                                  BytecodeLabel* label) {
    828   pipeline_->BindLabel(target, label);
    829   LeaveBasicBlock();
    830   return *this;
    831 }
    832 
    833 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
    834   DCHECK(!label->is_bound());
    835   OutputJump(label, 0);
    836   return *this;
    837 }
    838 
    839 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) {
    840   // The peephole optimizer attempts to simplify JumpIfToBooleanTrue
    841   // to JumpIfTrue.
    842   DCHECK(!label->is_bound());
    843   OutputJumpIfToBooleanTrue(label, 0);
    844   return *this;
    845 }
    846 
    847 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) {
    848   DCHECK(!label->is_bound());
    849   OutputJumpIfToBooleanFalse(label, 0);
    850   return *this;
    851 }
    852 
    853 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
    854   DCHECK(!label->is_bound());
    855   OutputJumpIfNull(label, 0);
    856   return *this;
    857 }
    858 
    859 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
    860     BytecodeLabel* label) {
    861   DCHECK(!label->is_bound());
    862   OutputJumpIfUndefined(label, 0);
    863   return *this;
    864 }
    865 
    866 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole(
    867     BytecodeLabel* label) {
    868   DCHECK(!label->is_bound());
    869   OutputJumpIfNotHole(label, 0);
    870   return *this;
    871 }
    872 
    873 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfJSReceiver(
    874     BytecodeLabel* label) {
    875   DCHECK(!label->is_bound());
    876   OutputJumpIfJSReceiver(label, 0);
    877   return *this;
    878 }
    879 
    880 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label,
    881                                                      int loop_depth) {
    882   DCHECK(label->is_bound());
    883   OutputJumpLoop(label, 0, loop_depth);
    884   return *this;
    885 }
    886 
    887 BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) {
    888   if (position != kNoSourcePosition) {
    889     // We need to attach a non-breakable source position to a stack
    890     // check, so we simply add it as expression position. There can be
    891     // a prior statement position from constructs like:
    892     //
    893     //    do var x;  while (false);
    894     //
    895     // A Nop could be inserted for empty statements, but since no code
    896     // is associated with these positions, instead we force the stack
    897     // check's expression position which eliminates the empty
    898     // statement's position.
    899     latest_source_info_.ForceExpressionPosition(position);
    900   }
    901   OutputStackCheck();
    902   return *this;
    903 }
    904 
    905 BytecodeArrayBuilder& BytecodeArrayBuilder::SetPendingMessage() {
    906   OutputSetPendingMessage();
    907   return *this;
    908 }
    909 
    910 BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
    911   OutputThrow();
    912   return *this;
    913 }
    914 
    915 BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() {
    916   OutputReThrow();
    917   return *this;
    918 }
    919 
    920 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
    921   SetReturnPosition();
    922   OutputReturn();
    923   return_seen_in_block_ = true;
    924   return *this;
    925 }
    926 
    927 BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() {
    928   OutputDebugger();
    929   return *this;
    930 }
    931 
    932 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare(
    933     Register receiver, RegisterList cache_info_triple) {
    934   DCHECK_EQ(3, cache_info_triple.register_count());
    935   OutputForInPrepare(receiver, cache_info_triple);
    936   return *this;
    937 }
    938 
    939 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInContinue(
    940     Register index, Register cache_length) {
    941   OutputForInContinue(index, cache_length);
    942   return *this;
    943 }
    944 
    945 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext(
    946     Register receiver, Register index, RegisterList cache_type_array_pair,
    947     int feedback_slot) {
    948   DCHECK_EQ(2, cache_type_array_pair.register_count());
    949   OutputForInNext(receiver, index, cache_type_array_pair, feedback_slot);
    950   return *this;
    951 }
    952 
    953 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
    954   OutputForInStep(index);
    955   return *this;
    956 }
    957 
    958 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreModuleVariable(int cell_index,
    959                                                                 int depth) {
    960   OutputStaModuleVariable(cell_index, depth);
    961   return *this;
    962 }
    963 
    964 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadModuleVariable(int cell_index,
    965                                                                int depth) {
    966   OutputLdaModuleVariable(cell_index, depth);
    967   return *this;
    968 }
    969 
    970 BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator(
    971     Register generator) {
    972   OutputSuspendGenerator(generator);
    973   return *this;
    974 }
    975 
    976 BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator(
    977     Register generator) {
    978   OutputResumeGenerator(generator);
    979   return *this;
    980 }
    981 
    982 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(
    983     int handler_id, HandlerTable::CatchPrediction catch_prediction) {
    984   BytecodeLabel handler;
    985   Bind(&handler);
    986   handler_table_builder()->SetHandlerTarget(handler_id, handler.offset());
    987   handler_table_builder()->SetPrediction(handler_id, catch_prediction);
    988   return *this;
    989 }
    990 
    991 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryBegin(int handler_id,
    992                                                          Register context) {
    993   BytecodeLabel try_begin;
    994   Bind(&try_begin);
    995   handler_table_builder()->SetTryRegionStart(handler_id, try_begin.offset());
    996   handler_table_builder()->SetContextRegister(handler_id, context);
    997   return *this;
    998 }
    999 
   1000 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) {
   1001   BytecodeLabel try_end;
   1002   Bind(&try_end);
   1003   handler_table_builder()->SetTryRegionEnd(handler_id, try_end.offset());
   1004   return *this;
   1005 }
   1006 
   1007 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
   1008                                                  RegisterList args,
   1009                                                  int feedback_slot,
   1010                                                  Call::CallType call_type,
   1011                                                  TailCallMode tail_call_mode) {
   1012   if (tail_call_mode == TailCallMode::kDisallow) {
   1013     if (call_type == Call::NAMED_PROPERTY_CALL ||
   1014         call_type == Call::KEYED_PROPERTY_CALL) {
   1015       OutputCallProperty(callable, args, args.register_count(), feedback_slot);
   1016     } else {
   1017       OutputCall(callable, args, args.register_count(), feedback_slot);
   1018     }
   1019   } else {
   1020     DCHECK(tail_call_mode == TailCallMode::kAllow);
   1021     OutputTailCall(callable, args, args.register_count(), feedback_slot);
   1022   }
   1023   return *this;
   1024 }
   1025 
   1026 BytecodeArrayBuilder& BytecodeArrayBuilder::CallWithSpread(Register callable,
   1027                                                            RegisterList args) {
   1028   OutputCallWithSpread(callable, args, args.register_count());
   1029   return *this;
   1030 }
   1031 
   1032 BytecodeArrayBuilder& BytecodeArrayBuilder::Construct(Register constructor,
   1033                                                       RegisterList args,
   1034                                                       int feedback_slot_id) {
   1035   OutputConstruct(constructor, args, args.register_count(), feedback_slot_id);
   1036   return *this;
   1037 }
   1038 
   1039 BytecodeArrayBuilder& BytecodeArrayBuilder::ConstructWithSpread(
   1040     Register constructor, RegisterList args) {
   1041   OutputConstructWithSpread(constructor, args, args.register_count());
   1042   return *this;
   1043 }
   1044 
   1045 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
   1046     Runtime::FunctionId function_id, RegisterList args) {
   1047   DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size);
   1048   DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort);
   1049   if (IntrinsicsHelper::IsSupported(function_id)) {
   1050     IntrinsicsHelper::IntrinsicId intrinsic_id =
   1051         IntrinsicsHelper::FromRuntimeId(function_id);
   1052     OutputInvokeIntrinsic(static_cast<int>(intrinsic_id), args,
   1053                           args.register_count());
   1054   } else {
   1055     OutputCallRuntime(static_cast<int>(function_id), args,
   1056                       args.register_count());
   1057   }
   1058   return *this;
   1059 }
   1060 
   1061 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
   1062     Runtime::FunctionId function_id, Register arg) {
   1063   return CallRuntime(function_id, RegisterList(arg.index(), 1));
   1064 }
   1065 
   1066 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
   1067     Runtime::FunctionId function_id) {
   1068   return CallRuntime(function_id, RegisterList());
   1069 }
   1070 
   1071 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
   1072     Runtime::FunctionId function_id, RegisterList args,
   1073     RegisterList return_pair) {
   1074   DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size);
   1075   DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort);
   1076   DCHECK_EQ(2, return_pair.register_count());
   1077   OutputCallRuntimeForPair(static_cast<uint16_t>(function_id), args,
   1078                            args.register_count(), return_pair);
   1079   return *this;
   1080 }
   1081 
   1082 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
   1083     Runtime::FunctionId function_id, Register arg, RegisterList return_pair) {
   1084   return CallRuntimeForPair(function_id, RegisterList(arg.index(), 1),
   1085                             return_pair);
   1086 }
   1087 
   1088 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index,
   1089                                                           RegisterList args) {
   1090   OutputCallJSRuntime(context_index, args, args.register_count());
   1091   return *this;
   1092 }
   1093 
   1094 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object,
   1095                                                    LanguageMode language_mode) {
   1096   if (language_mode == SLOPPY) {
   1097     OutputDeletePropertySloppy(object);
   1098   } else {
   1099     DCHECK_EQ(language_mode, STRICT);
   1100     OutputDeletePropertyStrict(object);
   1101   }
   1102   return *this;
   1103 }
   1104 
   1105 size_t BytecodeArrayBuilder::GetConstantPoolEntry(
   1106     const AstRawString* raw_string) {
   1107   return constant_array_builder()->Insert(raw_string);
   1108 }
   1109 
   1110 size_t BytecodeArrayBuilder::GetConstantPoolEntry(const AstValue* heap_number) {
   1111   DCHECK(heap_number->IsHeapNumber());
   1112   return constant_array_builder()->Insert(heap_number);
   1113 }
   1114 
   1115 size_t BytecodeArrayBuilder::GetConstantPoolEntry(const Scope* scope) {
   1116   return constant_array_builder()->Insert(scope);
   1117 }
   1118 
   1119 #define ENTRY_GETTER(NAME, ...)                            \
   1120   size_t BytecodeArrayBuilder::NAME##ConstantPoolEntry() { \
   1121     return constant_array_builder()->Insert##NAME();       \
   1122   }
   1123 SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)
   1124 #undef ENTRY_GETTER
   1125 
   1126 size_t BytecodeArrayBuilder::AllocateDeferredConstantPoolEntry() {
   1127   return constant_array_builder()->InsertDeferred();
   1128 }
   1129 
   1130 void BytecodeArrayBuilder::SetDeferredConstantPoolEntry(size_t entry,
   1131                                                         Handle<Object> object) {
   1132   constant_array_builder()->SetDeferredAt(entry, object);
   1133 }
   1134 
   1135 void BytecodeArrayBuilder::SetReturnPosition() {
   1136   if (return_position_ == kNoSourcePosition) return;
   1137   latest_source_info_.MakeStatementPosition(return_position_);
   1138 }
   1139 
   1140 bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const {
   1141   if (!reg.is_valid()) {
   1142     return false;
   1143   }
   1144 
   1145   if (reg.is_current_context() || reg.is_function_closure() ||
   1146       reg.is_new_target()) {
   1147     return true;
   1148   } else if (reg.is_parameter()) {
   1149     int parameter_index = reg.ToParameterIndex(parameter_count());
   1150     return parameter_index >= 0 && parameter_index < parameter_count();
   1151   } else if (reg.index() < fixed_register_count()) {
   1152     return true;
   1153   } else {
   1154     return register_allocator()->RegisterIsLive(reg);
   1155   }
   1156 }
   1157 
   1158 bool BytecodeArrayBuilder::RegisterListIsValid(RegisterList reg_list) const {
   1159   if (reg_list.register_count() == 0) {
   1160     return reg_list.first_register() == Register(0);
   1161   } else {
   1162     int first_reg_index = reg_list.first_register().index();
   1163     for (int i = 0; i < reg_list.register_count(); i++) {
   1164       if (!RegisterIsValid(Register(first_reg_index + i))) {
   1165         return false;
   1166       }
   1167     }
   1168     return true;
   1169   }
   1170 }
   1171 
   1172 template <Bytecode bytecode, AccumulatorUse accumulator_use>
   1173 void BytecodeArrayBuilder::PrepareToOutputBytecode() {
   1174   if (register_optimizer_)
   1175     register_optimizer_->PrepareForBytecode<bytecode, accumulator_use>();
   1176 }
   1177 
   1178 uint32_t BytecodeArrayBuilder::GetInputRegisterOperand(Register reg) {
   1179   DCHECK(RegisterIsValid(reg));
   1180   if (register_optimizer_) reg = register_optimizer_->GetInputRegister(reg);
   1181   return static_cast<uint32_t>(reg.ToOperand());
   1182 }
   1183 
   1184 uint32_t BytecodeArrayBuilder::GetOutputRegisterOperand(Register reg) {
   1185   DCHECK(RegisterIsValid(reg));
   1186   if (register_optimizer_) register_optimizer_->PrepareOutputRegister(reg);
   1187   return static_cast<uint32_t>(reg.ToOperand());
   1188 }
   1189 
   1190 uint32_t BytecodeArrayBuilder::GetInputRegisterListOperand(
   1191     RegisterList reg_list) {
   1192   DCHECK(RegisterListIsValid(reg_list));
   1193   if (register_optimizer_)
   1194     reg_list = register_optimizer_->GetInputRegisterList(reg_list);
   1195   return static_cast<uint32_t>(reg_list.first_register().ToOperand());
   1196 }
   1197 
   1198 uint32_t BytecodeArrayBuilder::GetOutputRegisterListOperand(
   1199     RegisterList reg_list) {
   1200   DCHECK(RegisterListIsValid(reg_list));
   1201   if (register_optimizer_)
   1202     register_optimizer_->PrepareOutputRegisterList(reg_list);
   1203   return static_cast<uint32_t>(reg_list.first_register().ToOperand());
   1204 }
   1205 
   1206 }  // namespace interpreter
   1207 }  // namespace internal
   1208 }  // namespace v8
   1209