bytecode-array-builder.cc 52.4 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

yangguo's avatar
yangguo committed
7
#include "src/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-inl.h"
16
#include "src/objects/smi.h"
17 18 19 20 21

namespace v8 {
namespace internal {
namespace interpreter {

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

  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_;
};

41
BytecodeArrayBuilder::BytecodeArrayBuilder(
42
    Zone* zone, int parameter_count, int locals_count,
43
    FeedbackVectorSpec* feedback_vector_spec,
44
    SourcePositionTableBuilder::RecordingMode source_position_mode)
45
    : zone_(zone),
46
      feedback_vector_spec_(feedback_vector_spec),
47
      bytecode_generated_(false),
48
      constant_array_builder_(zone),
49
      handler_table_builder_(zone),
50
      return_seen_in_block_(false),
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(return_seen_in_block_);
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 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
}

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;
118 119
}

120 121 122 123 124
void BytecodeArrayBuilder::SetDeferredSourceInfo(
    BytecodeSourceInfo source_info) {
  if (!source_info.is_valid()) return;
  deferred_source_info_ = source_info;
}
125

126 127 128 129
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_);
130 131 132 133 134
  } 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);
135
  }
136
  deferred_source_info_.set_invalid();
137 138
}

139 140 141 142 143 144 145 146 147 148 149 150 151 152
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);
}

void BytecodeArrayBuilder::WriteSwitch(BytecodeNode* node,
                                       BytecodeJumpTable* jump_table) {
  AttachOrEmitDeferredSourceInfo(node);
  bytecode_array_writer_.WriteSwitch(node, jump_table);
153 154
}

155
void BytecodeArrayBuilder::OutputLdarRaw(Register reg) {
156 157 158
  uint32_t operand = static_cast<uint32_t>(reg.ToOperand());
  BytecodeNode node(BytecodeNode::Ldar(BytecodeSourceInfo(), operand));
  Write(&node);
159 160 161
}

void BytecodeArrayBuilder::OutputStarRaw(Register reg) {
162 163 164
  uint32_t operand = static_cast<uint32_t>(reg.ToOperand());
  BytecodeNode node(BytecodeNode::Star(BytecodeSourceInfo(), operand));
  Write(&node);
165 166 167
}

void BytecodeArrayBuilder::OutputMovRaw(Register src, Register dest) {
168 169 170 171 172
  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);
173 174
}

175
namespace {
176

177 178 179
template <OperandTypeInfo type_info>
class UnsignedOperandHelper {
 public:
180 181
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
                                    size_t value) {
182 183 184
    DCHECK(IsValid(value));
    return static_cast<uint32_t>(value);
  }
185

186
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder, int value) {
187 188 189
    DCHECK_GE(value, 0);
    return Convert(builder, static_cast<size_t>(value));
  }
190

191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
 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> {};
213 214
UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
215 216 217 218 219
#undef DEFINE_UNSIGNED_OPERAND_HELPER

template <>
class OperandHelper<OperandType::kImm> {
 public:
220
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder, int value) {
221 222 223
    return static_cast<uint32_t>(value);
  }
};
224

225 226 227
template <>
class OperandHelper<OperandType::kReg> {
 public:
228 229
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
                                    Register reg) {
230 231 232 233 234 235 236
    return builder->GetInputRegisterOperand(reg);
  }
};

template <>
class OperandHelper<OperandType::kRegList> {
 public:
237 238
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
                                    RegisterList reg_list) {
239 240 241 242 243 244 245
    return builder->GetInputRegisterListOperand(reg_list);
  }
};

template <>
class OperandHelper<OperandType::kRegPair> {
 public:
246 247
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
                                    RegisterList reg_list) {
248 249 250 251
    DCHECK_EQ(reg_list.register_count(), 2);
    return builder->GetInputRegisterListOperand(reg_list);
  }
};
252

253 254 255
template <>
class OperandHelper<OperandType::kRegOut> {
 public:
256 257
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
                                    Register reg) {
258 259 260 261
    return builder->GetOutputRegisterOperand(reg);
  }
};

262 263 264
template <>
class OperandHelper<OperandType::kRegOutList> {
 public:
265 266
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
                                    RegisterList reg_list) {
267 268 269 270
    return builder->GetOutputRegisterListOperand(reg_list);
  }
};

271 272 273
template <>
class OperandHelper<OperandType::kRegOutPair> {
 public:
274 275
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
                                    RegisterList reg_list) {
276 277 278 279 280 281 282 283
    DCHECK_EQ(2, reg_list.register_count());
    return builder->GetOutputRegisterListOperand(reg_list);
  }
};

template <>
class OperandHelper<OperandType::kRegOutTriple> {
 public:
284 285
  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
                                    RegisterList reg_list) {
286 287 288 289 290
    DCHECK_EQ(3, reg_list.register_count());
    return builder->GetOutputRegisterListOperand(reg_list);
  }
};

