bytecode-array-builder.cc 53.6 KB
Newer Older
1 2 3 4 5
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/interpreter/bytecode-array-builder.h"
6

7
#include "src/common/globals.h"
8
#include "src/interpreter/bytecode-array-writer.h"
9
#include "src/interpreter/bytecode-jump-table.h"
10
#include "src/interpreter/bytecode-label.h"
11
#include "src/interpreter/bytecode-node.h"
12
#include "src/interpreter/bytecode-register-optimizer.h"
13
#include "src/interpreter/bytecode-source-info.h"
14
#include "src/interpreter/interpreter-intrinsics.h"
15
#include "src/objects/objects-inl.h"
16
#include "src/objects/smi.h"
17 18 19 20 21

namespace v8 {
namespace internal {
namespace interpreter {

22 23 24 25
class RegisterTransferWriter final
    : public NON_EXPORTED_BASE(BytecodeRegisterOptimizer::BytecodeWriter),
      public NON_EXPORTED_BASE(ZoneObject) {
 public:
26 27
  explicit RegisterTransferWriter(BytecodeArrayBuilder* builder)
      : builder_(builder) {}
28
  ~RegisterTransferWriter() override = default;
29 30 31 32 33 34 35 36 37 38 39 40 41

  void EmitLdar(Register input) override { builder_->OutputLdarRaw(input); }

  void EmitStar(Register output) override { builder_->OutputStarRaw(output); }

  void EmitMov(Register input, Register output) override {
    builder_->OutputMovRaw(input, output);
  }

 private:
  BytecodeArrayBuilder* builder_;
};

42
BytecodeArrayBuilder::BytecodeArrayBuilder(
43
    Zone* zone, int parameter_count, int locals_count,
44
    FeedbackVectorSpec* feedback_vector_spec,
45
    SourcePositionTableBuilder::RecordingMode source_position_mode)
46
    : zone_(zone),
47
      feedback_vector_spec_(feedback_vector_spec),
48
      bytecode_generated_(false),
49
      constant_array_builder_(zone),
50
      handler_table_builder_(zone),
51 52
      parameter_count_(parameter_count),
      local_register_count_(locals_count),
53 54 55 56
      register_allocator_(fixed_register_count()),
      bytecode_array_writer_(zone, &constant_array_builder_,
                             source_position_mode),
      register_optimizer_(nullptr) {
57
  DCHECK_GE(parameter_count_, 0);
58
  DCHECK_GE(local_register_count_, 0);
59

60
  if (FLAG_ignition_reo) {
61
    register_optimizer_ = new (zone) BytecodeRegisterOptimizer(
62
        zone, &register_allocator_, fixed_register_count(), parameter_count,
63
        new (zone) RegisterTransferWriter(this));
64
  }
65 66 67
}

Register BytecodeArrayBuilder::Parameter(int parameter_index) const {
68
  DCHECK_GE(parameter_index, 0);
69 70 71 72 73 74 75
  // The parameter indices are shifted by 1 (receiver is the
  // first entry).
  return Register::FromParameterIndex(parameter_index + 1, parameter_count());
}

Register BytecodeArrayBuilder::Receiver() const {
  return Register::FromParameterIndex(0, parameter_count());
76 77
}

78 79 80 81 82 83
Register BytecodeArrayBuilder::Local(int index) const {
  // TODO(marja): Make a DCHECK once crbug.com/706234 is fixed.
  CHECK_LT(index, locals_count());
  return Register(index);
}

84
Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) {
85
  DCHECK(RemainderOfBlockIsDead());
86 87
  DCHECK(!bytecode_generated_);
  bytecode_generated_ = true;
88

89 90 91 92 93 94 95
  int register_count = total_register_count();

  if (register_optimizer_) {
    register_optimizer_->Flush();
    register_count = register_optimizer_->maxiumum_register_index() + 1;
  }

96
  Handle<ByteArray> handler_table =
97
      handler_table_builder()->ToHandlerTable(isolate);
98 99
  return bytecode_array_writer_.ToBytecodeArray(
      isolate, register_count, parameter_count(), handler_table);
100 101
}

102
#ifdef DEBUG
103 104
int BytecodeArrayBuilder::CheckBytecodeMatches(Handle<BytecodeArray> bytecode) {
  return bytecode_array_writer_.CheckBytecodeMatches(bytecode);
105 106 107 108 109 110 111 112 113 114
}
#endif

Handle<ByteArray> BytecodeArrayBuilder::ToSourcePositionTable(
    Isolate* isolate) {
  DCHECK(RemainderOfBlockIsDead());

  return bytecode_array_writer_.ToSourcePositionTable(isolate);
}

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
BytecodeSourceInfo BytecodeArrayBuilder::CurrentSourcePosition(
    Bytecode bytecode) {
  BytecodeSourceInfo source_position;
  if (latest_source_info_.is_valid()) {
    // Statement positions need to be emitted immediately.  Expression
    // positions can be pushed back until a bytecode is found that can
    // throw (if expression position filtering is turned on). We only
    // invalidate the existing source position information if it is used.
    if (latest_source_info_.is_statement() ||
        !FLAG_ignition_filter_expression_positions ||
        !Bytecodes::IsWithoutExternalSideEffects(bytecode)) {
      source_position = latest_source_info_;
      latest_source_info_.set_invalid();
    }
  }
  return source_position;
131 132
}

133 134 135 136 137
void BytecodeArrayBuilder::SetDeferredSourceInfo(
    BytecodeSourceInfo source_info) {
  if (!source_info.is_valid()) return;
  deferred_source_info_ = source_info;
}
138

139 140 141 142
void BytecodeArrayBuilder::AttachOrEmitDeferredSourceInfo(BytecodeNode* node) {
  if (!deferred_source_info_.is_valid()) return;
  if (!node->source_info().is_valid()) {
    node->set_source_info(deferred_source_info_);
143 144 145 146 147
  } else if (deferred_source_info_.is_statement() &&
             node->source_info().is_expression()) {
    BytecodeSourceInfo source_position = node->source_info();
    source_position.MakeStatementPosition(source_position.source_position());
    node->set_source_info(source_position);
148
  }
149
  deferred_source_info_.set_invalid();
150 151
}

152 153 154 155 156 157 158 159 160 161
void BytecodeArrayBuilder::Write(BytecodeNode* node) {
  AttachOrEmitDeferredSourceInfo(node);
  bytecode_array_writer_.Write(node);
}

void BytecodeArrayBuilder::WriteJump(BytecodeNode* node, BytecodeLabel* label) {
  AttachOrEmitDeferredSourceInfo(node);
  bytecode_array_writer_.WriteJump(node, label);
}

162 163 164 165 166 167
void BytecodeArrayBuilder::WriteJumpLoop(BytecodeNode* node,
                                         BytecodeLoopHeader* loop_header) {
  AttachOrEmitDeferredSourceInfo(node);
  bytecode_array_writer_.WriteJumpLoop(node, loop_header);
}

168 169 170 171
void BytecodeArrayBuilder::WriteSwitch(BytecodeNode* node,
                                       BytecodeJumpTable* jump_table) {
  AttachOrEmitDeferredSourceInfo(node);
  bytecode_array_writer_.WriteSwitch(node, jump_table);
172 173
}

174
void BytecodeArrayBuilder::OutputLdarRaw(Register reg) {
175 176 177
  uint32_t operand = static_cast<uint32_t>(reg.ToOperand());
  BytecodeNode node(BytecodeNode::Ldar(BytecodeSourceInfo(), operand));
  Write(&node);
178 179 180
}

void BytecodeArrayBuilder::OutputStarRaw(Register reg) {
181 182 183
  uint32_t operand = static_cast<uint32_t>(reg.ToOperand());
  BytecodeNode node(BytecodeNode::Star(BytecodeSourceInfo(), operand));
  Write(&node);
184 185 186
}

void BytecodeArrayBuilder::OutputMovRaw(Register src, Register dest) {
187 188 189 190 191
  uint32_t operand0 = static_cast<uint32_t>(src.ToOperand());
  uint32_t operand1 = static_cast<uint32_t>(dest.ToOperand());
  BytecodeNode node(
      BytecodeNode::Mov(BytecodeSourceInfo(), operand0, operand1));
  Write(&node);
192 193
}

194
namespace {
195

196 197 198
template <OperandTypeInfo type_info>
class UnsignedOperandHelper {
 public:
199 200
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
                                    size_t value) {
201 202 203
    DCHECK(IsValid(value));
    return static_cast<uint32_t>(value);
  }
204

205
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder, int value) {
206 207 208
    DCHECK_GE(value, 0);
    return Convert(builder, static_cast<size_t>(value));
  }
209

210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
 private:
  static bool IsValid(size_t value) {
    switch (type_info) {
      case OperandTypeInfo::kFixedUnsignedByte:
        return value <= kMaxUInt8;
      case OperandTypeInfo::kFixedUnsignedShort:
        return value <= kMaxUInt16;
      case OperandTypeInfo::kScalableUnsignedByte:
        return value <= kMaxUInt32;
      default:
        UNREACHABLE();
    }
  }
};

template <OperandType>
class OperandHelper {};

#define DEFINE_UNSIGNED_OPERAND_HELPER(Name, Type) \
  template <>                                      \
  class OperandHelper<OperandType::k##Name>        \
      : public UnsignedOperandHelper<Type> {};
232 233
UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
234 235 236 237 238
#undef DEFINE_UNSIGNED_OPERAND_HELPER

template <>
class OperandHelper<OperandType::kImm> {
 public:
239
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder, int value) {
240 241 242
    return static_cast<uint32_t>(value);
  }
};
243

