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 namespace v8 {
      8 namespace internal {
      9 namespace interpreter {
     10 
     11 class BytecodeArrayBuilder::PreviousBytecodeHelper {
     12  public:
     13   explicit PreviousBytecodeHelper(const BytecodeArrayBuilder& array_builder)
     14       : array_builder_(array_builder),
     15         previous_bytecode_start_(array_builder_.last_bytecode_start_) {
     16     // This helper is expected to be instantiated only when the last bytecode is
     17     // in the same basic block.
     18     DCHECK(array_builder_.LastBytecodeInSameBlock());
     19   }
     20 
     21   // Returns the previous bytecode in the same basic block.
     22   MUST_USE_RESULT Bytecode GetBytecode() const {
     23     DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_);
     24     return Bytecodes::FromByte(
     25         array_builder_.bytecodes()->at(previous_bytecode_start_));
     26   }
     27 
     28   // Returns the operand at operand_index for the previous bytecode in the
     29   // same basic block.
     30   MUST_USE_RESULT uint32_t GetOperand(int operand_index) const {
     31     DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_);
     32     Bytecode bytecode = GetBytecode();
     33     DCHECK_GE(operand_index, 0);
     34     DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode));
     35     size_t operand_offset =
     36         previous_bytecode_start_ +
     37         Bytecodes::GetOperandOffset(bytecode, operand_index);
     38     OperandSize size = Bytecodes::GetOperandSize(bytecode, operand_index);
     39     switch (size) {
     40       default:
     41       case OperandSize::kNone:
     42         UNREACHABLE();
     43       case OperandSize::kByte:
     44         return static_cast<uint32_t>(
     45             array_builder_.bytecodes()->at(operand_offset));
     46       case OperandSize::kShort:
     47         uint16_t operand =
     48             (array_builder_.bytecodes()->at(operand_offset) << 8) +
     49             array_builder_.bytecodes()->at(operand_offset + 1);
     50         return static_cast<uint32_t>(operand);
     51     }
     52   }
     53 
     54   Handle<Object> GetConstantForIndexOperand(int operand_index) const {
     55     return array_builder_.constant_array_builder()->At(
     56         GetOperand(operand_index));
     57   }
     58 
     59  private:
     60   const BytecodeArrayBuilder& array_builder_;
     61   size_t previous_bytecode_start_;
     62 
     63   DISALLOW_COPY_AND_ASSIGN(PreviousBytecodeHelper);
     64 };
     65 
     66 
     67 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone)
     68     : isolate_(isolate),
     69       zone_(zone),
     70       bytecodes_(zone),
     71       bytecode_generated_(false),
     72       constant_array_builder_(isolate, zone),
     73       last_block_end_(0),
     74       last_bytecode_start_(~0),
     75       exit_seen_in_block_(false),
     76       unbound_jumps_(0),
     77       parameter_count_(-1),
     78       local_register_count_(-1),
     79       context_register_count_(-1),
     80       temporary_register_count_(0),
     81       free_temporaries_(zone) {}
     82 
     83 
     84 BytecodeArrayBuilder::~BytecodeArrayBuilder() { DCHECK_EQ(0, unbound_jumps_); }
     85 
     86 
     87 void BytecodeArrayBuilder::set_locals_count(int number_of_locals) {
     88   local_register_count_ = number_of_locals;
     89   DCHECK_LE(context_register_count_, 0);
     90 }
     91 
     92 
     93 void BytecodeArrayBuilder::set_parameter_count(int number_of_parameters) {
     94   parameter_count_ = number_of_parameters;
     95 }
     96 
     97 
     98 void BytecodeArrayBuilder::set_context_count(int number_of_contexts) {
     99   context_register_count_ = number_of_contexts;
    100   DCHECK_GE(local_register_count_, 0);
    101 }
    102 
    103 
    104 Register BytecodeArrayBuilder::first_context_register() const {
    105   DCHECK_GT(context_register_count_, 0);
    106   return Register(local_register_count_);
    107 }
    108 
    109 
    110 Register BytecodeArrayBuilder::last_context_register() const {
    111   DCHECK_GT(context_register_count_, 0);
    112   return Register(local_register_count_ + context_register_count_ - 1);
    113 }
    114 
    115 
    116 Register BytecodeArrayBuilder::first_temporary_register() const {
    117   DCHECK_GT(temporary_register_count_, 0);
    118   return Register(fixed_register_count());
    119 }
    120 
    121 
    122 Register BytecodeArrayBuilder::last_temporary_register() const {
    123   DCHECK_GT(temporary_register_count_, 0);
    124   return Register(fixed_register_count() + temporary_register_count_ - 1);
    125 }
    126 
    127 
    128 Register BytecodeArrayBuilder::Parameter(int parameter_index) const {
    129   DCHECK_GE(parameter_index, 0);
    130   return Register::FromParameterIndex(parameter_index, parameter_count());
    131 }
    132 
    133 
    134 bool BytecodeArrayBuilder::RegisterIsParameterOrLocal(Register reg) const {
    135   return reg.is_parameter() || reg.index() < locals_count();
    136 }
    137 
    138 
    139 bool BytecodeArrayBuilder::RegisterIsTemporary(Register reg) const {
    140   return temporary_register_count_ > 0 && first_temporary_register() <= reg &&
    141          reg <= last_temporary_register();
    142 }
    143 
    144 
    145 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() {
    146   DCHECK_EQ(bytecode_generated_, false);
    147   EnsureReturn();
    148 
    149   int bytecode_size = static_cast<int>(bytecodes_.size());
    150   int register_count = fixed_register_count() + temporary_register_count_;
    151   int frame_size = register_count * kPointerSize;
    152   Factory* factory = isolate_->factory();
    153   Handle<FixedArray> constant_pool =
    154       constant_array_builder()->ToFixedArray(factory);
    155   Handle<BytecodeArray> output =
    156       factory->NewBytecodeArray(bytecode_size, &bytecodes_.front(), frame_size,
    157                                 parameter_count(), constant_pool);
    158   bytecode_generated_ = true;
    159   return output;
    160 }
    161 
    162 
    163 template <size_t N>
    164 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) {
    165   // Don't output dead code.
    166   if (exit_seen_in_block_) return;
    167 
    168   DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), static_cast<int>(N));
    169   last_bytecode_start_ = bytecodes()->size();
    170   bytecodes()->push_back(Bytecodes::ToByte(bytecode));
    171   for (int i = 0; i < static_cast<int>(N); i++) {
    172     DCHECK(OperandIsValid(bytecode, i, operands[i]));
    173     switch (Bytecodes::GetOperandSize(bytecode, i)) {
    174       case OperandSize::kNone:
    175         UNREACHABLE();
    176       case OperandSize::kByte:
    177         bytecodes()->push_back(static_cast<uint8_t>(operands[i]));
    178         break;
    179       case OperandSize::kShort: {
    180         uint8_t operand_bytes[2];
    181         WriteUnalignedUInt16(operand_bytes, operands[i]);
    182         bytecodes()->insert(bytecodes()->end(), operand_bytes,
    183                             operand_bytes + 2);
    184         break;
    185       }
    186     }
    187   }
    188 }
    189 
    190 
    191 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
    192                                   uint32_t operand1, uint32_t operand2,
    193                                   uint32_t operand3) {
    194   uint32_t operands[] = {operand0, operand1, operand2, operand3};
    195   Output(bytecode, operands);
    196 }
    197 
    198 
    199 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
    200                                   uint32_t operand1, uint32_t operand2) {
    201   uint32_t operands[] = {operand0, operand1, operand2};
    202   Output(bytecode, operands);
    203 }
    204 
    205 
    206 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
    207                                   uint32_t operand1) {
    208   uint32_t operands[] = {operand0, operand1};
    209   Output(bytecode, operands);
    210 }
    211 
    212 
    213 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) {
    214   uint32_t operands[] = {operand0};
    215   Output(bytecode, operands);
    216 }
    217 
    218 
    219 void BytecodeArrayBuilder::Output(Bytecode bytecode) {
    220   // Don't output dead code.
    221   if (exit_seen_in_block_) return;
    222 
    223   DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0);
    224   last_bytecode_start_ = bytecodes()->size();
    225   bytecodes()->push_back(Bytecodes::ToByte(bytecode));
    226 }
    227 
    228 
    229 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
    230                                                             Register reg,
    231                                                             Strength strength) {
    232   if (is_strong(strength)) {
    233     UNIMPLEMENTED();
    234   }
    235 
    236   Output(BytecodeForBinaryOperation(op), reg.ToOperand());
    237   return *this;
    238 }
    239 
    240 
    241 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op,
    242                                                            Strength strength) {
    243   if (is_strong(strength)) {
    244     UNIMPLEMENTED();
    245   }
    246 
    247   Output(BytecodeForCountOperation(op));
    248   return *this;
    249 }
    250 
    251 
    252 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() {
    253   Output(Bytecode::kLogicalNot);
    254   return *this;
    255 }
    256 
    257 
    258 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
    259   Output(Bytecode::kTypeOf);
    260   return *this;
    261 }
    262 
    263 
    264 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
    265     Token::Value op, Register reg, Strength strength) {
    266   if (is_strong(strength)) {
    267     UNIMPLEMENTED();
    268   }
    269 
    270   Output(BytecodeForCompareOperation(op), reg.ToOperand());
    271   return *this;
    272 }
    273 
    274 
    275 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
    276     v8::internal::Smi* smi) {
    277   int32_t raw_smi = smi->value();
    278   if (raw_smi == 0) {
    279     Output(Bytecode::kLdaZero);
    280   } else if (raw_smi >= -128 && raw_smi <= 127) {
    281     Output(Bytecode::kLdaSmi8, static_cast<uint8_t>(raw_smi));
    282   } else {
    283     LoadLiteral(Handle<Object>(smi, isolate_));
    284   }
    285   return *this;
    286 }
    287 
    288 
    289 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) {
    290   size_t entry = GetConstantPoolEntry(object);
    291   if (FitsInIdx8Operand(entry)) {
    292     Output(Bytecode::kLdaConstant, static_cast<uint8_t>(entry));
    293   } else if (FitsInIdx16Operand(entry)) {
    294     Output(Bytecode::kLdaConstantWide, static_cast<uint16_t>(entry));
    295   } else {
    296     UNIMPLEMENTED();
    297   }
    298   return *this;
    299 }
    300 
    301 
    302 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
    303   Output(Bytecode::kLdaUndefined);
    304   return *this;
    305 }
    306 
    307 
    308 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() {
    309   Output(Bytecode::kLdaNull);
    310   return *this;
    311 }
    312 
    313 
    314 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() {
    315   Output(Bytecode::kLdaTheHole);
    316   return *this;
    317 }
    318 
    319 
    320 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() {
    321   Output(Bytecode::kLdaTrue);
    322   return *this;
    323 }
    324 
    325 
    326 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
    327   Output(Bytecode::kLdaFalse);
    328   return *this;
    329 }
    330 
    331 
    332 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadBooleanConstant(bool value) {
    333   if (value) {
    334     LoadTrue();
    335   } else {
    336     LoadFalse();
    337   }
    338   return *this;
    339 }
    340 
    341 
    342 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
    343     Register reg) {
    344   if (!IsRegisterInAccumulator(reg)) {
    345     Output(Bytecode::kLdar, reg.ToOperand());
    346   }
    347   return *this;
    348 }
    349 
    350 
    351 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
    352     Register reg) {
    353   // TODO(oth): Avoid storing the accumulator in the register if the
    354   // previous bytecode loaded the accumulator with the same register.
    355   //
    356   // TODO(oth): If the previous bytecode is a MOV into this register,
    357   // the previous instruction can be removed. The logic for determining
    358   // these redundant MOVs appears complex.
    359   Output(Bytecode::kStar, reg.ToOperand());
    360   if (!IsRegisterInAccumulator(reg)) {
    361     Output(Bytecode::kStar, reg.ToOperand());
    362   }
    363   return *this;
    364 }
    365 
    366 
    367 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
    368                                                          Register to) {
    369   DCHECK(from != to);
    370   Output(Bytecode::kMov, from.ToOperand(), to.ToOperand());
    371   return *this;
    372 }
    373 
    374 
    375 BytecodeArrayBuilder& BytecodeArrayBuilder::ExchangeRegisters(Register reg0,
    376                                                               Register reg1) {
    377   DCHECK(reg0 != reg1);
    378   if (FitsInReg8Operand(reg0)) {
    379     Output(Bytecode::kExchange, reg0.ToOperand(), reg1.ToWideOperand());
    380   } else if (FitsInReg8Operand(reg1)) {
    381     Output(Bytecode::kExchange, reg1.ToOperand(), reg0.ToWideOperand());
    382   } else {
    383     Output(Bytecode::kExchangeWide, reg0.ToWideOperand(), reg1.ToWideOperand());
    384   }
    385   return *this;
    386 }
    387 
    388 
    389 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(
    390     const Handle<String> name, int feedback_slot, LanguageMode language_mode,
    391     TypeofMode typeof_mode) {
    392   // TODO(rmcilroy): Potentially store language and typeof information in an
    393   // operand rather than having extra bytecodes.
    394   Bytecode bytecode = BytecodeForLoadGlobal(language_mode, typeof_mode);
    395   size_t name_index = GetConstantPoolEntry(name);
    396   if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) {
    397     Output(bytecode, static_cast<uint8_t>(name_index),
    398            static_cast<uint8_t>(feedback_slot));
    399   } else if (FitsInIdx16Operand(name_index) &&
    400              FitsInIdx16Operand(feedback_slot)) {
    401     Output(BytecodeForWideOperands(bytecode), static_cast<uint16_t>(name_index),
    402            static_cast<uint16_t>(feedback_slot));
    403   } else {
    404     UNIMPLEMENTED();
    405   }
    406   return *this;
    407 }
    408 
    409 
    410 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
    411     const Handle<String> name, int feedback_slot, LanguageMode language_mode) {
    412   Bytecode bytecode = BytecodeForStoreGlobal(language_mode);
    413   size_t name_index = GetConstantPoolEntry(name);
    414   if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) {
    415     Output(bytecode, static_cast<uint8_t>(name_index),
    416            static_cast<uint8_t>(feedback_slot));
    417   } else if (FitsInIdx16Operand(name_index) &&
    418              FitsInIdx16Operand(feedback_slot)) {
    419     Output(BytecodeForWideOperands(bytecode), static_cast<uint16_t>(name_index),
    420            static_cast<uint16_t>(feedback_slot));
    421   } else {
    422     UNIMPLEMENTED();
    423   }
    424   return *this;
    425 }
    426 
    427 
    428 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context,
    429                                                             int slot_index) {
    430   DCHECK(slot_index >= 0);
    431   if (FitsInIdx8Operand(slot_index)) {
    432     Output(Bytecode::kLdaContextSlot, context.ToOperand(),
    433            static_cast<uint8_t>(slot_index));
    434   } else if (FitsInIdx16Operand(slot_index)) {
    435     Output(Bytecode::kLdaContextSlotWide, context.ToOperand(),
    436            static_cast<uint16_t>(slot_index));
    437   } else {
    438     UNIMPLEMENTED();
    439   }
    440   return *this;
    441 }
    442 
    443 
    444 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
    445                                                              int slot_index) {
    446   DCHECK(slot_index >= 0);
    447   if (FitsInIdx8Operand(slot_index)) {
    448     Output(Bytecode::kStaContextSlot, context.ToOperand(),
    449            static_cast<uint8_t>(slot_index));
    450   } else if (FitsInIdx16Operand(slot_index)) {
    451     Output(Bytecode::kStaContextSlotWide, context.ToOperand(),
    452            static_cast<uint16_t>(slot_index));
    453   } else {
    454     UNIMPLEMENTED();
    455   }
    456   return *this;
    457 }
    458 
    459 
    460 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
    461     const Handle<String> name, TypeofMode typeof_mode) {
    462   Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF)
    463                           ? Bytecode::kLdaLookupSlotInsideTypeof
    464                           : Bytecode::kLdaLookupSlot;
    465   size_t name_index = GetConstantPoolEntry(name);
    466   if (FitsInIdx8Operand(name_index)) {
    467     Output(bytecode, static_cast<uint8_t>(name_index));
    468   } else if (FitsInIdx16Operand(name_index)) {
    469     Output(BytecodeForWideOperands(bytecode),
    470            static_cast<uint16_t>(name_index));
    471   } else {
    472     UNIMPLEMENTED();
    473   }
    474   return *this;
    475 }
    476 
    477 
    478 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot(
    479     const Handle<String> name, LanguageMode language_mode) {
    480   Bytecode bytecode = BytecodeForStoreLookupSlot(language_mode);
    481   size_t name_index = GetConstantPoolEntry(name);
    482   if (FitsInIdx8Operand(name_index)) {
    483     Output(bytecode, static_cast<uint8_t>(name_index));
    484   } else if (FitsInIdx16Operand(name_index)) {
    485     Output(BytecodeForWideOperands(bytecode),
    486            static_cast<uint16_t>(name_index));
    487   } else {
    488     UNIMPLEMENTED();
    489   }
    490   return *this;
    491 }
    492 
    493 
    494 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
    495     Register object, const Handle<String> name, int feedback_slot,
    496     LanguageMode language_mode) {
    497   Bytecode bytecode = BytecodeForLoadIC(language_mode);
    498   size_t name_index = GetConstantPoolEntry(name);
    499   if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) {
    500     Output(bytecode, object.ToOperand(), static_cast<uint8_t>(name_index),
    501            static_cast<uint8_t>(feedback_slot));
    502   } else if (FitsInIdx16Operand(name_index) &&
    503              FitsInIdx16Operand(feedback_slot)) {
    504     Output(BytecodeForWideOperands(bytecode), object.ToOperand(),
    505            static_cast<uint16_t>(name_index),
    506            static_cast<uint16_t>(feedback_slot));
    507   } else {
    508     UNIMPLEMENTED();
    509   }
    510   return *this;
    511 }
    512 
    513 
    514 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
    515     Register object, int feedback_slot, LanguageMode language_mode) {
    516   Bytecode bytecode = BytecodeForKeyedLoadIC(language_mode);
    517   if (FitsInIdx8Operand(feedback_slot)) {
    518     Output(bytecode, object.ToOperand(), static_cast<uint8_t>(feedback_slot));
    519   } else if (FitsInIdx16Operand(feedback_slot)) {
    520     Output(BytecodeForWideOperands(bytecode), object.ToOperand(),
    521            static_cast<uint16_t>(feedback_slot));
    522   } else {
    523     UNIMPLEMENTED();
    524   }
    525   return *this;
    526 }
    527 
    528 
    529 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
    530     Register object, const Handle<String> name, int feedback_slot,
    531     LanguageMode language_mode) {
    532   Bytecode bytecode = BytecodeForStoreIC(language_mode);
    533   size_t name_index = GetConstantPoolEntry(name);
    534   if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) {
    535     Output(bytecode, object.ToOperand(), static_cast<uint8_t>(name_index),
    536            static_cast<uint8_t>(feedback_slot));
    537   } else if (FitsInIdx16Operand(name_index) &&
    538              FitsInIdx16Operand(feedback_slot)) {
    539     Output(BytecodeForWideOperands(bytecode), object.ToOperand(),
    540            static_cast<uint16_t>(name_index),
    541            static_cast<uint16_t>(feedback_slot));
    542   } else {
    543     UNIMPLEMENTED();
    544   }
    545   return *this;
    546 }
    547 
    548 
    549 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty(
    550     Register object, Register key, int feedback_slot,
    551     LanguageMode language_mode) {
    552   Bytecode bytecode = BytecodeForKeyedStoreIC(language_mode);
    553   if (FitsInIdx8Operand(feedback_slot)) {
    554     Output(bytecode, object.ToOperand(), key.ToOperand(),
    555            static_cast<uint8_t>(feedback_slot));
    556   } else if (FitsInIdx16Operand(feedback_slot)) {
    557     Output(BytecodeForWideOperands(bytecode), object.ToOperand(),
    558            key.ToOperand(), static_cast<uint16_t>(feedback_slot));
    559   } else {
    560     UNIMPLEMENTED();
    561   }
    562   return *this;
    563 }
    564 
    565 
    566 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(
    567     Handle<SharedFunctionInfo> shared_info, PretenureFlag tenured) {
    568   size_t entry = GetConstantPoolEntry(shared_info);
    569   DCHECK(FitsInImm8Operand(tenured));
    570   if (FitsInIdx8Operand(entry)) {
    571     Output(Bytecode::kCreateClosure, static_cast<uint8_t>(entry),
    572            static_cast<uint8_t>(tenured));
    573   } else if (FitsInIdx16Operand(entry)) {
    574     Output(Bytecode::kCreateClosureWide, static_cast<uint16_t>(entry),
    575            static_cast<uint8_t>(tenured));
    576   } else {
    577     UNIMPLEMENTED();
    578   }
    579   return *this;
    580 }
    581 
    582 
    583 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
    584     CreateArgumentsType type) {
    585   // TODO(rmcilroy): Consider passing the type as a bytecode operand rather
    586   // than having two different bytecodes once we have better support for
    587   // branches in the InterpreterAssembler.
    588   Bytecode bytecode = BytecodeForCreateArguments(type);
    589   Output(bytecode);
    590   return *this;
    591 }
    592 
    593 
    594 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
    595     Handle<String> pattern, int literal_index, int flags) {
    596   DCHECK(FitsInImm8Operand(flags));  // Flags should fit in 8 bits.
    597   size_t pattern_entry = GetConstantPoolEntry(pattern);
    598   if (FitsInIdx8Operand(literal_index) && FitsInIdx8Operand(pattern_entry)) {
    599     Output(Bytecode::kCreateRegExpLiteral, static_cast<uint8_t>(pattern_entry),
    600            static_cast<uint8_t>(literal_index), static_cast<uint8_t>(flags));
    601   } else if (FitsInIdx16Operand(literal_index) &&
    602              FitsInIdx16Operand(pattern_entry)) {
    603     Output(Bytecode::kCreateRegExpLiteralWide,
    604            static_cast<uint16_t>(pattern_entry),
    605            static_cast<uint16_t>(literal_index), static_cast<uint8_t>(flags));
    606   } else {
    607     UNIMPLEMENTED();
    608   }
    609   return *this;
    610 }
    611 
    612 
    613 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
    614     Handle<FixedArray> constant_elements, int literal_index, int flags) {
    615   DCHECK(FitsInImm8Operand(flags));  // Flags should fit in 8 bits.
    616   size_t constant_elements_entry = GetConstantPoolEntry(constant_elements);
    617   if (FitsInIdx8Operand(literal_index) &&
    618       FitsInIdx8Operand(constant_elements_entry)) {
    619     Output(Bytecode::kCreateArrayLiteral,
    620            static_cast<uint8_t>(constant_elements_entry),
    621            static_cast<uint8_t>(literal_index), static_cast<uint8_t>(flags));
    622   } else if (FitsInIdx16Operand(literal_index) &&
    623              FitsInIdx16Operand(constant_elements_entry)) {
    624     Output(Bytecode::kCreateArrayLiteralWide,
    625            static_cast<uint16_t>(constant_elements_entry),
    626            static_cast<uint16_t>(literal_index), static_cast<uint8_t>(flags));
    627   } else {
    628     UNIMPLEMENTED();
    629   }
    630   return *this;
    631 }
    632 
    633 
    634 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
    635     Handle<FixedArray> constant_properties, int literal_index, int flags) {
    636   DCHECK(FitsInImm8Operand(flags));  // Flags should fit in 8 bits.
    637   size_t constant_properties_entry = GetConstantPoolEntry(constant_properties);
    638   if (FitsInIdx8Operand(literal_index) &&
    639       FitsInIdx8Operand(constant_properties_entry)) {
    640     Output(Bytecode::kCreateObjectLiteral,
    641            static_cast<uint8_t>(constant_properties_entry),
    642            static_cast<uint8_t>(literal_index), static_cast<uint8_t>(flags));
    643   } else if (FitsInIdx16Operand(literal_index) &&
    644              FitsInIdx16Operand(constant_properties_entry)) {
    645     Output(Bytecode::kCreateObjectLiteralWide,
    646            static_cast<uint16_t>(constant_properties_entry),
    647            static_cast<uint16_t>(literal_index), static_cast<uint8_t>(flags));
    648   } else {
    649     UNIMPLEMENTED();
    650   }
    651   return *this;
    652 }
    653 
    654 
    655 BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) {
    656   Output(Bytecode::kPushContext, context.ToOperand());
    657   return *this;
    658 }
    659 
    660 
    661 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) {
    662   Output(Bytecode::kPopContext, context.ToOperand());
    663   return *this;
    664 }
    665 
    666 
    667 bool BytecodeArrayBuilder::NeedToBooleanCast() {
    668   if (!LastBytecodeInSameBlock()) {
    669     return true;
    670   }
    671   PreviousBytecodeHelper previous_bytecode(*this);
    672   switch (previous_bytecode.GetBytecode()) {
    673     // If the previous bytecode puts a boolean in the accumulator return true.
    674     case Bytecode::kLdaTrue:
    675     case Bytecode::kLdaFalse:
    676     case Bytecode::kLogicalNot:
    677     case Bytecode::kTestEqual:
    678     case Bytecode::kTestNotEqual:
    679     case Bytecode::kTestEqualStrict:
    680     case Bytecode::kTestNotEqualStrict:
    681     case Bytecode::kTestLessThan:
    682     case Bytecode::kTestLessThanOrEqual:
    683     case Bytecode::kTestGreaterThan:
    684     case Bytecode::kTestGreaterThanOrEqual:
    685     case Bytecode::kTestInstanceOf:
    686     case Bytecode::kTestIn:
    687     case Bytecode::kForInDone:
    688       return false;
    689     default:
    690       return true;
    691   }
    692 }
    693 
    694 
    695 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToJSObject() {
    696   Output(Bytecode::kToObject);
    697   return *this;
    698 }
    699 
    700 
    701 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName() {
    702   if (LastBytecodeInSameBlock()) {
    703     PreviousBytecodeHelper previous_bytecode(*this);
    704     switch (previous_bytecode.GetBytecode()) {
    705       case Bytecode::kToName:
    706       case Bytecode::kTypeOf:
    707         return *this;
    708       case Bytecode::kLdaConstantWide:
    709       case Bytecode::kLdaConstant: {
    710         Handle<Object> object = previous_bytecode.GetConstantForIndexOperand(0);
    711         if (object->IsName()) return *this;
    712         break;
    713       }
    714       default:
    715         break;
    716     }
    717   }
    718   Output(Bytecode::kToName);
    719   return *this;
    720 }
    721 
    722 
    723 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToNumber() {
    724   // TODO(rmcilroy): consider omitting if the preceeding bytecode always returns
    725   // a number.
    726   Output(Bytecode::kToNumber);
    727   return *this;
    728 }
    729 
    730 
    731 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
    732   if (label->is_forward_target()) {
    733     // An earlier jump instruction refers to this label. Update it's location.
    734     PatchJump(bytecodes()->end(), bytecodes()->begin() + label->offset());
    735     // Now treat as if the label will only be back referred to.
    736   }
    737   label->bind_to(bytecodes()->size());
    738   LeaveBasicBlock();
    739   return *this;
    740 }
    741 
    742 
    743 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target,
    744                                                  BytecodeLabel* label) {
    745   DCHECK(!label->is_bound());
    746   DCHECK(target.is_bound());
    747   PatchJump(bytecodes()->begin() + target.offset(),
    748             bytecodes()->begin() + label->offset());
    749   label->bind_to(target.offset());
    750   LeaveBasicBlock();
    751   return *this;
    752 }
    753 
    754 
    755 // static
    756 Bytecode BytecodeArrayBuilder::GetJumpWithConstantOperand(
    757     Bytecode jump_bytecode) {
    758   switch (jump_bytecode) {
    759     case Bytecode::kJump:
    760       return Bytecode::kJumpConstant;
    761     case Bytecode::kJumpIfTrue:
    762       return Bytecode::kJumpIfTrueConstant;
    763     case Bytecode::kJumpIfFalse:
    764       return Bytecode::kJumpIfFalseConstant;
    765     case Bytecode::kJumpIfToBooleanTrue:
    766       return Bytecode::kJumpIfToBooleanTrueConstant;
    767     case Bytecode::kJumpIfToBooleanFalse:
    768       return Bytecode::kJumpIfToBooleanFalseConstant;
    769     case Bytecode::kJumpIfNull:
    770       return Bytecode::kJumpIfNullConstant;
    771     case Bytecode::kJumpIfUndefined:
    772       return Bytecode::kJumpIfUndefinedConstant;
    773     default:
    774       UNREACHABLE();
    775       return static_cast<Bytecode>(-1);
    776   }
    777 }
    778 
    779 
    780 // static
    781 Bytecode BytecodeArrayBuilder::GetJumpWithConstantWideOperand(
    782     Bytecode jump_bytecode) {
    783   switch (jump_bytecode) {
    784     case Bytecode::kJump:
    785       return Bytecode::kJumpConstantWide;
    786     case Bytecode::kJumpIfTrue:
    787       return Bytecode::kJumpIfTrueConstantWide;
    788     case Bytecode::kJumpIfFalse:
    789       return Bytecode::kJumpIfFalseConstantWide;
    790     case Bytecode::kJumpIfToBooleanTrue:
    791       return Bytecode::kJumpIfToBooleanTrueConstantWide;
    792     case Bytecode::kJumpIfToBooleanFalse:
    793       return Bytecode::kJumpIfToBooleanFalseConstantWide;
    794     case Bytecode::kJumpIfNull:
    795       return Bytecode::kJumpIfNullConstantWide;
    796     case Bytecode::kJumpIfUndefined:
    797       return Bytecode::kJumpIfUndefinedConstantWide;
    798     default:
    799       UNREACHABLE();
    800       return static_cast<Bytecode>(-1);
    801   }
    802 }
    803 
    804 
    805 // static
    806 Bytecode BytecodeArrayBuilder::GetJumpWithToBoolean(Bytecode jump_bytecode) {
    807   switch (jump_bytecode) {
    808     case Bytecode::kJump:
    809     case Bytecode::kJumpIfNull:
    810     case Bytecode::kJumpIfUndefined:
    811       return jump_bytecode;
    812     case Bytecode::kJumpIfTrue:
    813       return Bytecode::kJumpIfToBooleanTrue;
    814     case Bytecode::kJumpIfFalse:
    815       return Bytecode::kJumpIfToBooleanFalse;
    816     default:
    817       UNREACHABLE();
    818   }
    819   return static_cast<Bytecode>(-1);
    820 }
    821 
    822 
    823 void BytecodeArrayBuilder::PatchIndirectJumpWith8BitOperand(
    824     const ZoneVector<uint8_t>::iterator& jump_location, int delta) {
    825   Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location);
    826   DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode));
    827   ZoneVector<uint8_t>::iterator operand_location = jump_location + 1;
    828   DCHECK_EQ(*operand_location, 0);
    829   if (FitsInImm8Operand(delta)) {
    830     // The jump fits within the range of an Imm8 operand, so cancel
    831     // the reservation and jump directly.
    832     constant_array_builder()->DiscardReservedEntry(OperandSize::kByte);
    833     *operand_location = static_cast<uint8_t>(delta);
    834   } else {
    835     // The jump does not fit within the range of an Imm8 operand, so
    836     // commit reservation putting the offset into the constant pool,
    837     // and update the jump instruction and operand.
    838     size_t entry = constant_array_builder()->CommitReservedEntry(
    839         OperandSize::kByte, handle(Smi::FromInt(delta), isolate()));
    840     DCHECK(FitsInIdx8Operand(entry));
    841     jump_bytecode = GetJumpWithConstantOperand(jump_bytecode);
    842     *jump_location = Bytecodes::ToByte(jump_bytecode);
    843     *operand_location = static_cast<uint8_t>(entry);
    844   }
    845 }
    846 
    847 
    848 void BytecodeArrayBuilder::PatchIndirectJumpWith16BitOperand(
    849     const ZoneVector<uint8_t>::iterator& jump_location, int delta) {
    850   DCHECK(Bytecodes::IsJumpConstantWide(Bytecodes::FromByte(*jump_location)));
    851   ZoneVector<uint8_t>::iterator operand_location = jump_location + 1;
    852   size_t entry = constant_array_builder()->CommitReservedEntry(
    853       OperandSize::kShort, handle(Smi::FromInt(delta), isolate()));
    854   DCHECK(FitsInIdx16Operand(entry));
    855   uint8_t operand_bytes[2];
    856   WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(entry));
    857   DCHECK(*operand_location == 0 && *(operand_location + 1) == 0);
    858   *operand_location++ = operand_bytes[0];
    859   *operand_location = operand_bytes[1];
    860 }
    861 
    862 
    863 void BytecodeArrayBuilder::PatchJump(
    864     const ZoneVector<uint8_t>::iterator& jump_target,
    865     const ZoneVector<uint8_t>::iterator& jump_location) {
    866   Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location);
    867   int delta = static_cast<int>(jump_target - jump_location);
    868   DCHECK(Bytecodes::IsJump(jump_bytecode));
    869   switch (Bytecodes::GetOperandSize(jump_bytecode, 0)) {
    870     case OperandSize::kByte:
    871       PatchIndirectJumpWith8BitOperand(jump_location, delta);
    872       break;
    873     case OperandSize::kShort:
    874       PatchIndirectJumpWith16BitOperand(jump_location, delta);
    875       break;
    876     case OperandSize::kNone:
    877       UNREACHABLE();
    878   }
    879   unbound_jumps_--;
    880 }
    881 
    882 
    883 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode,
    884                                                        BytecodeLabel* label) {
    885   // Don't emit dead code.
    886   if (exit_seen_in_block_) return *this;
    887 
    888   // Check if the value in accumulator is boolean, if not choose an
    889   // appropriate JumpIfToBoolean bytecode.
    890   if (NeedToBooleanCast()) {
    891     jump_bytecode = GetJumpWithToBoolean(jump_bytecode);
    892   }
    893 
    894   if (label->is_bound()) {
    895     // Label has been bound already so this is a backwards jump.
    896     CHECK_GE(bytecodes()->size(), label->offset());
    897     CHECK_LE(bytecodes()->size(), static_cast<size_t>(kMaxInt));
    898     size_t abs_delta = bytecodes()->size() - label->offset();
    899     int delta = -static_cast<int>(abs_delta);
    900 
    901     if (FitsInImm8Operand(delta)) {
    902       Output(jump_bytecode, static_cast<uint8_t>(delta));
    903     } else {
    904       size_t entry =
    905           GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate()));
    906       if (FitsInIdx8Operand(entry)) {
    907         Output(GetJumpWithConstantOperand(jump_bytecode),
    908                static_cast<uint8_t>(entry));
    909       } else if (FitsInIdx16Operand(entry)) {
    910         Output(GetJumpWithConstantWideOperand(jump_bytecode),
    911                static_cast<uint16_t>(entry));
    912       } else {
    913         UNREACHABLE();
    914       }
    915     }
    916   } else {
    917     // The label has not yet been bound so this is a forward reference
    918     // that will be patched when the label is bound. We create a
    919     // reservation in the constant pool so the jump can be patched
    920     // when the label is bound. The reservation means the maximum size
    921     // of the operand for the constant is known and the jump can
    922     // be emitted into the bytecode stream with space for the operand.
    923     label->set_referrer(bytecodes()->size());
    924     unbound_jumps_++;
    925     OperandSize reserved_operand_size =
    926         constant_array_builder()->CreateReservedEntry();
    927     switch (reserved_operand_size) {
    928       case OperandSize::kByte:
    929         Output(jump_bytecode, 0);
    930         break;
    931       case OperandSize::kShort:
    932         Output(GetJumpWithConstantWideOperand(jump_bytecode), 0);
    933         break;
    934       case OperandSize::kNone:
    935         UNREACHABLE();
    936     }
    937   }
    938   LeaveBasicBlock();
    939   return *this;
    940 }
    941 
    942 
    943 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
    944   return OutputJump(Bytecode::kJump, label);
    945 }
    946 
    947 
    948 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) {
    949   return OutputJump(Bytecode::kJumpIfTrue, label);
    950 }
    951 
    952 
    953 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) {
    954   return OutputJump(Bytecode::kJumpIfFalse, label);
    955 }
    956 
    957 
    958 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
    959   return OutputJump(Bytecode::kJumpIfNull, label);
    960 }
    961 
    962 
    963 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
    964     BytecodeLabel* label) {
    965   return OutputJump(Bytecode::kJumpIfUndefined, label);
    966 }
    967 
    968 
    969 BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
    970   Output(Bytecode::kThrow);
    971   exit_seen_in_block_ = true;
    972   return *this;
    973 }
    974 
    975 
    976 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
    977   Output(Bytecode::kReturn);
    978   exit_seen_in_block_ = true;
    979   return *this;
    980 }
    981 
    982 
    983 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare(
    984     Register cache_type, Register cache_array, Register cache_length) {
    985   Output(Bytecode::kForInPrepare, cache_type.ToOperand(),
    986          cache_array.ToOperand(), cache_length.ToOperand());
    987   return *this;
    988 }
    989 
    990 
    991 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInDone(Register index,
    992                                                       Register cache_length) {
    993   Output(Bytecode::kForInDone, index.ToOperand(), cache_length.ToOperand());
    994   return *this;
    995 }
    996 
    997 
    998 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext(Register receiver,
    999                                                       Register cache_type,
   1000                                                       Register cache_array,
   1001                                                       Register index) {
   1002   Output(Bytecode::kForInNext, receiver.ToOperand(), cache_type.ToOperand(),
   1003          cache_array.ToOperand(), index.ToOperand());
   1004   return *this;
   1005 }
   1006 
   1007 
   1008 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
   1009   Output(Bytecode::kForInStep, index.ToOperand());
   1010   return *this;
   1011 }
   1012 
   1013 
   1014 void BytecodeArrayBuilder::LeaveBasicBlock() {
   1015   last_block_end_ = bytecodes()->size();
   1016   exit_seen_in_block_ = false;
   1017 }
   1018 
   1019 
   1020 void BytecodeArrayBuilder::EnsureReturn() {
   1021   if (!exit_seen_in_block_) {
   1022     LoadUndefined();
   1023     Return();
   1024   }
   1025 }
   1026 
   1027 
   1028 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
   1029                                                  Register receiver,
   1030                                                  size_t arg_count,
   1031                                                  int feedback_slot) {
   1032   if (FitsInIdx8Operand(arg_count) && FitsInIdx8Operand(feedback_slot)) {
   1033     Output(Bytecode::kCall, callable.ToOperand(), receiver.ToOperand(),
   1034            static_cast<uint8_t>(arg_count),
   1035            static_cast<uint8_t>(feedback_slot));
   1036   } else if (FitsInIdx16Operand(arg_count) &&
   1037              FitsInIdx16Operand(feedback_slot)) {
   1038     Output(Bytecode::kCallWide, callable.ToOperand(), receiver.ToOperand(),
   1039            static_cast<uint16_t>(arg_count),
   1040            static_cast<uint16_t>(feedback_slot));
   1041   } else {
   1042     UNIMPLEMENTED();
   1043   }
   1044   return *this;
   1045 }
   1046 
   1047 
   1048 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor,
   1049                                                 Register first_arg,
   1050                                                 size_t arg_count) {
   1051   if (!first_arg.is_valid()) {
   1052     DCHECK_EQ(0u, arg_count);
   1053     first_arg = Register(0);
   1054   }
   1055   DCHECK(FitsInIdx8Operand(arg_count));
   1056   Output(Bytecode::kNew, constructor.ToOperand(), first_arg.ToOperand(),
   1057          static_cast<uint8_t>(arg_count));
   1058   return *this;
   1059 }
   1060 
   1061 
   1062 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
   1063     Runtime::FunctionId function_id, Register first_arg, size_t arg_count) {
   1064   DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size);
   1065   DCHECK(FitsInIdx16Operand(function_id));
   1066   DCHECK(FitsInIdx8Operand(arg_count));
   1067   if (!first_arg.is_valid()) {
   1068     DCHECK_EQ(0u, arg_count);
   1069     first_arg = Register(0);
   1070   }
   1071   Output(Bytecode::kCallRuntime, static_cast<uint16_t>(function_id),
   1072          first_arg.ToOperand(), static_cast<uint8_t>(arg_count));
   1073   return *this;
   1074 }
   1075 
   1076 
   1077 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
   1078     Runtime::FunctionId function_id, Register first_arg, size_t arg_count,
   1079     Register first_return) {
   1080   DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size);
   1081   DCHECK(FitsInIdx16Operand(function_id));
   1082   DCHECK(FitsInIdx8Operand(arg_count));
   1083   if (!first_arg.is_valid()) {
   1084     DCHECK_EQ(0u, arg_count);
   1085     first_arg = Register(0);
   1086   }
   1087   Output(Bytecode::kCallRuntimeForPair, static_cast<uint16_t>(function_id),
   1088          first_arg.ToOperand(), static_cast<uint8_t>(arg_count),
   1089          first_return.ToOperand());
   1090   return *this;
   1091 }
   1092 
   1093 
   1094 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index,
   1095                                                           Register receiver,
   1096                                                           size_t arg_count) {
   1097   DCHECK(FitsInIdx16Operand(context_index));
   1098   DCHECK(FitsInIdx8Operand(arg_count));
   1099   Output(Bytecode::kCallJSRuntime, static_cast<uint16_t>(context_index),
   1100          receiver.ToOperand(), static_cast<uint8_t>(arg_count));
   1101   return *this;
   1102 }
   1103 
   1104 
   1105 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object,
   1106                                                    LanguageMode language_mode) {
   1107   Output(BytecodeForDelete(language_mode), object.ToOperand());
   1108   return *this;
   1109 }
   1110 
   1111 
   1112 BytecodeArrayBuilder& BytecodeArrayBuilder::DeleteLookupSlot() {
   1113   Output(Bytecode::kDeleteLookupSlot);
   1114   return *this;
   1115 }
   1116 
   1117 
   1118 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) {
   1119   return constant_array_builder()->Insert(object);
   1120 }
   1121 
   1122 
   1123 int BytecodeArrayBuilder::BorrowTemporaryRegister() {
   1124   if (free_temporaries_.empty()) {
   1125     temporary_register_count_ += 1;
   1126     return last_temporary_register().index();
   1127   } else {
   1128     auto pos = free_temporaries_.begin();
   1129     int retval = *pos;
   1130     free_temporaries_.erase(pos);
   1131     return retval;
   1132   }
   1133 }
   1134 
   1135 
   1136 int BytecodeArrayBuilder::BorrowTemporaryRegisterNotInRange(int start_index,
   1137                                                             int end_index) {
   1138   auto index = free_temporaries_.lower_bound(start_index);
   1139   if (index == free_temporaries_.begin()) {
   1140     // If start_index is the first free register, check for a register
   1141     // greater than end_index.
   1142     index = free_temporaries_.upper_bound(end_index);
   1143     if (index == free_temporaries_.end()) {
   1144       temporary_register_count_ += 1;
   1145       return last_temporary_register().index();
   1146     }
   1147   } else {
   1148     // If there is a free register < start_index
   1149     index--;
   1150   }
   1151 
   1152   int retval = *index;
   1153   free_temporaries_.erase(index);
   1154   return retval;
   1155 }
   1156 
   1157 
   1158 void BytecodeArrayBuilder::BorrowConsecutiveTemporaryRegister(int reg_index) {
   1159   DCHECK(free_temporaries_.find(reg_index) != free_temporaries_.end());
   1160   free_temporaries_.erase(reg_index);
   1161 }
   1162 
   1163 
   1164 void BytecodeArrayBuilder::ReturnTemporaryRegister(int reg_index) {
   1165   DCHECK(free_temporaries_.find(reg_index) == free_temporaries_.end());
   1166   free_temporaries_.insert(reg_index);
   1167 }
   1168 
   1169 
   1170 int BytecodeArrayBuilder::PrepareForConsecutiveTemporaryRegisters(
   1171     size_t count) {
   1172   if (count == 0) {
   1173     return -1;
   1174   }
   1175 
   1176   // Search within existing temporaries for a run.
   1177   auto start = free_temporaries_.begin();
   1178   size_t run_length = 0;
   1179   for (auto run_end = start; run_end != free_temporaries_.end(); run_end++) {
   1180     if (*run_end != *start + static_cast<int>(run_length)) {
   1181       start = run_end;
   1182       run_length = 0;
   1183     }
   1184     if (++run_length == count) {
   1185       return *start;
   1186     }
   1187   }
   1188 
   1189   // Continue run if possible across existing last temporary.
   1190   if (temporary_register_count_ > 0 &&
   1191       (start == free_temporaries_.end() ||
   1192        *start + static_cast<int>(run_length) !=
   1193            last_temporary_register().index() + 1)) {
   1194     run_length = 0;
   1195   }
   1196 
   1197   // Ensure enough registers for run.
   1198   while (run_length++ < count) {
   1199     temporary_register_count_++;
   1200     free_temporaries_.insert(last_temporary_register().index());
   1201   }
   1202   return last_temporary_register().index() - static_cast<int>(count) + 1;
   1203 }
   1204 
   1205 
   1206 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const {
   1207   if (temporary_register_count_ > 0) {
   1208     DCHECK(reg.index() >= first_temporary_register().index() &&
   1209            reg.index() <= last_temporary_register().index());
   1210     return free_temporaries_.find(reg.index()) == free_temporaries_.end();
   1211   } else {
   1212     return false;
   1213   }
   1214 }
   1215 
   1216 
   1217 bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const {
   1218   if (reg.is_function_context() || reg.is_function_closure() ||
   1219       reg.is_new_target()) {
   1220     return true;
   1221   } else if (reg.is_parameter()) {
   1222     int parameter_index = reg.ToParameterIndex(parameter_count_);
   1223     return parameter_index >= 0 && parameter_index < parameter_count_;
   1224   } else if (reg.index() < fixed_register_count()) {
   1225     return true;
   1226   } else {
   1227     return TemporaryRegisterIsLive(reg);
   1228   }
   1229 }
   1230 
   1231 
   1232 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index,
   1233                                           uint32_t operand_value) const {
   1234   OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index);
   1235   switch (operand_type) {
   1236     case OperandType::kNone:
   1237       return false;
   1238     case OperandType::kCount16:
   1239     case OperandType::kIdx16:
   1240       return static_cast<uint16_t>(operand_value) == operand_value;
   1241     case OperandType::kCount8:
   1242     case OperandType::kImm8:
   1243     case OperandType::kIdx8:
   1244       return static_cast<uint8_t>(operand_value) == operand_value;
   1245     case OperandType::kMaybeReg8:
   1246       if (operand_value == 0) {
   1247         return true;
   1248       }
   1249     // Fall-through to kReg8 case.
   1250     case OperandType::kReg8:
   1251       return RegisterIsValid(
   1252           Register::FromOperand(static_cast<uint8_t>(operand_value)));
   1253     case OperandType::kRegPair8: {
   1254       Register reg0 =
   1255           Register::FromOperand(static_cast<uint8_t>(operand_value));
   1256       Register reg1 = Register(reg0.index() + 1);
   1257       return RegisterIsValid(reg0) && RegisterIsValid(reg1);
   1258     }
   1259     case OperandType::kReg16:
   1260       if (bytecode != Bytecode::kExchange &&
   1261           bytecode != Bytecode::kExchangeWide) {
   1262         return false;
   1263       }
   1264       return RegisterIsValid(
   1265           Register::FromWideOperand(static_cast<uint16_t>(operand_value)));
   1266   }
   1267   UNREACHABLE();
   1268   return false;
   1269 }
   1270 
   1271 
   1272 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const {
   1273   return last_bytecode_start_ < bytecodes()->size() &&
   1274          last_bytecode_start_ >= last_block_end_;
   1275 }
   1276 
   1277 
   1278 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) {
   1279   if (LastBytecodeInSameBlock()) {
   1280     PreviousBytecodeHelper previous_bytecode(*this);
   1281     Bytecode bytecode = previous_bytecode.GetBytecode();
   1282     if ((bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar) &&
   1283         (reg == Register::FromOperand(previous_bytecode.GetOperand(0)))) {
   1284       return true;
   1285     }
   1286   }
   1287   return false;
   1288 }
   1289 
   1290 
   1291 // static
   1292 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) {
   1293   switch (op) {
   1294     case Token::Value::ADD:
   1295       return Bytecode::kAdd;
   1296     case Token::Value::SUB:
   1297       return Bytecode::kSub;
   1298     case Token::Value::MUL:
   1299       return Bytecode::kMul;
   1300     case Token::Value::DIV:
   1301       return Bytecode::kDiv;
   1302     case Token::Value::MOD:
   1303       return Bytecode::kMod;
   1304     case Token::Value::BIT_OR:
   1305       return Bytecode::kBitwiseOr;
   1306     case Token::Value::BIT_XOR:
   1307       return Bytecode::kBitwiseXor;
   1308     case Token::Value::BIT_AND:
   1309       return Bytecode::kBitwiseAnd;
   1310     case Token::Value::SHL:
   1311       return Bytecode::kShiftLeft;
   1312     case Token::Value::SAR:
   1313       return Bytecode::kShiftRight;
   1314     case Token::Value::SHR:
   1315       return Bytecode::kShiftRightLogical;
   1316     default:
   1317       UNREACHABLE();
   1318       return static_cast<Bytecode>(-1);
   1319   }
   1320 }
   1321 
   1322 
   1323 // static
   1324 Bytecode BytecodeArrayBuilder::BytecodeForCountOperation(Token::Value op) {
   1325   switch (op) {
   1326     case Token::Value::ADD:
   1327       return Bytecode::kInc;
   1328     case Token::Value::SUB:
   1329       return Bytecode::kDec;
   1330     default:
   1331       UNREACHABLE();
   1332       return static_cast<Bytecode>(-1);
   1333   }
   1334 }
   1335 
   1336 
   1337 // static
   1338 Bytecode BytecodeArrayBuilder::BytecodeForCompareOperation(Token::Value op) {
   1339   switch (op) {
   1340     case Token::Value::EQ:
   1341       return Bytecode::kTestEqual;
   1342     case Token::Value::NE:
   1343       return Bytecode::kTestNotEqual;
   1344     case Token::Value::EQ_STRICT:
   1345       return Bytecode::kTestEqualStrict;
   1346     case Token::Value::NE_STRICT:
   1347       return Bytecode::kTestNotEqualStrict;
   1348     case Token::Value::LT:
   1349       return Bytecode::kTestLessThan;
   1350     case Token::Value::GT:
   1351       return Bytecode::kTestGreaterThan;
   1352     case Token::Value::LTE:
   1353       return Bytecode::kTestLessThanOrEqual;
   1354     case Token::Value::GTE:
   1355       return Bytecode::kTestGreaterThanOrEqual;
   1356     case Token::Value::INSTANCEOF:
   1357       return Bytecode::kTestInstanceOf;
   1358     case Token::Value::IN:
   1359       return Bytecode::kTestIn;
   1360     default:
   1361       UNREACHABLE();
   1362       return static_cast<Bytecode>(-1);
   1363   }
   1364 }
   1365 
   1366 
   1367 // static
   1368 Bytecode BytecodeArrayBuilder::BytecodeForWideOperands(Bytecode bytecode) {
   1369   switch (bytecode) {
   1370     case Bytecode::kLoadICSloppy:
   1371       return Bytecode::kLoadICSloppyWide;
   1372     case Bytecode::kLoadICStrict:
   1373       return Bytecode::kLoadICStrictWide;
   1374     case Bytecode::kKeyedLoadICSloppy:
   1375       return Bytecode::kKeyedLoadICSloppyWide;
   1376     case Bytecode::kKeyedLoadICStrict:
   1377       return Bytecode::kKeyedLoadICStrictWide;
   1378     case Bytecode::kStoreICSloppy:
   1379       return Bytecode::kStoreICSloppyWide;
   1380     case Bytecode::kStoreICStrict:
   1381       return Bytecode::kStoreICStrictWide;
   1382     case Bytecode::kKeyedStoreICSloppy:
   1383       return Bytecode::kKeyedStoreICSloppyWide;
   1384     case Bytecode::kKeyedStoreICStrict:
   1385       return Bytecode::kKeyedStoreICStrictWide;
   1386     case Bytecode::kLdaGlobalSloppy:
   1387       return Bytecode::kLdaGlobalSloppyWide;
   1388     case Bytecode::kLdaGlobalStrict:
   1389       return Bytecode::kLdaGlobalStrictWide;
   1390     case Bytecode::kLdaGlobalInsideTypeofSloppy:
   1391       return Bytecode::kLdaGlobalInsideTypeofSloppyWide;
   1392     case Bytecode::kLdaGlobalInsideTypeofStrict:
   1393       return Bytecode::kLdaGlobalInsideTypeofStrictWide;
   1394     case Bytecode::kStaGlobalSloppy:
   1395       return Bytecode::kStaGlobalSloppyWide;
   1396     case Bytecode::kStaGlobalStrict:
   1397       return Bytecode::kStaGlobalStrictWide;
   1398     case Bytecode::kLdaLookupSlot:
   1399       return Bytecode::kLdaLookupSlotWide;
   1400     case Bytecode::kLdaLookupSlotInsideTypeof:
   1401       return Bytecode::kLdaLookupSlotInsideTypeofWide;
   1402     case Bytecode::kStaLookupSlotStrict:
   1403       return Bytecode::kStaLookupSlotStrictWide;
   1404     case Bytecode::kStaLookupSlotSloppy:
   1405       return Bytecode::kStaLookupSlotSloppyWide;
   1406     default:
   1407       UNREACHABLE();
   1408       return static_cast<Bytecode>(-1);
   1409   }
   1410 }
   1411 
   1412 
   1413 // static
   1414 Bytecode BytecodeArrayBuilder::BytecodeForLoadIC(LanguageMode language_mode) {
   1415   switch (language_mode) {
   1416     case SLOPPY:
   1417       return Bytecode::kLoadICSloppy;
   1418     case STRICT:
   1419       return Bytecode::kLoadICStrict;
   1420     case STRONG:
   1421       UNIMPLEMENTED();
   1422     default:
   1423       UNREACHABLE();
   1424   }
   1425   return static_cast<Bytecode>(-1);
   1426 }
   1427 
   1428 
   1429 // static
   1430 Bytecode BytecodeArrayBuilder::BytecodeForKeyedLoadIC(
   1431     LanguageMode language_mode) {
   1432   switch (language_mode) {
   1433     case SLOPPY:
   1434       return Bytecode::kKeyedLoadICSloppy;
   1435     case STRICT:
   1436       return Bytecode::kKeyedLoadICStrict;
   1437     case STRONG:
   1438       UNIMPLEMENTED();
   1439     default:
   1440       UNREACHABLE();
   1441   }
   1442   return static_cast<Bytecode>(-1);
   1443 }
   1444 
   1445 
   1446 // static
   1447 Bytecode BytecodeArrayBuilder::BytecodeForStoreIC(LanguageMode language_mode) {
   1448   switch (language_mode) {
   1449     case SLOPPY:
   1450       return Bytecode::kStoreICSloppy;
   1451     case STRICT:
   1452       return Bytecode::kStoreICStrict;
   1453     case STRONG:
   1454       UNIMPLEMENTED();
   1455     default:
   1456       UNREACHABLE();
   1457   }
   1458   return static_cast<Bytecode>(-1);
   1459 }
   1460 
   1461 
   1462 // static
   1463 Bytecode BytecodeArrayBuilder::BytecodeForKeyedStoreIC(
   1464     LanguageMode language_mode) {
   1465   switch (language_mode) {
   1466     case SLOPPY:
   1467       return Bytecode::kKeyedStoreICSloppy;
   1468     case STRICT:
   1469       return Bytecode::kKeyedStoreICStrict;
   1470     case STRONG:
   1471       UNIMPLEMENTED();
   1472     default:
   1473       UNREACHABLE();
   1474   }
   1475   return static_cast<Bytecode>(-1);
   1476 }
   1477 
   1478 
   1479 // static
   1480 Bytecode BytecodeArrayBuilder::BytecodeForLoadGlobal(LanguageMode language_mode,
   1481                                                      TypeofMode typeof_mode) {
   1482   switch (language_mode) {
   1483     case SLOPPY:
   1484       return typeof_mode == INSIDE_TYPEOF
   1485                  ? Bytecode::kLdaGlobalInsideTypeofSloppy
   1486                  : Bytecode::kLdaGlobalSloppy;
   1487     case STRICT:
   1488       return typeof_mode == INSIDE_TYPEOF
   1489                  ? Bytecode::kLdaGlobalInsideTypeofStrict
   1490                  : Bytecode::kLdaGlobalStrict;
   1491     case STRONG:
   1492       UNIMPLEMENTED();
   1493     default:
   1494       UNREACHABLE();
   1495   }
   1496   return static_cast<Bytecode>(-1);
   1497 }
   1498 
   1499 
   1500 // static
   1501 Bytecode BytecodeArrayBuilder::BytecodeForStoreGlobal(
   1502     LanguageMode language_mode) {
   1503   switch (language_mode) {
   1504     case SLOPPY:
   1505       return Bytecode::kStaGlobalSloppy;
   1506     case STRICT:
   1507       return Bytecode::kStaGlobalStrict;
   1508     case STRONG:
   1509       UNIMPLEMENTED();
   1510     default:
   1511       UNREACHABLE();
   1512   }
   1513   return static_cast<Bytecode>(-1);
   1514 }
   1515 
   1516 
   1517 // static
   1518 Bytecode BytecodeArrayBuilder::BytecodeForStoreLookupSlot(
   1519     LanguageMode language_mode) {
   1520   switch (language_mode) {
   1521     case SLOPPY:
   1522       return Bytecode::kStaLookupSlotSloppy;
   1523     case STRICT:
   1524       return Bytecode::kStaLookupSlotStrict;
   1525     case STRONG:
   1526       UNIMPLEMENTED();
   1527     default:
   1528       UNREACHABLE();
   1529   }
   1530   return static_cast<Bytecode>(-1);
   1531 }
   1532 
   1533 
   1534 // static
   1535 Bytecode BytecodeArrayBuilder::BytecodeForCreateArguments(
   1536     CreateArgumentsType type) {
   1537   switch (type) {
   1538     case CreateArgumentsType::kMappedArguments:
   1539       return Bytecode::kCreateMappedArguments;
   1540     case CreateArgumentsType::kUnmappedArguments:
   1541       return Bytecode::kCreateUnmappedArguments;
   1542     default:
   1543       UNREACHABLE();
   1544   }
   1545   return static_cast<Bytecode>(-1);
   1546 }
   1547 
   1548 
   1549 // static
   1550 Bytecode BytecodeArrayBuilder::BytecodeForDelete(LanguageMode language_mode) {
   1551   switch (language_mode) {
   1552     case SLOPPY:
   1553       return Bytecode::kDeletePropertySloppy;
   1554     case STRICT:
   1555       return Bytecode::kDeletePropertyStrict;
   1556     case STRONG:
   1557       UNIMPLEMENTED();
   1558     default:
   1559       UNREACHABLE();
   1560   }
   1561   return static_cast<Bytecode>(-1);
   1562 }
   1563 
   1564 
   1565 // static
   1566 bool BytecodeArrayBuilder::FitsInIdx8Operand(int value) {
   1567   return kMinUInt8 <= value && value <= kMaxUInt8;
   1568 }
   1569 
   1570 
   1571 // static
   1572 bool BytecodeArrayBuilder::FitsInIdx8Operand(size_t value) {
   1573   return value <= static_cast<size_t>(kMaxUInt8);
   1574 }
   1575 
   1576 
   1577 // static
   1578 bool BytecodeArrayBuilder::FitsInImm8Operand(int value) {
   1579   return kMinInt8 <= value && value <= kMaxInt8;
   1580 }
   1581 
   1582 
   1583 // static
   1584 bool BytecodeArrayBuilder::FitsInIdx16Operand(int value) {
   1585   return kMinUInt16 <= value && value <= kMaxUInt16;
   1586 }
   1587 
   1588 
   1589 // static
   1590 bool BytecodeArrayBuilder::FitsInIdx16Operand(size_t value) {
   1591   return value <= static_cast<size_t>(kMaxUInt16);
   1592 }
   1593 
   1594 
   1595 // static
   1596 bool BytecodeArrayBuilder::FitsInReg8Operand(Register value) {
   1597   return kMinInt8 <= value.index() && value.index() <= kMaxInt8;
   1598 }
   1599 
   1600 
   1601 // static
   1602 bool BytecodeArrayBuilder::FitsInReg16Operand(Register value) {
   1603   return kMinInt16 <= value.index() && value.index() <= kMaxInt16;
   1604 }
   1605 
   1606 }  // namespace interpreter
   1607 }  // namespace internal
   1608 }  // namespace v8
   1609