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