244 245 246
template <>
class OperandHelper<OperandType::kReg> {
 public:
247 248
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
                                    Register reg) {
249 250 251 252 253 254 255
    return builder->GetInputRegisterOperand(reg);
  }
};

template <>
class OperandHelper<OperandType::kRegList> {
 public:
256 257
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
                                    RegisterList reg_list) {
258 259 260 261 262 263 264
    return builder->GetInputRegisterListOperand(reg_list);
  }
};

template <>
class OperandHelper<OperandType::kRegPair> {
 public:
265 266
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
                                    RegisterList reg_list) {
267 268 269 270
    DCHECK_EQ(reg_list.register_count(), 2);
    return builder->GetInputRegisterListOperand(reg_list);
  }
};
271

272 273 274
template <>
class OperandHelper<OperandType::kRegOut> {
 public:
275 276
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
                                    Register reg) {
277 278 279 280
    return builder->GetOutputRegisterOperand(reg);
  }
};

281 282 283
template <>
class OperandHelper<OperandType::kRegOutList> {
 public:
284 285
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
                                    RegisterList reg_list) {
286 287 288 289
    return builder->GetOutputRegisterListOperand(reg_list);
  }
};

290 291 292
template <>
class OperandHelper<OperandType::kRegOutPair> {
 public:
293 294
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
                                    RegisterList reg_list) {
295 296 297 298 299 300 301 302
    DCHECK_EQ(2, reg_list.register_count());
    return builder->GetOutputRegisterListOperand(reg_list);
  }
};

template <>
class OperandHelper<OperandType::kRegOutTriple> {
 public:
303 304
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
                                    RegisterList reg_list) {
305 306 307 308 309
    DCHECK_EQ(3, reg_list.register_count());
    return builder->GetOutputRegisterListOperand(reg_list);
  }
};

310
}  // namespace
311

312 313
template <Bytecode bytecode, AccumulatorUse accumulator_use,
          OperandType... operand_types>
314
class BytecodeNodeBuilder {
315 316
 public:
  template <typename... Operands>
317 318
  V8_INLINE static BytecodeNode Make(BytecodeArrayBuilder* builder,
                                     Operands... operands) {
319 320
    static_assert(sizeof...(Operands) <= Bytecodes::kMaxOperands,
                  "too many operands for bytecode");
321 322 323 324 325
    builder->PrepareToOutputBytecode<bytecode, accumulator_use>();
    // The "OperandHelper<operand_types>::Convert(builder, operands)..." will
    // expand both the OperandType... and Operands... parameter packs e.g. for:
    //   BytecodeNodeBuilder<OperandType::kReg, OperandType::kImm>::Make<
    //       Register, int>(..., Register reg, int immediate)
326
    // the code will expand into:
327 328 329 330 331
    //    OperandHelper<OperandType::kReg>::Convert(builder, reg),
    //    OperandHelper<OperandType::kImm>::Convert(builder, immediate),
    return BytecodeNode::Create<bytecode, accumulator_use, operand_types...>(
        builder->CurrentSourcePosition(bytecode),
        OperandHelper<operand_types>::Convert(builder, operands)...);
332 333 334
  }
};