291
}  // namespace
292

293 294
template <Bytecode bytecode, AccumulatorUse accumulator_use,
          OperandType... operand_types>
295
class BytecodeNodeBuilder {
296 297
 public:
  template <typename... Operands>
298 299
  V8_INLINE static BytecodeNode Make(BytecodeArrayBuilder* builder,
                                     Operands... operands) {
300 301
    static_assert(sizeof...(Operands) <= Bytecodes::kMaxOperands,
                  "too many operands for bytecode");
302 303 304 305 306
    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)
307
    // the code will expand into:
308 309 310 311 312
    //    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)...);
313 314 315
  }
};

316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
#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) {     \
    DCHECK(Bytecodes::IsJump(Bytecode::k##name));                     \
    BytecodeNode node(Create##name##Node(operands...));               \
    WriteJump(&node, label);                                          \
    LeaveBasicBlock();                                                \
337 338 339
  }
BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT)
#undef DEFINE_BYTECODE_OUTPUT
340

341 342
void BytecodeArrayBuilder::OutputSwitchOnSmiNoFeedback(
    BytecodeJumpTable* jump_table) {
343 344 345 346 347
  BytecodeNode node(CreateSwitchOnSmiNoFeedbackNode(
      jump_table->constant_pool_index(), jump_table->size(),
      jump_table->case_value_base()));
  WriteSwitch(&node, jump_table);
  LeaveBasicBlock();
348 349
}

350
BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
351 352
                                                            Register reg,
                                                            int feedback_slot) {
353 354
  switch (op) {
    case Token::Value::ADD:
355
      OutputAdd(reg, feedback_slot);
356 357
      break;
    case Token::Value::SUB:
358
      OutputSub(reg, feedback_slot);
359 360
      break;
    case Token::Value::MUL:
361
      OutputMul(reg, feedback_slot);
362 363
      break;
    case Token::Value::DIV:
364
      OutputDiv(reg, feedback_slot);
365 366
      break;
    case Token::Value::MOD:
367
      OutputMod(reg, feedback_slot);
368
      break;
369 370 371
    case Token::Value::EXP:
      OutputExp(reg, feedback_slot);
      break;
372
    case Token::Value::BIT_OR:
373
      OutputBitwiseOr(reg, feedback_slot);
374 375
      break;
    case Token::Value::BIT_XOR:
376
      OutputBitwiseXor(reg, feedback_slot);
377 378
      break;
    case Token::Value::BIT_AND:
379
      OutputBitwiseAnd(reg, feedback_slot);
380 381
      break;
    case Token::Value::SHL:
382
      OutputShiftLeft(reg, feedback_slot);
383 384
      break;
    case Token::Value::SAR:
385
      OutputShiftRight(reg, feedback_slot);
386 387
      break;
    case Token::Value::SHR:
388
      OutputShiftRightLogical(reg, feedback_slot);
389 390 391 392
      break;
    default:
      UNREACHABLE();
  }
393 394 395
  return *this;
}

396
BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperationSmiLiteral(
397
    Token::Value op, Smi literal, int feedback_slot) {
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
  switch (op) {
    case Token::Value::ADD:
      OutputAddSmi(literal->value(), feedback_slot);
      break;
    case Token::Value::SUB:
      OutputSubSmi(literal->value(), feedback_slot);
      break;
    case Token::Value::MUL:
      OutputMulSmi(literal->value(), feedback_slot);
      break;
    case Token::Value::DIV:
      OutputDivSmi(literal->value(), feedback_slot);
      break;
    case Token::Value::MOD:
      OutputModSmi(literal->value(), feedback_slot);
      break;
414 415 416
    case Token::Value::EXP:
      OutputExpSmi(literal->value(), feedback_slot);
      break;
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
    case Token::Value::BIT_OR:
      OutputBitwiseOrSmi(literal->value(), feedback_slot);
      break;
    case Token::Value::BIT_XOR:
      OutputBitwiseXorSmi(literal->value(), feedback_slot);
      break;
    case Token::Value::BIT_AND:
      OutputBitwiseAndSmi(literal->value(), feedback_slot);
      break;
    case Token::Value::SHL:
      OutputShiftLeftSmi(literal->value(), feedback_slot);
      break;
    case Token::Value::SAR:
      OutputShiftRightSmi(literal->value(), feedback_slot);
      break;
    case Token::Value::SHR:
      OutputShiftRightLogicalSmi(literal->value(), feedback_slot);
      break;
    default:
      UNREACHABLE();
  }
  return *this;
}

441
BytecodeArrayBuilder& BytecodeArrayBuilder::UnaryOperation(Token::Value op,
442
                                                           int feedback_slot) {
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
  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();
461
  }
462 463 464
  return *this;
}

