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