335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
#define DEFINE_BYTECODE_OUTPUT(name, ...)                             \
  template <typename... Operands>                                     \
  BytecodeNode BytecodeArrayBuilder::Create##name##Node(              \
      Operands... operands) {                                         \
    return BytecodeNodeBuilder<Bytecode::k##name, __VA_ARGS__>::Make( \
        this, operands...);                                           \
  }                                                                   \
                                                                      \
  template <typename... Operands>                                     \
  void BytecodeArrayBuilder::Output##name(Operands... operands) {     \
    BytecodeNode node(Create##name##Node(operands...));               \
    Write(&node);                                                     \
  }                                                                   \
                                                                      \
  template <typename... Operands>                                     \
  void BytecodeArrayBuilder::Output##name(BytecodeLabel* label,       \
                                          Operands... operands) {     \
352
    DCHECK(Bytecodes::IsForwardJump(Bytecode::k##name));              \
353 354
    BytecodeNode node(Create##name##Node(operands...));               \
    WriteJump(&node, label);                                          \
355 356 357
  }
BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT)
#undef DEFINE_BYTECODE_OUTPUT
358

359 360 361 362 363 364
void BytecodeArrayBuilder::OutputJumpLoop(BytecodeLoopHeader* loop_header,
                                          int loop_depth) {
  BytecodeNode node(CreateJumpLoopNode(0, loop_depth));
  WriteJumpLoop(&node, loop_header);
}

365 366
void BytecodeArrayBuilder::OutputSwitchOnSmiNoFeedback(
    BytecodeJumpTable* jump_table) {
367 368 369 370
  BytecodeNode node(CreateSwitchOnSmiNoFeedbackNode(
      jump_table->constant_pool_index(), jump_table->size(),
      jump_table->case_value_base()));
  WriteSwitch(&node, jump_table);
371 372
}

373
BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
374 375
                                                            Register reg,
                                                            int feedback_slot) {
376 377
  switch (op) {
    case Token::Value::ADD:
378
      OutputAdd(reg, feedback_slot);
379 380
      break;
    case Token::Value::SUB:
381
      OutputSub(reg, feedback_slot);
382 383
      break;
    case Token::Value::MUL:
384
      OutputMul(reg, feedback_slot);
385 386
      break;
    case Token::Value::DIV:
387
      OutputDiv(reg, feedback_slot);
388 389
      break;
    case Token::Value::MOD:
390
      OutputMod(reg, feedback_slot);
391
      break;
392 393 394
    case Token::Value::EXP:
      OutputExp(reg, feedback_slot);
      break;
395
    case Token::Value::BIT_OR:
396
      OutputBitwiseOr(reg, feedback_slot);
397 398
      break;
    case Token::Value::BIT_XOR:
399
      OutputBitwiseXor(reg, feedback_slot);
400 401
      break;
    case Token::Value::BIT_AND:
402
      OutputBitwiseAnd(reg, feedback_slot);
403 404
      break;
    case Token::Value::SHL:
405
      OutputShiftLeft(reg, feedback_slot);
406 407
      break;
    case Token::Value::SAR:
408
      OutputShiftRight(reg, feedback_slot);
409 410
      break;
    case Token::Value::SHR:
411
      OutputShiftRightLogical(reg, feedback_slot);
412 413 414 415
      break;
    default:
      UNREACHABLE();
  }
416 417 418
  return *this;
}

419
BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperationSmiLiteral(
420
    Token::Value op, Smi literal, int feedback_slot) {
421 422
  switch (op) {
    case Token::Value::ADD:
423
      OutputAddSmi(literal.value(), feedback_slot);
424 425
      break;
    case Token::Value::SUB:
426
      OutputSubSmi(literal.value(), feedback_slot);
427 428
      break;
    case Token::Value::MUL:
429
      OutputMulSmi(literal.value(), feedback_slot);
430 431
      break;
    case Token::Value::DIV:
432
      OutputDivSmi(literal.value(), feedback_slot);
433 434
      break;
    case Token::Value::MOD:
435
      OutputModSmi(literal.value(), feedback_slot);
436
      break;
437
    case Token::Value::EXP:
438
      OutputExpSmi(literal.value(), feedback_slot);
439
      break;
440
    case Token::Value::BIT_OR:
441
      OutputBitwiseOrSmi(literal.value(), feedback_slot);
442 443
      break;
    case Token::Value::BIT_XOR:
444
      OutputBitwiseXorSmi(literal.value(), feedback_slot);
445 446
      break;
    case Token::Value::BIT_AND:
447
      OutputBitwiseAndSmi(literal.value(), feedback_slot);
448 449
      break;
    case Token::Value::SHL:
450
      OutputShiftLeftSmi(literal.value(), feedback_slot);
451 452
      break;
    case Token::Value::SAR:
453
      OutputShiftRightSmi(literal.value(), feedback_slot);
454 455
      break;
    case Token::Value::SHR:
456
      OutputShiftRightLogicalSmi(literal.value(), feedback_slot);
457 458 459 460 461 462 463
      break;
    default:
      UNREACHABLE();
  }
  return *this;
}

464
BytecodeArrayBuilder& BytecodeArrayBuilder::UnaryOperation(Token::Value op,
465
                                                           int feedback_slot) {
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
  switch (op) {
    case Token::Value::INC:
      OutputInc(feedback_slot);
      break;
    case Token::Value::DEC:
      OutputDec(feedback_slot);
      break;
    case Token::Value::ADD:
      OutputToNumber(feedback_slot);
      break;
    case Token::Value::SUB:
      OutputNegate(feedback_slot);
      break;
    case Token::Value::BIT_NOT:
      OutputBitwiseNot(feedback_slot);
      break;
    default:
      UNREACHABLE();
484
  }
485 486 487
  return *this;
}

488 489 490 491 492 493 494
BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot(ToBooleanMode mode) {
  if (mode == ToBooleanMode::kAlreadyBoolean) {
    OutputLogicalNot();
  } else {
    DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
    OutputToBooleanLogicalNot();
  }
495 496 497 498
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
499
  OutputTypeOf();
500 501 502
  return *this;
}

503 504 505 506 507
BytecodeArrayBuilder& BytecodeArrayBuilder::GetSuperConstructor(Register out) {
  OutputGetSuperConstructor(out);
  return *this;
}

508 509
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
    Token::Value op, Register reg, int feedback_slot) {
510 511
  switch (op) {
    case Token::Value::EQ:
512
      OutputTestEqual(reg, feedback_slot);
513 514
      break;
    case Token::Value::EQ_STRICT:
515
      OutputTestEqualStrict(reg, feedback_slot);
516 517
      break;
    case Token::Value::LT:
518
      OutputTestLessThan(reg, feedback_slot);
519 520
      break;
    case Token::Value::GT:
521
      OutputTestGreaterThan(reg, feedback_slot);
522 523
      break;
    case Token::Value::LTE:
524
      OutputTestLessThanOrEqual(reg, feedback_slot);
525 526
      break;
    case Token::Value::GTE:
527
      OutputTestGreaterThanOrEqual(reg, feedback_slot);
528
      break;
529 530 531
    case Token::Value::INSTANCEOF:
      OutputTestInstanceOf(reg, feedback_slot);
      break;
532
    case Token::Value::IN:
533
      OutputTestIn(reg, feedback_slot);
534 535 536
      break;
    default:
      UNREACHABLE();
537
  }
538 539 540
  return *this;
}

541 542 543 544 545
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareReference(Register reg) {
  OutputTestReferenceEqual(reg);
  return *this;
}