465 466 467 468 469 470 471
BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot(ToBooleanMode mode) {
  if (mode == ToBooleanMode::kAlreadyBoolean) {
    OutputLogicalNot();
  } else {
    DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
    OutputToBooleanLogicalNot();
  }
472 473 474 475
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
476
  OutputTypeOf();
477 478 479
  return *this;
}

480 481 482 483 484
BytecodeArrayBuilder& BytecodeArrayBuilder::GetSuperConstructor(Register out) {
  OutputGetSuperConstructor(out);
  return *this;
}

485 486
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
    Token::Value op, Register reg, int feedback_slot) {
487 488
  switch (op) {
    case Token::Value::EQ:
489
      OutputTestEqual(reg, feedback_slot);
490 491
      break;
    case Token::Value::EQ_STRICT:
492
      OutputTestEqualStrict(reg, feedback_slot);
493 494
      break;
    case Token::Value::LT:
495
      OutputTestLessThan(reg, feedback_slot);
496 497
      break;
    case Token::Value::GT:
498
      OutputTestGreaterThan(reg, feedback_slot);
499 500
      break;
    case Token::Value::LTE:
501
      OutputTestLessThanOrEqual(reg, feedback_slot);
502 503
      break;
    case Token::Value::GTE:
504
      OutputTestGreaterThanOrEqual(reg, feedback_slot);
505
      break;
506 507 508
    case Token::Value::INSTANCEOF:
      OutputTestInstanceOf(reg, feedback_slot);
      break;
509 510 511 512 513 514 515 516 517
    default:
      UNREACHABLE();
  }
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op,
                                                             Register reg) {
  switch (op) {
518
    case Token::Value::IN:
519
      OutputTestIn(reg);
520 521 522
      break;
    default:
      UNREACHABLE();
523
  }
524 525 526
  return *this;
}

527 528 529 530 531
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareReference(Register reg) {
  OutputTestReferenceEqual(reg);
  return *this;
}

532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
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();
    }
  }
}

562 563
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareTypeOf(
    TestTypeOfFlags::LiteralFlag literal_flag) {
564
  DCHECK_NE(literal_flag, TestTypeOfFlags::LiteralFlag::kOther);
565 566 567 568
  OutputTestTypeOf(TestTypeOfFlags::Encode(literal_flag));
  return *this;
}

569 570
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry(
    size_t entry) {
571
  OutputLdaConstant(entry);
572 573 574
  return *this;
}

575
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Smi smi) {
576 577
  int32_t raw_smi = smi->value();
  if (raw_smi == 0) {
578
    OutputLdaZero();
579
  } else {
580
    OutputLdaSmi(raw_smi);
581 582 583 584
  }
  return *this;
}

585 586 587 588 589 590
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(double value) {
  size_t entry = GetConstantPoolEntry(value);
  OutputLdaConstant(entry);
  return *this;
}

591 592 593 594 595 596 597 598 599
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);
600
  OutputLdaConstant(entry);
601 602 603
  return *this;
}

604 605 606 607 608 609 610 611 612 613 614 615 616
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
617
  }
618 619
  OutputLdaConstant(entry);
  return *this;
620 621
}

622
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
623
  OutputLdaUndefined();
624 625 626 627
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() {
628
  OutputLdaNull();
629 630 631 632
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() {
633
  OutputLdaTheHole();
634 635 636 637
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() {
638
  OutputLdaTrue();
639 640 641 642
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
643
  OutputLdaFalse();
644 645 646
  return *this;
}

647 648 649 650
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadBoolean(bool value) {
  return value ? LoadTrue() : LoadFalse();
}

651
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
652
    Register reg) {
653
  if (register_optimizer_) {
654
    // Defer source info so that if we elide the bytecode transfer, we attach
655
    // the source info to a subsequent bytecode if it exists.
656 657
    SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kLdar));
    register_optimizer_->DoLdar(reg);
658 659 660
  } else {
    OutputLdar(reg);
  }
661 662 663 664
  return *this;
}

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

677 678 679
BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
                                                         Register to) {
  DCHECK(from != to);
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::kMov));
    register_optimizer_->DoMov(from, to);
685 686 687
  } else {
    OutputMov(from, to);
  }
688 689 690
  return *this;
}

691 692 693
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(const AstRawString* name,
                                                       int feedback_slot,
                                                       TypeofMode typeof_mode) {
694
  size_t name_index = GetConstantPoolEntry(name);
695 696 697 698
  // 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);
699
  if (typeof_mode == INSIDE_TYPEOF) {
700
    OutputLdaGlobalInsideTypeof(name_index, feedback_slot);
701 702
  } else {
    DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
703
    OutputLdaGlobal(name_index, feedback_slot);
704
  }
705 706 707 708
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
709
    const AstRawString* name, int feedback_slot) {
710
  size_t name_index = GetConstantPoolEntry(name);
711
  OutputStaGlobal(name_index, feedback_slot);
712 713 714
  return *this;
}

