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/compiler.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(Isolate* isolate, Zone* zone,
     20                                            int parameter_count,
     21                                            int context_count, int locals_count,
     22                                            FunctionLiteral* literal)
     23     : isolate_(isolate),
     24       zone_(zone),
     25       bytecode_generated_(false),
     26       constant_array_builder_(isolate, zone),
     27       handler_table_builder_(isolate, zone),
     28       return_seen_in_block_(false),
     29       parameter_count_(parameter_count),
     30       local_register_count_(locals_count),
     31       context_register_count_(context_count),
     32       temporary_allocator_(zone, fixed_register_count()),
     33       bytecode_array_writer_(isolate, zone, &constant_array_builder_),
     34       pipeline_(&bytecode_array_writer_) {
     35   DCHECK_GE(parameter_count_, 0);
     36   DCHECK_GE(context_register_count_, 0);
     37   DCHECK_GE(local_register_count_, 0);
     38 
     39   if (FLAG_ignition_deadcode) {
     40     pipeline_ = new (zone) BytecodeDeadCodeOptimizer(pipeline_);
     41   }
     42 
     43   if (FLAG_ignition_peephole) {
     44     pipeline_ = new (zone)
     45         BytecodePeepholeOptimizer(&constant_array_builder_, pipeline_);
     46   }
     47 
     48   if (FLAG_ignition_reo) {
     49     pipeline_ = new (zone) BytecodeRegisterOptimizer(
     50         zone, &temporary_allocator_, parameter_count, pipeline_);
     51   }
     52 
     53   return_position_ =
     54       literal ? std::max(literal->start_position(), literal->end_position() - 1)
     55               : RelocInfo::kNoPosition;
     56 }
     57 
     58 Register BytecodeArrayBuilder::first_context_register() const {
     59   DCHECK_GT(context_register_count_, 0);
     60   return Register(local_register_count_);
     61 }
     62 
     63 Register BytecodeArrayBuilder::last_context_register() const {
     64   DCHECK_GT(context_register_count_, 0);
     65   return Register(local_register_count_ + context_register_count_ - 1);
     66 }
     67 
     68 Register BytecodeArrayBuilder::Parameter(int parameter_index) const {
     69   DCHECK_GE(parameter_index, 0);
     70   return Register::FromParameterIndex(parameter_index, parameter_count());
     71 }
     72 
     73 bool BytecodeArrayBuilder::RegisterIsParameterOrLocal(Register reg) const {
     74   return reg.is_parameter() || reg.index() < locals_count();
     75 }
     76 
     77 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() {
     78   DCHECK(return_seen_in_block_);
     79   DCHECK(!bytecode_generated_);
     80   bytecode_generated_ = true;
     81 
     82   Handle<FixedArray> handler_table = handler_table_builder()->ToHandlerTable();
     83   return pipeline_->ToBytecodeArray(fixed_register_count(), parameter_count(),
     84                                     handler_table);
     85 }
     86 
     87 namespace {
     88 
     89 static bool ExpressionPositionIsNeeded(Bytecode bytecode) {
     90   // An expression position is always needed if filtering is turned
     91   // off. Otherwise an expression is only needed if the bytecode has
     92   // external side effects.
     93   return !FLAG_ignition_filter_expression_positions ||
     94          !Bytecodes::IsWithoutExternalSideEffects(bytecode);
     95 }
     96 
     97 }  // namespace
     98 
     99 void BytecodeArrayBuilder::AttachSourceInfo(BytecodeNode* node) {
    100   if (latest_source_info_.is_valid()) {
    101     // Statement positions need to be emitted immediately.  Expression
    102     // positions can be pushed back until a bytecode is found that can
    103     // throw. Hence we only invalidate the existing source position
    104     // information if it is used.
    105     if (latest_source_info_.is_statement() ||
    106         ExpressionPositionIsNeeded(node->bytecode())) {
    107       node->source_info().Clone(latest_source_info_);
    108       latest_source_info_.set_invalid();
    109     }
    110   }
    111 }
    112 
    113 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
    114                                   uint32_t operand1, uint32_t operand2,
    115                                   uint32_t operand3) {
    116   DCHECK(OperandsAreValid(bytecode, 4, operand0, operand1, operand2, operand3));
    117   BytecodeNode node(bytecode, operand0, operand1, operand2, operand3);
    118   AttachSourceInfo(&node);
    119   pipeline()->Write(&node);
    120 }
    121 
    122 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
    123                                   uint32_t operand1, uint32_t operand2) {
    124   DCHECK(OperandsAreValid(bytecode, 3, operand0, operand1, operand2));
    125   BytecodeNode node(bytecode, operand0, operand1, operand2);
    126   AttachSourceInfo(&node);
    127   pipeline()->Write(&node);
    128 }
    129 
    130 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
    131                                   uint32_t operand1) {
    132   DCHECK(OperandsAreValid(bytecode, 2, operand0, operand1));
    133   BytecodeNode node(bytecode, operand0, operand1);
    134   AttachSourceInfo(&node);
    135   pipeline()->Write(&node);
    136 }
    137 
    138 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) {
    139   DCHECK(OperandsAreValid(bytecode, 1, operand0));
    140   BytecodeNode node(bytecode, operand0);
    141   AttachSourceInfo(&node);
    142   pipeline()->Write(&node);
    143 }
    144 
    145 void BytecodeArrayBuilder::Output(Bytecode bytecode) {
    146   DCHECK(OperandsAreValid(bytecode, 0));
    147   BytecodeNode node(bytecode);
    148   AttachSourceInfo(&node);
    149   pipeline()->Write(&node);
    150 }
    151 
    152 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
    153                                                             Register reg) {
    154   Output(BytecodeForBinaryOperation(op), RegisterOperand(reg));
    155   return *this;
    156 }
    157 
    158 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op) {
    159   Output(BytecodeForCountOperation(op));
    160   return *this;
    161 }
    162 
    163 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() {
    164   Output(Bytecode::kToBooleanLogicalNot);
    165   return *this;
    166 }
    167 
    168 
    169 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
    170   Output(Bytecode::kTypeOf);
    171   return *this;
    172 }
    173 
    174 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op,
    175                                                              Register reg) {
    176   Output(BytecodeForCompareOperation(op), RegisterOperand(reg));
    177   return *this;
    178 }
    179 
    180 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
    181     v8::internal::Smi* smi) {
    182   int32_t raw_smi = smi->value();
    183   if (raw_smi == 0) {
    184     Output(Bytecode::kLdaZero);
    185   } else {
    186     Output(Bytecode::kLdaSmi, SignedOperand(raw_smi));
    187   }
    188   return *this;
    189 }
    190 
    191 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) {
    192   size_t entry = GetConstantPoolEntry(object);
    193   Output(Bytecode::kLdaConstant, UnsignedOperand(entry));
    194   return *this;
    195 }
    196 
    197 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
    198   Output(Bytecode::kLdaUndefined);
    199   return *this;
    200 }
    201 
    202 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() {
    203   Output(Bytecode::kLdaNull);
    204   return *this;
    205 }
    206 
    207 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() {
    208   Output(Bytecode::kLdaTheHole);
    209   return *this;
    210 }
    211 
    212 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() {
    213   Output(Bytecode::kLdaTrue);
    214   return *this;
    215 }
    216 
    217 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
    218   Output(Bytecode::kLdaFalse);
    219   return *this;
    220 }
    221 
    222 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
    223     Register reg) {
    224   Output(Bytecode::kLdar, RegisterOperand(reg));
    225   return *this;
    226 }
    227 
    228 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
    229     Register reg) {
    230   Output(Bytecode::kStar, RegisterOperand(reg));
    231   return *this;
    232 }
    233 
    234 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
    235                                                          Register to) {
    236   DCHECK(from != to);
    237   Output(Bytecode::kMov, RegisterOperand(from), RegisterOperand(to));
    238   return *this;
    239 }
    240 
    241 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int feedback_slot,
    242                                                        TypeofMode typeof_mode) {
    243   // TODO(rmcilroy): Potentially store typeof information in an
    244   // operand rather than having extra bytecodes.
    245   Bytecode bytecode = BytecodeForLoadGlobal(typeof_mode);
    246   Output(bytecode, UnsignedOperand(feedback_slot));
    247   return *this;
    248 }
    249 
    250 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
    251     const Handle<String> name, int feedback_slot, LanguageMode language_mode) {
    252   Bytecode bytecode = BytecodeForStoreGlobal(language_mode);
    253   size_t name_index = GetConstantPoolEntry(name);
    254   Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(feedback_slot));
    255   return *this;
    256 }
    257 
    258 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context,
    259                                                             int slot_index) {
    260   Output(Bytecode::kLdaContextSlot, RegisterOperand(context),
    261          UnsignedOperand(slot_index));
    262   return *this;
    263 }
    264 
    265 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
    266                                                              int slot_index) {
    267   Output(Bytecode::kStaContextSlot, RegisterOperand(context),
    268          UnsignedOperand(slot_index));
    269   return *this;
    270 }
    271 
    272 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
    273     const Handle<String> name, TypeofMode typeof_mode) {
    274   Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF)
    275                           ? Bytecode::kLdaLookupSlotInsideTypeof
    276                           : Bytecode::kLdaLookupSlot;
    277   size_t name_index = GetConstantPoolEntry(name);
    278   Output(bytecode, UnsignedOperand(name_index));
    279   return *this;
    280 }
    281 
    282 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot(
    283     const Handle<String> name, LanguageMode language_mode) {
    284   Bytecode bytecode = BytecodeForStoreLookupSlot(language_mode);
    285   size_t name_index = GetConstantPoolEntry(name);
    286   Output(bytecode, UnsignedOperand(name_index));
    287   return *this;
    288 }
    289 
    290 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
    291     Register object, const Handle<Name> name, int feedback_slot) {
    292   size_t name_index = GetConstantPoolEntry(name);
    293   Output(Bytecode::kLdaNamedProperty, RegisterOperand(object),
    294          UnsignedOperand(name_index), UnsignedOperand(feedback_slot));
    295   return *this;
    296 }
    297 
    298 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
    299     Register object, int feedback_slot) {
    300   Output(Bytecode::kLdaKeyedProperty, RegisterOperand(object),
    301          UnsignedOperand(feedback_slot));
    302   return *this;
    303 }
    304 
    305 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
    306     Register object, const Handle<Name> name, int feedback_slot,
    307     LanguageMode language_mode) {
    308   Bytecode bytecode = BytecodeForStoreNamedProperty(language_mode);
    309   size_t name_index = GetConstantPoolEntry(name);
    310   Output(bytecode, RegisterOperand(object), UnsignedOperand(name_index),
    311          UnsignedOperand(feedback_slot));
    312   return *this;
    313 }
    314 
    315 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty(
    316     Register object, Register key, int feedback_slot,
    317     LanguageMode language_mode) {
    318   Bytecode bytecode = BytecodeForStoreKeyedProperty(language_mode);
    319   Output(bytecode, RegisterOperand(object), RegisterOperand(key),
    320          UnsignedOperand(feedback_slot));
    321   return *this;
    322 }
    323 
    324 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(
    325     Handle<SharedFunctionInfo> shared_info, PretenureFlag tenured) {
    326   size_t entry = GetConstantPoolEntry(shared_info);
    327   Output(Bytecode::kCreateClosure, UnsignedOperand(entry),
    328          UnsignedOperand(static_cast<size_t>(tenured)));
    329   return *this;
    330 }
    331 
    332 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
    333     CreateArgumentsType type) {
    334   // TODO(rmcilroy): Consider passing the type as a bytecode operand rather
    335   // than having two different bytecodes once we have better support for
    336   // branches in the InterpreterAssembler.
    337   Bytecode bytecode = BytecodeForCreateArguments(type);
    338   Output(bytecode);
    339   return *this;
    340 }
    341 
    342 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
    343     Handle<String> pattern, int literal_index, int flags) {
    344   size_t pattern_entry = GetConstantPoolEntry(pattern);
    345   Output(Bytecode::kCreateRegExpLiteral, UnsignedOperand(pattern_entry),
    346          UnsignedOperand(literal_index), UnsignedOperand(flags));
    347   return *this;
    348 }
    349 
    350 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
    351     Handle<FixedArray> constant_elements, int literal_index, int flags) {
    352   size_t constant_elements_entry = GetConstantPoolEntry(constant_elements);
    353   Output(Bytecode::kCreateArrayLiteral,
    354          UnsignedOperand(constant_elements_entry),
    355          UnsignedOperand(literal_index), UnsignedOperand(flags));
    356   return *this;
    357 }
    358 
    359 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
    360     Handle<FixedArray> constant_properties, int literal_index, int flags) {
    361   size_t constant_properties_entry = GetConstantPoolEntry(constant_properties);
    362   Output(Bytecode::kCreateObjectLiteral,
    363          UnsignedOperand(constant_properties_entry),
    364          UnsignedOperand(literal_index), UnsignedOperand(flags));
    365   return *this;
    366 }
    367 
    368 BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) {
    369   Output(Bytecode::kPushContext, RegisterOperand(context));
    370   return *this;
    371 }
    372 
    373 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) {
    374   Output(Bytecode::kPopContext, RegisterOperand(context));
    375   return *this;
    376 }
    377 
    378 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToJSObject() {
    379   Output(Bytecode::kToObject);
    380   return *this;
    381 }
    382 
    383 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName() {
    384   Output(Bytecode::kToName);
    385   return *this;
    386 }
    387 
    388 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToNumber() {
    389   Output(Bytecode::kToNumber);
    390   return *this;
    391 }
    392 
    393 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
    394   pipeline_->BindLabel(label);
    395   LeaveBasicBlock();
    396   return *this;
    397 }
    398 
    399 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target,
    400                                                  BytecodeLabel* label) {
    401   pipeline_->BindLabel(target, label);
    402   LeaveBasicBlock();
    403   return *this;
    404 }
    405 
    406 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode,
    407                                                        BytecodeLabel* label) {
    408   BytecodeNode node(jump_bytecode, 0);
    409   AttachSourceInfo(&node);
    410   pipeline_->WriteJump(&node, label);
    411   LeaveBasicBlock();
    412   return *this;
    413 }
    414 
    415 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
    416   return OutputJump(Bytecode::kJump, label);
    417 }
    418 
    419 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) {
    420   // The peephole optimizer attempts to simplify JumpIfToBooleanTrue
    421   // to JumpIfTrue.
    422   return OutputJump(Bytecode::kJumpIfToBooleanTrue, label);
    423 }
    424 
    425 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) {
    426   // The peephole optimizer attempts to simplify JumpIfToBooleanFalse
    427   // to JumpIfFalse.
    428   return OutputJump(Bytecode::kJumpIfToBooleanFalse, label);
    429 }
    430 
    431 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
    432   return OutputJump(Bytecode::kJumpIfNull, label);
    433 }
    434 
    435 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
    436     BytecodeLabel* label) {
    437   return OutputJump(Bytecode::kJumpIfUndefined, label);
    438 }
    439 
    440 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole(
    441     BytecodeLabel* label) {
    442   return OutputJump(Bytecode::kJumpIfNotHole, label);
    443 }
    444 
    445 BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) {
    446   if (position != RelocInfo::kNoPosition) {
    447     // We need to attach a non-breakable source position to a stack
    448     // check, so we simply add it as expression position. There can be
    449     // a prior statement position from constructs like:
    450     //
    451     //    do var x;  while (false);
    452     //
    453     // A Nop could be inserted for empty statements, but since no code
    454     // is associated with these positions, instead we force the stack
    455     // check's expression position which eliminates the empty
    456     // statement's position.
    457     latest_source_info_.ForceExpressionPosition(position);
    458   }
    459   Output(Bytecode::kStackCheck);
    460   return *this;
    461 }
    462 
    463 BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
    464   Output(Bytecode::kThrow);
    465   return *this;
    466 }
    467 
    468 BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() {
    469   Output(Bytecode::kReThrow);
    470   return *this;
    471 }
    472 
    473 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
    474   SetReturnPosition();
    475   Output(Bytecode::kReturn);
    476   return_seen_in_block_ = true;
    477   return *this;
    478 }
    479 
    480 BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() {
    481   Output(Bytecode::kDebugger);
    482   return *this;
    483 }
    484 
    485 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare(
    486     Register cache_info_triple) {
    487   Output(Bytecode::kForInPrepare, RegisterOperand(cache_info_triple));
    488   return *this;
    489 }
    490 
    491 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInDone(Register index,
    492                                                       Register cache_length) {
    493   Output(Bytecode::kForInDone, RegisterOperand(index),
    494          RegisterOperand(cache_length));
    495   return *this;
    496 }
    497 
    498 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext(
    499     Register receiver, Register index, Register cache_type_array_pair,
    500     int feedback_slot) {
    501   Output(Bytecode::kForInNext, RegisterOperand(receiver),
    502          RegisterOperand(index), RegisterOperand(cache_type_array_pair),
    503          UnsignedOperand(feedback_slot));
    504   return *this;
    505 }
    506 
    507 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
    508   Output(Bytecode::kForInStep, RegisterOperand(index));
    509   return *this;
    510 }
    511 
    512 BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator(
    513     Register generator) {
    514   Output(Bytecode::kSuspendGenerator, RegisterOperand(generator));
    515   return *this;
    516 }
    517 
    518 BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator(
    519     Register generator) {
    520   Output(Bytecode::kResumeGenerator, RegisterOperand(generator));
    521   return *this;
    522 }
    523 
    524 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(int handler_id,
    525                                                         bool will_catch) {
    526   BytecodeLabel handler;
    527   Bind(&handler);
    528   handler_table_builder()->SetHandlerTarget(handler_id, handler.offset());
    529   handler_table_builder()->SetPrediction(handler_id, will_catch);
    530   return *this;
    531 }
    532 
    533 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryBegin(int handler_id,
    534                                                          Register context) {
    535   BytecodeLabel try_begin;
    536   Bind(&try_begin);
    537   handler_table_builder()->SetTryRegionStart(handler_id, try_begin.offset());
    538   handler_table_builder()->SetContextRegister(handler_id, context);
    539   return *this;
    540 }
    541 
    542 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) {
    543   BytecodeLabel try_end;
    544   Bind(&try_end);
    545   handler_table_builder()->SetTryRegionEnd(handler_id, try_end.offset());
    546   return *this;
    547 }
    548 
    549 void BytecodeArrayBuilder::EnsureReturn() {
    550   if (!return_seen_in_block_) {
    551     LoadUndefined();
    552     Return();
    553   }
    554   DCHECK(return_seen_in_block_);
    555 }
    556 
    557 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
    558                                                  Register receiver_args,
    559                                                  size_t receiver_args_count,
    560                                                  int feedback_slot,
    561                                                  TailCallMode tail_call_mode) {
    562   Bytecode bytecode = BytecodeForCall(tail_call_mode);
    563   Output(bytecode, RegisterOperand(callable), RegisterOperand(receiver_args),
    564          UnsignedOperand(receiver_args_count), UnsignedOperand(feedback_slot));
    565   return *this;
    566 }
    567 
    568 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor,
    569                                                 Register first_arg,
    570                                                 size_t arg_count) {
    571   if (!first_arg.is_valid()) {
    572     DCHECK_EQ(0u, arg_count);
    573     first_arg = Register(0);
    574   }
    575   Output(Bytecode::kNew, RegisterOperand(constructor),
    576          RegisterOperand(first_arg), UnsignedOperand(arg_count));
    577   return *this;
    578 }
    579 
    580 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
    581     Runtime::FunctionId function_id, Register first_arg, size_t arg_count) {
    582   DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size);
    583   DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort);
    584   if (!first_arg.is_valid()) {
    585     DCHECK_EQ(0u, arg_count);
    586     first_arg = Register(0);
    587   }
    588   Bytecode bytecode;
    589   uint32_t id;
    590   if (IntrinsicsHelper::IsSupported(function_id)) {
    591     bytecode = Bytecode::kInvokeIntrinsic;
    592     id = static_cast<uint32_t>(IntrinsicsHelper::FromRuntimeId(function_id));
    593   } else {
    594     bytecode = Bytecode::kCallRuntime;
    595     id = static_cast<uint32_t>(function_id);
    596   }
    597   Output(bytecode, id, RegisterOperand(first_arg), UnsignedOperand(arg_count));
    598   return *this;
    599 }
    600 
    601 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
    602     Runtime::FunctionId function_id, Register first_arg, size_t arg_count,
    603     Register first_return) {
    604   DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size);
    605   DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort);
    606   if (!first_arg.is_valid()) {
    607     DCHECK_EQ(0u, arg_count);
    608     first_arg = Register(0);
    609   }
    610   Output(Bytecode::kCallRuntimeForPair, static_cast<uint16_t>(function_id),
    611          RegisterOperand(first_arg), UnsignedOperand(arg_count),
    612          RegisterOperand(first_return));
    613   return *this;
    614 }
    615 
    616 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(
    617     int context_index, Register receiver_args, size_t receiver_args_count) {
    618   Output(Bytecode::kCallJSRuntime, UnsignedOperand(context_index),
    619          RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count));
    620   return *this;
    621 }
    622 
    623 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object,
    624                                                    LanguageMode language_mode) {
    625   Output(BytecodeForDelete(language_mode), RegisterOperand(object));
    626   return *this;
    627 }
    628 
    629 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) {
    630   return constant_array_builder()->Insert(object);
    631 }
    632 
    633 void BytecodeArrayBuilder::SetReturnPosition() {
    634   if (return_position_ == RelocInfo::kNoPosition) return;
    635   latest_source_info_.MakeStatementPosition(return_position_);
    636 }
    637 
    638 void BytecodeArrayBuilder::SetStatementPosition(Statement* stmt) {
    639   if (stmt->position() == RelocInfo::kNoPosition) return;
    640   latest_source_info_.MakeStatementPosition(stmt->position());
    641 }
    642 
    643 void BytecodeArrayBuilder::SetExpressionPosition(Expression* expr) {
    644   if (expr->position() == RelocInfo::kNoPosition) return;
    645   if (!latest_source_info_.is_statement()) {
    646     // Ensure the current expression position is overwritten with the
    647     // latest value.
    648     latest_source_info_.MakeExpressionPosition(expr->position());
    649   }
    650 }
    651 
    652 void BytecodeArrayBuilder::SetExpressionAsStatementPosition(Expression* expr) {
    653   if (expr->position() == RelocInfo::kNoPosition) return;
    654   latest_source_info_.MakeStatementPosition(expr->position());
    655 }
    656 
    657 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const {
    658   return temporary_register_allocator()->RegisterIsLive(reg);
    659 }
    660 
    661 bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const {
    662   if (!reg.is_valid()) {
    663     return false;
    664   }
    665 
    666   if (reg.is_current_context() || reg.is_function_closure() ||
    667       reg.is_new_target()) {
    668     return true;
    669   } else if (reg.is_parameter()) {
    670     int parameter_index = reg.ToParameterIndex(parameter_count());
    671     return parameter_index >= 0 && parameter_index < parameter_count();
    672   } else if (reg.index() < fixed_register_count()) {
    673     return true;
    674   } else {
    675     return TemporaryRegisterIsLive(reg);
    676   }
    677 }
    678 
    679 bool BytecodeArrayBuilder::OperandsAreValid(
    680     Bytecode bytecode, int operand_count, uint32_t operand0, uint32_t operand1,
    681     uint32_t operand2, uint32_t operand3) const {
    682   if (Bytecodes::NumberOfOperands(bytecode) != operand_count) {
    683     return false;
    684   }
    685 
    686   uint32_t operands[] = {operand0, operand1, operand2, operand3};
    687   const OperandType* operand_types = Bytecodes::GetOperandTypes(bytecode);
    688   for (int i = 0; i < operand_count; ++i) {
    689     switch (operand_types[i]) {
    690       case OperandType::kNone:
    691         return false;
    692       case OperandType::kRegCount: {
    693         CHECK_NE(i, 0);
    694         CHECK(operand_types[i - 1] == OperandType::kMaybeReg ||
    695               operand_types[i - 1] == OperandType::kReg);
    696         if (i > 0 && operands[i] > 0) {
    697           Register start = Register::FromOperand(operands[i - 1]);
    698           Register end(start.index() + static_cast<int>(operands[i]) - 1);
    699           if (!RegisterIsValid(start) || !RegisterIsValid(end) || start > end) {
    700             return false;
    701           }
    702         }
    703         break;
    704       }
    705       case OperandType::kFlag8:
    706       case OperandType::kIntrinsicId:
    707         if (Bytecodes::SizeForUnsignedOperand(operands[i]) >
    708             OperandSize::kByte) {
    709           return false;
    710         }
    711         break;
    712       case OperandType::kRuntimeId:
    713         if (Bytecodes::SizeForUnsignedOperand(operands[i]) >
    714             OperandSize::kShort) {
    715           return false;
    716         }
    717         break;
    718       case OperandType::kIdx:
    719         // TODO(oth): Consider splitting OperandType::kIdx into two
    720         // operand types. One which is a constant pool index that can
    721         // be checked, and the other is an unsigned value.
    722         break;
    723       case OperandType::kImm:
    724         break;
    725       case OperandType::kMaybeReg:
    726         if (Register::FromOperand(operands[i]) == Register(0)) {
    727           break;
    728         }
    729       // Fall-through to kReg case.
    730       case OperandType::kReg:
    731       case OperandType::kRegOut: {
    732         Register reg = Register::FromOperand(operands[i]);
    733         if (!RegisterIsValid(reg)) {
    734           return false;
    735         }
    736         break;
    737       }
    738       case OperandType::kRegOutPair:
    739       case OperandType::kRegPair: {
    740         Register reg0 = Register::FromOperand(operands[i]);
    741         Register reg1 = Register(reg0.index() + 1);
    742         if (!RegisterIsValid(reg0) || !RegisterIsValid(reg1)) {
    743           return false;
    744         }
    745         break;
    746       }
    747       case OperandType::kRegOutTriple: {
    748         Register reg0 = Register::FromOperand(operands[i]);
    749         Register reg1 = Register(reg0.index() + 1);
    750         Register reg2 = Register(reg0.index() + 2);
    751         if (!RegisterIsValid(reg0) || !RegisterIsValid(reg1) ||
    752             !RegisterIsValid(reg2)) {
    753           return false;
    754         }
    755         break;
    756       }
    757     }
    758   }
    759 
    760   return true;
    761 }
    762 
    763 // static
    764 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) {
    765   switch (op) {
    766     case Token::Value::ADD:
    767       return Bytecode::kAdd;
    768     case Token::Value::SUB:
    769       return Bytecode::kSub;
    770     case Token::Value::MUL:
    771       return Bytecode::kMul;
    772     case Token::Value::DIV:
    773       return Bytecode::kDiv;
    774     case Token::Value::MOD:
    775       return Bytecode::kMod;
    776     case Token::Value::BIT_OR:
    777       return Bytecode::kBitwiseOr;
    778     case Token::Value::BIT_XOR:
    779       return Bytecode::kBitwiseXor;
    780     case Token::Value::BIT_AND:
    781       return Bytecode::kBitwiseAnd;
    782     case Token::Value::SHL:
    783       return Bytecode::kShiftLeft;
    784     case Token::Value::SAR:
    785       return Bytecode::kShiftRight;
    786     case Token::Value::SHR:
    787       return Bytecode::kShiftRightLogical;
    788     default:
    789       UNREACHABLE();
    790       return Bytecode::kIllegal;
    791   }
    792 }
    793 
    794 // static
    795 Bytecode BytecodeArrayBuilder::BytecodeForCountOperation(Token::Value op) {
    796   switch (op) {
    797     case Token::Value::ADD:
    798       return Bytecode::kInc;
    799     case Token::Value::SUB:
    800       return Bytecode::kDec;
    801     default:
    802       UNREACHABLE();
    803       return Bytecode::kIllegal;
    804   }
    805 }
    806 
    807 // static
    808 Bytecode BytecodeArrayBuilder::BytecodeForCompareOperation(Token::Value op) {
    809   switch (op) {
    810     case Token::Value::EQ:
    811       return Bytecode::kTestEqual;
    812     case Token::Value::NE:
    813       return Bytecode::kTestNotEqual;
    814     case Token::Value::EQ_STRICT:
    815       return Bytecode::kTestEqualStrict;
    816     case Token::Value::LT:
    817       return Bytecode::kTestLessThan;
    818     case Token::Value::GT:
    819       return Bytecode::kTestGreaterThan;
    820     case Token::Value::LTE:
    821       return Bytecode::kTestLessThanOrEqual;
    822     case Token::Value::GTE:
    823       return Bytecode::kTestGreaterThanOrEqual;
    824     case Token::Value::INSTANCEOF:
    825       return Bytecode::kTestInstanceOf;
    826     case Token::Value::IN:
    827       return Bytecode::kTestIn;
    828     default:
    829       UNREACHABLE();
    830       return Bytecode::kIllegal;
    831   }
    832 }
    833 
    834 // static
    835 Bytecode BytecodeArrayBuilder::BytecodeForStoreNamedProperty(
    836     LanguageMode language_mode) {
    837   switch (language_mode) {
    838     case SLOPPY:
    839       return Bytecode::kStaNamedPropertySloppy;
    840     case STRICT:
    841       return Bytecode::kStaNamedPropertyStrict;
    842     default:
    843       UNREACHABLE();
    844   }
    845   return Bytecode::kIllegal;
    846 }
    847 
    848 // static
    849 Bytecode BytecodeArrayBuilder::BytecodeForStoreKeyedProperty(
    850     LanguageMode language_mode) {
    851   switch (language_mode) {
    852     case SLOPPY:
    853       return Bytecode::kStaKeyedPropertySloppy;
    854     case STRICT:
    855       return Bytecode::kStaKeyedPropertyStrict;
    856     default:
    857       UNREACHABLE();
    858   }
    859   return Bytecode::kIllegal;
    860 }
    861 
    862 // static
    863 Bytecode BytecodeArrayBuilder::BytecodeForLoadGlobal(TypeofMode typeof_mode) {
    864   return typeof_mode == INSIDE_TYPEOF ? Bytecode::kLdaGlobalInsideTypeof
    865                                       : Bytecode::kLdaGlobal;
    866 }
    867 
    868 // static
    869 Bytecode BytecodeArrayBuilder::BytecodeForStoreGlobal(
    870     LanguageMode language_mode) {
    871   switch (language_mode) {
    872     case SLOPPY:
    873       return Bytecode::kStaGlobalSloppy;
    874     case STRICT:
    875       return Bytecode::kStaGlobalStrict;
    876     default:
    877       UNREACHABLE();
    878   }
    879   return Bytecode::kIllegal;
    880 }
    881 
    882 // static
    883 Bytecode BytecodeArrayBuilder::BytecodeForStoreLookupSlot(
    884     LanguageMode language_mode) {
    885   switch (language_mode) {
    886     case SLOPPY:
    887       return Bytecode::kStaLookupSlotSloppy;
    888     case STRICT:
    889       return Bytecode::kStaLookupSlotStrict;
    890     default:
    891       UNREACHABLE();
    892   }
    893   return Bytecode::kIllegal;
    894 }
    895 
    896 // static
    897 Bytecode BytecodeArrayBuilder::BytecodeForCreateArguments(
    898     CreateArgumentsType type) {
    899   switch (type) {
    900     case CreateArgumentsType::kMappedArguments:
    901       return Bytecode::kCreateMappedArguments;
    902     case CreateArgumentsType::kUnmappedArguments:
    903       return Bytecode::kCreateUnmappedArguments;
    904     case CreateArgumentsType::kRestParameter:
    905       return Bytecode::kCreateRestParameter;
    906   }
    907   UNREACHABLE();
    908   return Bytecode::kIllegal;
    909 }
    910 
    911 // static
    912 Bytecode BytecodeArrayBuilder::BytecodeForDelete(LanguageMode language_mode) {
    913   switch (language_mode) {
    914     case SLOPPY:
    915       return Bytecode::kDeletePropertySloppy;
    916     case STRICT:
    917       return Bytecode::kDeletePropertyStrict;
    918     default:
    919       UNREACHABLE();
    920   }
    921   return Bytecode::kIllegal;
    922 }
    923 
    924 // static
    925 Bytecode BytecodeArrayBuilder::BytecodeForCall(TailCallMode tail_call_mode) {
    926   switch (tail_call_mode) {
    927     case TailCallMode::kDisallow:
    928       return Bytecode::kCall;
    929     case TailCallMode::kAllow:
    930       return Bytecode::kTailCall;
    931     default:
    932       UNREACHABLE();
    933   }
    934   return Bytecode::kIllegal;
    935 }
    936 
    937 }  // namespace interpreter
    938 }  // namespace internal
    939 }  // namespace v8
    940