1// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/interpreter/bytecode-array-builder.h"
6
7#include "src/common/assert-scope.h"
8#include "src/common/globals.h"
9#include "src/interpreter/bytecode-array-writer.h"
10#include "src/interpreter/bytecode-jump-table.h"
11#include "src/interpreter/bytecode-label.h"
12#include "src/interpreter/bytecode-node.h"
13#include "src/interpreter/bytecode-register-optimizer.h"
14#include "src/interpreter/bytecode-source-info.h"
15#include "src/interpreter/interpreter-intrinsics.h"
16#include "src/objects/feedback-vector-inl.h"
17#include "src/objects/smi.h"
18
19namespace v8 {
20namespace internal {
21namespace interpreter {
22
23class RegisterTransferWriter final
24    : public NON_EXPORTED_BASE(BytecodeRegisterOptimizer::BytecodeWriter),
25      public NON_EXPORTED_BASE(ZoneObject) {
26 public:
27  explicit RegisterTransferWriter(BytecodeArrayBuilder* builder)
28      : builder_(builder) {}
29  ~RegisterTransferWriter() override = default;
30
31  void EmitLdar(Register input) override { builder_->OutputLdarRaw(input); }
32
33  void EmitStar(Register output) override { builder_->OutputStarRaw(output); }
34
35  void EmitMov(Register input, Register output) override {
36    builder_->OutputMovRaw(input, output);
37  }
38
39 private:
40  BytecodeArrayBuilder* builder_;
41};
42
43BytecodeArrayBuilder::BytecodeArrayBuilder(
44    Zone* zone, int parameter_count, int locals_count,
45    FeedbackVectorSpec* feedback_vector_spec,
46    SourcePositionTableBuilder::RecordingMode source_position_mode)
47    : zone_(zone),
48      feedback_vector_spec_(feedback_vector_spec),
49      bytecode_generated_(false),
50      constant_array_builder_(zone),
51      handler_table_builder_(zone),
52      parameter_count_(parameter_count),
53      local_register_count_(locals_count),
54      register_allocator_(fixed_register_count()),
55      bytecode_array_writer_(zone, &constant_array_builder_,
56                             source_position_mode),
57      register_optimizer_(nullptr) {
58  DCHECK_GE(parameter_count_, 0);
59  DCHECK_GE(local_register_count_, 0);
60
61  if (FLAG_ignition_reo) {
62    register_optimizer_ = zone->New<BytecodeRegisterOptimizer>(
63        zone, &register_allocator_, fixed_register_count(), parameter_count,
64        zone->New<RegisterTransferWriter>(this));
65  }
66}
67
68Register BytecodeArrayBuilder::Parameter(int parameter_index) const {
69  DCHECK_GE(parameter_index, 0);
70  // The parameter indices are shifted by 1 (receiver is the
71  // first entry).
72  return Register::FromParameterIndex(parameter_index + 1);
73}
74
75Register BytecodeArrayBuilder::Receiver() const {
76  return Register::FromParameterIndex(0);
77}
78
79Register BytecodeArrayBuilder::Local(int index) const {
80  DCHECK_LT(index, locals_count());
81  return Register(index);
82}
83
84template <typename IsolateT>
85Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(IsolateT* isolate) {
86  DCHECK(RemainderOfBlockIsDead());
87  DCHECK(!bytecode_generated_);
88  bytecode_generated_ = true;
89
90  int register_count = total_register_count();
91
92  if (register_optimizer_) {
93    register_optimizer_->Flush();
94    register_count = register_optimizer_->maxiumum_register_index() + 1;
95  }
96
97  Handle<ByteArray> handler_table =
98      handler_table_builder()->ToHandlerTable(isolate);
99  return bytecode_array_writer_.ToBytecodeArray(
100      isolate, register_count, parameter_count(), handler_table);
101}
102
103template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
104    Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(
105        Isolate* isolate);
106template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
107    Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(
108        LocalIsolate* isolate);
109
110#ifdef DEBUG
111int BytecodeArrayBuilder::CheckBytecodeMatches(BytecodeArray bytecode) {
112  DisallowGarbageCollection no_gc;
113  return bytecode_array_writer_.CheckBytecodeMatches(bytecode);
114}
115#endif
116
117template <typename IsolateT>
118Handle<ByteArray> BytecodeArrayBuilder::ToSourcePositionTable(
119    IsolateT* isolate) {
120  DCHECK(RemainderOfBlockIsDead());
121
122  return bytecode_array_writer_.ToSourcePositionTable(isolate);
123}
124
125template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
126    Handle<ByteArray> BytecodeArrayBuilder::ToSourcePositionTable(
127        Isolate* isolate);
128template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
129    Handle<ByteArray> BytecodeArrayBuilder::ToSourcePositionTable(
130        LocalIsolate* isolate);
131
132BytecodeSourceInfo BytecodeArrayBuilder::CurrentSourcePosition(
133    Bytecode bytecode) {
134  BytecodeSourceInfo source_position;
135  if (latest_source_info_.is_valid()) {
136    // Statement positions need to be emitted immediately.  Expression
137    // positions can be pushed back until a bytecode is found that can
138    // throw (if expression position filtering is turned on). We only
139    // invalidate the existing source position information if it is used.
140    if (latest_source_info_.is_statement() ||
141        !FLAG_ignition_filter_expression_positions ||
142        !Bytecodes::IsWithoutExternalSideEffects(bytecode)) {
143      source_position = latest_source_info_;
144      latest_source_info_.set_invalid();
145    }
146  }
147  return source_position;
148}
149
150void BytecodeArrayBuilder::SetDeferredSourceInfo(
151    BytecodeSourceInfo source_info) {
152  if (!source_info.is_valid()) return;
153  deferred_source_info_ = source_info;
154}
155
156void BytecodeArrayBuilder::AttachOrEmitDeferredSourceInfo(BytecodeNode* node) {
157  if (!deferred_source_info_.is_valid()) return;
158  if (!node->source_info().is_valid()) {
159    node->set_source_info(deferred_source_info_);
160  } else if (deferred_source_info_.is_statement() &&
161             node->source_info().is_expression()) {
162    BytecodeSourceInfo source_position = node->source_info();
163    source_position.MakeStatementPosition(source_position.source_position());
164    node->set_source_info(source_position);
165  }
166  deferred_source_info_.set_invalid();
167}
168
169void BytecodeArrayBuilder::Write(BytecodeNode* node) {
170  AttachOrEmitDeferredSourceInfo(node);
171  bytecode_array_writer_.Write(node);
172}
173
174void BytecodeArrayBuilder::WriteJump(BytecodeNode* node, BytecodeLabel* label) {
175  AttachOrEmitDeferredSourceInfo(node);
176  bytecode_array_writer_.WriteJump(node, label);
177}
178
179void BytecodeArrayBuilder::WriteJumpLoop(BytecodeNode* node,
180                                         BytecodeLoopHeader* loop_header) {
181  AttachOrEmitDeferredSourceInfo(node);
182  bytecode_array_writer_.WriteJumpLoop(node, loop_header);
183}
184
185void BytecodeArrayBuilder::WriteSwitch(BytecodeNode* node,
186                                       BytecodeJumpTable* jump_table) {
187  AttachOrEmitDeferredSourceInfo(node);
188  bytecode_array_writer_.WriteSwitch(node, jump_table);
189}
190
191void BytecodeArrayBuilder::OutputLdarRaw(Register reg) {
192  uint32_t operand = static_cast<uint32_t>(reg.ToOperand());
193  BytecodeNode node(BytecodeNode::Ldar(BytecodeSourceInfo(), operand));
194  Write(&node);
195}
196
197void BytecodeArrayBuilder::OutputStarRaw(Register reg) {
198  uint32_t operand = static_cast<uint32_t>(reg.ToOperand());
199  base::Optional<Bytecode> short_code = reg.TryToShortStar();
200  BytecodeNode node = short_code
201                          ? BytecodeNode(*short_code)
202                          : BytecodeNode::Star(BytecodeSourceInfo(), operand);
203  Write(&node);
204}
205
206void BytecodeArrayBuilder::OutputMovRaw(Register src, Register dest) {
207  uint32_t operand0 = static_cast<uint32_t>(src.ToOperand());
208  uint32_t operand1 = static_cast<uint32_t>(dest.ToOperand());
209  BytecodeNode node(
210      BytecodeNode::Mov(BytecodeSourceInfo(), operand0, operand1));
211  Write(&node);
212}
213
214namespace {
215
216template <OperandTypeInfo type_info>
217class UnsignedOperandHelper {
218 public:
219  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
220                                    size_t value) {
221    DCHECK(IsValid(value));
222    return static_cast<uint32_t>(value);
223  }
224
225  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder, int value) {
226    DCHECK_GE(value, 0);
227    return Convert(builder, static_cast<size_t>(value));
228  }
229
230 private:
231  static bool IsValid(size_t value) {
232    switch (type_info) {
233      case OperandTypeInfo::kFixedUnsignedByte:
234        return value <= kMaxUInt8;
235      case OperandTypeInfo::kFixedUnsignedShort:
236        return value <= kMaxUInt16;
237      case OperandTypeInfo::kScalableUnsignedByte:
238        return value <= kMaxUInt32;
239      default:
240        UNREACHABLE();
241    }
242  }
243};
244
245template <OperandType>
246class OperandHelper {};
247
248#define DEFINE_UNSIGNED_OPERAND_HELPER(Name, Type) \
249  template <>                                      \
250  class OperandHelper<OperandType::k##Name>        \
251      : public UnsignedOperandHelper<Type> {};
252UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
253UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
254#undef DEFINE_UNSIGNED_OPERAND_HELPER
255
256template <>
257class OperandHelper<OperandType::kImm> {
258 public:
259  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder, int value) {
260    return static_cast<uint32_t>(value);
261  }
262};
263
264template <>
265class OperandHelper<OperandType::kReg> {
266 public:
267  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
268                                    Register reg) {
269    return builder->GetInputRegisterOperand(reg);
270  }
271};
272
273template <>
274class OperandHelper<OperandType::kRegList> {
275 public:
276  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
277                                    RegisterList reg_list) {
278    return builder->GetInputRegisterListOperand(reg_list);
279  }
280};
281
282template <>
283class OperandHelper<OperandType::kRegPair> {
284 public:
285  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
286                                    RegisterList reg_list) {
287    DCHECK_EQ(reg_list.register_count(), 2);
288    return builder->GetInputRegisterListOperand(reg_list);
289  }
290};
291
292template <>
293class OperandHelper<OperandType::kRegOut> {
294 public:
295  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
296                                    Register reg) {
297    return builder->GetOutputRegisterOperand(reg);
298  }
299};
300
301template <>
302class OperandHelper<OperandType::kRegOutList> {
303 public:
304  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
305                                    RegisterList reg_list) {
306    return builder->GetOutputRegisterListOperand(reg_list);
307  }
308};
309
310template <>
311class OperandHelper<OperandType::kRegOutPair> {
312 public:
313  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
314                                    RegisterList reg_list) {
315    DCHECK_EQ(2, reg_list.register_count());
316    return builder->GetOutputRegisterListOperand(reg_list);
317  }
318};
319
320template <>
321class OperandHelper<OperandType::kRegOutTriple> {
322 public:
323  V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
324                                    RegisterList reg_list) {
325    DCHECK_EQ(3, reg_list.register_count());
326    return builder->GetOutputRegisterListOperand(reg_list);
327  }
328};
329
330}  // namespace
331
332template <Bytecode bytecode, ImplicitRegisterUse implicit_register_use,
333          OperandType... operand_types>
334class BytecodeNodeBuilder {
335 public:
336  template <typename... Operands>
337  V8_INLINE static BytecodeNode Make(BytecodeArrayBuilder* builder,
338                                     Operands... operands) {
339    static_assert(sizeof...(Operands) <= Bytecodes::kMaxOperands,
340                  "too many operands for bytecode");
341    builder->PrepareToOutputBytecode<bytecode, implicit_register_use>();
342    // The "OperandHelper<operand_types>::Convert(builder, operands)..." will
343    // expand both the OperandType... and Operands... parameter packs e.g. for:
344    //   BytecodeNodeBuilder<OperandType::kReg, OperandType::kImm>::Make<
345    //       Register, int>(..., Register reg, int immediate)
346    // the code will expand into:
347    //    OperandHelper<OperandType::kReg>::Convert(builder, reg),
348    //    OperandHelper<OperandType::kImm>::Convert(builder, immediate),
349    return BytecodeNode::Create<bytecode, implicit_register_use,
350                                operand_types...>(
351        builder->CurrentSourcePosition(bytecode),
352        OperandHelper<operand_types>::Convert(builder, operands)...);
353  }
354};
355
356#define DEFINE_BYTECODE_OUTPUT(name, ...)                             \
357  template <typename... Operands>                                     \
358  BytecodeNode BytecodeArrayBuilder::Create##name##Node(              \
359      Operands... operands) {                                         \
360    return BytecodeNodeBuilder<Bytecode::k##name, __VA_ARGS__>::Make( \
361        this, operands...);                                           \
362  }                                                                   \
363                                                                      \
364  template <typename... Operands>                                     \
365  void BytecodeArrayBuilder::Output##name(Operands... operands) {     \
366    BytecodeNode node(Create##name##Node(operands...));               \
367    Write(&node);                                                     \
368  }                                                                   \
369                                                                      \
370  template <typename... Operands>                                     \
371  void BytecodeArrayBuilder::Output##name(BytecodeLabel* label,       \
372                                          Operands... operands) {     \
373    DCHECK(Bytecodes::IsForwardJump(Bytecode::k##name));              \
374    BytecodeNode node(Create##name##Node(operands...));               \
375    WriteJump(&node, label);                                          \
376  }
377BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT)
378#undef DEFINE_BYTECODE_OUTPUT
379
380void BytecodeArrayBuilder::OutputJumpLoop(BytecodeLoopHeader* loop_header,
381                                          int loop_depth) {
382  BytecodeNode node(CreateJumpLoopNode(0, loop_depth));
383  WriteJumpLoop(&node, loop_header);
384}
385
386void BytecodeArrayBuilder::OutputSwitchOnSmiNoFeedback(
387    BytecodeJumpTable* jump_table) {
388  BytecodeNode node(CreateSwitchOnSmiNoFeedbackNode(
389      jump_table->constant_pool_index(), jump_table->size(),
390      jump_table->case_value_base()));
391  WriteSwitch(&node, jump_table);
392}
393
394BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
395                                                            Register reg,
396                                                            int feedback_slot) {
397  switch (op) {
398    case Token::Value::ADD:
399      OutputAdd(reg, feedback_slot);
400      break;
401    case Token::Value::SUB:
402      OutputSub(reg, feedback_slot);
403      break;
404    case Token::Value::MUL:
405      OutputMul(reg, feedback_slot);
406      break;
407    case Token::Value::DIV:
408      OutputDiv(reg, feedback_slot);
409      break;
410    case Token::Value::MOD:
411      OutputMod(reg, feedback_slot);
412      break;
413    case Token::Value::EXP:
414      OutputExp(reg, feedback_slot);
415      break;
416    case Token::Value::BIT_OR:
417      OutputBitwiseOr(reg, feedback_slot);
418      break;
419    case Token::Value::BIT_XOR:
420      OutputBitwiseXor(reg, feedback_slot);
421      break;
422    case Token::Value::BIT_AND:
423      OutputBitwiseAnd(reg, feedback_slot);
424      break;
425    case Token::Value::SHL:
426      OutputShiftLeft(reg, feedback_slot);
427      break;
428    case Token::Value::SAR:
429      OutputShiftRight(reg, feedback_slot);
430      break;
431    case Token::Value::SHR:
432      OutputShiftRightLogical(reg, feedback_slot);
433      break;
434    default:
435      UNREACHABLE();
436  }
437  return *this;
438}
439
440BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperationSmiLiteral(
441    Token::Value op, Smi literal, int feedback_slot) {
442  switch (op) {
443    case Token::Value::ADD:
444      OutputAddSmi(literal.value(), feedback_slot);
445      break;
446    case Token::Value::SUB:
447      OutputSubSmi(literal.value(), feedback_slot);
448      break;
449    case Token::Value::MUL:
450      OutputMulSmi(literal.value(), feedback_slot);
451      break;
452    case Token::Value::DIV:
453      OutputDivSmi(literal.value(), feedback_slot);
454      break;
455    case Token::Value::MOD:
456      OutputModSmi(literal.value(), feedback_slot);
457      break;
458    case Token::Value::EXP:
459      OutputExpSmi(literal.value(), feedback_slot);
460      break;
461    case Token::Value::BIT_OR:
462      OutputBitwiseOrSmi(literal.value(), feedback_slot);
463      break;
464    case Token::Value::BIT_XOR:
465      OutputBitwiseXorSmi(literal.value(), feedback_slot);
466      break;
467    case Token::Value::BIT_AND:
468      OutputBitwiseAndSmi(literal.value(), feedback_slot);
469      break;
470    case Token::Value::SHL:
471      OutputShiftLeftSmi(literal.value(), feedback_slot);
472      break;
473    case Token::Value::SAR:
474      OutputShiftRightSmi(literal.value(), feedback_slot);
475      break;
476    case Token::Value::SHR:
477      OutputShiftRightLogicalSmi(literal.value(), feedback_slot);
478      break;
479    default:
480      UNREACHABLE();
481  }
482  return *this;
483}
484
485BytecodeArrayBuilder& BytecodeArrayBuilder::UnaryOperation(Token::Value op,
486                                                           int feedback_slot) {
487  switch (op) {
488    case Token::Value::INC:
489      OutputInc(feedback_slot);
490      break;
491    case Token::Value::DEC:
492      OutputDec(feedback_slot);
493      break;
494    case Token::Value::ADD:
495      OutputToNumber(feedback_slot);
496      break;
497    case Token::Value::SUB:
498      OutputNegate(feedback_slot);
499      break;
500    case Token::Value::BIT_NOT:
501      OutputBitwiseNot(feedback_slot);
502      break;
503    default:
504      UNREACHABLE();
505  }
506  return *this;
507}
508
509BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot(ToBooleanMode mode) {
510  if (mode == ToBooleanMode::kAlreadyBoolean) {
511    OutputLogicalNot();
512  } else {
513    DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
514    OutputToBooleanLogicalNot();
515  }
516  return *this;
517}
518
519BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
520  OutputTypeOf();
521  return *this;
522}
523
524BytecodeArrayBuilder& BytecodeArrayBuilder::GetSuperConstructor(Register out) {
525  OutputGetSuperConstructor(out);
526  return *this;
527}
528
529BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
530    Token::Value op, Register reg, int feedback_slot) {
531  switch (op) {
532    case Token::Value::EQ:
533      OutputTestEqual(reg, feedback_slot);
534      break;
535    case Token::Value::EQ_STRICT:
536      OutputTestEqualStrict(reg, feedback_slot);
537      break;
538    case Token::Value::LT:
539      OutputTestLessThan(reg, feedback_slot);
540      break;
541    case Token::Value::GT:
542      OutputTestGreaterThan(reg, feedback_slot);
543      break;
544    case Token::Value::LTE:
545      OutputTestLessThanOrEqual(reg, feedback_slot);
546      break;
547    case Token::Value::GTE:
548      OutputTestGreaterThanOrEqual(reg, feedback_slot);
549      break;
550    case Token::Value::INSTANCEOF:
551      OutputTestInstanceOf(reg, feedback_slot);
552      break;
553    case Token::Value::IN:
554      OutputTestIn(reg, feedback_slot);
555      break;
556    default:
557      UNREACHABLE();
558  }
559  return *this;
560}
561
562BytecodeArrayBuilder& BytecodeArrayBuilder::CompareReference(Register reg) {
563  OutputTestReferenceEqual(reg);
564  return *this;
565}
566
567BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndetectable() {
568  OutputTestUndetectable();
569  return *this;
570}
571
572BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndefined() {
573  OutputTestUndefined();
574  return *this;
575}
576
577BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNull() {
578  OutputTestNull();
579  return *this;
580}
581
582BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNil(Token::Value op,
583                                                       NilValue nil) {
584  if (op == Token::EQ) {
585    return CompareUndetectable();
586  } else {
587    DCHECK_EQ(Token::EQ_STRICT, op);
588    if (nil == kUndefinedValue) {
589      return CompareUndefined();
590    } else {
591      DCHECK_EQ(kNullValue, nil);
592      return CompareNull();
593    }
594  }
595}
596
597BytecodeArrayBuilder& BytecodeArrayBuilder::CompareTypeOf(
598    TestTypeOfFlags::LiteralFlag literal_flag) {
599  DCHECK_NE(literal_flag, TestTypeOfFlags::LiteralFlag::kOther);
600  OutputTestTypeOf(TestTypeOfFlags::Encode(literal_flag));
601  return *this;
602}
603
604BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry(
605    size_t entry) {
606  OutputLdaConstant(entry);
607  return *this;
608}
609
610BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Smi smi) {
611  int32_t raw_smi = smi.value();
612  if (raw_smi == 0) {
613    OutputLdaZero();
614  } else {
615    OutputLdaSmi(raw_smi);
616  }
617  return *this;
618}
619
620BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(double value) {
621  // If we can encode the value as a Smi, we should.
622  int smi;
623  if (DoubleToSmiInteger(value, &smi)) {
624    LoadLiteral(Smi::FromInt(smi));
625  } else {
626    size_t entry = GetConstantPoolEntry(value);
627    OutputLdaConstant(entry);
628  }
629  return *this;
630}
631
632BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
633    const AstRawString* raw_string) {
634  size_t entry = GetConstantPoolEntry(raw_string);
635  OutputLdaConstant(entry);
636  return *this;
637}
638
639BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(const Scope* scope) {
640  size_t entry = GetConstantPoolEntry(scope);
641  OutputLdaConstant(entry);
642  return *this;
643}
644
645BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(AstBigInt bigint) {
646  size_t entry = GetConstantPoolEntry(bigint);
647  OutputLdaConstant(entry);
648  return *this;
649}
650
651BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
652  OutputLdaUndefined();
653  return *this;
654}
655
656BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() {
657  OutputLdaNull();
658  return *this;
659}
660
661BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() {
662  OutputLdaTheHole();
663  return *this;
664}
665
666BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() {
667  OutputLdaTrue();
668  return *this;
669}
670
671BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
672  OutputLdaFalse();
673  return *this;
674}
675
676BytecodeArrayBuilder& BytecodeArrayBuilder::LoadBoolean(bool value) {
677  return value ? LoadTrue() : LoadFalse();
678}
679
680BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
681    Register reg) {
682  if (register_optimizer_) {
683    // Defer source info so that if we elide the bytecode transfer, we attach
684    // the source info to a subsequent bytecode if it exists.
685    SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kLdar));
686    register_optimizer_->DoLdar(reg);
687  } else {
688    OutputLdar(reg);
689  }
690  return *this;
691}
692
693BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
694    Register reg) {
695  if (register_optimizer_) {
696    // Defer source info so that if we elide the bytecode transfer, we attach
697    // the source info to a subsequent bytecode if it exists.
698    SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kStar));
699    register_optimizer_->DoStar(reg);
700  } else {
701    OutputStarRaw(reg);
702  }
703  return *this;
704}
705
706BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
707                                                         Register to) {
708  DCHECK(from != to);
709  if (register_optimizer_) {
710    // Defer source info so that if we elide the bytecode transfer, we attach
711    // the source info to a subsequent bytecode if it exists.
712    SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kMov));
713    register_optimizer_->DoMov(from, to);
714  } else {
715    OutputMov(from, to);
716  }
717  return *this;
718}
719
720BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(const AstRawString* name,
721                                                       int feedback_slot,
722                                                       TypeofMode typeof_mode) {
723  size_t name_index = GetConstantPoolEntry(name);
724  // Ensure that typeof mode is in sync with the IC slot kind.
725  DCHECK_EQ(GetTypeofModeFromSlotKind(feedback_vector_spec()->GetKind(
726                FeedbackVector::ToSlot(feedback_slot))),
727            typeof_mode);
728  switch (typeof_mode) {
729    case TypeofMode::kInside:
730      OutputLdaGlobalInsideTypeof(name_index, feedback_slot);
731      break;
732    case TypeofMode::kNotInside:
733      OutputLdaGlobal(name_index, feedback_slot);
734      break;
735  }
736  return *this;
737}
738
739BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
740    const AstRawString* name, int feedback_slot) {
741  size_t name_index = GetConstantPoolEntry(name);
742  OutputStaGlobal(name_index, feedback_slot);
743  return *this;
744}
745
746BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(
747    Register context, int slot_index, int depth,
748    ContextSlotMutability mutability) {
749  if (context.is_current_context() && depth == 0) {
750    if (mutability == kImmutableSlot) {
751      OutputLdaImmutableCurrentContextSlot(slot_index);
752    } else {
753      DCHECK_EQ(kMutableSlot, mutability);
754      OutputLdaCurrentContextSlot(slot_index);
755    }
756  } else if (mutability == kImmutableSlot) {
757    OutputLdaImmutableContextSlot(context, slot_index, depth);
758  } else {
759    DCHECK_EQ(mutability, kMutableSlot);
760    OutputLdaContextSlot(context, slot_index, depth);
761  }
762  return *this;
763}
764
765BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
766                                                             int slot_index,
767                                                             int depth) {
768  if (context.is_current_context() && depth == 0) {
769    OutputStaCurrentContextSlot(slot_index);
770  } else {
771    OutputStaContextSlot(context, slot_index, depth);
772  }
773  return *this;
774}
775
776BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
777    const AstRawString* name, TypeofMode typeof_mode) {
778  size_t name_index = GetConstantPoolEntry(name);
779  switch (typeof_mode) {
780    case TypeofMode::kInside:
781      OutputLdaLookupSlotInsideTypeof(name_index);
782      break;
783    case TypeofMode::kNotInside:
784      OutputLdaLookupSlot(name_index);
785      break;
786  }
787  return *this;
788}
789
790BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot(
791    const AstRawString* name, TypeofMode typeof_mode, int slot_index,
792    int depth) {
793  size_t name_index = GetConstantPoolEntry(name);
794  switch (typeof_mode) {
795    case TypeofMode::kInside:
796      OutputLdaLookupContextSlotInsideTypeof(name_index, slot_index, depth);
797      break;
798    case TypeofMode::kNotInside:
799      OutputLdaLookupContextSlot(name_index, slot_index, depth);
800      break;
801  }
802  return *this;
803}
804
805BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot(
806    const AstRawString* name, TypeofMode typeof_mode, int feedback_slot,
807    int depth) {
808  size_t name_index = GetConstantPoolEntry(name);
809  switch (typeof_mode) {
810    case TypeofMode::kInside:
811      OutputLdaLookupGlobalSlotInsideTypeof(name_index, feedback_slot, depth);
812      break;
813    case TypeofMode::kNotInside:
814      OutputLdaLookupGlobalSlot(name_index, feedback_slot, depth);
815      break;
816  }
817  return *this;
818}
819
820BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot(
821    const AstRawString* name, LanguageMode language_mode,
822    LookupHoistingMode lookup_hoisting_mode) {
823  size_t name_index = GetConstantPoolEntry(name);
824  uint8_t flags =
825      StoreLookupSlotFlags::Encode(language_mode, lookup_hoisting_mode);
826  OutputStaLookupSlot(name_index, flags);
827  return *this;
828}
829
830BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
831    Register object, const AstRawString* name, int feedback_slot) {
832  size_t name_index = GetConstantPoolEntry(name);
833  OutputGetNamedProperty(object, name_index, feedback_slot);
834  return *this;
835}
836
837BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedPropertyFromSuper(
838    Register object, const AstRawString* name, int feedback_slot) {
839  size_t name_index = GetConstantPoolEntry(name);
840  OutputGetNamedPropertyFromSuper(object, name_index, feedback_slot);
841  return *this;
842}
843
844BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
845    Register object, int feedback_slot) {
846  OutputGetKeyedProperty(object, feedback_slot);
847  return *this;
848}
849
850BytecodeArrayBuilder& BytecodeArrayBuilder::LoadIteratorProperty(
851    Register object, int feedback_slot) {
852  size_t name_index = IteratorSymbolConstantPoolEntry();
853  OutputGetNamedProperty(object, name_index, feedback_slot);
854  return *this;
855}
856
857BytecodeArrayBuilder& BytecodeArrayBuilder::GetIterator(
858    Register object, int load_feedback_slot, int call_feedback_slot) {
859  OutputGetIterator(object, load_feedback_slot, call_feedback_slot);
860  return *this;
861}
862
863BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAsyncIteratorProperty(
864    Register object, int feedback_slot) {
865  size_t name_index = AsyncIteratorSymbolConstantPoolEntry();
866  OutputGetNamedProperty(object, name_index, feedback_slot);
867  return *this;
868}
869
870BytecodeArrayBuilder& BytecodeArrayBuilder::DefineKeyedOwnPropertyInLiteral(
871    Register object, Register name, DefineKeyedOwnPropertyInLiteralFlags flags,
872    int feedback_slot) {
873  OutputDefineKeyedOwnPropertyInLiteral(object, name, flags, feedback_slot);
874  return *this;
875}
876
877BytecodeArrayBuilder& BytecodeArrayBuilder::CollectTypeProfile(int position) {
878  OutputCollectTypeProfile(position);
879  return *this;
880}
881
882BytecodeArrayBuilder& BytecodeArrayBuilder::SetNamedProperty(
883    Register object, size_t name_index, int feedback_slot,
884    LanguageMode language_mode) {
885  // Ensure that language mode is in sync with the IC slot kind.
886  DCHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(
887                FeedbackVector::ToSlot(feedback_slot))),
888            language_mode);
889  OutputSetNamedProperty(object, name_index, feedback_slot);
890  return *this;
891}
892
893BytecodeArrayBuilder& BytecodeArrayBuilder::SetNamedProperty(
894    Register object, const AstRawString* name, int feedback_slot,
895    LanguageMode language_mode) {
896  size_t name_index = GetConstantPoolEntry(name);
897  return SetNamedProperty(object, name_index, feedback_slot, language_mode);
898}
899
900BytecodeArrayBuilder& BytecodeArrayBuilder::DefineNamedOwnProperty(
901    Register object, const AstRawString* name, int feedback_slot) {
902  size_t name_index = GetConstantPoolEntry(name);
903  // Ensure that the store operation is in sync with the IC slot kind.
904  DCHECK_EQ(
905      FeedbackSlotKind::kDefineNamedOwn,
906      feedback_vector_spec()->GetKind(FeedbackVector::ToSlot(feedback_slot)));
907  OutputDefineNamedOwnProperty(object, name_index, feedback_slot);
908  return *this;
909}
910
911BytecodeArrayBuilder& BytecodeArrayBuilder::SetKeyedProperty(
912    Register object, Register key, int feedback_slot,
913    LanguageMode language_mode) {
914  // Ensure that language mode is in sync with the IC slot kind.
915  DCHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(
916                FeedbackVector::ToSlot(feedback_slot))),
917            language_mode);
918  OutputSetKeyedProperty(object, key, feedback_slot);
919  return *this;
920}
921
922BytecodeArrayBuilder& BytecodeArrayBuilder::DefineKeyedOwnProperty(
923    Register object, Register key, int feedback_slot) {
924  // Ensure that the IC uses a strict language mode, as this is the only
925  // supported mode for this use case.
926  DCHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(
927                FeedbackVector::ToSlot(feedback_slot))),
928            LanguageMode::kStrict);
929  OutputDefineKeyedOwnProperty(object, key, feedback_slot);
930  return *this;
931}
932
933BytecodeArrayBuilder& BytecodeArrayBuilder::StoreInArrayLiteral(
934    Register array, Register index, int feedback_slot) {
935  OutputStaInArrayLiteral(array, index, feedback_slot);
936  return *this;
937}
938
939BytecodeArrayBuilder& BytecodeArrayBuilder::StoreClassFieldsInitializer(
940    Register constructor, int feedback_slot) {
941  size_t name_index = ClassFieldsSymbolConstantPoolEntry();
942  return SetNamedProperty(constructor, name_index, feedback_slot,
943                          LanguageMode::kStrict);
944}
945
946BytecodeArrayBuilder& BytecodeArrayBuilder::LoadClassFieldsInitializer(
947    Register constructor, int feedback_slot) {
948  size_t name_index = ClassFieldsSymbolConstantPoolEntry();
949  OutputGetNamedProperty(constructor, name_index, feedback_slot);
950  return *this;
951}
952
953BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(
954    size_t shared_function_info_entry, int slot, int flags) {
955  OutputCreateClosure(shared_function_info_entry, slot, flags);
956  return *this;
957}
958
959BytecodeArrayBuilder& BytecodeArrayBuilder::CreateBlockContext(
960    const Scope* scope) {
961  size_t entry = GetConstantPoolEntry(scope);
962  OutputCreateBlockContext(entry);
963  return *this;
964}
965
966BytecodeArrayBuilder& BytecodeArrayBuilder::CreateCatchContext(
967    Register exception, const Scope* scope) {
968  size_t scope_index = GetConstantPoolEntry(scope);
969  OutputCreateCatchContext(exception, scope_index);
970  return *this;
971}
972
973BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(
974    const Scope* scope, int slots) {
975  size_t scope_index = GetConstantPoolEntry(scope);
976  OutputCreateFunctionContext(scope_index, slots);
977  return *this;
978}
979
980BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEvalContext(
981    const Scope* scope, int slots) {
982  size_t scope_index = GetConstantPoolEntry(scope);
983  OutputCreateEvalContext(scope_index, slots);
984  return *this;
985}
986
987BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext(
988    Register object, const Scope* scope) {
989  size_t scope_index = GetConstantPoolEntry(scope);
990  OutputCreateWithContext(object, scope_index);
991  return *this;
992}
993
994BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
995    CreateArgumentsType type) {
996  switch (type) {
997    case CreateArgumentsType::kMappedArguments:
998      OutputCreateMappedArguments();
999      break;
1000    case CreateArgumentsType::kUnmappedArguments:
1001      OutputCreateUnmappedArguments();
1002      break;
1003    case CreateArgumentsType::kRestParameter:
1004      OutputCreateRestParameter();
1005      break;
1006    default:
1007      UNREACHABLE();
1008  }
1009  return *this;
1010}
1011
1012BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
1013    const AstRawString* pattern, int literal_index, int flags) {
1014  size_t pattern_entry = GetConstantPoolEntry(pattern);
1015  OutputCreateRegExpLiteral(pattern_entry, literal_index, flags);
1016  return *this;
1017}
1018
1019BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyArrayLiteral(
1020    int literal_index) {
1021  OutputCreateEmptyArrayLiteral(literal_index);
1022  return *this;
1023}
1024
1025BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
1026    size_t constant_elements_entry, int literal_index, int flags) {
1027  OutputCreateArrayLiteral(constant_elements_entry, literal_index, flags);
1028  return *this;
1029}
1030
1031BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayFromIterable() {
1032  OutputCreateArrayFromIterable();
1033  return *this;
1034}
1035
1036BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
1037    size_t constant_properties_entry, int literal_index, int flags) {
1038  OutputCreateObjectLiteral(constant_properties_entry, literal_index, flags);
1039  return *this;
1040}
1041
1042BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyObjectLiteral() {
1043  OutputCreateEmptyObjectLiteral();
1044  return *this;
1045}
1046
1047BytecodeArrayBuilder& BytecodeArrayBuilder::CloneObject(Register source,
1048                                                        int flags,
1049                                                        int feedback_slot) {
1050  OutputCloneObject(source, flags, feedback_slot);
1051  return *this;
1052}
1053
1054BytecodeArrayBuilder& BytecodeArrayBuilder::GetTemplateObject(
1055    size_t template_object_description_entry, int feedback_slot) {
1056  OutputGetTemplateObject(template_object_description_entry, feedback_slot);
1057  return *this;
1058}
1059
1060BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) {
1061  OutputPushContext(context);
1062  return *this;
1063}
1064
1065BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) {
1066  OutputPopContext(context);
1067  return *this;
1068}
1069
1070BytecodeArrayBuilder& BytecodeArrayBuilder::ToObject(Register out) {
1071  OutputToObject(out);
1072  return *this;
1073}
1074
1075BytecodeArrayBuilder& BytecodeArrayBuilder::ToName(Register out) {
1076  OutputToName(out);
1077  return *this;
1078}
1079
1080BytecodeArrayBuilder& BytecodeArrayBuilder::ToString() {
1081  OutputToString();
1082  return *this;
1083}
1084
1085BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumber(int feedback_slot) {
1086  OutputToNumber(feedback_slot);
1087  return *this;
1088}
1089
1090BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumeric(int feedback_slot) {
1091  OutputToNumeric(feedback_slot);
1092  return *this;
1093}
1094
1095BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
1096  // Don't generate code for a label which hasn't had a corresponding forward
1097  // jump generated already. For backwards jumps, use BindLoopHeader.
1098  if (!label->has_referrer_jump()) return *this;
1099
1100  // Flush the register optimizer when binding a label to ensure all
1101  // expected registers are valid when jumping to this label.
1102  if (register_optimizer_) register_optimizer_->Flush();
1103  bytecode_array_writer_.BindLabel(label);
1104  return *this;
1105}
1106
1107BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(
1108    BytecodeLoopHeader* loop_header) {
1109  // Flush the register optimizer when starting a loop to ensure all expected
1110  // registers are valid when jumping to the loop header.
1111  if (register_optimizer_) register_optimizer_->Flush();
1112  bytecode_array_writer_.BindLoopHeader(loop_header);
1113  return *this;
1114}
1115
1116BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeJumpTable* jump_table,
1117                                                 int case_value) {
1118  // Flush the register optimizer when binding a jump table entry to ensure
1119  // all expected registers are valid when jumping to this location.
1120  if (register_optimizer_) register_optimizer_->Flush();
1121  bytecode_array_writer_.BindJumpTableEntry(jump_table, case_value);
1122  return *this;
1123}
1124
1125BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(
1126    int handler_id, HandlerTable::CatchPrediction catch_prediction) {
1127  // The handler starts a new basic block, and any reasonable try block won't
1128  // let control fall through into it.
1129  DCHECK_IMPLIES(register_optimizer_,
1130                 register_optimizer_->EnsureAllRegistersAreFlushed());
1131  bytecode_array_writer_.BindHandlerTarget(handler_table_builder(), handler_id);
1132  handler_table_builder()->SetPrediction(handler_id, catch_prediction);
1133  return *this;
1134}
1135
1136BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryBegin(int handler_id,
1137                                                         Register context) {
1138  // Flush registers to make sure everything visible to the handler is
1139  // materialized.
1140  if (register_optimizer_) register_optimizer_->Flush();
1141  bytecode_array_writer_.BindTryRegionStart(handler_table_builder(),
1142                                            handler_id);
1143  handler_table_builder()->SetContextRegister(handler_id, context);
1144  return *this;
1145}
1146
1147BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) {
1148  bytecode_array_writer_.BindTryRegionEnd(handler_table_builder(), handler_id);
1149  return *this;
1150}
1151
1152BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
1153  DCHECK(!label->is_bound());
1154  OutputJump(label, 0);
1155  return *this;
1156}
1157
1158BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(ToBooleanMode mode,
1159                                                       BytecodeLabel* label) {
1160  DCHECK(!label->is_bound());
1161  if (mode == ToBooleanMode::kAlreadyBoolean) {
1162    OutputJumpIfTrue(label, 0);
1163  } else {
1164    DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
1165    OutputJumpIfToBooleanTrue(label, 0);
1166  }
1167  return *this;
1168}
1169
1170BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(ToBooleanMode mode,
1171                                                        BytecodeLabel* label) {
1172  DCHECK(!label->is_bound());
1173  if (mode == ToBooleanMode::kAlreadyBoolean) {
1174    OutputJumpIfFalse(label, 0);
1175  } else {
1176    DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
1177    OutputJumpIfToBooleanFalse(label, 0);
1178  }
1179  return *this;
1180}
1181
1182BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
1183  DCHECK(!label->is_bound());
1184  OutputJumpIfNull(label, 0);
1185  return *this;
1186}
1187
1188BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNull(
1189    BytecodeLabel* label) {
1190  DCHECK(!label->is_bound());
1191  OutputJumpIfNotNull(label, 0);
1192  return *this;
1193}
1194
1195BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
1196    BytecodeLabel* label) {
1197  DCHECK(!label->is_bound());
1198  OutputJumpIfUndefined(label, 0);
1199  return *this;
1200}
1201
1202BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefinedOrNull(
1203    BytecodeLabel* label) {
1204  DCHECK(!label->is_bound());
1205  OutputJumpIfUndefinedOrNull(label, 0);
1206  return *this;
1207}
1208
1209BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotUndefined(
1210    BytecodeLabel* label) {
1211  DCHECK(!label->is_bound());
1212  OutputJumpIfNotUndefined(label, 0);
1213  return *this;
1214}
1215
1216BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNil(BytecodeLabel* label,
1217                                                      Token::Value op,
1218                                                      NilValue nil) {
1219  if (op == Token::EQ) {
1220    // TODO(rmcilroy): Implement JumpIfUndetectable.
1221    return CompareUndetectable().JumpIfTrue(ToBooleanMode::kAlreadyBoolean,
1222                                            label);
1223  } else {
1224    DCHECK_EQ(Token::EQ_STRICT, op);
1225    if (nil == kUndefinedValue) {
1226      return JumpIfUndefined(label);
1227    } else {
1228      DCHECK_EQ(kNullValue, nil);
1229      return JumpIfNull(label);
1230    }
1231  }
1232}
1233
1234BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNil(BytecodeLabel* label,
1235                                                         Token::Value op,
1236                                                         NilValue nil) {
1237  if (op == Token::EQ) {
1238    // TODO(rmcilroy): Implement JumpIfUndetectable.
1239    return CompareUndetectable().JumpIfFalse(ToBooleanMode::kAlreadyBoolean,
1240                                             label);
1241  } else {
1242    DCHECK_EQ(Token::EQ_STRICT, op);
1243    if (nil == kUndefinedValue) {
1244      return JumpIfNotUndefined(label);
1245    } else {
1246      DCHECK_EQ(kNullValue, nil);
1247      return JumpIfNotNull(label);
1248    }
1249  }
1250}
1251
1252BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfJSReceiver(
1253    BytecodeLabel* label) {
1254  DCHECK(!label->is_bound());
1255  OutputJumpIfJSReceiver(label, 0);
1256  return *this;
1257}
1258
1259BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(
1260    BytecodeLoopHeader* loop_header, int loop_depth, int position) {
1261  if (position != kNoSourcePosition) {
1262    // We need to attach a non-breakable source position to JumpLoop for its
1263    // implicit stack check, so we simply add it as expression position. There
1264    // can be a prior statement position from constructs like:
1265    //
1266    //    do var x;  while (false);
1267    //
1268    // A Nop could be inserted for empty statements, but since no code
1269    // is associated with these positions, instead we force the jump loop's
1270    // expression position which eliminates the empty statement's position.
1271    latest_source_info_.ForceExpressionPosition(position);
1272  }
1273  OutputJumpLoop(loop_header, loop_depth);
1274  return *this;
1275}
1276
1277BytecodeArrayBuilder& BytecodeArrayBuilder::SwitchOnSmiNoFeedback(
1278    BytecodeJumpTable* jump_table) {
1279  OutputSwitchOnSmiNoFeedback(jump_table);
1280  return *this;
1281}
1282
1283BytecodeArrayBuilder& BytecodeArrayBuilder::SetPendingMessage() {
1284  OutputSetPendingMessage();
1285  return *this;
1286}
1287
1288BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
1289  OutputThrow();
1290  return *this;
1291}
1292
1293BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() {
1294  OutputReThrow();
1295  return *this;
1296}
1297
1298BytecodeArrayBuilder& BytecodeArrayBuilder::Abort(AbortReason reason) {
1299  DCHECK_LT(reason, AbortReason::kLastErrorMessage);
1300  DCHECK_GE(reason, AbortReason::kNoReason);
1301  OutputAbort(static_cast<int>(reason));
1302  return *this;
1303}
1304
1305BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
1306  OutputReturn();
1307  return *this;
1308}
1309
1310BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowReferenceErrorIfHole(
1311    const AstRawString* name) {
1312  size_t entry = GetConstantPoolEntry(name);
1313  OutputThrowReferenceErrorIfHole(entry);
1314  return *this;
1315}
1316
1317BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowSuperNotCalledIfHole() {
1318  OutputThrowSuperNotCalledIfHole();
1319  return *this;
1320}
1321
1322BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowSuperAlreadyCalledIfNotHole() {
1323  OutputThrowSuperAlreadyCalledIfNotHole();
1324  return *this;
1325}
1326
1327BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowIfNotSuperConstructor(
1328    Register constructor) {
1329  OutputThrowIfNotSuperConstructor(constructor);
1330  return *this;
1331}
1332
1333BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() {
1334  OutputDebugger();
1335  return *this;
1336}
1337
1338BytecodeArrayBuilder& BytecodeArrayBuilder::IncBlockCounter(
1339    int coverage_array_slot) {
1340  OutputIncBlockCounter(coverage_array_slot);
1341  return *this;
1342}
1343
1344BytecodeArrayBuilder& BytecodeArrayBuilder::ForInEnumerate(Register receiver) {
1345  OutputForInEnumerate(receiver);
1346  return *this;
1347}
1348
1349BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare(
1350    RegisterList cache_info_triple, int feedback_slot) {
1351  DCHECK_EQ(3, cache_info_triple.register_count());
1352  OutputForInPrepare(cache_info_triple, feedback_slot);
1353  return *this;
1354}
1355
1356BytecodeArrayBuilder& BytecodeArrayBuilder::ForInContinue(
1357    Register index, Register cache_length) {
1358  OutputForInContinue(index, cache_length);
1359  return *this;
1360}
1361
1362BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext(
1363    Register receiver, Register index, RegisterList cache_type_array_pair,
1364    int feedback_slot) {
1365  DCHECK_EQ(2, cache_type_array_pair.register_count());
1366  OutputForInNext(receiver, index, cache_type_array_pair, feedback_slot);
1367  return *this;
1368}
1369
1370BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
1371  OutputForInStep(index);
1372  return *this;
1373}
1374
1375BytecodeArrayBuilder& BytecodeArrayBuilder::StoreModuleVariable(int cell_index,
1376                                                                int depth) {
1377  OutputStaModuleVariable(cell_index, depth);
1378  return *this;
1379}
1380
1381BytecodeArrayBuilder& BytecodeArrayBuilder::LoadModuleVariable(int cell_index,
1382                                                               int depth) {
1383  OutputLdaModuleVariable(cell_index, depth);
1384  return *this;
1385}
1386
1387BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator(
1388    Register generator, RegisterList registers, int suspend_id) {
1389  OutputSuspendGenerator(generator, registers, registers.register_count(),
1390                         suspend_id);
1391  return *this;
1392}
1393
1394BytecodeArrayBuilder& BytecodeArrayBuilder::SwitchOnGeneratorState(
1395    Register generator, BytecodeJumpTable* jump_table) {
1396  DCHECK_EQ(jump_table->case_value_base(), 0);
1397  BytecodeNode node(CreateSwitchOnGeneratorStateNode(
1398      generator, jump_table->constant_pool_index(), jump_table->size()));
1399  WriteSwitch(&node, jump_table);
1400  return *this;
1401}
1402
1403BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator(
1404    Register generator, RegisterList registers) {
1405  OutputResumeGenerator(generator, registers, registers.register_count());
1406  return *this;
1407}
1408
1409BytecodeArrayBuilder& BytecodeArrayBuilder::CallProperty(Register callable,
1410                                                         RegisterList args,
1411                                                         int feedback_slot) {
1412  if (args.register_count() == 1) {
1413    OutputCallProperty0(callable, args[0], feedback_slot);
1414  } else if (args.register_count() == 2) {
1415    OutputCallProperty1(callable, args[0], args[1], feedback_slot);
1416  } else if (args.register_count() == 3) {
1417    OutputCallProperty2(callable, args[0], args[1], args[2], feedback_slot);
1418  } else {
1419    OutputCallProperty(callable, args, args.register_count(), feedback_slot);
1420  }
1421  return *this;
1422}
1423
1424BytecodeArrayBuilder& BytecodeArrayBuilder::CallUndefinedReceiver(
1425    Register callable, RegisterList args, int feedback_slot) {
1426  if (args.register_count() == 0) {
1427    OutputCallUndefinedReceiver0(callable, feedback_slot);
1428  } else if (args.register_count() == 1) {
1429    OutputCallUndefinedReceiver1(callable, args[0], feedback_slot);
1430  } else if (args.register_count() == 2) {
1431    OutputCallUndefinedReceiver2(callable, args[0], args[1], feedback_slot);
1432  } else {
1433    OutputCallUndefinedReceiver(callable, args, args.register_count(),
1434                                feedback_slot);
1435  }
1436  return *this;
1437}
1438
1439BytecodeArrayBuilder& BytecodeArrayBuilder::CallAnyReceiver(Register callable,
1440                                                            RegisterList args,
1441                                                            int feedback_slot) {
1442  OutputCallAnyReceiver(callable, args, args.register_count(), feedback_slot);
1443  return *this;
1444}
1445
1446BytecodeArrayBuilder& BytecodeArrayBuilder::CallWithSpread(Register callable,
1447                                                           RegisterList args,
1448                                                           int feedback_slot) {
1449  OutputCallWithSpread(callable, args, args.register_count(), feedback_slot);
1450  return *this;
1451}
1452
1453BytecodeArrayBuilder& BytecodeArrayBuilder::Construct(Register constructor,
1454                                                      RegisterList args,
1455                                                      int feedback_slot_id) {
1456  OutputConstruct(constructor, args, args.register_count(), feedback_slot_id);
1457  return *this;
1458}
1459
1460BytecodeArrayBuilder& BytecodeArrayBuilder::ConstructWithSpread(
1461    Register constructor, RegisterList args, int feedback_slot_id) {
1462  OutputConstructWithSpread(constructor, args, args.register_count(),
1463                            feedback_slot_id);
1464  return *this;
1465}
1466
1467BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1468    Runtime::FunctionId function_id, RegisterList args) {
1469  DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size);
1470  DCHECK_LE(Bytecodes::SizeForUnsignedOperand(function_id),
1471            OperandSize::kShort);
1472  if (IntrinsicsHelper::IsSupported(function_id)) {
1473    IntrinsicsHelper::IntrinsicId intrinsic_id =
1474        IntrinsicsHelper::FromRuntimeId(function_id);
1475    OutputInvokeIntrinsic(static_cast<int>(intrinsic_id), args,
1476                          args.register_count());
1477  } else {
1478    OutputCallRuntime(static_cast<int>(function_id), args,
1479                      args.register_count());
1480  }
1481  return *this;
1482}
1483
1484BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1485    Runtime::FunctionId function_id, Register arg) {
1486  return CallRuntime(function_id, RegisterList(arg));
1487}
1488
1489BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1490    Runtime::FunctionId function_id) {
1491  return CallRuntime(function_id, RegisterList());
1492}
1493
1494BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1495    Runtime::FunctionId function_id, RegisterList args,
1496    RegisterList return_pair) {
1497  DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size);
1498  DCHECK_LE(Bytecodes::SizeForUnsignedOperand(function_id),
1499            OperandSize::kShort);
1500  DCHECK_EQ(2, return_pair.register_count());
1501  OutputCallRuntimeForPair(static_cast<uint16_t>(function_id), args,
1502                           args.register_count(), return_pair);
1503  return *this;
1504}
1505
1506BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1507    Runtime::FunctionId function_id, Register arg, RegisterList return_pair) {
1508  return CallRuntimeForPair(function_id, RegisterList(arg), return_pair);
1509}
1510
1511BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index,
1512                                                          RegisterList args) {
1513  OutputCallJSRuntime(context_index, args, args.register_count());
1514  return *this;
1515}
1516
1517BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object,
1518                                                   LanguageMode language_mode) {
1519  if (language_mode == LanguageMode::kSloppy) {
1520    OutputDeletePropertySloppy(object);
1521  } else {
1522    DCHECK_EQ(language_mode, LanguageMode::kStrict);
1523    OutputDeletePropertyStrict(object);
1524  }
1525  return *this;
1526}
1527
1528size_t BytecodeArrayBuilder::GetConstantPoolEntry(
1529    const AstRawString* raw_string) {
1530  return constant_array_builder()->Insert(raw_string);
1531}
1532
1533size_t BytecodeArrayBuilder::GetConstantPoolEntry(AstBigInt bigint) {
1534  return constant_array_builder()->Insert(bigint);
1535}
1536
1537size_t BytecodeArrayBuilder::GetConstantPoolEntry(const Scope* scope) {
1538  return constant_array_builder()->Insert(scope);
1539}
1540
1541size_t BytecodeArrayBuilder::GetConstantPoolEntry(double number) {
1542  return constant_array_builder()->Insert(number);
1543}
1544
1545#define ENTRY_GETTER(NAME, ...)                            \
1546  size_t BytecodeArrayBuilder::NAME##ConstantPoolEntry() { \
1547    return constant_array_builder()->Insert##NAME();       \
1548  }
1549SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)
1550#undef ENTRY_GETTER
1551
1552BytecodeJumpTable* BytecodeArrayBuilder::AllocateJumpTable(
1553    int size, int case_value_base) {
1554  DCHECK_GT(size, 0);
1555
1556  size_t constant_pool_index = constant_array_builder()->InsertJumpTable(size);
1557
1558  return zone()->New<BytecodeJumpTable>(constant_pool_index, size,
1559                                        case_value_base, zone());
1560}
1561
1562size_t BytecodeArrayBuilder::AllocateDeferredConstantPoolEntry() {
1563  return constant_array_builder()->InsertDeferred();
1564}
1565
1566void BytecodeArrayBuilder::SetDeferredConstantPoolEntry(size_t entry,
1567                                                        Handle<Object> object) {
1568  constant_array_builder()->SetDeferredAt(entry, object);
1569}
1570
1571bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const {
1572  if (!reg.is_valid()) {
1573    return false;
1574  }
1575
1576  if (reg.is_current_context() || reg.is_function_closure()) {
1577    return true;
1578  } else if (reg.is_parameter()) {
1579    int parameter_index = reg.ToParameterIndex();
1580    return parameter_index >= 0 && parameter_index < parameter_count();
1581  } else if (reg.index() < fixed_register_count()) {
1582    return true;
1583  } else {
1584    return register_allocator()->RegisterIsLive(reg);
1585  }
1586}
1587
1588bool BytecodeArrayBuilder::RegisterListIsValid(RegisterList reg_list) const {
1589  if (reg_list.register_count() == 0) {
1590    return reg_list.first_register() == Register(0);
1591  } else {
1592    int first_reg_index = reg_list.first_register().index();
1593    for (int i = 0; i < reg_list.register_count(); i++) {
1594      if (!RegisterIsValid(Register(first_reg_index + i))) {
1595        return false;
1596      }
1597    }
1598    return true;
1599  }
1600}
1601
1602template <Bytecode bytecode, ImplicitRegisterUse implicit_register_use>
1603void BytecodeArrayBuilder::PrepareToOutputBytecode() {
1604  if (register_optimizer_)
1605    register_optimizer_->PrepareForBytecode<bytecode, implicit_register_use>();
1606}
1607
1608uint32_t BytecodeArrayBuilder::GetInputRegisterOperand(Register reg) {
1609  DCHECK(RegisterIsValid(reg));
1610  if (register_optimizer_) reg = register_optimizer_->GetInputRegister(reg);
1611  return static_cast<uint32_t>(reg.ToOperand());
1612}
1613
1614uint32_t BytecodeArrayBuilder::GetOutputRegisterOperand(Register reg) {
1615  DCHECK(RegisterIsValid(reg));
1616  if (register_optimizer_) register_optimizer_->PrepareOutputRegister(reg);
1617  return static_cast<uint32_t>(reg.ToOperand());
1618}
1619
1620uint32_t BytecodeArrayBuilder::GetInputRegisterListOperand(
1621    RegisterList reg_list) {
1622  DCHECK(RegisterListIsValid(reg_list));
1623  if (register_optimizer_)
1624    reg_list = register_optimizer_->GetInputRegisterList(reg_list);
1625  return static_cast<uint32_t>(reg_list.first_register().ToOperand());
1626}
1627
1628uint32_t BytecodeArrayBuilder::GetOutputRegisterListOperand(
1629    RegisterList reg_list) {
1630  DCHECK(RegisterListIsValid(reg_list));
1631  if (register_optimizer_)
1632    register_optimizer_->PrepareOutputRegisterList(reg_list);
1633  return static_cast<uint32_t>(reg_list.first_register().ToOperand());
1634}
1635
1636void BytecodeArrayBuilder::EmitFunctionStartSourcePosition(int position) {
1637  bytecode_array_writer_.SetFunctionEntrySourcePosition(position);
1638  // Force an expression position to make sure we have one. If the next bytecode
1639  // overwrites it, it’s fine since it would mean we have a source position
1640  // anyway.
1641  latest_source_info_.ForceExpressionPosition(position);
1642}
1643
1644std::ostream& operator<<(std::ostream& os,
1645                         const BytecodeArrayBuilder::ToBooleanMode& mode) {
1646  switch (mode) {
1647    case BytecodeArrayBuilder::ToBooleanMode::kAlreadyBoolean:
1648      return os << "AlreadyBoolean";
1649    case BytecodeArrayBuilder::ToBooleanMode::kConvertToBoolean:
1650      return os << "ConvertToBoolean";
1651  }
1652  UNREACHABLE();
1653}
1654
1655}  // namespace interpreter
1656}  // namespace internal
1657}  // namespace v8
1658