715 716 717
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(
    Register context, int slot_index, int depth,
    ContextSlotMutability mutability) {
718
  if (context.is_current_context() && depth == 0) {
719 720 721 722 723 724 725 726
    if (mutability == kImmutableSlot) {
      OutputLdaImmutableCurrentContextSlot(slot_index);
    } else {
      DCHECK_EQ(kMutableSlot, mutability);
      OutputLdaCurrentContextSlot(slot_index);
    }
  } else if (mutability == kImmutableSlot) {
    OutputLdaImmutableContextSlot(context, slot_index, depth);
727
  } else {
728
    DCHECK_EQ(mutability, kMutableSlot);
729 730
    OutputLdaContextSlot(context, slot_index, depth);
  }
731 732 733
  return *this;
}

734
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
735 736
                                                             int slot_index,
                                                             int depth) {
737 738 739 740 741
  if (context.is_current_context() && depth == 0) {
    OutputStaCurrentContextSlot(slot_index);
  } else {
    OutputStaContextSlot(context, slot_index, depth);
  }
742 743 744
  return *this;
}

745
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
746
    const AstRawString* name, TypeofMode typeof_mode) {
747
  size_t name_index = GetConstantPoolEntry(name);
748
  if (typeof_mode == INSIDE_TYPEOF) {
749
    OutputLdaLookupSlotInsideTypeof(name_index);
750 751
  } else {
    DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
752
    OutputLdaLookupSlot(name_index);
753
  }
754 755 756
  return *this;
}

757
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot(
758
    const AstRawString* name, TypeofMode typeof_mode, int slot_index,
759 760
    int depth) {
  size_t name_index = GetConstantPoolEntry(name);
761 762 763 764 765 766
  if (typeof_mode == INSIDE_TYPEOF) {
    OutputLdaLookupContextSlotInsideTypeof(name_index, slot_index, depth);
  } else {
    DCHECK(typeof_mode == NOT_INSIDE_TYPEOF);
    OutputLdaLookupContextSlot(name_index, slot_index, depth);
  }
767 768 769
  return *this;
}

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

783
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot(
784 785
    const AstRawString* name, LanguageMode language_mode,
    LookupHoistingMode lookup_hoisting_mode) {
786
  size_t name_index = GetConstantPoolEntry(name);
787 788 789
  uint8_t flags =
      StoreLookupSlotFlags::Encode(language_mode, lookup_hoisting_mode);
  OutputStaLookupSlot(name_index, flags);
790 791 792
  return *this;
}

793
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
794
    Register object, const AstRawString* name, int feedback_slot) {
795
  size_t name_index = GetConstantPoolEntry(name);
796
  OutputLdaNamedProperty(object, name_index, feedback_slot);
797 798 799
  return *this;
}

800 801 802 803 804 805 806
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedPropertyNoFeedback(
    Register object, const AstRawString* name) {
  size_t name_index = GetConstantPoolEntry(name);
  OutputLdaNamedPropertyNoFeedback(object, name_index);
  return *this;
}

807
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
808
    Register object, int feedback_slot) {
809
  OutputLdaKeyedProperty(object, feedback_slot);
810 811 812
  return *this;
}

813 814 815 816 817 818 819
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadIteratorProperty(
    Register object, int feedback_slot) {
  size_t name_index = IteratorSymbolConstantPoolEntry();
  OutputLdaNamedProperty(object, name_index, feedback_slot);
  return *this;
}

820 821 822 823 824 825 826
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAsyncIteratorProperty(
    Register object, int feedback_slot) {
  size_t name_index = AsyncIteratorSymbolConstantPoolEntry();
  OutputLdaNamedProperty(object, name_index, feedback_slot);
  return *this;
}

827
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreDataPropertyInLiteral(
828 829 830
    Register object, Register name, DataPropertyInLiteralFlags flags,
    int feedback_slot) {
  OutputStaDataPropertyInLiteral(object, name, flags, feedback_slot);
831 832 833
  return *this;
}

834 835
BytecodeArrayBuilder& BytecodeArrayBuilder::CollectTypeProfile(int position) {
  OutputCollectTypeProfile(position);
836 837 838
  return *this;
}

839
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
840
    Register object, size_t name_index, int feedback_slot,
841
    LanguageMode language_mode) {
842 843 844 845
  // 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);
846
  OutputStaNamedProperty(object, name_index, feedback_slot);
847 848 849
  return *this;
}

850 851 852 853 854 855 856
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);
}

857 858 859 860 861 862 863 864
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;
}

865 866 867
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedOwnProperty(
    Register object, const AstRawString* name, int feedback_slot) {
  size_t name_index = GetConstantPoolEntry(name);
868 869 870 871
  // 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)));
872 873 874 875
  OutputStaNamedOwnProperty(object, name_index, feedback_slot);
  return *this;
}