546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndetectable() {
  OutputTestUndetectable();
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndefined() {
  OutputTestUndefined();
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNull() {
  OutputTestNull();
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNil(Token::Value op,
                                                       NilValue nil) {
  if (op == Token::EQ) {
    return CompareUndetectable();
  } else {
    DCHECK_EQ(Token::EQ_STRICT, op);
    if (nil == kUndefinedValue) {
      return CompareUndefined();
    } else {
      DCHECK_EQ(kNullValue, nil);
      return CompareNull();
    }
  }
}

576 577
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareTypeOf(
    TestTypeOfFlags::LiteralFlag literal_flag) {
578
  DCHECK_NE(literal_flag, TestTypeOfFlags::LiteralFlag::kOther);
579 580 581 582
  OutputTestTypeOf(TestTypeOfFlags::Encode(literal_flag));
  return *this;
}

583 584
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry(
    size_t entry) {
585
  OutputLdaConstant(entry);
586 587 588
  return *this;
}

589
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Smi smi) {
590
  int32_t raw_smi = smi.value();
591
  if (raw_smi == 0) {
592
    OutputLdaZero();
593
  } else {
594
    OutputLdaSmi(raw_smi);
595 596 597 598
  }
  return *this;
}

599 600 601 602 603 604
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(double value) {
  size_t entry = GetConstantPoolEntry(value);
  OutputLdaConstant(entry);
  return *this;
}

605 606 607 608 609 610 611 612 613
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
    const AstRawString* raw_string) {
  size_t entry = GetConstantPoolEntry(raw_string);
  OutputLdaConstant(entry);
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(const Scope* scope) {
  size_t entry = GetConstantPoolEntry(scope);
614
  OutputLdaConstant(entry);
615 616 617
  return *this;
}

618 619 620 621 622 623 624 625 626 627 628 629 630
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(AstBigInt bigint) {
  size_t entry = GetConstantPoolEntry(bigint);
  OutputLdaConstant(entry);
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(AstSymbol symbol) {
  size_t entry;
  switch (symbol) {
    case AstSymbol::kHomeObjectSymbol:
      entry = HomeObjectSymbolConstantPoolEntry();
      break;
      // No default case so that we get a warning if AstSymbol changes
631
  }
632 633
  OutputLdaConstant(entry);
  return *this;
634 635
}

636
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
637
  OutputLdaUndefined();
638 639 640 641
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() {
642
  OutputLdaNull();
643 644 645 646
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() {
647
  OutputLdaTheHole();
648 649 650 651
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() {
652
  OutputLdaTrue();
653 654 655 656
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
657
  OutputLdaFalse();
658 659 660
  return *this;
}

661 662 663 664
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadBoolean(bool value) {
  return value ? LoadTrue() : LoadFalse();
}

665
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
666
    Register reg) {
667
  if (register_optimizer_) {
668
    // Defer source info so that if we elide the bytecode transfer, we attach
669
    // the source info to a subsequent bytecode if it exists.
670 671
    SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kLdar));
    register_optimizer_->DoLdar(reg);
672 673 674
  } else {
    OutputLdar(reg);
  }
675 676 677 678
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
679
    Register reg) {
680
  if (register_optimizer_) {
681
    // Defer source info so that if we elide the bytecode transfer, we attach
682
    // the source info to a subsequent bytecode if it exists.
683 684
    SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kStar));
    register_optimizer_->DoStar(reg);
685 686 687
  } else {
    OutputStar(reg);
  }
688 689 690
  return *this;
}

691 692 693
BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
                                                         Register to) {
  DCHECK(from != to);
694
  if (register_optimizer_) {
695
    // Defer source info so that if we elide the bytecode transfer, we attach
696
    // the source info to a subsequent bytecode if it exists.
697 698
    SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kMov));
    register_optimizer_->DoMov(from, to);
699 700 701
  } else {
    OutputMov(from, to);
  }
702 703 704
  return *this;
}

705 706 707
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(const AstRawString* name,
                                                       int feedback_slot,
                                                       TypeofMode typeof_mode) {
708
  size_t name_index = GetConstantPoolEntry(name);
709 710 711 712
  // Ensure that typeof mode is in sync with the IC slot kind.
  DCHECK_EQ(GetTypeofModeFromSlotKind(feedback_vector_spec()->GetKind(
                FeedbackVector::ToSlot(feedback_slot))),
            typeof_mode);
713
  if (typeof_mode == INSIDE_TYPEOF) {
714
    OutputLdaGlobalInsideTypeof(name_index, feedback_slot);
715 716
  } else {
    DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
717
    OutputLdaGlobal(name_index, feedback_slot);
718
  }
719 720 721 722
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
723
    const AstRawString* name, int feedback_slot) {
724
  size_t name_index = GetConstantPoolEntry(name);
725
  OutputStaGlobal(name_index, feedback_slot);
726 727 728
  return *this;
}

729 730 731
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(
    Register context, int slot_index, int depth,
    ContextSlotMutability mutability) {
732
  if (context.is_current_context() && depth == 0) {
733 734 735 736 737 738 739 740
    if (mutability == kImmutableSlot) {
      OutputLdaImmutableCurrentContextSlot(slot_index);
    } else {
      DCHECK_EQ(kMutableSlot, mutability);
      OutputLdaCurrentContextSlot(slot_index);
    }
  } else if (mutability == kImmutableSlot) {
    OutputLdaImmutableContextSlot(context, slot_index, depth);
741
  } else {
742
    DCHECK_EQ(mutability, kMutableSlot);
743 744
    OutputLdaContextSlot(context, slot_index, depth);
  }
745 746 747
  return *this;
}

748
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
749 750
                                                             int slot_index,
                                                             int depth) {
751 752 753 754 755
  if (context.is_current_context() && depth == 0) {
    OutputStaCurrentContextSlot(slot_index);
  } else {
    OutputStaContextSlot(context, slot_index, depth);
  }
756 757 758
  return *this;
}

759
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
760
    const AstRawString* name, TypeofMode typeof_mode) {
761
  size_t name_index = GetConstantPoolEntry(name);
762
  if (typeof_mode == INSIDE_TYPEOF) {
763
    OutputLdaLookupSlotInsideTypeof(name_index);
764 765
  } else {
    DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
766
    OutputLdaLookupSlot(name_index);
767
  }
768 769 770
  return *this;
}

771
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot(
772
    const AstRawString* name, TypeofMode typeof_mode, int slot_index,
773 774
    int depth) {
  size_t name_index = GetConstantPoolEntry(name);
775 776 777 778 779 780
  if (typeof_mode == INSIDE_TYPEOF) {
    OutputLdaLookupContextSlotInsideTypeof(name_index, slot_index, depth);
  } else {
    DCHECK(typeof_mode == NOT_INSIDE_TYPEOF);
    OutputLdaLookupContextSlot(name_index, slot_index, depth);
  }
781 782 783
  return *this;
}

784
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot(
785
    const AstRawString* name, TypeofMode typeof_mode, int feedback_slot,
786 787
    int depth) {
  size_t name_index = GetConstantPoolEntry(name);
788 789 790 791 792 793
  if (typeof_mode == INSIDE_TYPEOF) {
    OutputLdaLookupGlobalSlotInsideTypeof(name_index, feedback_slot, depth);
  } else {
    DCHECK(typeof_mode == NOT_INSIDE_TYPEOF);
    OutputLdaLookupGlobalSlot(name_index, feedback_slot, depth);
  }
794 795 796
  return *this;
}

797
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot(
798 799
    const AstRawString* name, LanguageMode language_mode,
    LookupHoistingMode lookup_hoisting_mode) {
800
  size_t name_index = GetConstantPoolEntry(name);
801 802 803
  uint8_t flags =
      StoreLookupSlotFlags::Encode(language_mode, lookup_hoisting_mode);
  OutputStaLookupSlot(name_index, flags);
804 805 806
  return *this;
}

807
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
808
    Register object, const AstRawString* name, int feedback_slot) {
809
  size_t name_index = GetConstantPoolEntry(name);
810
  OutputLdaNamedProperty(object, name_index, feedback_slot);
811 812 813
  return *this;
}

814 815 816 817 818 819 820
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedPropertyNoFeedback(
    Register object, const AstRawString* name) {
  size_t name_index = GetConstantPoolEntry(name);
  OutputLdaNamedPropertyNoFeedback(object, name_index);
  return *this;
}

821
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
822
    Register object, int feedback_slot) {
823
  OutputLdaKeyedProperty(object, feedback_slot);
824 825 826
  return *this;
}

