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-jump-table.h"
     10 #include "src/interpreter/bytecode-label.h"
     11 #include "src/interpreter/bytecode-node.h"
     12 #include "src/interpreter/bytecode-register-optimizer.h"
     13 #include "src/interpreter/bytecode-source-info.h"
     14 #include "src/interpreter/interpreter-intrinsics.h"
     15 #include "src/objects-inl.h"
     16 
     17 namespace v8 {
     18 namespace internal {
     19 namespace interpreter {
     20 
     21 class RegisterTransferWriter final
     22     : public NON_EXPORTED_BASE(BytecodeRegisterOptimizer::BytecodeWriter),
     23       public NON_EXPORTED_BASE(ZoneObject) {
     24  public:
     25   RegisterTransferWriter(BytecodeArrayBuilder* builder) : builder_(builder) {}
     26   ~RegisterTransferWriter() override {}
     27 
     28   void EmitLdar(Register input) override { builder_->OutputLdarRaw(input); }
     29 
     30   void EmitStar(Register output) override { builder_->OutputStarRaw(output); }
     31 
     32   void EmitMov(Register input, Register output) override {
     33     builder_->OutputMovRaw(input, output);
     34   }
     35 
     36  private:
     37   BytecodeArrayBuilder* builder_;
     38 };
     39 
     40 BytecodeArrayBuilder::BytecodeArrayBuilder(
     41     Zone* zone, int parameter_count, int locals_count,
     42     FeedbackVectorSpec* feedback_vector_spec,
     43     SourcePositionTableBuilder::RecordingMode source_position_mode)
     44     : zone_(zone),
     45       feedback_vector_spec_(feedback_vector_spec),
     46       bytecode_generated_(false),
     47       constant_array_builder_(zone),
     48       handler_table_builder_(zone),
     49       return_seen_in_block_(false),
     50       parameter_count_(parameter_count),
     51       local_register_count_(locals_count),
     52       register_allocator_(fixed_register_count()),
     53       bytecode_array_writer_(zone, &constant_array_builder_,
     54                              source_position_mode),
     55       register_optimizer_(nullptr) {
     56   DCHECK_GE(parameter_count_, 0);
     57   DCHECK_GE(local_register_count_, 0);
     58 
     59   if (FLAG_ignition_reo) {
     60     register_optimizer_ = new (zone) BytecodeRegisterOptimizer(
     61         zone, &register_allocator_, fixed_register_count(), parameter_count,
     62         new (zone) RegisterTransferWriter(this));
     63   }
     64 }
     65 
     66 Register BytecodeArrayBuilder::Parameter(int parameter_index) const {
     67   DCHECK_GE(parameter_index, 0);
     68   // The parameter indices are shifted by 1 (receiver is the
     69   // first entry).
     70   return Register::FromParameterIndex(parameter_index + 1, parameter_count());
     71 }
     72 
     73 Register BytecodeArrayBuilder::Receiver() const {
     74   return Register::FromParameterIndex(0, parameter_count());
     75 }
     76 
     77 Register BytecodeArrayBuilder::Local(int index) const {
     78   // TODO(marja): Make a DCHECK once crbug.com/706234 is fixed.
     79   CHECK_LT(index, locals_count());
     80   return Register(index);
     81 }
     82 
     83 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) {
     84   DCHECK(return_seen_in_block_);
     85   DCHECK(!bytecode_generated_);
     86   bytecode_generated_ = true;
     87 
     88   int register_count = total_register_count();
     89 
     90   if (register_optimizer_) {
     91     register_optimizer_->Flush();
     92     register_count = register_optimizer_->maxiumum_register_index() + 1;
     93   }
     94 
     95   Handle<ByteArray> handler_table =
     96       handler_table_builder()->ToHandlerTable(isolate);
     97   return bytecode_array_writer_.ToBytecodeArray(
     98       isolate, register_count, parameter_count(), handler_table);
     99 }
    100 
    101 BytecodeSourceInfo BytecodeArrayBuilder::CurrentSourcePosition(
    102     Bytecode bytecode) {
    103   BytecodeSourceInfo source_position;
    104   if (latest_source_info_.is_valid()) {
    105     // Statement positions need to be emitted immediately.  Expression
    106     // positions can be pushed back until a bytecode is found that can
    107     // throw (if expression position filtering is turned on). We only
    108     // invalidate the existing source position information if it is used.
    109     if (latest_source_info_.is_statement() ||
    110         !FLAG_ignition_filter_expression_positions ||
    111         !Bytecodes::IsWithoutExternalSideEffects(bytecode)) {
    112       source_position = latest_source_info_;
    113       latest_source_info_.set_invalid();
    114     }
    115   }
    116   return source_position;
    117 }
    118 
    119 void BytecodeArrayBuilder::SetDeferredSourceInfo(
    120     BytecodeSourceInfo source_info) {
    121   if (!source_info.is_valid()) return;
    122   deferred_source_info_ = source_info;
    123 }
    124 
    125 void BytecodeArrayBuilder::AttachOrEmitDeferredSourceInfo(BytecodeNode* node) {
    126   if (!deferred_source_info_.is_valid()) return;
    127   if (!node->source_info().is_valid()) {
    128     node->set_source_info(deferred_source_info_);
    129   } else if (deferred_source_info_.is_statement() &&
    130              node->source_info().is_expression()) {
    131     BytecodeSourceInfo source_position = node->source_info();
    132     source_position.MakeStatementPosition(source_position.source_position());
    133     node->set_source_info(source_position);
    134   }
    135   deferred_source_info_.set_invalid();
    136 }
    137 
    138 void BytecodeArrayBuilder::Write(BytecodeNode* node) {
    139   AttachOrEmitDeferredSourceInfo(node);
    140   bytecode_array_writer_.Write(node);
    141 }
    142 
    143 void BytecodeArrayBuilder::WriteJump(BytecodeNode* node, BytecodeLabel* label) {
    144   AttachOrEmitDeferredSourceInfo(node);
    145   bytecode_array_writer_.WriteJump(node, label);
    146 }
    147 
    148 void BytecodeArrayBuilder::WriteSwitch(BytecodeNode* node,
    149                                        BytecodeJumpTable* jump_table) {
    150   AttachOrEmitDeferredSourceInfo(node);
    151   bytecode_array_writer_.WriteSwitch(node, jump_table);
    152 }
    153 
    154 void BytecodeArrayBuilder::OutputLdarRaw(Register reg) {
    155   uint32_t operand = static_cast<uint32_t>(reg.ToOperand());
    156   BytecodeNode node(BytecodeNode::Ldar(BytecodeSourceInfo(), operand));
    157   Write(&node);
    158 }
    159 
    160 void BytecodeArrayBuilder::OutputStarRaw(Register reg) {
    161   uint32_t operand = static_cast<uint32_t>(reg.ToOperand());
    162   BytecodeNode node(BytecodeNode::Star(BytecodeSourceInfo(), operand));
    163   Write(&node);
    164 }
    165 
    166 void BytecodeArrayBuilder::OutputMovRaw(Register src, Register dest) {
    167   uint32_t operand0 = static_cast<uint32_t>(src.ToOperand());
    168   uint32_t operand1 = static_cast<uint32_t>(dest.ToOperand());
    169   BytecodeNode node(
    170       BytecodeNode::Mov(BytecodeSourceInfo(), operand0, operand1));
    171   Write(&node);
    172 }
    173 
    174 namespace {
    175 
    176 template <OperandTypeInfo type_info>
    177 class UnsignedOperandHelper {
    178  public:
    179   V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
    180                                     size_t value) {
    181     DCHECK(IsValid(value));
    182     return static_cast<uint32_t>(value);
    183   }
    184 
    185   V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder, int value) {
    186     DCHECK_GE(value, 0);
    187     return Convert(builder, static_cast<size_t>(value));
    188   }
    189 
    190  private:
    191   static bool IsValid(size_t value) {
    192     switch (type_info) {
    193       case OperandTypeInfo::kFixedUnsignedByte:
    194         return value <= kMaxUInt8;
    195       case OperandTypeInfo::kFixedUnsignedShort:
    196         return value <= kMaxUInt16;
    197       case OperandTypeInfo::kScalableUnsignedByte:
    198         return value <= kMaxUInt32;
    199       default:
    200         UNREACHABLE();
    201     }
    202   }
    203 };
    204 
    205 template <OperandType>
    206 class OperandHelper {};
    207 
    208 #define DEFINE_UNSIGNED_OPERAND_HELPER(Name, Type) \
    209   template <>                                      \
    210   class OperandHelper<OperandType::k##Name>        \
    211       : public UnsignedOperandHelper<Type> {};
    212 UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
    213 UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
    214 #undef DEFINE_UNSIGNED_OPERAND_HELPER
    215 
    216 template <>
    217 class OperandHelper<OperandType::kImm> {
    218  public:
    219   V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder, int value) {
    220     return static_cast<uint32_t>(value);
    221   }
    222 };
    223 
    224 template <>
    225 class OperandHelper<OperandType::kReg> {
    226  public:
    227   V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
    228                                     Register reg) {
    229     return builder->GetInputRegisterOperand(reg);
    230   }
    231 };
    232 
    233 template <>
    234 class OperandHelper<OperandType::kRegList> {
    235  public:
    236   V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
    237                                     RegisterList reg_list) {
    238     return builder->GetInputRegisterListOperand(reg_list);
    239   }
    240 };
    241 
    242 template <>
    243 class OperandHelper<OperandType::kRegPair> {
    244  public:
    245   V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
    246                                     RegisterList reg_list) {
    247     DCHECK_EQ(reg_list.register_count(), 2);
    248     return builder->GetInputRegisterListOperand(reg_list);
    249   }
    250 };
    251 
    252 template <>
    253 class OperandHelper<OperandType::kRegOut> {
    254  public:
    255   V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
    256                                     Register reg) {
    257     return builder->GetOutputRegisterOperand(reg);
    258   }
    259 };
    260 
    261 template <>
    262 class OperandHelper<OperandType::kRegOutList> {
    263  public:
    264   V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
    265                                     RegisterList reg_list) {
    266     return builder->GetOutputRegisterListOperand(reg_list);
    267   }
    268 };
    269 
    270 template <>
    271 class OperandHelper<OperandType::kRegOutPair> {
    272  public:
    273   V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
    274                                     RegisterList reg_list) {
    275     DCHECK_EQ(2, reg_list.register_count());
    276     return builder->GetOutputRegisterListOperand(reg_list);
    277   }
    278 };
    279 
    280 template <>
    281 class OperandHelper<OperandType::kRegOutTriple> {
    282  public:
    283   V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
    284                                     RegisterList reg_list) {
    285     DCHECK_EQ(3, reg_list.register_count());
    286     return builder->GetOutputRegisterListOperand(reg_list);
    287   }
    288 };
    289 
    290 }  // namespace
    291 
    292 template <Bytecode bytecode, AccumulatorUse accumulator_use,
    293           OperandType... operand_types>
    294 class BytecodeNodeBuilder {
    295  public:
    296   template <typename... Operands>
    297   V8_INLINE static BytecodeNode Make(BytecodeArrayBuilder* builder,
    298                                      Operands... operands) {
    299     static_assert(sizeof...(Operands) <= Bytecodes::kMaxOperands,
    300                   "too many operands for bytecode");
    301     builder->PrepareToOutputBytecode<bytecode, accumulator_use>();
    302     // The "OperandHelper<operand_types>::Convert(builder, operands)..." will
    303     // expand both the OperandType... and Operands... parameter packs e.g. for:
    304     //   BytecodeNodeBuilder<OperandType::kReg, OperandType::kImm>::Make<
    305     //       Register, int>(..., Register reg, int immediate)
    306     // the code will expand into:
    307     //    OperandHelper<OperandType::kReg>::Convert(builder, reg),
    308     //    OperandHelper<OperandType::kImm>::Convert(builder, immediate),
    309     return BytecodeNode::Create<bytecode, accumulator_use, operand_types...>(
    310         builder->CurrentSourcePosition(bytecode),
    311         OperandHelper<operand_types>::Convert(builder, operands)...);
    312   }
    313 };
    314 
    315 #define DEFINE_BYTECODE_OUTPUT(name, ...)                             \
    316   template <typename... Operands>                                     \
    317   BytecodeNode BytecodeArrayBuilder::Create##name##Node(              \
    318       Operands... operands) {                                         \
    319     return BytecodeNodeBuilder<Bytecode::k##name, __VA_ARGS__>::Make( \
    320         this, operands...);                                           \
    321   }                                                                   \
    322                                                                       \
    323   template <typename... Operands>                                     \
    324   void BytecodeArrayBuilder::Output##name(Operands... operands) {     \
    325     BytecodeNode node(Create##name##Node(operands...));               \
    326     Write(&node);                                                     \
    327   }                                                                   \
    328                                                                       \
    329   template <typename... Operands>                                     \
    330   void BytecodeArrayBuilder::Output##name(BytecodeLabel* label,       \
    331                                           Operands... operands) {     \
    332     DCHECK(Bytecodes::IsJump(Bytecode::k##name));                     \
    333     BytecodeNode node(Create##name##Node(operands...));               \
    334     WriteJump(&node, label);                                          \
    335     LeaveBasicBlock();                                                \
    336   }
    337 BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT)
    338 #undef DEFINE_BYTECODE_OUTPUT
    339 
    340 void BytecodeArrayBuilder::OutputSwitchOnSmiNoFeedback(
    341     BytecodeJumpTable* jump_table) {
    342   BytecodeNode node(CreateSwitchOnSmiNoFeedbackNode(
    343       jump_table->constant_pool_index(), jump_table->size(),
    344       jump_table->case_value_base()));
    345   WriteSwitch(&node, jump_table);
    346   LeaveBasicBlock();
    347 }
    348 
    349 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
    350                                                             Register reg,
    351                                                             int feedback_slot) {
    352   switch (op) {
    353     case Token::Value::ADD:
    354       OutputAdd(reg, feedback_slot);
    355       break;
    356     case Token::Value::SUB:
    357       OutputSub(reg, feedback_slot);
    358       break;
    359     case Token::Value::MUL:
    360       OutputMul(reg, feedback_slot);
    361       break;
    362     case Token::Value::DIV:
    363       OutputDiv(reg, feedback_slot);
    364       break;
    365     case Token::Value::MOD:
    366       OutputMod(reg, feedback_slot);
    367       break;
    368     case Token::Value::EXP:
    369       OutputExp(reg, feedback_slot);
    370       break;
    371     case Token::Value::BIT_OR:
    372       OutputBitwiseOr(reg, feedback_slot);
    373       break;
    374     case Token::Value::BIT_XOR:
    375       OutputBitwiseXor(reg, feedback_slot);
    376       break;
    377     case Token::Value::BIT_AND:
    378       OutputBitwiseAnd(reg, feedback_slot);
    379       break;
    380     case Token::Value::SHL:
    381       OutputShiftLeft(reg, feedback_slot);
    382       break;
    383     case Token::Value::SAR:
    384       OutputShiftRight(reg, feedback_slot);
    385       break;
    386     case Token::Value::SHR:
    387       OutputShiftRightLogical(reg, feedback_slot);
    388       break;
    389     default:
    390       UNREACHABLE();
    391   }
    392   return *this;
    393 }
    394 
    395 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperationSmiLiteral(
    396     Token::Value op, Smi* literal, int feedback_slot) {
    397   switch (op) {
    398     case Token::Value::ADD:
    399       OutputAddSmi(literal->value(), feedback_slot);
    400       break;
    401     case Token::Value::SUB:
    402       OutputSubSmi(literal->value(), feedback_slot);
    403       break;
    404     case Token::Value::MUL:
    405       OutputMulSmi(literal->value(), feedback_slot);
    406       break;
    407     case Token::Value::DIV:
    408       OutputDivSmi(literal->value(), feedback_slot);
    409       break;
    410     case Token::Value::MOD:
    411       OutputModSmi(literal->value(), feedback_slot);
    412       break;
    413     case Token::Value::EXP:
    414       OutputExpSmi(literal->value(), feedback_slot);
    415       break;
    416     case Token::Value::BIT_OR:
    417       OutputBitwiseOrSmi(literal->value(), feedback_slot);
    418       break;
    419     case Token::Value::BIT_XOR:
    420       OutputBitwiseXorSmi(literal->value(), feedback_slot);
    421       break;
    422     case Token::Value::BIT_AND:
    423       OutputBitwiseAndSmi(literal->value(), feedback_slot);
    424       break;
    425     case Token::Value::SHL:
    426       OutputShiftLeftSmi(literal->value(), feedback_slot);
    427       break;
    428     case Token::Value::SAR:
    429       OutputShiftRightSmi(literal->value(), feedback_slot);
    430       break;
    431     case Token::Value::SHR:
    432       OutputShiftRightLogicalSmi(literal->value(), feedback_slot);
    433       break;
    434     default:
    435       UNREACHABLE();
    436   }
    437   return *this;
    438 }
    439 
    440 BytecodeArrayBuilder& BytecodeArrayBuilder::UnaryOperation(Token::Value op,
    441                                                            int feedback_slot) {
    442   switch (op) {
    443     case Token::Value::INC:
    444       OutputInc(feedback_slot);
    445       break;
    446     case Token::Value::DEC:
    447       OutputDec(feedback_slot);
    448       break;
    449     case Token::Value::ADD:
    450       OutputToNumber(feedback_slot);
    451       break;
    452     case Token::Value::SUB:
    453       OutputNegate(feedback_slot);
    454       break;
    455     case Token::Value::BIT_NOT:
    456       OutputBitwiseNot(feedback_slot);
    457       break;
    458     default:
    459       UNREACHABLE();
    460   }
    461   return *this;
    462 }
    463 
    464 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot(ToBooleanMode mode) {
    465   if (mode == ToBooleanMode::kAlreadyBoolean) {
    466     OutputLogicalNot();
    467   } else {
    468     DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
    469     OutputToBooleanLogicalNot();
    470   }
    471   return *this;
    472 }
    473 
    474 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
    475   OutputTypeOf();
    476   return *this;
    477 }
    478 
    479 BytecodeArrayBuilder& BytecodeArrayBuilder::GetSuperConstructor(Register out) {
    480   OutputGetSuperConstructor(out);
    481   return *this;
    482 }
    483 
    484 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
    485     Token::Value op, Register reg, int feedback_slot) {
    486   switch (op) {
    487     case Token::Value::EQ:
    488       OutputTestEqual(reg, feedback_slot);
    489       break;
    490     case Token::Value::EQ_STRICT:
    491       OutputTestEqualStrict(reg, feedback_slot);
    492       break;
    493     case Token::Value::LT:
    494       OutputTestLessThan(reg, feedback_slot);
    495       break;
    496     case Token::Value::GT:
    497       OutputTestGreaterThan(reg, feedback_slot);
    498       break;
    499     case Token::Value::LTE:
    500       OutputTestLessThanOrEqual(reg, feedback_slot);
    501       break;
    502     case Token::Value::GTE:
    503       OutputTestGreaterThanOrEqual(reg, feedback_slot);
    504       break;
    505     case Token::Value::INSTANCEOF:
    506       OutputTestInstanceOf(reg, feedback_slot);
    507       break;
    508     default:
    509       UNREACHABLE();
    510   }
    511   return *this;
    512 }
    513 
    514 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op,
    515                                                              Register reg) {
    516   switch (op) {
    517     case Token::Value::IN:
    518       OutputTestIn(reg);
    519       break;
    520     default:
    521       UNREACHABLE();
    522   }
    523   return *this;
    524 }
    525 
    526 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareReference(Register reg) {
    527   OutputTestReferenceEqual(reg);
    528   return *this;
    529 }
    530 
    531 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndetectable() {
    532   OutputTestUndetectable();
    533   return *this;
    534 }
    535 
    536 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndefined() {
    537   OutputTestUndefined();
    538   return *this;
    539 }
    540 
    541 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNull() {
    542   OutputTestNull();
    543   return *this;
    544 }
    545 
    546 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNil(Token::Value op,
    547                                                        NilValue nil) {
    548   if (op == Token::EQ) {
    549     return CompareUndetectable();
    550   } else {
    551     DCHECK_EQ(Token::EQ_STRICT, op);
    552     if (nil == kUndefinedValue) {
    553       return CompareUndefined();
    554     } else {
    555       DCHECK_EQ(kNullValue, nil);
    556       return CompareNull();
    557     }
    558   }
    559 }
    560 
    561 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareTypeOf(
    562     TestTypeOfFlags::LiteralFlag literal_flag) {
    563   DCHECK_NE(literal_flag, TestTypeOfFlags::LiteralFlag::kOther);
    564   OutputTestTypeOf(TestTypeOfFlags::Encode(literal_flag));
    565   return *this;
    566 }
    567 
    568 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry(
    569     size_t entry) {
    570   OutputLdaConstant(entry);
    571   return *this;
    572 }
    573 
    574 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
    575     v8::internal::Smi* smi) {
    576   int32_t raw_smi = smi->value();
    577   if (raw_smi == 0) {
    578     OutputLdaZero();
    579   } else {
    580     OutputLdaSmi(raw_smi);
    581   }
    582   return *this;
    583 }
    584 
    585 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(double value) {
    586   size_t entry = GetConstantPoolEntry(value);
    587   OutputLdaConstant(entry);
    588   return *this;
    589 }
    590 
    591 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
    592     const AstRawString* raw_string) {
    593   size_t entry = GetConstantPoolEntry(raw_string);
    594   OutputLdaConstant(entry);
    595   return *this;
    596 }
    597 
    598 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(const Scope* scope) {
    599   size_t entry = GetConstantPoolEntry(scope);
    600   OutputLdaConstant(entry);
    601   return *this;
    602 }
    603 
    604 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(AstBigInt bigint) {
    605   size_t entry = GetConstantPoolEntry(bigint);
    606   OutputLdaConstant(entry);
    607   return *this;
    608 }
    609 
    610 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(AstSymbol symbol) {
    611   size_t entry;
    612   switch (symbol) {
    613     case AstSymbol::kHomeObjectSymbol:
    614       entry = HomeObjectSymbolConstantPoolEntry();
    615       break;
    616       // No default case so that we get a warning if AstSymbol changes
    617   }
    618   OutputLdaConstant(entry);
    619   return *this;
    620 }
    621 
    622 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
    623   OutputLdaUndefined();
    624   return *this;
    625 }
    626 
    627 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() {
    628   OutputLdaNull();
    629   return *this;
    630 }
    631 
    632 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() {
    633   OutputLdaTheHole();
    634   return *this;
    635 }
    636 
    637 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() {
    638   OutputLdaTrue();
    639   return *this;
    640 }
    641 
    642 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
    643   OutputLdaFalse();
    644   return *this;
    645 }
    646 
    647 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadBoolean(bool value) {
    648   return value ? LoadTrue() : LoadFalse();
    649 }
    650 
    651 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
    652     Register reg) {
    653   if (register_optimizer_) {
    654     // Defer source info so that if we elide the bytecode transfer, we attach
    655     // the source info to a subsequent bytecode if it exists.
    656     SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kLdar));
    657     register_optimizer_->DoLdar(reg);
    658   } else {
    659     OutputLdar(reg);
    660   }
    661   return *this;
    662 }
    663 
    664 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
    665     Register reg) {
    666   if (register_optimizer_) {
    667     // Defer source info so that if we elide the bytecode transfer, we attach
    668     // the source info to a subsequent bytecode if it exists.
    669     SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kStar));
    670     register_optimizer_->DoStar(reg);
    671   } else {
    672     OutputStar(reg);
    673   }
    674   return *this;
    675 }
    676 
    677 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
    678                                                          Register to) {
    679   DCHECK(from != to);
    680   if (register_optimizer_) {
    681     // Defer source info so that if we elide the bytecode transfer, we attach
    682     // the source info to a subsequent bytecode if it exists.
    683     SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kMov));
    684     register_optimizer_->DoMov(from, to);
    685   } else {
    686     OutputMov(from, to);
    687   }
    688   return *this;
    689 }
    690 
    691 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(const AstRawString* name,
    692                                                        int feedback_slot,
    693                                                        TypeofMode typeof_mode) {
    694   size_t name_index = GetConstantPoolEntry(name);
    695   // Ensure that typeof mode is in sync with the IC slot kind.
    696   DCHECK_EQ(GetTypeofModeFromSlotKind(feedback_vector_spec()->GetKind(
    697                 FeedbackVector::ToSlot(feedback_slot))),
    698             typeof_mode);
    699   if (typeof_mode == INSIDE_TYPEOF) {
    700     OutputLdaGlobalInsideTypeof(name_index, feedback_slot);
    701   } else {
    702     DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
    703     OutputLdaGlobal(name_index, feedback_slot);
    704   }
    705   return *this;
    706 }
    707 
    708 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
    709     const AstRawString* name, int feedback_slot) {
    710   size_t name_index = GetConstantPoolEntry(name);
    711   OutputStaGlobal(name_index, feedback_slot);
    712   return *this;
    713 }
    714 
    715 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(
    716     Register context, int slot_index, int depth,
    717     ContextSlotMutability mutability) {
    718   if (context.is_current_context() && depth == 0) {
    719     if (mutability == kImmutableSlot) {
    720       OutputLdaImmutableCurrentContextSlot(slot_index);
    721     } else {
    722       DCHECK_EQ(kMutableSlot, mutability);
    723       OutputLdaCurrentContextSlot(slot_index);
    724     }
    725   } else if (mutability == kImmutableSlot) {
    726     OutputLdaImmutableContextSlot(context, slot_index, depth);
    727   } else {
    728     DCHECK_EQ(mutability, kMutableSlot);
    729     OutputLdaContextSlot(context, slot_index, depth);
    730   }
    731   return *this;
    732 }
    733 
    734 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
    735                                                              int slot_index,
    736                                                              int depth) {
    737   if (context.is_current_context() && depth == 0) {
    738     OutputStaCurrentContextSlot(slot_index);
    739   } else {
    740     OutputStaContextSlot(context, slot_index, depth);
    741   }
    742   return *this;
    743 }
    744 
    745 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
    746     const AstRawString* name, TypeofMode typeof_mode) {
    747   size_t name_index = GetConstantPoolEntry(name);
    748   if (typeof_mode == INSIDE_TYPEOF) {
    749     OutputLdaLookupSlotInsideTypeof(name_index);
    750   } else {
    751     DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
    752     OutputLdaLookupSlot(name_index);
    753   }
    754   return *this;
    755 }
    756 
    757 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot(
    758     const AstRawString* name, TypeofMode typeof_mode, int slot_index,
    759     int depth) {
    760   size_t name_index = GetConstantPoolEntry(name);
    761   if (typeof_mode == INSIDE_TYPEOF) {
    762     OutputLdaLookupContextSlotInsideTypeof(name_index, slot_index, depth);
    763   } else {
    764     DCHECK(typeof_mode == NOT_INSIDE_TYPEOF);
    765     OutputLdaLookupContextSlot(name_index, slot_index, depth);
    766   }
    767   return *this;
    768 }
    769 
    770 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot(
    771     const AstRawString* name, TypeofMode typeof_mode, int feedback_slot,
    772     int depth) {
    773   size_t name_index = GetConstantPoolEntry(name);
    774   if (typeof_mode == INSIDE_TYPEOF) {
    775     OutputLdaLookupGlobalSlotInsideTypeof(name_index, feedback_slot, depth);
    776   } else {
    777     DCHECK(typeof_mode == NOT_INSIDE_TYPEOF);
    778     OutputLdaLookupGlobalSlot(name_index, feedback_slot, depth);
    779   }
    780   return *this;
    781 }
    782 
    783 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot(
    784     const AstRawString* name, LanguageMode language_mode,
    785     LookupHoistingMode lookup_hoisting_mode) {
    786   size_t name_index = GetConstantPoolEntry(name);
    787   uint8_t flags =
    788       StoreLookupSlotFlags::Encode(language_mode, lookup_hoisting_mode);
    789   OutputStaLookupSlot(name_index, flags);
    790   return *this;
    791 }
    792 
    793 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
    794     Register object, const AstRawString* name, int feedback_slot) {
    795   size_t name_index = GetConstantPoolEntry(name);
    796   OutputLdaNamedProperty(object, name_index, feedback_slot);
    797   return *this;
    798 }
    799 
    800 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
    801     Register object, int feedback_slot) {
    802   OutputLdaKeyedProperty(object, feedback_slot);
    803   return *this;
    804 }
    805 
    806 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadIteratorProperty(
    807     Register object, int feedback_slot) {
    808   size_t name_index = IteratorSymbolConstantPoolEntry();
    809   OutputLdaNamedProperty(object, name_index, feedback_slot);
    810   return *this;
    811 }
    812 
    813 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAsyncIteratorProperty(
    814     Register object, int feedback_slot) {
    815   size_t name_index = AsyncIteratorSymbolConstantPoolEntry();
    816   OutputLdaNamedProperty(object, name_index, feedback_slot);
    817   return *this;
    818 }
    819 
    820 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreDataPropertyInLiteral(
    821     Register object, Register name, DataPropertyInLiteralFlags flags,
    822     int feedback_slot) {
    823   OutputStaDataPropertyInLiteral(object, name, flags, feedback_slot);
    824   return *this;
    825 }
    826 
    827 BytecodeArrayBuilder& BytecodeArrayBuilder::CollectTypeProfile(int position) {
    828   OutputCollectTypeProfile(position);
    829   return *this;
    830 }
    831 
    832 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
    833     Register object, size_t name_index, int feedback_slot,
    834     LanguageMode language_mode) {
    835   // Ensure that language mode is in sync with the IC slot kind.
    836   DCHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(
    837                 FeedbackVector::ToSlot(feedback_slot))),
    838             language_mode);
    839   OutputStaNamedProperty(object, name_index, feedback_slot);
    840   return *this;
    841 }
    842 
    843 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
    844     Register object, const AstRawString* name, int feedback_slot,
    845     LanguageMode language_mode) {
    846   size_t name_index = GetConstantPoolEntry(name);
    847   return StoreNamedProperty(object, name_index, feedback_slot, language_mode);
    848 }
    849 
    850 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedOwnProperty(
    851     Register object, const AstRawString* name, int feedback_slot) {
    852   size_t name_index = GetConstantPoolEntry(name);
    853   // Ensure that the store operation is in sync with the IC slot kind.
    854   DCHECK_EQ(
    855       FeedbackSlotKind::kStoreOwnNamed,
    856       feedback_vector_spec()->GetKind(FeedbackVector::ToSlot(feedback_slot)));
    857   OutputStaNamedOwnProperty(object, name_index, feedback_slot);
    858   return *this;
    859 }
    860 
    861 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty(
    862     Register object, Register key, int feedback_slot,
    863     LanguageMode language_mode) {
    864   // Ensure that language mode is in sync with the IC slot kind.
    865   DCHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(
    866                 FeedbackVector::ToSlot(feedback_slot))),
    867             language_mode);
    868   OutputStaKeyedProperty(object, key, feedback_slot);
    869   return *this;
    870 }
    871 
    872 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreInArrayLiteral(
    873     Register array, Register index, int feedback_slot) {
    874   OutputStaInArrayLiteral(array, index, feedback_slot);
    875   return *this;
    876 }
    877 
    878 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreHomeObjectProperty(
    879     Register object, int feedback_slot, LanguageMode language_mode) {
    880   size_t name_index = HomeObjectSymbolConstantPoolEntry();
    881   return StoreNamedProperty(object, name_index, feedback_slot, language_mode);
    882 }
    883 
    884 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreClassFieldsInitializer(
    885     Register constructor, int feedback_slot) {
    886   size_t name_index = ClassFieldsSymbolConstantPoolEntry();
    887   return StoreNamedProperty(constructor, name_index, feedback_slot,
    888                             LanguageMode::kStrict);
    889 }
    890 
    891 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadClassFieldsInitializer(
    892     Register constructor, int feedback_slot) {
    893   size_t name_index = ClassFieldsSymbolConstantPoolEntry();
    894   OutputLdaNamedProperty(constructor, name_index, feedback_slot);
    895   return *this;
    896 }
    897 
    898 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(
    899     size_t shared_function_info_entry, int slot, int flags) {
    900   OutputCreateClosure(shared_function_info_entry, slot, flags);
    901   return *this;
    902 }
    903 
    904 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateBlockContext(
    905     const Scope* scope) {
    906   size_t entry = GetConstantPoolEntry(scope);
    907   OutputCreateBlockContext(entry);
    908   return *this;
    909 }
    910 
    911 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateCatchContext(
    912     Register exception, const Scope* scope) {
    913   size_t scope_index = GetConstantPoolEntry(scope);
    914   OutputCreateCatchContext(exception, scope_index);
    915   return *this;
    916 }
    917 
    918 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(
    919     const Scope* scope, int slots) {
    920   size_t scope_index = GetConstantPoolEntry(scope);
    921   OutputCreateFunctionContext(scope_index, slots);
    922   return *this;
    923 }
    924 
    925 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEvalContext(
    926     const Scope* scope, int slots) {
    927   size_t scope_index = GetConstantPoolEntry(scope);
    928   OutputCreateEvalContext(scope_index, slots);
    929   return *this;
    930 }
    931 
    932 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext(
    933     Register object, const Scope* scope) {
    934   size_t scope_index = GetConstantPoolEntry(scope);
    935   OutputCreateWithContext(object, scope_index);
    936   return *this;
    937 }
    938 
    939 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
    940     CreateArgumentsType type) {
    941   switch (type) {
    942     case CreateArgumentsType::kMappedArguments:
    943       OutputCreateMappedArguments();
    944       break;
    945     case CreateArgumentsType::kUnmappedArguments:
    946       OutputCreateUnmappedArguments();
    947       break;
    948     case CreateArgumentsType::kRestParameter:
    949       OutputCreateRestParameter();
    950       break;
    951     default:
    952       UNREACHABLE();
    953   }
    954   return *this;
    955 }
    956 
    957 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
    958     const AstRawString* pattern, int literal_index, int flags) {
    959   size_t pattern_entry = GetConstantPoolEntry(pattern);
    960   OutputCreateRegExpLiteral(pattern_entry, literal_index, flags);
    961   return *this;
    962 }
    963 
    964 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyArrayLiteral(
    965     int literal_index) {
    966   OutputCreateEmptyArrayLiteral(literal_index);
    967   return *this;
    968 }
    969 
    970 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
    971     size_t constant_elements_entry, int literal_index, int flags) {
    972   OutputCreateArrayLiteral(constant_elements_entry, literal_index, flags);
    973   return *this;
    974 }
    975 
    976 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
    977     size_t constant_properties_entry, int literal_index, int flags,
    978     Register output) {
    979   OutputCreateObjectLiteral(constant_properties_entry, literal_index, flags,
    980                             output);
    981   return *this;
    982 }
    983 
    984 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyObjectLiteral() {
    985   OutputCreateEmptyObjectLiteral();
    986   return *this;
    987 }
    988 
    989 BytecodeArrayBuilder& BytecodeArrayBuilder::CloneObject(Register source,
    990                                                         int flags,
    991                                                         int feedback_slot) {
    992   OutputCloneObject(source, flags, feedback_slot);
    993   return *this;
    994 }
    995 
    996 BytecodeArrayBuilder& BytecodeArrayBuilder::GetTemplateObject(
    997     size_t template_object_description_entry, int feedback_slot) {
    998   OutputGetTemplateObject(template_object_description_entry, feedback_slot);
    999   return *this;
   1000 }
   1001 
   1002 BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) {
   1003   OutputPushContext(context);
   1004   return *this;
   1005 }
   1006 
   1007 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) {
   1008   OutputPopContext(context);
   1009   return *this;
   1010 }
   1011 
   1012 BytecodeArrayBuilder& BytecodeArrayBuilder::ToObject(Register out) {
   1013   OutputToObject(out);
   1014   return *this;
   1015 }
   1016 
   1017 BytecodeArrayBuilder& BytecodeArrayBuilder::ToName(Register out) {
   1018   OutputToName(out);
   1019   return *this;
   1020 }
   1021 
   1022 BytecodeArrayBuilder& BytecodeArrayBuilder::ToString() {
   1023   OutputToString();
   1024   return *this;
   1025 }
   1026 
   1027 BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumber(int feedback_slot) {
   1028   OutputToNumber(feedback_slot);
   1029   return *this;
   1030 }
   1031 
   1032 BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumeric(int feedback_slot) {
   1033   OutputToNumeric(feedback_slot);
   1034   return *this;
   1035 }
   1036 
   1037 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
   1038   // Flush the register optimizer when binding a label to ensure all
   1039   // expected registers are valid when jumping to this label.
   1040   if (register_optimizer_) register_optimizer_->Flush();
   1041   bytecode_array_writer_.BindLabel(label);
   1042   LeaveBasicBlock();
   1043   return *this;
   1044 }
   1045 
   1046 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target,
   1047                                                  BytecodeLabel* label) {
   1048   bytecode_array_writer_.BindLabel(target, label);
   1049   LeaveBasicBlock();
   1050   return *this;
   1051 }
   1052 
   1053 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeJumpTable* jump_table,
   1054                                                  int case_value) {
   1055   // Flush the register optimizer when binding a jump table entry to ensure
   1056   // all expected registers are valid when jumping to this location.
   1057   if (register_optimizer_) register_optimizer_->Flush();
   1058   bytecode_array_writer_.BindJumpTableEntry(jump_table, case_value);
   1059   LeaveBasicBlock();
   1060   return *this;
   1061 }
   1062 
   1063 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
   1064   DCHECK(!label->is_bound());
   1065   OutputJump(label, 0);
   1066   return *this;
   1067 }
   1068 
   1069 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(ToBooleanMode mode,
   1070                                                        BytecodeLabel* label) {
   1071   DCHECK(!label->is_bound());
   1072   if (mode == ToBooleanMode::kAlreadyBoolean) {
   1073     OutputJumpIfTrue(label, 0);
   1074   } else {
   1075     DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
   1076     OutputJumpIfToBooleanTrue(label, 0);
   1077   }
   1078   return *this;
   1079 }
   1080 
   1081 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(ToBooleanMode mode,
   1082                                                         BytecodeLabel* label) {
   1083   DCHECK(!label->is_bound());
   1084   if (mode == ToBooleanMode::kAlreadyBoolean) {
   1085     OutputJumpIfFalse(label, 0);
   1086   } else {
   1087     DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
   1088     OutputJumpIfToBooleanFalse(label, 0);
   1089   }
   1090   return *this;
   1091 }
   1092 
   1093 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
   1094   DCHECK(!label->is_bound());
   1095   OutputJumpIfNull(label, 0);
   1096   return *this;
   1097 }
   1098 
   1099 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNull(
   1100     BytecodeLabel* label) {
   1101   DCHECK(!label->is_bound());
   1102   OutputJumpIfNotNull(label, 0);
   1103   return *this;
   1104 }
   1105 
   1106 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
   1107     BytecodeLabel* label) {
   1108   DCHECK(!label->is_bound());
   1109   OutputJumpIfUndefined(label, 0);
   1110   return *this;
   1111 }
   1112 
   1113 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotUndefined(
   1114     BytecodeLabel* label) {
   1115   DCHECK(!label->is_bound());
   1116   OutputJumpIfNotUndefined(label, 0);
   1117   return *this;
   1118 }
   1119 
   1120 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNil(BytecodeLabel* label,
   1121                                                       Token::Value op,
   1122                                                       NilValue nil) {
   1123   if (op == Token::EQ) {
   1124     // TODO(rmcilroy): Implement JumpIfUndetectable.
   1125     return CompareUndetectable().JumpIfTrue(ToBooleanMode::kAlreadyBoolean,
   1126                                             label);
   1127   } else {
   1128     DCHECK_EQ(Token::EQ_STRICT, op);
   1129     if (nil == kUndefinedValue) {
   1130       return JumpIfUndefined(label);
   1131     } else {
   1132       DCHECK_EQ(kNullValue, nil);
   1133       return JumpIfNull(label);
   1134     }
   1135   }
   1136 }
   1137 
   1138 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNil(BytecodeLabel* label,
   1139                                                          Token::Value op,
   1140                                                          NilValue nil) {
   1141   if (op == Token::EQ) {
   1142     // TODO(rmcilroy): Implement JumpIfUndetectable.
   1143     return CompareUndetectable().JumpIfFalse(ToBooleanMode::kAlreadyBoolean,
   1144                                              label);
   1145   } else {
   1146     DCHECK_EQ(Token::EQ_STRICT, op);
   1147     if (nil == kUndefinedValue) {
   1148       return JumpIfNotUndefined(label);
   1149     } else {
   1150       DCHECK_EQ(kNullValue, nil);
   1151       return JumpIfNotNull(label);
   1152     }
   1153   }
   1154 }
   1155 
   1156 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfJSReceiver(
   1157     BytecodeLabel* label) {
   1158   DCHECK(!label->is_bound());
   1159   OutputJumpIfJSReceiver(label, 0);
   1160   return *this;
   1161 }
   1162 
   1163 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label,
   1164                                                      int loop_depth) {
   1165   DCHECK(label->is_bound());
   1166   OutputJumpLoop(label, 0, loop_depth);
   1167   return *this;
   1168 }
   1169 
   1170 BytecodeArrayBuilder& BytecodeArrayBuilder::SwitchOnSmiNoFeedback(
   1171     BytecodeJumpTable* jump_table) {
   1172   OutputSwitchOnSmiNoFeedback(jump_table);
   1173   return *this;
   1174 }
   1175 
   1176 BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) {
   1177   if (position != kNoSourcePosition) {
   1178     // We need to attach a non-breakable source position to a stack
   1179     // check, so we simply add it as expression position. There can be
   1180     // a prior statement position from constructs like:
   1181     //
   1182     //    do var x;  while (false);
   1183     //
   1184     // A Nop could be inserted for empty statements, but since no code
   1185     // is associated with these positions, instead we force the stack
   1186     // check's expression position which eliminates the empty
   1187     // statement's position.
   1188     latest_source_info_.ForceExpressionPosition(position);
   1189   }
   1190   OutputStackCheck();
   1191   return *this;
   1192 }
   1193 
   1194 BytecodeArrayBuilder& BytecodeArrayBuilder::SetPendingMessage() {
   1195   OutputSetPendingMessage();
   1196   return *this;
   1197 }
   1198 
   1199 BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
   1200   OutputThrow();
   1201   return *this;
   1202 }
   1203 
   1204 BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() {
   1205   OutputReThrow();
   1206   return *this;
   1207 }
   1208 
   1209 BytecodeArrayBuilder& BytecodeArrayBuilder::Abort(AbortReason reason) {
   1210   DCHECK_LT(reason, AbortReason::kLastErrorMessage);
   1211   DCHECK_GE(reason, AbortReason::kNoReason);
   1212   OutputAbort(static_cast<int>(reason));
   1213   return *this;
   1214 }
   1215 
   1216 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
   1217   OutputReturn();
   1218   return_seen_in_block_ = true;
   1219   return *this;
   1220 }
   1221 
   1222 BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowReferenceErrorIfHole(
   1223     const AstRawString* name) {
   1224   size_t entry = GetConstantPoolEntry(name);
   1225   OutputThrowReferenceErrorIfHole(entry);
   1226   return *this;
   1227 }
   1228 
   1229 BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowSuperNotCalledIfHole() {
   1230   OutputThrowSuperNotCalledIfHole();
   1231   return *this;
   1232 }
   1233 
   1234 BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowSuperAlreadyCalledIfNotHole() {
   1235   OutputThrowSuperAlreadyCalledIfNotHole();
   1236   return *this;
   1237 }
   1238 
   1239 BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() {
   1240   OutputDebugger();
   1241   return *this;
   1242 }
   1243 
   1244 BytecodeArrayBuilder& BytecodeArrayBuilder::IncBlockCounter(
   1245     int coverage_array_slot) {
   1246   OutputIncBlockCounter(coverage_array_slot);
   1247   return *this;
   1248 }
   1249 
   1250 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInEnumerate(Register receiver) {
   1251   OutputForInEnumerate(receiver);
   1252   return *this;
   1253 }
   1254 
   1255 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare(
   1256     RegisterList cache_info_triple, int feedback_slot) {
   1257   DCHECK_EQ(3, cache_info_triple.register_count());
   1258   OutputForInPrepare(cache_info_triple, feedback_slot);
   1259   return *this;
   1260 }
   1261 
   1262 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInContinue(
   1263     Register index, Register cache_length) {
   1264   OutputForInContinue(index, cache_length);
   1265   return *this;
   1266 }
   1267 
   1268 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext(
   1269     Register receiver, Register index, RegisterList cache_type_array_pair,
   1270     int feedback_slot) {
   1271   DCHECK_EQ(2, cache_type_array_pair.register_count());
   1272   OutputForInNext(receiver, index, cache_type_array_pair, feedback_slot);
   1273   return *this;
   1274 }
   1275 
   1276 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
   1277   OutputForInStep(index);
   1278   return *this;
   1279 }
   1280 
   1281 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreModuleVariable(int cell_index,
   1282                                                                 int depth) {
   1283   OutputStaModuleVariable(cell_index, depth);
   1284   return *this;
   1285 }
   1286 
   1287 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadModuleVariable(int cell_index,
   1288                                                                int depth) {
   1289   OutputLdaModuleVariable(cell_index, depth);
   1290   return *this;
   1291 }
   1292 
   1293 BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator(
   1294     Register generator, RegisterList registers, int suspend_id) {
   1295   OutputSuspendGenerator(generator, registers, registers.register_count(),
   1296                          suspend_id);
   1297   return *this;
   1298 }
   1299 
   1300 BytecodeArrayBuilder& BytecodeArrayBuilder::SwitchOnGeneratorState(
   1301     Register generator, BytecodeJumpTable* jump_table) {
   1302   DCHECK_EQ(jump_table->case_value_base(), 0);
   1303   BytecodeNode node(CreateSwitchOnGeneratorStateNode(
   1304       generator, jump_table->constant_pool_index(), jump_table->size()));
   1305   WriteSwitch(&node, jump_table);
   1306   LeaveBasicBlock();
   1307   return *this;
   1308 }
   1309 
   1310 BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator(
   1311     Register generator, RegisterList registers) {
   1312   OutputResumeGenerator(generator, registers, registers.register_count());
   1313   return *this;
   1314 }
   1315 
   1316 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(
   1317     int handler_id, HandlerTable::CatchPrediction catch_prediction) {
   1318   BytecodeLabel handler;
   1319   Bind(&handler);
   1320   handler_table_builder()->SetHandlerTarget(handler_id, handler.offset());
   1321   handler_table_builder()->SetPrediction(handler_id, catch_prediction);
   1322   return *this;
   1323 }
   1324 
   1325 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryBegin(int handler_id,
   1326                                                          Register context) {
   1327   BytecodeLabel try_begin;
   1328   Bind(&try_begin);
   1329   handler_table_builder()->SetTryRegionStart(handler_id, try_begin.offset());
   1330   handler_table_builder()->SetContextRegister(handler_id, context);
   1331   return *this;
   1332 }
   1333 
   1334 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) {
   1335   BytecodeLabel try_end;
   1336   Bind(&try_end);
   1337   handler_table_builder()->SetTryRegionEnd(handler_id, try_end.offset());
   1338   return *this;
   1339 }
   1340 
   1341 BytecodeArrayBuilder& BytecodeArrayBuilder::CallProperty(Register callable,
   1342                                                          RegisterList args,
   1343                                                          int feedback_slot) {
   1344   if (args.register_count() == 1) {
   1345     OutputCallProperty0(callable, args[0], feedback_slot);
   1346   } else if (args.register_count() == 2) {
   1347     OutputCallProperty1(callable, args[0], args[1], feedback_slot);
   1348   } else if (args.register_count() == 3) {
   1349     OutputCallProperty2(callable, args[0], args[1], args[2], feedback_slot);
   1350   } else {
   1351     OutputCallProperty(callable, args, args.register_count(), feedback_slot);
   1352   }
   1353   return *this;
   1354 }
   1355 
   1356 BytecodeArrayBuilder& BytecodeArrayBuilder::CallUndefinedReceiver(
   1357     Register callable, RegisterList args, int feedback_slot) {
   1358   if (args.register_count() == 0) {
   1359     OutputCallUndefinedReceiver0(callable, feedback_slot);
   1360   } else if (args.register_count() == 1) {
   1361     OutputCallUndefinedReceiver1(callable, args[0], feedback_slot);
   1362   } else if (args.register_count() == 2) {
   1363     OutputCallUndefinedReceiver2(callable, args[0], args[1], feedback_slot);
   1364   } else {
   1365     OutputCallUndefinedReceiver(callable, args, args.register_count(),
   1366                                 feedback_slot);
   1367   }
   1368   return *this;
   1369 }
   1370 
   1371 BytecodeArrayBuilder& BytecodeArrayBuilder::CallAnyReceiver(Register callable,
   1372                                                             RegisterList args,
   1373                                                             int feedback_slot) {
   1374   OutputCallAnyReceiver(callable, args, args.register_count(), feedback_slot);
   1375   return *this;
   1376 }
   1377 
   1378 BytecodeArrayBuilder& BytecodeArrayBuilder::CallWithSpread(Register callable,
   1379                                                            RegisterList args,
   1380                                                            int feedback_slot) {
   1381   OutputCallWithSpread(callable, args, args.register_count(), feedback_slot);
   1382   return *this;
   1383 }
   1384 
   1385 BytecodeArrayBuilder& BytecodeArrayBuilder::Construct(Register constructor,
   1386                                                       RegisterList args,
   1387                                                       int feedback_slot_id) {
   1388   OutputConstruct(constructor, args, args.register_count(), feedback_slot_id);
   1389   return *this;
   1390 }
   1391 
   1392 BytecodeArrayBuilder& BytecodeArrayBuilder::ConstructWithSpread(
   1393     Register constructor, RegisterList args, int feedback_slot_id) {
   1394   OutputConstructWithSpread(constructor, args, args.register_count(),
   1395                             feedback_slot_id);
   1396   return *this;
   1397 }
   1398 
   1399 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
   1400     Runtime::FunctionId function_id, RegisterList args) {
   1401   DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size);
   1402   DCHECK_LE(Bytecodes::SizeForUnsignedOperand(function_id),
   1403             OperandSize::kShort);
   1404   if (IntrinsicsHelper::IsSupported(function_id)) {
   1405     IntrinsicsHelper::IntrinsicId intrinsic_id =
   1406         IntrinsicsHelper::FromRuntimeId(function_id);
   1407     OutputInvokeIntrinsic(static_cast<int>(intrinsic_id), args,
   1408                           args.register_count());
   1409   } else {
   1410     OutputCallRuntime(static_cast<int>(function_id), args,
   1411                       args.register_count());
   1412   }
   1413   return *this;
   1414 }
   1415 
   1416 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
   1417     Runtime::FunctionId function_id, Register arg) {
   1418   return CallRuntime(function_id, RegisterList(arg));
   1419 }
   1420 
   1421 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
   1422     Runtime::FunctionId function_id) {
   1423   return CallRuntime(function_id, RegisterList());
   1424 }
   1425 
   1426 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
   1427     Runtime::FunctionId function_id, RegisterList args,
   1428     RegisterList return_pair) {
   1429   DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size);
   1430   DCHECK_LE(Bytecodes::SizeForUnsignedOperand(function_id),
   1431             OperandSize::kShort);
   1432   DCHECK_EQ(2, return_pair.register_count());
   1433   OutputCallRuntimeForPair(static_cast<uint16_t>(function_id), args,
   1434                            args.register_count(), return_pair);
   1435   return *this;
   1436 }
   1437 
   1438 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
   1439     Runtime::FunctionId function_id, Register arg, RegisterList return_pair) {
   1440   return CallRuntimeForPair(function_id, RegisterList(arg), return_pair);
   1441 }
   1442 
   1443 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index,
   1444                                                           RegisterList args) {
   1445   OutputCallJSRuntime(context_index, args, args.register_count());
   1446   return *this;
   1447 }
   1448 
   1449 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object,
   1450                                                    LanguageMode language_mode) {
   1451   if (language_mode == LanguageMode::kSloppy) {
   1452     OutputDeletePropertySloppy(object);
   1453   } else {
   1454     DCHECK_EQ(language_mode, LanguageMode::kStrict);
   1455     OutputDeletePropertyStrict(object);
   1456   }
   1457   return *this;
   1458 }
   1459 
   1460 size_t BytecodeArrayBuilder::GetConstantPoolEntry(
   1461     const AstRawString* raw_string) {
   1462   return constant_array_builder()->Insert(raw_string);
   1463 }
   1464 
   1465 size_t BytecodeArrayBuilder::GetConstantPoolEntry(AstBigInt bigint) {
   1466   return constant_array_builder()->Insert(bigint);
   1467 }
   1468 
   1469 size_t BytecodeArrayBuilder::GetConstantPoolEntry(const Scope* scope) {
   1470   return constant_array_builder()->Insert(scope);
   1471 }
   1472 
   1473 size_t BytecodeArrayBuilder::GetConstantPoolEntry(double number) {
   1474   return constant_array_builder()->Insert(number);
   1475 }
   1476 
   1477 #define ENTRY_GETTER(NAME, ...)                            \
   1478   size_t BytecodeArrayBuilder::NAME##ConstantPoolEntry() { \
   1479     return constant_array_builder()->Insert##NAME();       \
   1480   }
   1481 SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)
   1482 #undef ENTRY_GETTER
   1483 
   1484 BytecodeJumpTable* BytecodeArrayBuilder::AllocateJumpTable(
   1485     int size, int case_value_base) {
   1486   DCHECK_GT(size, 0);
   1487 
   1488   size_t constant_pool_index = constant_array_builder()->InsertJumpTable(size);
   1489 
   1490   return new (zone())
   1491       BytecodeJumpTable(constant_pool_index, size, case_value_base, zone());
   1492 }
   1493 
   1494 size_t BytecodeArrayBuilder::AllocateDeferredConstantPoolEntry() {
   1495   return constant_array_builder()->InsertDeferred();
   1496 }
   1497 
   1498 void BytecodeArrayBuilder::SetDeferredConstantPoolEntry(size_t entry,
   1499                                                         Handle<Object> object) {
   1500   constant_array_builder()->SetDeferredAt(entry, object);
   1501 }
   1502 
   1503 bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const {
   1504   if (!reg.is_valid()) {
   1505     return false;
   1506   }
   1507 
   1508   if (reg.is_current_context() || reg.is_function_closure()) {
   1509     return true;
   1510   } else if (reg.is_parameter()) {
   1511     int parameter_index = reg.ToParameterIndex(parameter_count());
   1512     return parameter_index >= 0 && parameter_index < parameter_count();
   1513   } else if (reg.index() < fixed_register_count()) {
   1514     return true;
   1515   } else {
   1516     return register_allocator()->RegisterIsLive(reg);
   1517   }
   1518 }
   1519 
   1520 bool BytecodeArrayBuilder::RegisterListIsValid(RegisterList reg_list) const {
   1521   if (reg_list.register_count() == 0) {
   1522     return reg_list.first_register() == Register(0);
   1523   } else {
   1524     int first_reg_index = reg_list.first_register().index();
   1525     for (int i = 0; i < reg_list.register_count(); i++) {
   1526       if (!RegisterIsValid(Register(first_reg_index + i))) {
   1527         return false;
   1528       }
   1529     }
   1530     return true;
   1531   }
   1532 }
   1533 
   1534 template <Bytecode bytecode, AccumulatorUse accumulator_use>
   1535 void BytecodeArrayBuilder::PrepareToOutputBytecode() {
   1536   if (register_optimizer_)
   1537     register_optimizer_->PrepareForBytecode<bytecode, accumulator_use>();
   1538 }
   1539 
   1540 uint32_t BytecodeArrayBuilder::GetInputRegisterOperand(Register reg) {
   1541   DCHECK(RegisterIsValid(reg));
   1542   if (register_optimizer_) reg = register_optimizer_->GetInputRegister(reg);
   1543   return static_cast<uint32_t>(reg.ToOperand());
   1544 }
   1545 
   1546 uint32_t BytecodeArrayBuilder::GetOutputRegisterOperand(Register reg) {
   1547   DCHECK(RegisterIsValid(reg));
   1548   if (register_optimizer_) register_optimizer_->PrepareOutputRegister(reg);
   1549   return static_cast<uint32_t>(reg.ToOperand());
   1550 }
   1551 
   1552 uint32_t BytecodeArrayBuilder::GetInputRegisterListOperand(
   1553     RegisterList reg_list) {
   1554   DCHECK(RegisterListIsValid(reg_list));
   1555   if (register_optimizer_)
   1556     reg_list = register_optimizer_->GetInputRegisterList(reg_list);
   1557   return static_cast<uint32_t>(reg_list.first_register().ToOperand());
   1558 }
   1559 
   1560 uint32_t BytecodeArrayBuilder::GetOutputRegisterListOperand(
   1561     RegisterList reg_list) {
   1562   DCHECK(RegisterListIsValid(reg_list));
   1563   if (register_optimizer_)
   1564     register_optimizer_->PrepareOutputRegisterList(reg_list);
   1565   return static_cast<uint32_t>(reg_list.first_register().ToOperand());
   1566 }
   1567 
   1568 std::ostream& operator<<(std::ostream& os,
   1569                          const BytecodeArrayBuilder::ToBooleanMode& mode) {
   1570   switch (mode) {
   1571     case BytecodeArrayBuilder::ToBooleanMode::kAlreadyBoolean:
   1572       return os << "AlreadyBoolean";
   1573     case BytecodeArrayBuilder::ToBooleanMode::kConvertToBoolean:
   1574       return os << "ConvertToBoolean";
   1575   }
   1576   UNREACHABLE();
   1577 }
   1578 
   1579 }  // namespace interpreter
   1580 }  // namespace internal
   1581 }  // namespace v8
   1582