876 877 878
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty(
    Register object, Register key, int feedback_slot,
    LanguageMode language_mode) {
879 880 881 882
  // 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);
883
  OutputStaKeyedProperty(object, key, feedback_slot);
884 885 886
  return *this;
}

887 888 889 890 891 892
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreInArrayLiteral(
    Register array, Register index, int feedback_slot) {
  OutputStaInArrayLiteral(array, index, feedback_slot);
  return *this;
}

893 894 895 896 897 898
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);
}

899 900 901 902 903 904 905 906 907 908 909 910 911 912
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;
}

913 914 915
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(
    size_t shared_function_info_entry, int slot, int flags) {
  OutputCreateClosure(shared_function_info_entry, slot, flags);
916 917 918
  return *this;
}

919
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateBlockContext(
920 921
    const Scope* scope) {
  size_t entry = GetConstantPoolEntry(scope);
922
  OutputCreateBlockContext(entry);
923 924 925
  return *this;
}

926
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateCatchContext(
927
    Register exception, const Scope* scope) {
928
  size_t scope_index = GetConstantPoolEntry(scope);
929
  OutputCreateCatchContext(exception, scope_index);
930 931 932
  return *this;
}

933 934 935 936
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(
    const Scope* scope, int slots) {
  size_t scope_index = GetConstantPoolEntry(scope);
  OutputCreateFunctionContext(scope_index, slots);
937 938 939
  return *this;
}

940 941 942 943
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEvalContext(
    const Scope* scope, int slots) {
  size_t scope_index = GetConstantPoolEntry(scope);
  OutputCreateEvalContext(scope_index, slots);
944 945 946
  return *this;
}

947
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext(
948 949 950
    Register object, const Scope* scope) {
  size_t scope_index = GetConstantPoolEntry(scope);
  OutputCreateWithContext(object, scope_index);
951 952 953
  return *this;
}

954 955
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
    CreateArgumentsType type) {
956 957
  switch (type) {
    case CreateArgumentsType::kMappedArguments:
958
      OutputCreateMappedArguments();
959 960
      break;
    case CreateArgumentsType::kUnmappedArguments:
961
      OutputCreateUnmappedArguments();
962 963
      break;
    case CreateArgumentsType::kRestParameter:
964
      OutputCreateRestParameter();
965 966 967 968
      break;
    default:
      UNREACHABLE();
  }
969 970 971
  return *this;
}

972
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
973
    const AstRawString* pattern, int literal_index, int flags) {
974
  size_t pattern_entry = GetConstantPoolEntry(pattern);
975
  OutputCreateRegExpLiteral(pattern_entry, literal_index, flags);
976 977 978
  return *this;
}

979 980 981 982 983 984
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyArrayLiteral(
    int literal_index) {
  OutputCreateEmptyArrayLiteral(literal_index);
  return *this;
}

985
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
986
    size_t constant_elements_entry, int literal_index, int flags) {
987
  OutputCreateArrayLiteral(constant_elements_entry, literal_index, flags);
988 989 990
  return *this;
}

991 992 993 994 995
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayFromIterable() {
  OutputCreateArrayFromIterable();
  return *this;
}

996
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
997 998
    size_t constant_properties_entry, int literal_index, int flags) {
  OutputCreateObjectLiteral(constant_properties_entry, literal_index, flags);
999 1000 1001
  return *this;
}

1002 1003
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyObjectLiteral() {
  OutputCreateEmptyObjectLiteral();
1004 1005 1006
  return *this;
}

1007 1008 1009 1010 1011 1012 1013
BytecodeArrayBuilder& BytecodeArrayBuilder::CloneObject(Register source,
                                                        int flags,
                                                        int feedback_slot) {
  OutputCloneObject(source, flags, feedback_slot);
  return *this;
}

1014
BytecodeArrayBuilder& BytecodeArrayBuilder::GetTemplateObject(
1015 1016
    size_t template_object_description_entry, int feedback_slot) {
  OutputGetTemplateObject(template_object_description_entry, feedback_slot);
1017 1018 1019
  return *this;
}

1020
BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) {
1021
  OutputPushContext(context);
1022 1023 1024 1025
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) {
1026
  OutputPopContext(context);
1027 1028 1029
  return *this;
}

1030
BytecodeArrayBuilder& BytecodeArrayBuilder::ToObject(Register out) {
1031
  OutputToObject(out);
1032 1033 1034
  return *this;
}

1035
BytecodeArrayBuilder& BytecodeArrayBuilder::ToName(Register out) {
1036
  OutputToName(out);
1037 1038 1039
  return *this;
}

1040 1041 1042 1043 1044
BytecodeArrayBuilder& BytecodeArrayBuilder::ToString() {
  OutputToString();
  return *this;
}

