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