827 828 829 830 831 832 833 834 835 836
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadIteratorProperty(
    Register object, int feedback_slot) {
  size_t name_index = IteratorSymbolConstantPoolEntry();
  OutputLdaNamedProperty(object, name_index, feedback_slot);
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::GetIterator(
    Register object, int load_feedback_slot, int call_feedback_slot) {
  OutputGetIterator(object, load_feedback_slot, call_feedback_slot);
837 838 839
  return *this;
}

840 841 842 843 844 845 846
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAsyncIteratorProperty(
    Register object, int feedback_slot) {
  size_t name_index = AsyncIteratorSymbolConstantPoolEntry();
  OutputLdaNamedProperty(object, name_index, feedback_slot);
  return *this;
}

847
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreDataPropertyInLiteral(
848 849 850
    Register object, Register name, DataPropertyInLiteralFlags flags,
    int feedback_slot) {
  OutputStaDataPropertyInLiteral(object, name, flags, feedback_slot);
851 852 853
  return *this;
}

854 855
BytecodeArrayBuilder& BytecodeArrayBuilder::CollectTypeProfile(int position) {
  OutputCollectTypeProfile(position);
856 857 858
  return *this;
}

859
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
860
    Register object, size_t name_index, int feedback_slot,
861
    LanguageMode language_mode) {
862 863 864 865
  // Ensure that language mode is in sync with the IC slot kind.
  DCHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(
                FeedbackVector::ToSlot(feedback_slot))),
            language_mode);
866
  OutputStaNamedProperty(object, name_index, feedback_slot);
867 868 869
  return *this;
}

870 871 872 873 874 875 876
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
    Register object, const AstRawString* name, int feedback_slot,
    LanguageMode language_mode) {
  size_t name_index = GetConstantPoolEntry(name);
  return StoreNamedProperty(object, name_index, feedback_slot, language_mode);
}

877 878 879 880 881 882 883 884
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedPropertyNoFeedback(
    Register object, const AstRawString* name, LanguageMode language_mode) {
  size_t name_index = GetConstantPoolEntry(name);
  OutputStaNamedPropertyNoFeedback(object, name_index,
                                   static_cast<uint8_t>(language_mode));
  return *this;
}

885 886 887
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedOwnProperty(
    Register object, const AstRawString* name, int feedback_slot) {
  size_t name_index = GetConstantPoolEntry(name);
888 889 890 891
  // Ensure that the store operation is in sync with the IC slot kind.
  DCHECK_EQ(
      FeedbackSlotKind::kStoreOwnNamed,
      feedback_vector_spec()->GetKind(FeedbackVector::ToSlot(feedback_slot)));
892 893 894 895
  OutputStaNamedOwnProperty(object, name_index, feedback_slot);
  return *this;
}

896 897 898
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty(
    Register object, Register key, int feedback_slot,
    LanguageMode language_mode) {
899 900 901 902
  // Ensure that language mode is in sync with the IC slot kind.
  DCHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(
                FeedbackVector::ToSlot(feedback_slot))),
            language_mode);
903
  OutputStaKeyedProperty(object, key, feedback_slot);
904 905 906
  return *this;
}

907 908 909 910 911 912
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreInArrayLiteral(
    Register array, Register index, int feedback_slot) {
  OutputStaInArrayLiteral(array, index, feedback_slot);
  return *this;
}

913 914 915 916 917 918
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreHomeObjectProperty(
    Register object, int feedback_slot, LanguageMode language_mode) {
  size_t name_index = HomeObjectSymbolConstantPoolEntry();
  return StoreNamedProperty(object, name_index, feedback_slot, language_mode);
}

919 920 921 922 923 924 925 926 927 928 929 930 931 932
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreClassFieldsInitializer(
    Register constructor, int feedback_slot) {
  size_t name_index = ClassFieldsSymbolConstantPoolEntry();
  return StoreNamedProperty(constructor, name_index, feedback_slot,
                            LanguageMode::kStrict);
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadClassFieldsInitializer(
    Register constructor, int feedback_slot) {
  size_t name_index = ClassFieldsSymbolConstantPoolEntry();
  OutputLdaNamedProperty(constructor, name_index, feedback_slot);
  return *this;
}

933 934 935
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(
    size_t shared_function_info_entry, int slot, int flags) {
  OutputCreateClosure(shared_function_info_entry, slot, flags);
936 937 938
  return *this;
}

939
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateBlockContext(
940 941
    const Scope* scope) {
  size_t entry = GetConstantPoolEntry(scope);
942
  OutputCreateBlockContext(entry);
943 944 945
  return *this;
}

946
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateCatchContext(
947
    Register exception, const Scope* scope) {
948
  size_t scope_index = GetConstantPoolEntry(scope);
949
  OutputCreateCatchContext(exception, scope_index);
950 951 952
  return *this;
}

953 954 955 956
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(
    const Scope* scope, int slots) {
  size_t scope_index = GetConstantPoolEntry(scope);
  OutputCreateFunctionContext(scope_index, slots);
957 958 959
  return *this;
}

960 961 962 963
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEvalContext(
    const Scope* scope, int slots) {
  size_t scope_index = GetConstantPoolEntry(scope);
  OutputCreateEvalContext(scope_index, slots);
964 965 966
  return *this;
}

967
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext(
968 969 970
    Register object, const Scope* scope) {
  size_t scope_index = GetConstantPoolEntry(scope);
  OutputCreateWithContext(object, scope_index);
971 972 973
  return *this;
}

974 975
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
    CreateArgumentsType type) {
976 977
  switch (type) {
    case CreateArgumentsType::kMappedArguments:
978
      OutputCreateMappedArguments();
979 980
      break;
    case CreateArgumentsType::kUnmappedArguments:
981
      OutputCreateUnmappedArguments();
982 983
      break;
    case CreateArgumentsType::kRestParameter:
984
      OutputCreateRestParameter();
985 986 987 988
      break;
    default:
      UNREACHABLE();
  }
989 990 991
  return *this;
}

992
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
993
    const AstRawString* pattern, int literal_index, int flags) {
994
  size_t pattern_entry = GetConstantPoolEntry(pattern);
995
  OutputCreateRegExpLiteral(pattern_entry, literal_index, flags);
996 997 998
  return *this;
}

999 1000 1001 1002 1003 1004
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyArrayLiteral(
    int literal_index) {
  OutputCreateEmptyArrayLiteral(literal_index);
  return *this;
}

1005
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
1006
    size_t constant_elements_entry, int literal_index, int flags) {
1007
  OutputCreateArrayLiteral(constant_elements_entry, literal_index, flags);
1008 1009 1010
  return *this;
}

1011 1012 1013 1014 1015
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayFromIterable() {
  OutputCreateArrayFromIterable();
  return *this;
}

1016
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
1017 1018
    size_t constant_properties_entry, int literal_index, int flags) {
  OutputCreateObjectLiteral(constant_properties_entry, literal_index, flags);
1019 1020 1021
  return *this;
}

1022 1023
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyObjectLiteral() {
  OutputCreateEmptyObjectLiteral();
1024 1025 1026
  return *this;
}

1027 1028 1029 1030 1031 1032 1033
BytecodeArrayBuilder& BytecodeArrayBuilder::CloneObject(Register source,
                                                        int flags,
                                                        int feedback_slot) {
  OutputCloneObject(source, flags, feedback_slot);
  return *this;
}

1034
BytecodeArrayBuilder& BytecodeArrayBuilder::GetTemplateObject(
1035 1036
    size_t template_object_description_entry, int feedback_slot) {
  OutputGetTemplateObject(template_object_description_entry, feedback_slot);
1037 1038 1039
  return *this;
}

