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