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