1040
BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) {
1041
  OutputPushContext(context);
1042 1043 1044 1045
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) {
1046
  OutputPopContext(context);
1047 1048 1049
  return *this;
}

1050
BytecodeArrayBuilder& BytecodeArrayBuilder::ToObject(Register out) {
1051
  OutputToObject(out);
1052 1053 1054
  return *this;
}

1055
BytecodeArrayBuilder& BytecodeArrayBuilder::ToName(Register out) {
1056
  OutputToName(out);
1057 1058 1059
  return *this;
}

1060 1061 1062 1063 1064
BytecodeArrayBuilder& BytecodeArrayBuilder::ToString() {
  OutputToString();
  return *this;
}

1065 1066
BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumber(int feedback_slot) {
  OutputToNumber(feedback_slot);
1067 1068 1069
  return *this;
}

1070 1071 1072 1073 1074
BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumeric(int feedback_slot) {
  OutputToNumeric(feedback_slot);
  return *this;
}

1075
BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
1076 1077 1078 1079
  // Don't generate code for a label which hasn't had a corresponding forward
  // jump generated already. For backwards jumps, use BindLoopHeader.
  if (!label->has_referrer_jump()) return *this;

1080 1081 1082
  // Flush the register optimizer when binding a label to ensure all
  // expected registers are valid when jumping to this label.
  if (register_optimizer_) register_optimizer_->Flush();
1083
  bytecode_array_writer_.BindLabel(label);
1084 1085 1086
  return *this;
}

1087 1088 1089 1090 1091 1092
BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(
    BytecodeLoopHeader* loop_header) {
  // Flush the register optimizer when starting a loop to ensure all expected
  // registers are valid when jumping to the loop header.
  if (register_optimizer_) register_optimizer_->Flush();
  bytecode_array_writer_.BindLoopHeader(loop_header);
1093
  return *this;
1094 1095
}

1096 1097 1098 1099 1100
BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeJumpTable* jump_table,
                                                 int case_value) {
  // Flush the register optimizer when binding a jump table entry to ensure
  // all expected registers are valid when jumping to this location.
  if (register_optimizer_) register_optimizer_->Flush();
1101
  bytecode_array_writer_.BindJumpTableEntry(jump_table, case_value);
1102 1103 1104
  return *this;
}

1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131
BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(
    int handler_id, HandlerTable::CatchPrediction catch_prediction) {
  // The handler starts a new basic block, and any reasonable try block won't
  // let control fall through into it.
  DCHECK_IMPLIES(register_optimizer_,
                 register_optimizer_->EnsureAllRegistersAreFlushed());
  bytecode_array_writer_.BindHandlerTarget(handler_table_builder(), handler_id);
  handler_table_builder()->SetPrediction(handler_id, catch_prediction);
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryBegin(int handler_id,
                                                         Register context) {
  // Flush registers to make sure everything visible to the handler is
  // materialized.
  if (register_optimizer_) register_optimizer_->Flush();
  bytecode_array_writer_.BindTryRegionStart(handler_table_builder(),
                                            handler_id);
  handler_table_builder()->SetContextRegister(handler_id, context);
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) {
  bytecode_array_writer_.BindTryRegionEnd(handler_table_builder(), handler_id);
  return *this;
}

1132
BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
1133
  DCHECK(!label->is_bound());
1134
  OutputJump(label, 0);
1135
  return *this;
1136 1137
}

1138 1139
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(ToBooleanMode mode,
                                                       BytecodeLabel* label) {
1140
  DCHECK(!label->is_bound());
1141 1142 1143 1144 1145 1146
  if (mode == ToBooleanMode::kAlreadyBoolean) {
    OutputJumpIfTrue(label, 0);
  } else {
    DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
    OutputJumpIfToBooleanTrue(label, 0);
  }
1147
  return *this;
1148 1149
}

1150 1151
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(ToBooleanMode mode,
                                                        BytecodeLabel* label) {
1152
  DCHECK(!label->is_bound());
1153 1154 1155 1156 1157 1158
  if (mode == ToBooleanMode::kAlreadyBoolean) {
    OutputJumpIfFalse(label, 0);
  } else {
    DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
    OutputJumpIfToBooleanFalse(label, 0);
  }
1159
  return *this;
1160 1161
}

1162
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
1163
  DCHECK(!label->is_bound());
1164
  OutputJumpIfNull(label, 0);
1165
  return *this;
1166 1167
}

1168 1169 1170 1171 1172 1173 1174
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNull(
    BytecodeLabel* label) {
  DCHECK(!label->is_bound());
  OutputJumpIfNotNull(label, 0);
  return *this;
}

1175 1176
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
    BytecodeLabel* label) {
1177
  DCHECK(!label->is_bound());
1178
  OutputJumpIfUndefined(label, 0);
1179
  return *this;
1180 1181
}

1182 1183 1184 1185 1186 1187 1188
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefinedOrNull(
    BytecodeLabel* label) {
  DCHECK(!label->is_bound());
  OutputJumpIfUndefinedOrNull(label, 0);
  return *this;
}

1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotUndefined(
    BytecodeLabel* label) {
  DCHECK(!label->is_bound());
  OutputJumpIfNotUndefined(label, 0);
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNil(BytecodeLabel* label,
                                                      Token::Value op,
                                                      NilValue nil) {
  if (op == Token::EQ) {
    // TODO(rmcilroy): Implement JumpIfUndetectable.
1201 1202
    return CompareUndetectable().JumpIfTrue(ToBooleanMode::kAlreadyBoolean,
                                            label);
1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218
  } else {
    DCHECK_EQ(Token::EQ_STRICT, op);
    if (nil == kUndefinedValue) {
      return JumpIfUndefined(label);
    } else {
      DCHECK_EQ(kNullValue, nil);
      return JumpIfNull(label);
    }
  }
}

BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNil(BytecodeLabel* label,
                                                         Token::Value op,
                                                         NilValue nil) {
  if (op == Token::EQ) {
    // TODO(rmcilroy): Implement JumpIfUndetectable.
1219 1220
    return CompareUndetectable().JumpIfFalse(ToBooleanMode::kAlreadyBoolean,
                                             label);
1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231
  } else {
    DCHECK_EQ(Token::EQ_STRICT, op);
    if (nil == kUndefinedValue) {
      return JumpIfNotUndefined(label);
    } else {
      DCHECK_EQ(kNullValue, nil);
      return JumpIfNotNull(label);
    }
  }
}

1232 1233
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfJSReceiver(
    BytecodeLabel* label) {
1234
  DCHECK(!label->is_bound());
1235 1236 1237 1238
  OutputJumpIfJSReceiver(label, 0);
  return *this;
}

1239 1240 1241
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(
    BytecodeLoopHeader* loop_header, int loop_depth) {
  OutputJumpLoop(loop_header, loop_depth);
1242
  return *this;
1243 1244
}

1245 1246 1247 1248 1249 1250
BytecodeArrayBuilder& BytecodeArrayBuilder::SwitchOnSmiNoFeedback(
    BytecodeJumpTable* jump_table) {
  OutputSwitchOnSmiNoFeedback(jump_table);
  return *this;
}

1251
BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) {
yangguo's avatar
yangguo committed
1252
  if (position != kNoSourcePosition) {
1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263
    // We need to attach a non-breakable source position to a stack
    // check, so we simply add it as expression position. There can be
    // a prior statement position from constructs like:
    //
    //    do var x;  while (false);
    //
    // A Nop could be inserted for empty statements, but since no code
    // is associated with these positions, instead we force the stack
    // check's expression position which eliminates the empty
    // statement's position.
    latest_source_info_.ForceExpressionPosition(position);
1264
  }
1265
  OutputStackCheck();
1266
  return *this;
1267 1268
}