1045 1046
BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumber(int feedback_slot) {
  OutputToNumber(feedback_slot);
1047 1048 1049
  return *this;
}

1050 1051 1052 1053 1054
BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumeric(int feedback_slot) {
  OutputToNumeric(feedback_slot);
  return *this;
}

1055
BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
1056 1057 1058
  // 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();
1059
  bytecode_array_writer_.BindLabel(label);
1060
  LeaveBasicBlock();
1061 1062 1063
  return *this;
}

1064 1065
BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target,
                                                 BytecodeLabel* label) {
1066 1067
  bytecode_array_writer_.BindLabel(target, label);
  LeaveBasicBlock();
1068
  return *this;
1069 1070
}

1071 1072 1073 1074 1075
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();
1076
  bytecode_array_writer_.BindJumpTableEntry(jump_table, case_value);
1077 1078 1079 1080
  LeaveBasicBlock();
  return *this;
}

1081
BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
1082
  DCHECK(!label->is_bound());
1083
  OutputJump(label, 0);
1084
  return *this;
1085 1086
}

1087 1088
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(ToBooleanMode mode,
                                                       BytecodeLabel* label) {
1089
  DCHECK(!label->is_bound());
1090 1091 1092 1093 1094 1095
  if (mode == ToBooleanMode::kAlreadyBoolean) {
    OutputJumpIfTrue(label, 0);
  } else {
    DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
    OutputJumpIfToBooleanTrue(label, 0);
  }
1096
  return *this;
1097 1098
}

1099 1100
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(ToBooleanMode mode,
                                                        BytecodeLabel* label) {
1101
  DCHECK(!label->is_bound());
1102 1103 1104 1105 1106 1107
  if (mode == ToBooleanMode::kAlreadyBoolean) {
    OutputJumpIfFalse(label, 0);
  } else {
    DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
    OutputJumpIfToBooleanFalse(label, 0);
  }
1108
  return *this;
1109 1110
}

1111
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
1112
  DCHECK(!label->is_bound());
1113
  OutputJumpIfNull(label, 0);
1114
  return *this;
1115 1116
}

1117 1118 1119 1120 1121 1122 1123
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNull(
    BytecodeLabel* label) {
  DCHECK(!label->is_bound());
  OutputJumpIfNotNull(label, 0);
  return *this;
}

1124 1125
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
    BytecodeLabel* label) {
1126
  DCHECK(!label->is_bound());
1127
  OutputJumpIfUndefined(label, 0);
1128
  return *this;
1129 1130
}

1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142
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.
1143 1144
    return CompareUndetectable().JumpIfTrue(ToBooleanMode::kAlreadyBoolean,
                                            label);
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160
  } 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.
1161 1162
    return CompareUndetectable().JumpIfFalse(ToBooleanMode::kAlreadyBoolean,
                                             label);
1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173
  } else {
    DCHECK_EQ(Token::EQ_STRICT, op);
    if (nil == kUndefinedValue) {
      return JumpIfNotUndefined(label);
    } else {
      DCHECK_EQ(kNullValue, nil);
      return JumpIfNotNull(label);
    }
  }
}

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

1181 1182
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label,
                                                     int loop_depth) {
1183
  DCHECK(label->is_bound());
1184
  OutputJumpLoop(label, 0, loop_depth);
1185
  return *this;
1186 1187
}

1188 1189 1190 1191 1192 1193
BytecodeArrayBuilder& BytecodeArrayBuilder::SwitchOnSmiNoFeedback(
    BytecodeJumpTable* jump_table) {
  OutputSwitchOnSmiNoFeedback(jump_table);
  return *this;
}

1194
BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) {
yangguo's avatar
yangguo committed
1195
  if (position != kNoSourcePosition) {
1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206
    // 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);
1207
  }
1208
  OutputStackCheck();
1209
  return *this;
1210 1211
}

1212 1213 1214 1215 1216
BytecodeArrayBuilder& BytecodeArrayBuilder::SetPendingMessage() {
  OutputSetPendingMessage();
  return *this;
}

1217
BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
1218
  OutputThrow();
1219 1220 1221
  return *this;
}

1222
BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() {
1223
  OutputReThrow();
1224 1225 1226
  return *this;
}

1227
BytecodeArrayBuilder& BytecodeArrayBuilder::Abort(AbortReason reason) {
1228
  DCHECK_LT(reason, AbortReason::kLastErrorMessage);
1229 1230
  DCHECK_GE(reason, AbortReason::kNoReason);
  OutputAbort(static_cast<int>(reason));
1231 1232 1233
  return *this;
}

1234
BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
1235
  OutputReturn();
1236
  return_seen_in_block_ = true;
1237 1238 1239
  return *this;
}

1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256
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;
}

