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