1269 1270 1271 1272 1273
BytecodeArrayBuilder& BytecodeArrayBuilder::SetPendingMessage() {
  OutputSetPendingMessage();
  return *this;
}

1274
BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
1275
  OutputThrow();
1276 1277 1278
  return *this;
}

1279
BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() {
1280
  OutputReThrow();
1281 1282 1283
  return *this;
}

1284
BytecodeArrayBuilder& BytecodeArrayBuilder::Abort(AbortReason reason) {
1285
  DCHECK_LT(reason, AbortReason::kLastErrorMessage);
1286 1287
  DCHECK_GE(reason, AbortReason::kNoReason);
  OutputAbort(static_cast<int>(reason));
1288 1289 1290
  return *this;
}

1291
BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
1292
  OutputReturn();
1293 1294 1295
  return *this;
}

1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312
BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowReferenceErrorIfHole(
    const AstRawString* name) {
  size_t entry = GetConstantPoolEntry(name);
  OutputThrowReferenceErrorIfHole(entry);
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowSuperNotCalledIfHole() {
  OutputThrowSuperNotCalledIfHole();
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowSuperAlreadyCalledIfNotHole() {
  OutputThrowSuperAlreadyCalledIfNotHole();
  return *this;
}

1313
BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() {
1314
  OutputDebugger();
1315 1316
  return *this;
}
1317

1318 1319 1320 1321 1322 1323
BytecodeArrayBuilder& BytecodeArrayBuilder::IncBlockCounter(
    int coverage_array_slot) {
  OutputIncBlockCounter(coverage_array_slot);
  return *this;
}

1324 1325 1326 1327 1328
BytecodeArrayBuilder& BytecodeArrayBuilder::ForInEnumerate(Register receiver) {
  OutputForInEnumerate(receiver);
  return *this;
}

1329
BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare(
1330
    RegisterList cache_info_triple, int feedback_slot) {
1331
  DCHECK_EQ(3, cache_info_triple.register_count());
1332
  OutputForInPrepare(cache_info_triple, feedback_slot);
1333 1334 1335
  return *this;
}

1336 1337
BytecodeArrayBuilder& BytecodeArrayBuilder::ForInContinue(
    Register index, Register cache_length) {
1338
  OutputForInContinue(index, cache_length);
1339 1340 1341
  return *this;
}

1342
BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext(
1343
    Register receiver, Register index, RegisterList cache_type_array_pair,
1344
    int feedback_slot) {
1345
  DCHECK_EQ(2, cache_type_array_pair.register_count());
1346
  OutputForInNext(receiver, index, cache_type_array_pair, feedback_slot);
1347 1348 1349
  return *this;
}

1350
BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
1351
  OutputForInStep(index);
1352 1353 1354
  return *this;
}

1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreModuleVariable(int cell_index,
                                                                int depth) {
  OutputStaModuleVariable(cell_index, depth);
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadModuleVariable(int cell_index,
                                                               int depth) {
  OutputLdaModuleVariable(cell_index, depth);
  return *this;
}

1367
BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator(
1368 1369 1370
    Register generator, RegisterList registers, int suspend_id) {
  OutputSuspendGenerator(generator, registers, registers.register_count(),
                         suspend_id);
1371 1372 1373
  return *this;
}

1374 1375 1376 1377 1378 1379
BytecodeArrayBuilder& BytecodeArrayBuilder::SwitchOnGeneratorState(
    Register generator, BytecodeJumpTable* jump_table) {
  DCHECK_EQ(jump_table->case_value_base(), 0);
  BytecodeNode node(CreateSwitchOnGeneratorStateNode(
      generator, jump_table->constant_pool_index(), jump_table->size()));
  WriteSwitch(&node, jump_table);
1380 1381 1382
  return *this;
}

1383
BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator(
1384 1385
    Register generator, RegisterList registers) {
  OutputResumeGenerator(generator, registers, registers.register_count());
1386 1387 1388
  return *this;
}

1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411
BytecodeArrayBuilder& BytecodeArrayBuilder::CallProperty(Register callable,
                                                         RegisterList args,
                                                         int feedback_slot) {
  if (args.register_count() == 1) {
    OutputCallProperty0(callable, args[0], feedback_slot);
  } else if (args.register_count() == 2) {
    OutputCallProperty1(callable, args[0], args[1], feedback_slot);
  } else if (args.register_count() == 3) {
    OutputCallProperty2(callable, args[0], args[1], args[2], feedback_slot);
  } else {
    OutputCallProperty(callable, args, args.register_count(), feedback_slot);
  }
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::CallUndefinedReceiver(
    Register callable, RegisterList args, int feedback_slot) {
  if (args.register_count() == 0) {
    OutputCallUndefinedReceiver0(callable, feedback_slot);
  } else if (args.register_count() == 1) {
    OutputCallUndefinedReceiver1(callable, args[0], feedback_slot);
  } else if (args.register_count() == 2) {
    OutputCallUndefinedReceiver2(callable, args[0], args[1], feedback_slot);
1412
  } else {
1413 1414
    OutputCallUndefinedReceiver(callable, args, args.register_count(),
                                feedback_slot);
1415
  }
1416 1417 1418
  return *this;
}

1419 1420 1421 1422 1423 1424 1425
BytecodeArrayBuilder& BytecodeArrayBuilder::CallAnyReceiver(Register callable,
                                                            RegisterList args,
                                                            int feedback_slot) {
  OutputCallAnyReceiver(callable, args, args.register_count(), feedback_slot);
  return *this;
}

1426 1427 1428 1429 1430 1431
BytecodeArrayBuilder& BytecodeArrayBuilder::CallNoFeedback(Register callable,
                                                           RegisterList args) {
  OutputCallNoFeedback(callable, args, args.register_count());
  return *this;
}

1432
BytecodeArrayBuilder& BytecodeArrayBuilder::CallWithSpread(Register callable,
1433 1434 1435
                                                           RegisterList args,
                                                           int feedback_slot) {
  OutputCallWithSpread(callable, args, args.register_count(), feedback_slot);
1436 1437 1438
  return *this;
}

1439 1440 1441 1442 1443 1444 1445 1446
BytecodeArrayBuilder& BytecodeArrayBuilder::Construct(Register constructor,
                                                      RegisterList args,
                                                      int feedback_slot_id) {
  OutputConstruct(constructor, args, args.register_count(), feedback_slot_id);
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::ConstructWithSpread(
1447 1448 1449
    Register constructor, RegisterList args, int feedback_slot_id) {
  OutputConstructWithSpread(constructor, args, args.register_count(),
                            feedback_slot_id);
1450 1451 1452
  return *this;
}

1453
BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1454
    Runtime::FunctionId function_id, RegisterList args) {
1455
  DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size);
1456 1457
  DCHECK_LE(Bytecodes::SizeForUnsignedOperand(function_id),
            OperandSize::kShort);
1458
  if (IntrinsicsHelper::IsSupported(function_id)) {
1459 1460 1461 1462
    IntrinsicsHelper::IntrinsicId intrinsic_id =
        IntrinsicsHelper::FromRuntimeId(function_id);
    OutputInvokeIntrinsic(static_cast<int>(intrinsic_id), args,
                          args.register_count());
1463
  } else {
1464 1465
    OutputCallRuntime(static_cast<int>(function_id), args,
                      args.register_count());
1466
  }
1467 1468 1469
  return *this;
}

1470 1471
BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
    Runtime::FunctionId function_id, Register arg) {
1472
  return CallRuntime(function_id, RegisterList(arg));
1473 1474 1475 1476 1477 1478 1479
}

BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
    Runtime::FunctionId function_id) {
  return CallRuntime(function_id, RegisterList());
}