1257
BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() {
1258
  OutputDebugger();
1259 1260
  return *this;
}
1261

1262 1263 1264 1265 1266 1267
BytecodeArrayBuilder& BytecodeArrayBuilder::IncBlockCounter(
    int coverage_array_slot) {
  OutputIncBlockCounter(coverage_array_slot);
  return *this;
}

1268 1269 1270 1271 1272
BytecodeArrayBuilder& BytecodeArrayBuilder::ForInEnumerate(Register receiver) {
  OutputForInEnumerate(receiver);
  return *this;
}

1273
BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare(
1274
    RegisterList cache_info_triple, int feedback_slot) {
1275
  DCHECK_EQ(3, cache_info_triple.register_count());
1276
  OutputForInPrepare(cache_info_triple, feedback_slot);
1277 1278 1279
  return *this;
}

1280 1281
BytecodeArrayBuilder& BytecodeArrayBuilder::ForInContinue(
    Register index, Register cache_length) {
1282
  OutputForInContinue(index, cache_length);
1283 1284 1285
  return *this;
}

1286
BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext(
1287
    Register receiver, Register index, RegisterList cache_type_array_pair,
1288
    int feedback_slot) {
1289
  DCHECK_EQ(2, cache_type_array_pair.register_count());
1290
  OutputForInNext(receiver, index, cache_type_array_pair, feedback_slot);
1291 1292 1293
  return *this;
}

1294
BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
1295
  OutputForInStep(index);
1296 1297 1298
  return *this;
}

1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310
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;
}

1311
BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator(
1312 1313 1314
    Register generator, RegisterList registers, int suspend_id) {
  OutputSuspendGenerator(generator, registers, registers.register_count(),
                         suspend_id);
1315 1316 1317
  return *this;
}

1318 1319 1320 1321 1322 1323 1324
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);
  LeaveBasicBlock();
1325 1326 1327
  return *this;
}

1328
BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator(
1329 1330
    Register generator, RegisterList registers) {
  OutputResumeGenerator(generator, registers, registers.register_count());
1331 1332 1333
  return *this;
}

1334 1335
BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(
    int handler_id, HandlerTable::CatchPrediction catch_prediction) {
1336 1337 1338
  BytecodeLabel handler;
  Bind(&handler);
  handler_table_builder()->SetHandlerTarget(handler_id, handler.offset());
1339
  handler_table_builder()->SetPrediction(handler_id, catch_prediction);
1340 1341 1342 1343 1344
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryBegin(int handler_id,
                                                         Register context) {
1345 1346
  // TODO(leszeks): Do we need to start a new basic block here? Could we simply
  // get the current bytecode offset from the array writer instead?
1347 1348 1349
  BytecodeLabel try_begin;
  Bind(&try_begin);
  handler_table_builder()->SetTryRegionStart(handler_id, try_begin.offset());
1350 1351 1352 1353 1354
  handler_table_builder()->SetContextRegister(handler_id, context);
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) {
1355 1356 1357
  BytecodeLabel try_end;
  Bind(&try_end);
  handler_table_builder()->SetTryRegionEnd(handler_id, try_end.offset());
1358 1359 1360
  return *this;
}

1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383
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);
1384
  } else {
1385 1386
    OutputCallUndefinedReceiver(callable, args, args.register_count(),
                                feedback_slot);
1387
  }
1388 1389 1390
  return *this;
}

1391 1392 1393 1394 1395 1396 1397
BytecodeArrayBuilder& BytecodeArrayBuilder::CallAnyReceiver(Register callable,
                                                            RegisterList args,
                                                            int feedback_slot) {
  OutputCallAnyReceiver(callable, args, args.register_count(), feedback_slot);
  return *this;
}

1398 1399 1400 1401 1402 1403
BytecodeArrayBuilder& BytecodeArrayBuilder::CallNoFeedback(Register callable,
                                                           RegisterList args) {
  OutputCallNoFeedback(callable, args, args.register_count());
  return *this;
}

1404
BytecodeArrayBuilder& BytecodeArrayBuilder::CallWithSpread(Register callable,
1405 1406 1407
                                                           RegisterList args,
                                                           int feedback_slot) {
  OutputCallWithSpread(callable, args, args.register_count(), feedback_slot);
1408 1409 1410
  return *this;
}

1411 1412 1413 1414 1415 1416 1417 1418
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(
1419 1420 1421
    Register constructor, RegisterList args, int feedback_slot_id) {
  OutputConstructWithSpread(constructor, args, args.register_count(),
                            feedback_slot_id);
1422 1423 1424
  return *this;
}

1425
BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1426
    Runtime::FunctionId function_id, RegisterList args) {
1427
  DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size);
1428 1429
  DCHECK_LE(Bytecodes::SizeForUnsignedOperand(function_id),
            OperandSize::kShort);
