LCOV - code coverage report
Current view: top level - src/interpreter - bytecode-array-builder.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 406 440 92.3 %
Date: 2017-04-26 Functions: 268 282 95.0 %

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

Generated by: LCOV version 1.10