1480
BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1481 1482
    Runtime::FunctionId function_id, RegisterList args,
    RegisterList return_pair) {
1483
  DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size);
1484 1485
  DCHECK_LE(Bytecodes::SizeForUnsignedOperand(function_id),
            OperandSize::kShort);
1486
  DCHECK_EQ(2, return_pair.register_count());
1487 1488
  OutputCallRuntimeForPair(static_cast<uint16_t>(function_id), args,
                           args.register_count(), return_pair);
1489 1490 1491
  return *this;
}

1492
BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1493
    Runtime::FunctionId function_id, Register arg, RegisterList return_pair) {
1494
  return CallRuntimeForPair(function_id, RegisterList(arg), return_pair);
1495 1496 1497 1498
}

BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index,
                                                          RegisterList args) {
1499
  OutputCallJSRuntime(context_index, args, args.register_count());
1500 1501 1502
  return *this;
}

1503 1504
BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object,
                                                   LanguageMode language_mode) {
1505
  if (language_mode == LanguageMode::kSloppy) {
1506
    OutputDeletePropertySloppy(object);
1507
  } else {
1508
    DCHECK_EQ(language_mode, LanguageMode::kStrict);
1509
    OutputDeletePropertyStrict(object);
1510
  }
1511 1512 1513
  return *this;
}

1514 1515 1516 1517 1518
size_t BytecodeArrayBuilder::GetConstantPoolEntry(
    const AstRawString* raw_string) {
  return constant_array_builder()->Insert(raw_string);
}

1519 1520
size_t BytecodeArrayBuilder::GetConstantPoolEntry(AstBigInt bigint) {
  return constant_array_builder()->Insert(bigint);
1521 1522
}

1523 1524 1525 1526
size_t BytecodeArrayBuilder::GetConstantPoolEntry(const Scope* scope) {
  return constant_array_builder()->Insert(scope);
}

1527 1528 1529 1530
size_t BytecodeArrayBuilder::GetConstantPoolEntry(double number) {
  return constant_array_builder()->Insert(number);
}

1531 1532 1533 1534 1535 1536 1537
#define ENTRY_GETTER(NAME, ...)                            \
  size_t BytecodeArrayBuilder::NAME##ConstantPoolEntry() { \
    return constant_array_builder()->Insert##NAME();       \
  }
SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)
#undef ENTRY_GETTER

1538 1539 1540 1541 1542 1543 1544 1545 1546 1547
BytecodeJumpTable* BytecodeArrayBuilder::AllocateJumpTable(
    int size, int case_value_base) {
  DCHECK_GT(size, 0);

  size_t constant_pool_index = constant_array_builder()->InsertJumpTable(size);

  return new (zone())
      BytecodeJumpTable(constant_pool_index, size, case_value_base, zone());
}

1548 1549
size_t BytecodeArrayBuilder::AllocateDeferredConstantPoolEntry() {
  return constant_array_builder()->InsertDeferred();
1550 1551
}

1552 1553 1554
void BytecodeArrayBuilder::SetDeferredConstantPoolEntry(size_t entry,
                                                        Handle<Object> object) {
  constant_array_builder()->SetDeferredAt(entry, object);
1555 1556
}

1557
bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const {
1558 1559 1560 1561
  if (!reg.is_valid()) {
    return false;
  }

1562
  if (reg.is_current_context() || reg.is_function_closure()) {
1563 1564
    return true;
  } else if (reg.is_parameter()) {
1565 1566
    int parameter_index = reg.ToParameterIndex(parameter_count());
    return parameter_index >= 0 && parameter_index < parameter_count();
1567 1568
  } else if (reg.index() < fixed_register_count()) {
    return true;
1569
  } else {
1570
    return register_allocator()->RegisterIsLive(reg);
1571 1572 1573
  }
}

1574 1575 1576 1577 1578 1579 1580
bool BytecodeArrayBuilder::RegisterListIsValid(RegisterList reg_list) const {
  if (reg_list.register_count() == 0) {
    return reg_list.first_register() == Register(0);
  } else {
    int first_reg_index = reg_list.first_register().index();
    for (int i = 0; i < reg_list.register_count(); i++) {
      if (!RegisterIsValid(Register(first_reg_index + i))) {
1581 1582 1583
        return false;
      }
    }
1584
    return true;
1585
  }
1586 1587
}

1588
template <Bytecode bytecode, AccumulatorUse accumulator_use>
1589 1590 1591
void BytecodeArrayBuilder::PrepareToOutputBytecode() {
  if (register_optimizer_)
    register_optimizer_->PrepareForBytecode<bytecode, accumulator_use>();
1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612
}

uint32_t BytecodeArrayBuilder::GetInputRegisterOperand(Register reg) {
  DCHECK(RegisterIsValid(reg));
  if (register_optimizer_) reg = register_optimizer_->GetInputRegister(reg);
  return static_cast<uint32_t>(reg.ToOperand());
}

uint32_t BytecodeArrayBuilder::GetOutputRegisterOperand(Register reg) {
  DCHECK(RegisterIsValid(reg));
  if (register_optimizer_) register_optimizer_->PrepareOutputRegister(reg);
  return static_cast<uint32_t>(reg.ToOperand());
}

uint32_t BytecodeArrayBuilder::GetInputRegisterListOperand(
    RegisterList reg_list) {
  DCHECK(RegisterListIsValid(reg_list));
  if (register_optimizer_)
    reg_list = register_optimizer_->GetInputRegisterList(reg_list);
  return static_cast<uint32_t>(reg_list.first_register().ToOperand());
}
1613

1614 1615 1616 1617 1618 1619
uint32_t BytecodeArrayBuilder::GetOutputRegisterListOperand(
    RegisterList reg_list) {
  DCHECK(RegisterListIsValid(reg_list));
  if (register_optimizer_)
    register_optimizer_->PrepareOutputRegisterList(reg_list);
  return static_cast<uint32_t>(reg_list.first_register().ToOperand());
1620 1621
}

1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632
std::ostream& operator<<(std::ostream& os,
                         const BytecodeArrayBuilder::ToBooleanMode& mode) {
  switch (mode) {
    case BytecodeArrayBuilder::ToBooleanMode::kAlreadyBoolean:
      return os << "AlreadyBoolean";
    case BytecodeArrayBuilder::ToBooleanMode::kConvertToBoolean:
      return os << "ConvertToBoolean";
  }
  UNREACHABLE();
}

1633 1634 1635
}  // namespace interpreter
}  // namespace internal
}  // namespace v8