1430
  if (IntrinsicsHelper::IsSupported(function_id)) {
1431 1432 1433 1434
    IntrinsicsHelper::IntrinsicId intrinsic_id =
        IntrinsicsHelper::FromRuntimeId(function_id);
    OutputInvokeIntrinsic(static_cast<int>(intrinsic_id), args,
                          args.register_count());
1435
  } else {
1436 1437
    OutputCallRuntime(static_cast<int>(function_id), args,
                      args.register_count());
1438
  }
1439 1440 1441
  return *this;
}

1442 1443
BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
    Runtime::FunctionId function_id, Register arg) {
1444
  return CallRuntime(function_id, RegisterList(arg));
1445 1446 1447 1448 1449 1450 1451
}

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

1452
BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1453 1454
    Runtime::FunctionId function_id, RegisterList args,
    RegisterList return_pair) {
1455
  DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size);
1456 1457
  DCHECK_LE(Bytecodes::SizeForUnsignedOperand(function_id),
            OperandSize::kShort);
1458
  DCHECK_EQ(2, return_pair.register_count());
1459 1460
  OutputCallRuntimeForPair(static_cast<uint16_t>(function_id), args,
                           args.register_count(), return_pair);
1461 1462 1463
  return *this;
}

1464
BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1465
    Runtime::FunctionId function_id, Register arg, RegisterList return_pair) {
1466
  return CallRuntimeForPair(function_id, RegisterList(arg), return_pair);
1467 1468 1469 1470
}

BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index,
                                                          RegisterList args) {
1471
  OutputCallJSRuntime(context_index, args, args.register_count());
1472 1473 1474
  return *this;
}

1475 1476
BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object,
                                                   LanguageMode language_mode) {
1477
  if (language_mode == LanguageMode::kSloppy) {
1478
    OutputDeletePropertySloppy(object);
1479
  } else {
1480
    DCHECK_EQ(language_mode, LanguageMode::kStrict);
1481
    OutputDeletePropertyStrict(object);
1482
  }
1483 1484 1485
  return *this;
}

1486 1487 1488 1489 1490
size_t BytecodeArrayBuilder::GetConstantPoolEntry(
    const AstRawString* raw_string) {
  return constant_array_builder()->Insert(raw_string);
}

1491 1492
size_t BytecodeArrayBuilder::GetConstantPoolEntry(AstBigInt bigint) {
  return constant_array_builder()->Insert(bigint);
1493 1494
}

1495 1496 1497 1498
size_t BytecodeArrayBuilder::GetConstantPoolEntry(const Scope* scope) {
  return constant_array_builder()->Insert(scope);
}

1499 1500 1501 1502
size_t BytecodeArrayBuilder::GetConstantPoolEntry(double number) {
  return constant_array_builder()->Insert(number);
}

1503 1504 1505 1506 1507 1508 1509
#define ENTRY_GETTER(NAME, ...)                            \
  size_t BytecodeArrayBuilder::NAME##ConstantPoolEntry() { \
    return constant_array_builder()->Insert##NAME();       \
  }
SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)
#undef ENTRY_GETTER

1510 1511 1512 1513 1514 1515 1516 1517 1518 1519
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());
}

1520 1521
size_t BytecodeArrayBuilder::AllocateDeferredConstantPoolEntry() {
  return constant_array_builder()->InsertDeferred();
1522 1523
}

1524 1525 1526
void BytecodeArrayBuilder::SetDeferredConstantPoolEntry(size_t entry,
                                                        Handle<Object> object) {
  constant_array_builder()->SetDeferredAt(entry, object);
1527 1528
}

1529
bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const {
1530 1531 1532 1533
  if (!reg.is_valid()) {
    return false;
  }

1534
  if (reg.is_current_context() || reg.is_function_closure()) {
1535 1536
    return true;
  } else if (reg.is_parameter()) {
1537 1538
    int parameter_index = reg.ToParameterIndex(parameter_count());
    return parameter_index >= 0 && parameter_index < parameter_count();
1539 1540
  } else if (reg.index() < fixed_register_count()) {
    return true;
1541
  } else {
1542
    return register_allocator()->RegisterIsLive(reg);
1543 1544 1545
  }
}

1546 1547 1548 1549 1550 1551 1552
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))) {
1553 1554 1555
        return false;
      }
    }
1556
    return true;
1557
  }
1558 1559
}

1560
template <Bytecode bytecode, AccumulatorUse accumulator_use>
1561 1562 1563
void BytecodeArrayBuilder::PrepareToOutputBytecode() {
  if (register_optimizer_)
    register_optimizer_->PrepareForBytecode<bytecode, accumulator_use>();
1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584
}

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());
}
1585

1586 1587 1588 1589 1590 1591
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());
1592 1593
}

1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604
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();
}

1605 1606 1607
}  // namespace interpreter
}  // namespace internal
}  // namespace v8