• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/interpreter/bytecode-array-builder.h"
6 
7 #include "src/globals.h"
8 #include "src/interpreter/bytecode-array-writer.h"
9 #include "src/interpreter/bytecode-dead-code-optimizer.h"
10 #include "src/interpreter/bytecode-label.h"
11 #include "src/interpreter/bytecode-peephole-optimizer.h"
12 #include "src/interpreter/bytecode-register-optimizer.h"
13 #include "src/interpreter/interpreter-intrinsics.h"
14 #include "src/objects-inl.h"
15 
16 namespace v8 {
17 namespace internal {
18 namespace interpreter {
19 
BytecodeArrayBuilder(Isolate * isolate,Zone * zone,int parameter_count,int context_count,int locals_count,FunctionLiteral * literal,SourcePositionTableBuilder::RecordingMode source_position_mode)20 BytecodeArrayBuilder::BytecodeArrayBuilder(
21     Isolate* isolate, Zone* zone, int parameter_count, int context_count,
22     int locals_count, FunctionLiteral* literal,
23     SourcePositionTableBuilder::RecordingMode source_position_mode)
24     : zone_(zone),
25       literal_(literal),
26       bytecode_generated_(false),
27       constant_array_builder_(zone),
28       handler_table_builder_(zone),
29       return_seen_in_block_(false),
30       parameter_count_(parameter_count),
31       local_register_count_(locals_count),
32       context_register_count_(context_count),
33       register_allocator_(fixed_register_count()),
34       bytecode_array_writer_(zone, &constant_array_builder_,
35                              source_position_mode),
36       pipeline_(&bytecode_array_writer_),
37       register_optimizer_(nullptr) {
38   DCHECK_GE(parameter_count_, 0);
39   DCHECK_GE(context_register_count_, 0);
40   DCHECK_GE(local_register_count_, 0);
41 
42   if (FLAG_ignition_deadcode) {
43     pipeline_ = new (zone) BytecodeDeadCodeOptimizer(pipeline_);
44   }
45 
46   if (FLAG_ignition_peephole) {
47     pipeline_ = new (zone) BytecodePeepholeOptimizer(pipeline_);
48   }
49 
50   if (FLAG_ignition_reo) {
51     register_optimizer_ = new (zone) BytecodeRegisterOptimizer(
52         zone, &register_allocator_, fixed_register_count(), parameter_count,
53         pipeline_);
54   }
55 
56   return_position_ = literal ? literal->return_position() : kNoSourcePosition;
57 }
58 
first_context_register() const59 Register BytecodeArrayBuilder::first_context_register() const {
60   DCHECK_GT(context_register_count_, 0);
61   return Register(local_register_count_);
62 }
63 
last_context_register() const64 Register BytecodeArrayBuilder::last_context_register() const {
65   DCHECK_GT(context_register_count_, 0);
66   return Register(local_register_count_ + context_register_count_ - 1);
67 }
68 
Parameter(int parameter_index) const69 Register BytecodeArrayBuilder::Parameter(int parameter_index) const {
70   DCHECK_GE(parameter_index, 0);
71   return Register::FromParameterIndex(parameter_index, parameter_count());
72 }
73 
Local(int index) const74 Register BytecodeArrayBuilder::Local(int index) const {
75   // TODO(marja): Make a DCHECK once crbug.com/706234 is fixed.
76   CHECK_LT(index, locals_count());
77   return Register(index);
78 }
79 
ToBytecodeArray(Isolate * isolate)80 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) {
81   DCHECK(return_seen_in_block_);
82   DCHECK(!bytecode_generated_);
83   bytecode_generated_ = true;
84 
85   int register_count = total_register_count();
86 
87   if (register_optimizer_) {
88     register_optimizer_->Flush();
89     register_count = register_optimizer_->maxiumum_register_index() + 1;
90   }
91 
92   Handle<FixedArray> handler_table =
93       handler_table_builder()->ToHandlerTable(isolate);
94   return pipeline_->ToBytecodeArray(isolate, register_count, parameter_count(),
95                                     handler_table);
96 }
97 
CurrentSourcePosition(Bytecode bytecode)98 BytecodeSourceInfo BytecodeArrayBuilder::CurrentSourcePosition(
99     Bytecode bytecode) {
100   BytecodeSourceInfo source_position;
101   if (latest_source_info_.is_valid()) {
102     // Statement positions need to be emitted immediately.  Expression
103     // positions can be pushed back until a bytecode is found that can
104     // throw (if expression position filtering is turned on). We only
105     // invalidate the existing source position information if it is used.
106     if (latest_source_info_.is_statement() ||
107         !FLAG_ignition_filter_expression_positions ||
108         !Bytecodes::IsWithoutExternalSideEffects(bytecode)) {
109       source_position = latest_source_info_;
110       latest_source_info_.set_invalid();
111     }
112   }
113   return source_position;
114 }
115 
116 namespace {
117 
118 template <OperandTypeInfo type_info>
119 class UnsignedOperandHelper {
120  public:
INLINE(static uint32_t Convert (BytecodeArrayBuilder * builder,size_t value))121   INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, size_t value)) {
122     DCHECK(IsValid(value));
123     return static_cast<uint32_t>(value);
124   }
125 
INLINE(static uint32_t Convert (BytecodeArrayBuilder * builder,int value))126   INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, int value)) {
127     DCHECK_GE(value, 0);
128     return Convert(builder, static_cast<size_t>(value));
129   }
130 
131  private:
IsValid(size_t value)132   static bool IsValid(size_t value) {
133     switch (type_info) {
134       case OperandTypeInfo::kFixedUnsignedByte:
135         return value <= kMaxUInt8;
136       case OperandTypeInfo::kFixedUnsignedShort:
137         return value <= kMaxUInt16;
138       case OperandTypeInfo::kScalableUnsignedByte:
139         return value <= kMaxUInt32;
140       default:
141         UNREACHABLE();
142         return false;
143     }
144   }
145 };
146 
147 template <OperandType>
148 class OperandHelper {};
149 
150 #define DEFINE_UNSIGNED_OPERAND_HELPER(Name, Type) \
151   template <>                                      \
152   class OperandHelper<OperandType::k##Name>        \
153       : public UnsignedOperandHelper<Type> {};
154 UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
155 UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
156 #undef DEFINE_UNSIGNED_OPERAND_HELPER
157 
158 template <>
159 class OperandHelper<OperandType::kImm> {
160  public:
INLINE(static uint32_t Convert (BytecodeArrayBuilder * builder,int value))161   INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, int value)) {
162     return static_cast<uint32_t>(value);
163   }
164 };
165 
166 template <>
167 class OperandHelper<OperandType::kReg> {
168  public:
INLINE(static uint32_t Convert (BytecodeArrayBuilder * builder,Register reg))169   INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, Register reg)) {
170     return builder->GetInputRegisterOperand(reg);
171   }
172 };
173 
174 template <>
175 class OperandHelper<OperandType::kRegList> {
176  public:
INLINE(static uint32_t Convert (BytecodeArrayBuilder * builder,RegisterList reg_list))177   INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
178                                  RegisterList reg_list)) {
179     return builder->GetInputRegisterListOperand(reg_list);
180   }
181 };
182 
183 template <>
184 class OperandHelper<OperandType::kRegPair> {
185  public:
INLINE(static uint32_t Convert (BytecodeArrayBuilder * builder,RegisterList reg_list))186   INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
187                                  RegisterList reg_list)) {
188     DCHECK_EQ(reg_list.register_count(), 2);
189     return builder->GetInputRegisterListOperand(reg_list);
190   }
191 };
192 
193 template <>
194 class OperandHelper<OperandType::kRegOut> {
195  public:
INLINE(static uint32_t Convert (BytecodeArrayBuilder * builder,Register reg))196   INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, Register reg)) {
197     return builder->GetOutputRegisterOperand(reg);
198   }
199 };
200 
201 template <>
202 class OperandHelper<OperandType::kRegOutPair> {
203  public:
INLINE(static uint32_t Convert (BytecodeArrayBuilder * builder,RegisterList reg_list))204   INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
205                                  RegisterList reg_list)) {
206     DCHECK_EQ(2, reg_list.register_count());
207     return builder->GetOutputRegisterListOperand(reg_list);
208   }
209 };
210 
211 template <>
212 class OperandHelper<OperandType::kRegOutTriple> {
213  public:
INLINE(static uint32_t Convert (BytecodeArrayBuilder * builder,RegisterList reg_list))214   INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
215                                  RegisterList reg_list)) {
216     DCHECK_EQ(3, reg_list.register_count());
217     return builder->GetOutputRegisterListOperand(reg_list);
218   }
219 };
220 
221 }  // namespace
222 
223 template <Bytecode bytecode, AccumulatorUse accumulator_use,
224           OperandType... operand_types>
225 class BytecodeNodeBuilder {
226  public:
227   template <typename... Operands>
INLINE(static BytecodeNode Make (BytecodeArrayBuilder * builder,BytecodeSourceInfo source_info,Operands...operands))228   INLINE(static BytecodeNode Make(BytecodeArrayBuilder* builder,
229                                   BytecodeSourceInfo source_info,
230                                   Operands... operands)) {
231     builder->PrepareToOutputBytecode<bytecode, accumulator_use>();
232     // The "OperandHelper<operand_types>::Convert(builder, operands)..." will
233     // expand both the OperandType... and Operands... parameter packs e.g. for:
234     //   BytecodeNodeBuilder<OperandType::kReg, OperandType::kImm>::Make<
235     //       Register, int>(..., Register reg, int immediate)
236     // the code will expand into:
237     //    OperandHelper<OperandType::kReg>::Convert(builder, reg),
238     //    OperandHelper<OperandType::kImm>::Convert(builder, immediate),
239     return BytecodeNode::Create<bytecode, accumulator_use, operand_types...>(
240         source_info,
241         OperandHelper<operand_types>::Convert(builder, operands)...);
242   }
243 };
244 
245 #define DEFINE_BYTECODE_OUTPUT(name, ...)                                \
246   template <typename... Operands>                                        \
247   void BytecodeArrayBuilder::Output##name(Operands... operands) {        \
248     static_assert(sizeof...(Operands) <= Bytecodes::kMaxOperands,        \
249                   "too many operands for bytecode");                     \
250     BytecodeNode node(                                                   \
251         BytecodeNodeBuilder<Bytecode::k##name, __VA_ARGS__>::Make<       \
252             Operands...>(this, CurrentSourcePosition(Bytecode::k##name), \
253                          operands...));                                  \
254     pipeline()->Write(&node);                                            \
255   }                                                                      \
256                                                                          \
257   template <typename... Operands>                                        \
258   void BytecodeArrayBuilder::Output##name(BytecodeLabel* label,          \
259                                           Operands... operands) {        \
260     DCHECK(Bytecodes::IsJump(Bytecode::k##name));                        \
261     BytecodeNode node(                                                   \
262         BytecodeNodeBuilder<Bytecode::k##name, __VA_ARGS__>::Make<       \
263             Operands...>(this, CurrentSourcePosition(Bytecode::k##name), \
264                          operands...));                                  \
265     pipeline()->WriteJump(&node, label);                                 \
266     LeaveBasicBlock();                                                   \
267   }
BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT)268 BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT)
269 #undef DEFINE_BYTECODE_OUTPUT
270 
271 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
272                                                             Register reg,
273                                                             int feedback_slot) {
274   switch (op) {
275     case Token::Value::ADD:
276       OutputAdd(reg, feedback_slot);
277       break;
278     case Token::Value::SUB:
279       OutputSub(reg, feedback_slot);
280       break;
281     case Token::Value::MUL:
282       OutputMul(reg, feedback_slot);
283       break;
284     case Token::Value::DIV:
285       OutputDiv(reg, feedback_slot);
286       break;
287     case Token::Value::MOD:
288       OutputMod(reg, feedback_slot);
289       break;
290     case Token::Value::BIT_OR:
291       OutputBitwiseOr(reg, feedback_slot);
292       break;
293     case Token::Value::BIT_XOR:
294       OutputBitwiseXor(reg, feedback_slot);
295       break;
296     case Token::Value::BIT_AND:
297       OutputBitwiseAnd(reg, feedback_slot);
298       break;
299     case Token::Value::SHL:
300       OutputShiftLeft(reg, feedback_slot);
301       break;
302     case Token::Value::SAR:
303       OutputShiftRight(reg, feedback_slot);
304       break;
305     case Token::Value::SHR:
306       OutputShiftRightLogical(reg, feedback_slot);
307       break;
308     default:
309       UNREACHABLE();
310   }
311   return *this;
312 }
313 
CountOperation(Token::Value op,int feedback_slot)314 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op,
315                                                            int feedback_slot) {
316   if (op == Token::Value::ADD) {
317     OutputInc(feedback_slot);
318   } else {
319     DCHECK_EQ(op, Token::Value::SUB);
320     OutputDec(feedback_slot);
321   }
322   return *this;
323 }
324 
LogicalNot()325 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() {
326   OutputToBooleanLogicalNot();
327   return *this;
328 }
329 
TypeOf()330 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
331   OutputTypeOf();
332   return *this;
333 }
334 
GetSuperConstructor(Register out)335 BytecodeArrayBuilder& BytecodeArrayBuilder::GetSuperConstructor(Register out) {
336   OutputGetSuperConstructor(out);
337   return *this;
338 }
339 
CompareOperation(Token::Value op,Register reg,int feedback_slot)340 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
341     Token::Value op, Register reg, int feedback_slot) {
342   switch (op) {
343     case Token::Value::EQ:
344       OutputTestEqual(reg, feedback_slot);
345       break;
346     case Token::Value::NE:
347       OutputTestNotEqual(reg, feedback_slot);
348       break;
349     case Token::Value::EQ_STRICT:
350       OutputTestEqualStrict(reg, feedback_slot);
351       break;
352     case Token::Value::LT:
353       OutputTestLessThan(reg, feedback_slot);
354       break;
355     case Token::Value::GT:
356       OutputTestGreaterThan(reg, feedback_slot);
357       break;
358     case Token::Value::LTE:
359       OutputTestLessThanOrEqual(reg, feedback_slot);
360       break;
361     case Token::Value::GTE:
362       OutputTestGreaterThanOrEqual(reg, feedback_slot);
363       break;
364     case Token::Value::INSTANCEOF:
365       OutputTestInstanceOf(reg);
366       break;
367     case Token::Value::IN:
368       OutputTestIn(reg);
369       break;
370     default:
371       UNREACHABLE();
372   }
373   return *this;
374 }
375 
LoadConstantPoolEntry(size_t entry)376 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry(
377     size_t entry) {
378   OutputLdaConstant(entry);
379   return *this;
380 }
381 
LoadLiteral(v8::internal::Smi * smi)382 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
383     v8::internal::Smi* smi) {
384   int32_t raw_smi = smi->value();
385   if (raw_smi == 0) {
386     OutputLdaZero();
387   } else {
388     OutputLdaSmi(raw_smi);
389   }
390   return *this;
391 }
392 
LoadLiteral(const AstRawString * raw_string)393 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
394     const AstRawString* raw_string) {
395   size_t entry = GetConstantPoolEntry(raw_string);
396   OutputLdaConstant(entry);
397   return *this;
398 }
399 
LoadLiteral(const Scope * scope)400 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(const Scope* scope) {
401   size_t entry = GetConstantPoolEntry(scope);
402   OutputLdaConstant(entry);
403   return *this;
404 }
405 
LoadLiteral(const AstValue * ast_value)406 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
407     const AstValue* ast_value) {
408   if (ast_value->IsSmi()) {
409     return LoadLiteral(ast_value->AsSmi());
410   } else if (ast_value->IsUndefined()) {
411     return LoadUndefined();
412   } else if (ast_value->IsTrue()) {
413     return LoadTrue();
414   } else if (ast_value->IsFalse()) {
415     return LoadFalse();
416   } else if (ast_value->IsNull()) {
417     return LoadNull();
418   } else if (ast_value->IsTheHole()) {
419     return LoadTheHole();
420   } else if (ast_value->IsString()) {
421     return LoadLiteral(ast_value->AsString());
422   } else if (ast_value->IsHeapNumber()) {
423     size_t entry = GetConstantPoolEntry(ast_value);
424     OutputLdaConstant(entry);
425     return *this;
426   } else {
427     // This should be the only ast value type left.
428     DCHECK(ast_value->IsSymbol());
429     size_t entry;
430     switch (ast_value->AsSymbol()) {
431       case AstSymbol::kHomeObjectSymbol:
432         entry = HomeObjectSymbolConstantPoolEntry();
433         break;
434         // No default case so that we get a warning if AstSymbol changes
435     }
436     OutputLdaConstant(entry);
437     return *this;
438   }
439 }
440 
LoadUndefined()441 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
442   OutputLdaUndefined();
443   return *this;
444 }
445 
LoadNull()446 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() {
447   OutputLdaNull();
448   return *this;
449 }
450 
LoadTheHole()451 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() {
452   OutputLdaTheHole();
453   return *this;
454 }
455 
LoadTrue()456 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() {
457   OutputLdaTrue();
458   return *this;
459 }
460 
LoadFalse()461 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
462   OutputLdaFalse();
463   return *this;
464 }
465 
LoadAccumulatorWithRegister(Register reg)466 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
467     Register reg) {
468   if (register_optimizer_) {
469     register_optimizer_->DoLdar(reg, CurrentSourcePosition(Bytecode::kLdar));
470   } else {
471     OutputLdar(reg);
472   }
473   return *this;
474 }
475 
StoreAccumulatorInRegister(Register reg)476 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
477     Register reg) {
478   if (register_optimizer_) {
479     register_optimizer_->DoStar(reg, CurrentSourcePosition(Bytecode::kStar));
480   } else {
481     OutputStar(reg);
482   }
483   return *this;
484 }
485 
MoveRegister(Register from,Register to)486 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
487                                                          Register to) {
488   DCHECK(from != to);
489   if (register_optimizer_) {
490     register_optimizer_->DoMov(from, to, CurrentSourcePosition(Bytecode::kMov));
491   } else {
492     OutputMov(from, to);
493   }
494   return *this;
495 }
496 
LoadGlobal(const AstRawString * name,int feedback_slot,TypeofMode typeof_mode)497 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(const AstRawString* name,
498                                                        int feedback_slot,
499                                                        TypeofMode typeof_mode) {
500   size_t name_index = GetConstantPoolEntry(name);
501   // Ensure that typeof mode is in sync with the IC slot kind if the function
502   // literal is available (not a unit test case).
503   // TODO(ishell): check only in debug mode.
504   if (literal_) {
505     FeedbackSlot slot = FeedbackVector::ToSlot(feedback_slot);
506     CHECK_EQ(GetTypeofModeFromSlotKind(feedback_vector_spec()->GetKind(slot)),
507              typeof_mode);
508   }
509   if (typeof_mode == INSIDE_TYPEOF) {
510     OutputLdaGlobalInsideTypeof(name_index, feedback_slot);
511   } else {
512     DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
513     OutputLdaGlobal(name_index, feedback_slot);
514   }
515   return *this;
516 }
517 
StoreGlobal(const AstRawString * name,int feedback_slot,LanguageMode language_mode)518 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
519     const AstRawString* name, int feedback_slot, LanguageMode language_mode) {
520   size_t name_index = GetConstantPoolEntry(name);
521   if (language_mode == SLOPPY) {
522     OutputStaGlobalSloppy(name_index, feedback_slot);
523   } else {
524     DCHECK_EQ(language_mode, STRICT);
525     OutputStaGlobalStrict(name_index, feedback_slot);
526   }
527   return *this;
528 }
529 
LoadContextSlot(Register context,int slot_index,int depth,ContextSlotMutability mutability)530 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(
531     Register context, int slot_index, int depth,
532     ContextSlotMutability mutability) {
533   if (context.is_current_context() && depth == 0) {
534     if (mutability == kImmutableSlot) {
535       OutputLdaImmutableCurrentContextSlot(slot_index);
536     } else {
537       DCHECK_EQ(kMutableSlot, mutability);
538       OutputLdaCurrentContextSlot(slot_index);
539     }
540   } else if (mutability == kImmutableSlot) {
541     OutputLdaImmutableContextSlot(context, slot_index, depth);
542   } else {
543     DCHECK_EQ(mutability, kMutableSlot);
544     OutputLdaContextSlot(context, slot_index, depth);
545   }
546   return *this;
547 }
548 
StoreContextSlot(Register context,int slot_index,int depth)549 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
550                                                              int slot_index,
551                                                              int depth) {
552   if (context.is_current_context() && depth == 0) {
553     OutputStaCurrentContextSlot(slot_index);
554   } else {
555     OutputStaContextSlot(context, slot_index, depth);
556   }
557   return *this;
558 }
559 
LoadLookupSlot(const AstRawString * name,TypeofMode typeof_mode)560 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
561     const AstRawString* name, TypeofMode typeof_mode) {
562   size_t name_index = GetConstantPoolEntry(name);
563   if (typeof_mode == INSIDE_TYPEOF) {
564     OutputLdaLookupSlotInsideTypeof(name_index);
565   } else {
566     DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
567     OutputLdaLookupSlot(name_index);
568   }
569   return *this;
570 }
571 
LoadLookupContextSlot(const AstRawString * name,TypeofMode typeof_mode,int slot_index,int depth)572 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot(
573     const AstRawString* name, TypeofMode typeof_mode, int slot_index,
574     int depth) {
575   size_t name_index = GetConstantPoolEntry(name);
576   if (typeof_mode == INSIDE_TYPEOF) {
577     OutputLdaLookupContextSlotInsideTypeof(name_index, slot_index, depth);
578   } else {
579     DCHECK(typeof_mode == NOT_INSIDE_TYPEOF);
580     OutputLdaLookupContextSlot(name_index, slot_index, depth);
581   }
582   return *this;
583 }
584 
LoadLookupGlobalSlot(const AstRawString * name,TypeofMode typeof_mode,int feedback_slot,int depth)585 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot(
586     const AstRawString* name, TypeofMode typeof_mode, int feedback_slot,
587     int depth) {
588   size_t name_index = GetConstantPoolEntry(name);
589   if (typeof_mode == INSIDE_TYPEOF) {
590     OutputLdaLookupGlobalSlotInsideTypeof(name_index, feedback_slot, depth);
591   } else {
592     DCHECK(typeof_mode == NOT_INSIDE_TYPEOF);
593     OutputLdaLookupGlobalSlot(name_index, feedback_slot, depth);
594   }
595   return *this;
596 }
597 
StoreLookupSlot(const AstRawString * name,LanguageMode language_mode)598 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot(
599     const AstRawString* name, LanguageMode language_mode) {
600   size_t name_index = GetConstantPoolEntry(name);
601   if (language_mode == SLOPPY) {
602     OutputStaLookupSlotSloppy(name_index);
603   } else {
604     DCHECK_EQ(language_mode, STRICT);
605     OutputStaLookupSlotStrict(name_index);
606   }
607   return *this;
608 }
609 
LoadNamedProperty(Register object,const AstRawString * name,int feedback_slot)610 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
611     Register object, const AstRawString* name, int feedback_slot) {
612   size_t name_index = GetConstantPoolEntry(name);
613   OutputLdaNamedProperty(object, name_index, feedback_slot);
614   return *this;
615 }
616 
LoadKeyedProperty(Register object,int feedback_slot)617 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
618     Register object, int feedback_slot) {
619   OutputLdaKeyedProperty(object, feedback_slot);
620   return *this;
621 }
622 
LoadIteratorProperty(Register object,int feedback_slot)623 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadIteratorProperty(
624     Register object, int feedback_slot) {
625   size_t name_index = IteratorSymbolConstantPoolEntry();
626   OutputLdaNamedProperty(object, name_index, feedback_slot);
627   return *this;
628 }
629 
LoadAsyncIteratorProperty(Register object,int feedback_slot)630 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAsyncIteratorProperty(
631     Register object, int feedback_slot) {
632   size_t name_index = AsyncIteratorSymbolConstantPoolEntry();
633   OutputLdaNamedProperty(object, name_index, feedback_slot);
634   return *this;
635 }
636 
StoreDataPropertyInLiteral(Register object,Register name,DataPropertyInLiteralFlags flags,int feedback_slot)637 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreDataPropertyInLiteral(
638     Register object, Register name, DataPropertyInLiteralFlags flags,
639     int feedback_slot) {
640   OutputStaDataPropertyInLiteral(object, name, flags, feedback_slot);
641   return *this;
642 }
643 
StoreNamedProperty(Register object,size_t name_index,int feedback_slot,LanguageMode language_mode)644 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
645     Register object, size_t name_index, int feedback_slot,
646     LanguageMode language_mode) {
647   // Ensure that language mode is in sync with the IC slot kind if the function
648   // literal is available (not a unit test case).
649   // TODO(ishell): check only in debug mode.
650   if (literal_) {
651     FeedbackSlot slot = FeedbackVector::ToSlot(feedback_slot);
652     CHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(slot)),
653              language_mode);
654   }
655   if (language_mode == SLOPPY) {
656     OutputStaNamedPropertySloppy(object, name_index, feedback_slot);
657   } else {
658     DCHECK_EQ(language_mode, STRICT);
659     OutputStaNamedPropertyStrict(object, name_index, feedback_slot);
660   }
661   return *this;
662 }
663 
StoreNamedProperty(Register object,const AstRawString * name,int feedback_slot,LanguageMode language_mode)664 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
665     Register object, const AstRawString* name, int feedback_slot,
666     LanguageMode language_mode) {
667   size_t name_index = GetConstantPoolEntry(name);
668   return StoreNamedProperty(object, name_index, feedback_slot, language_mode);
669 }
670 
StoreNamedOwnProperty(Register object,const AstRawString * name,int feedback_slot)671 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedOwnProperty(
672     Register object, const AstRawString* name, int feedback_slot) {
673   size_t name_index = GetConstantPoolEntry(name);
674   // Ensure that the store operation is in sync with the IC slot kind if
675   // the function literal is available (not a unit test case).
676   // TODO(ishell): check only in debug mode.
677   if (literal_) {
678     FeedbackSlot slot = FeedbackVector::ToSlot(feedback_slot);
679     CHECK_EQ(FeedbackSlotKind::kStoreOwnNamed,
680              feedback_vector_spec()->GetKind(slot));
681   }
682   OutputStaNamedOwnProperty(object, name_index, feedback_slot);
683   return *this;
684 }
685 
StoreKeyedProperty(Register object,Register key,int feedback_slot,LanguageMode language_mode)686 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty(
687     Register object, Register key, int feedback_slot,
688     LanguageMode language_mode) {
689   // Ensure that language mode is in sync with the IC slot kind if the function
690   // literal is available (not a unit test case).
691   // TODO(ishell): check only in debug mode.
692   if (literal_) {
693     FeedbackSlot slot = FeedbackVector::ToSlot(feedback_slot);
694     CHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(slot)),
695              language_mode);
696   }
697   if (language_mode == SLOPPY) {
698     OutputStaKeyedPropertySloppy(object, key, feedback_slot);
699   } else {
700     DCHECK_EQ(language_mode, STRICT);
701     OutputStaKeyedPropertyStrict(object, key, feedback_slot);
702   }
703   return *this;
704 }
705 
StoreHomeObjectProperty(Register object,int feedback_slot,LanguageMode language_mode)706 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreHomeObjectProperty(
707     Register object, int feedback_slot, LanguageMode language_mode) {
708   size_t name_index = HomeObjectSymbolConstantPoolEntry();
709   return StoreNamedProperty(object, name_index, feedback_slot, language_mode);
710 }
711 
CreateClosure(size_t shared_function_info_entry,int slot,int flags)712 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(
713     size_t shared_function_info_entry, int slot, int flags) {
714   OutputCreateClosure(shared_function_info_entry, slot, flags);
715   return *this;
716 }
717 
CreateBlockContext(const Scope * scope)718 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateBlockContext(
719     const Scope* scope) {
720   size_t entry = GetConstantPoolEntry(scope);
721   OutputCreateBlockContext(entry);
722   return *this;
723 }
724 
CreateCatchContext(Register exception,const AstRawString * name,const Scope * scope)725 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateCatchContext(
726     Register exception, const AstRawString* name, const Scope* scope) {
727   size_t name_index = GetConstantPoolEntry(name);
728   size_t scope_index = GetConstantPoolEntry(scope);
729   OutputCreateCatchContext(exception, name_index, scope_index);
730   return *this;
731 }
732 
CreateFunctionContext(int slots)733 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(int slots) {
734   OutputCreateFunctionContext(slots);
735   return *this;
736 }
737 
CreateEvalContext(int slots)738 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEvalContext(int slots) {
739   OutputCreateEvalContext(slots);
740   return *this;
741 }
742 
CreateWithContext(Register object,const Scope * scope)743 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext(
744     Register object, const Scope* scope) {
745   size_t scope_index = GetConstantPoolEntry(scope);
746   OutputCreateWithContext(object, scope_index);
747   return *this;
748 }
749 
CreateArguments(CreateArgumentsType type)750 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
751     CreateArgumentsType type) {
752   switch (type) {
753     case CreateArgumentsType::kMappedArguments:
754       OutputCreateMappedArguments();
755       break;
756     case CreateArgumentsType::kUnmappedArguments:
757       OutputCreateUnmappedArguments();
758       break;
759     case CreateArgumentsType::kRestParameter:
760       OutputCreateRestParameter();
761       break;
762     default:
763       UNREACHABLE();
764   }
765   return *this;
766 }
767 
CreateRegExpLiteral(const AstRawString * pattern,int literal_index,int flags)768 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
769     const AstRawString* pattern, int literal_index, int flags) {
770   size_t pattern_entry = GetConstantPoolEntry(pattern);
771   OutputCreateRegExpLiteral(pattern_entry, literal_index, flags);
772   return *this;
773 }
774 
CreateArrayLiteral(size_t constant_elements_entry,int literal_index,int flags)775 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
776     size_t constant_elements_entry, int literal_index, int flags) {
777   OutputCreateArrayLiteral(constant_elements_entry, literal_index, flags);
778   return *this;
779 }
780 
CreateObjectLiteral(size_t constant_properties_entry,int literal_index,int flags,Register output)781 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
782     size_t constant_properties_entry, int literal_index, int flags,
783     Register output) {
784   OutputCreateObjectLiteral(constant_properties_entry, literal_index, flags,
785                             output);
786   return *this;
787 }
788 
PushContext(Register context)789 BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) {
790   OutputPushContext(context);
791   return *this;
792 }
793 
PopContext(Register context)794 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) {
795   OutputPopContext(context);
796   return *this;
797 }
798 
ConvertAccumulatorToObject(Register out)799 BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToObject(
800     Register out) {
801   OutputToObject(out);
802   return *this;
803 }
804 
ConvertAccumulatorToName(Register out)805 BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToName(
806     Register out) {
807   OutputToName(out);
808   return *this;
809 }
810 
ConvertAccumulatorToNumber(Register out)811 BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToNumber(
812     Register out) {
813   OutputToNumber(out);
814   return *this;
815 }
816 
Bind(BytecodeLabel * label)817 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
818   // Flush the register optimizer when binding a label to ensure all
819   // expected registers are valid when jumping to this label.
820   if (register_optimizer_) register_optimizer_->Flush();
821   pipeline_->BindLabel(label);
822   LeaveBasicBlock();
823   return *this;
824 }
825 
Bind(const BytecodeLabel & target,BytecodeLabel * label)826 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target,
827                                                  BytecodeLabel* label) {
828   pipeline_->BindLabel(target, label);
829   LeaveBasicBlock();
830   return *this;
831 }
832 
Jump(BytecodeLabel * label)833 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
834   DCHECK(!label->is_bound());
835   OutputJump(label, 0);
836   return *this;
837 }
838 
JumpIfTrue(BytecodeLabel * label)839 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) {
840   // The peephole optimizer attempts to simplify JumpIfToBooleanTrue
841   // to JumpIfTrue.
842   DCHECK(!label->is_bound());
843   OutputJumpIfToBooleanTrue(label, 0);
844   return *this;
845 }
846 
JumpIfFalse(BytecodeLabel * label)847 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) {
848   DCHECK(!label->is_bound());
849   OutputJumpIfToBooleanFalse(label, 0);
850   return *this;
851 }
852 
JumpIfNull(BytecodeLabel * label)853 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
854   DCHECK(!label->is_bound());
855   OutputJumpIfNull(label, 0);
856   return *this;
857 }
858 
JumpIfUndefined(BytecodeLabel * label)859 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
860     BytecodeLabel* label) {
861   DCHECK(!label->is_bound());
862   OutputJumpIfUndefined(label, 0);
863   return *this;
864 }
865 
JumpIfNotHole(BytecodeLabel * label)866 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole(
867     BytecodeLabel* label) {
868   DCHECK(!label->is_bound());
869   OutputJumpIfNotHole(label, 0);
870   return *this;
871 }
872 
JumpIfJSReceiver(BytecodeLabel * label)873 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfJSReceiver(
874     BytecodeLabel* label) {
875   DCHECK(!label->is_bound());
876   OutputJumpIfJSReceiver(label, 0);
877   return *this;
878 }
879 
JumpLoop(BytecodeLabel * label,int loop_depth)880 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label,
881                                                      int loop_depth) {
882   DCHECK(label->is_bound());
883   OutputJumpLoop(label, 0, loop_depth);
884   return *this;
885 }
886 
StackCheck(int position)887 BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) {
888   if (position != kNoSourcePosition) {
889     // We need to attach a non-breakable source position to a stack
890     // check, so we simply add it as expression position. There can be
891     // a prior statement position from constructs like:
892     //
893     //    do var x;  while (false);
894     //
895     // A Nop could be inserted for empty statements, but since no code
896     // is associated with these positions, instead we force the stack
897     // check's expression position which eliminates the empty
898     // statement's position.
899     latest_source_info_.ForceExpressionPosition(position);
900   }
901   OutputStackCheck();
902   return *this;
903 }
904 
SetPendingMessage()905 BytecodeArrayBuilder& BytecodeArrayBuilder::SetPendingMessage() {
906   OutputSetPendingMessage();
907   return *this;
908 }
909 
Throw()910 BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
911   OutputThrow();
912   return *this;
913 }
914 
ReThrow()915 BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() {
916   OutputReThrow();
917   return *this;
918 }
919 
Return()920 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
921   SetReturnPosition();
922   OutputReturn();
923   return_seen_in_block_ = true;
924   return *this;
925 }
926 
Debugger()927 BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() {
928   OutputDebugger();
929   return *this;
930 }
931 
ForInPrepare(Register receiver,RegisterList cache_info_triple)932 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare(
933     Register receiver, RegisterList cache_info_triple) {
934   DCHECK_EQ(3, cache_info_triple.register_count());
935   OutputForInPrepare(receiver, cache_info_triple);
936   return *this;
937 }
938 
ForInContinue(Register index,Register cache_length)939 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInContinue(
940     Register index, Register cache_length) {
941   OutputForInContinue(index, cache_length);
942   return *this;
943 }
944 
ForInNext(Register receiver,Register index,RegisterList cache_type_array_pair,int feedback_slot)945 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext(
946     Register receiver, Register index, RegisterList cache_type_array_pair,
947     int feedback_slot) {
948   DCHECK_EQ(2, cache_type_array_pair.register_count());
949   OutputForInNext(receiver, index, cache_type_array_pair, feedback_slot);
950   return *this;
951 }
952 
ForInStep(Register index)953 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
954   OutputForInStep(index);
955   return *this;
956 }
957 
StoreModuleVariable(int cell_index,int depth)958 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreModuleVariable(int cell_index,
959                                                                 int depth) {
960   OutputStaModuleVariable(cell_index, depth);
961   return *this;
962 }
963 
LoadModuleVariable(int cell_index,int depth)964 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadModuleVariable(int cell_index,
965                                                                int depth) {
966   OutputLdaModuleVariable(cell_index, depth);
967   return *this;
968 }
969 
SuspendGenerator(Register generator)970 BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator(
971     Register generator) {
972   OutputSuspendGenerator(generator);
973   return *this;
974 }
975 
ResumeGenerator(Register generator)976 BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator(
977     Register generator) {
978   OutputResumeGenerator(generator);
979   return *this;
980 }
981 
MarkHandler(int handler_id,HandlerTable::CatchPrediction catch_prediction)982 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(
983     int handler_id, HandlerTable::CatchPrediction catch_prediction) {
984   BytecodeLabel handler;
985   Bind(&handler);
986   handler_table_builder()->SetHandlerTarget(handler_id, handler.offset());
987   handler_table_builder()->SetPrediction(handler_id, catch_prediction);
988   return *this;
989 }
990 
MarkTryBegin(int handler_id,Register context)991 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryBegin(int handler_id,
992                                                          Register context) {
993   BytecodeLabel try_begin;
994   Bind(&try_begin);
995   handler_table_builder()->SetTryRegionStart(handler_id, try_begin.offset());
996   handler_table_builder()->SetContextRegister(handler_id, context);
997   return *this;
998 }
999 
MarkTryEnd(int handler_id)1000 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) {
1001   BytecodeLabel try_end;
1002   Bind(&try_end);
1003   handler_table_builder()->SetTryRegionEnd(handler_id, try_end.offset());
1004   return *this;
1005 }
1006 
Call(Register callable,RegisterList args,int feedback_slot,Call::CallType call_type,TailCallMode tail_call_mode)1007 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
1008                                                  RegisterList args,
1009                                                  int feedback_slot,
1010                                                  Call::CallType call_type,
1011                                                  TailCallMode tail_call_mode) {
1012   if (tail_call_mode == TailCallMode::kDisallow) {
1013     if (call_type == Call::NAMED_PROPERTY_CALL ||
1014         call_type == Call::KEYED_PROPERTY_CALL) {
1015       OutputCallProperty(callable, args, args.register_count(), feedback_slot);
1016     } else {
1017       OutputCall(callable, args, args.register_count(), feedback_slot);
1018     }
1019   } else {
1020     DCHECK(tail_call_mode == TailCallMode::kAllow);
1021     OutputTailCall(callable, args, args.register_count(), feedback_slot);
1022   }
1023   return *this;
1024 }
1025 
CallWithSpread(Register callable,RegisterList args)1026 BytecodeArrayBuilder& BytecodeArrayBuilder::CallWithSpread(Register callable,
1027                                                            RegisterList args) {
1028   OutputCallWithSpread(callable, args, args.register_count());
1029   return *this;
1030 }
1031 
Construct(Register constructor,RegisterList args,int feedback_slot_id)1032 BytecodeArrayBuilder& BytecodeArrayBuilder::Construct(Register constructor,
1033                                                       RegisterList args,
1034                                                       int feedback_slot_id) {
1035   OutputConstruct(constructor, args, args.register_count(), feedback_slot_id);
1036   return *this;
1037 }
1038 
ConstructWithSpread(Register constructor,RegisterList args)1039 BytecodeArrayBuilder& BytecodeArrayBuilder::ConstructWithSpread(
1040     Register constructor, RegisterList args) {
1041   OutputConstructWithSpread(constructor, args, args.register_count());
1042   return *this;
1043 }
1044 
CallRuntime(Runtime::FunctionId function_id,RegisterList args)1045 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1046     Runtime::FunctionId function_id, RegisterList args) {
1047   DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size);
1048   DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort);
1049   if (IntrinsicsHelper::IsSupported(function_id)) {
1050     IntrinsicsHelper::IntrinsicId intrinsic_id =
1051         IntrinsicsHelper::FromRuntimeId(function_id);
1052     OutputInvokeIntrinsic(static_cast<int>(intrinsic_id), args,
1053                           args.register_count());
1054   } else {
1055     OutputCallRuntime(static_cast<int>(function_id), args,
1056                       args.register_count());
1057   }
1058   return *this;
1059 }
1060 
CallRuntime(Runtime::FunctionId function_id,Register arg)1061 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1062     Runtime::FunctionId function_id, Register arg) {
1063   return CallRuntime(function_id, RegisterList(arg.index(), 1));
1064 }
1065 
CallRuntime(Runtime::FunctionId function_id)1066 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1067     Runtime::FunctionId function_id) {
1068   return CallRuntime(function_id, RegisterList());
1069 }
1070 
CallRuntimeForPair(Runtime::FunctionId function_id,RegisterList args,RegisterList return_pair)1071 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1072     Runtime::FunctionId function_id, RegisterList args,
1073     RegisterList return_pair) {
1074   DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size);
1075   DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort);
1076   DCHECK_EQ(2, return_pair.register_count());
1077   OutputCallRuntimeForPair(static_cast<uint16_t>(function_id), args,
1078                            args.register_count(), return_pair);
1079   return *this;
1080 }
1081 
CallRuntimeForPair(Runtime::FunctionId function_id,Register arg,RegisterList return_pair)1082 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1083     Runtime::FunctionId function_id, Register arg, RegisterList return_pair) {
1084   return CallRuntimeForPair(function_id, RegisterList(arg.index(), 1),
1085                             return_pair);
1086 }
1087 
CallJSRuntime(int context_index,RegisterList args)1088 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index,
1089                                                           RegisterList args) {
1090   OutputCallJSRuntime(context_index, args, args.register_count());
1091   return *this;
1092 }
1093 
Delete(Register object,LanguageMode language_mode)1094 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object,
1095                                                    LanguageMode language_mode) {
1096   if (language_mode == SLOPPY) {
1097     OutputDeletePropertySloppy(object);
1098   } else {
1099     DCHECK_EQ(language_mode, STRICT);
1100     OutputDeletePropertyStrict(object);
1101   }
1102   return *this;
1103 }
1104 
GetConstantPoolEntry(const AstRawString * raw_string)1105 size_t BytecodeArrayBuilder::GetConstantPoolEntry(
1106     const AstRawString* raw_string) {
1107   return constant_array_builder()->Insert(raw_string);
1108 }
1109 
GetConstantPoolEntry(const AstValue * heap_number)1110 size_t BytecodeArrayBuilder::GetConstantPoolEntry(const AstValue* heap_number) {
1111   DCHECK(heap_number->IsHeapNumber());
1112   return constant_array_builder()->Insert(heap_number);
1113 }
1114 
GetConstantPoolEntry(const Scope * scope)1115 size_t BytecodeArrayBuilder::GetConstantPoolEntry(const Scope* scope) {
1116   return constant_array_builder()->Insert(scope);
1117 }
1118 
1119 #define ENTRY_GETTER(NAME, ...)                            \
1120   size_t BytecodeArrayBuilder::NAME##ConstantPoolEntry() { \
1121     return constant_array_builder()->Insert##NAME();       \
1122   }
SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)1123 SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)
1124 #undef ENTRY_GETTER
1125 
1126 size_t BytecodeArrayBuilder::AllocateDeferredConstantPoolEntry() {
1127   return constant_array_builder()->InsertDeferred();
1128 }
1129 
SetDeferredConstantPoolEntry(size_t entry,Handle<Object> object)1130 void BytecodeArrayBuilder::SetDeferredConstantPoolEntry(size_t entry,
1131                                                         Handle<Object> object) {
1132   constant_array_builder()->SetDeferredAt(entry, object);
1133 }
1134 
SetReturnPosition()1135 void BytecodeArrayBuilder::SetReturnPosition() {
1136   if (return_position_ == kNoSourcePosition) return;
1137   latest_source_info_.MakeStatementPosition(return_position_);
1138 }
1139 
RegisterIsValid(Register reg) const1140 bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const {
1141   if (!reg.is_valid()) {
1142     return false;
1143   }
1144 
1145   if (reg.is_current_context() || reg.is_function_closure() ||
1146       reg.is_new_target()) {
1147     return true;
1148   } else if (reg.is_parameter()) {
1149     int parameter_index = reg.ToParameterIndex(parameter_count());
1150     return parameter_index >= 0 && parameter_index < parameter_count();
1151   } else if (reg.index() < fixed_register_count()) {
1152     return true;
1153   } else {
1154     return register_allocator()->RegisterIsLive(reg);
1155   }
1156 }
1157 
RegisterListIsValid(RegisterList reg_list) const1158 bool BytecodeArrayBuilder::RegisterListIsValid(RegisterList reg_list) const {
1159   if (reg_list.register_count() == 0) {
1160     return reg_list.first_register() == Register(0);
1161   } else {
1162     int first_reg_index = reg_list.first_register().index();
1163     for (int i = 0; i < reg_list.register_count(); i++) {
1164       if (!RegisterIsValid(Register(first_reg_index + i))) {
1165         return false;
1166       }
1167     }
1168     return true;
1169   }
1170 }
1171 
1172 template <Bytecode bytecode, AccumulatorUse accumulator_use>
PrepareToOutputBytecode()1173 void BytecodeArrayBuilder::PrepareToOutputBytecode() {
1174   if (register_optimizer_)
1175     register_optimizer_->PrepareForBytecode<bytecode, accumulator_use>();
1176 }
1177 
GetInputRegisterOperand(Register reg)1178 uint32_t BytecodeArrayBuilder::GetInputRegisterOperand(Register reg) {
1179   DCHECK(RegisterIsValid(reg));
1180   if (register_optimizer_) reg = register_optimizer_->GetInputRegister(reg);
1181   return static_cast<uint32_t>(reg.ToOperand());
1182 }
1183 
GetOutputRegisterOperand(Register reg)1184 uint32_t BytecodeArrayBuilder::GetOutputRegisterOperand(Register reg) {
1185   DCHECK(RegisterIsValid(reg));
1186   if (register_optimizer_) register_optimizer_->PrepareOutputRegister(reg);
1187   return static_cast<uint32_t>(reg.ToOperand());
1188 }
1189 
GetInputRegisterListOperand(RegisterList reg_list)1190 uint32_t BytecodeArrayBuilder::GetInputRegisterListOperand(
1191     RegisterList reg_list) {
1192   DCHECK(RegisterListIsValid(reg_list));
1193   if (register_optimizer_)
1194     reg_list = register_optimizer_->GetInputRegisterList(reg_list);
1195   return static_cast<uint32_t>(reg_list.first_register().ToOperand());
1196 }
1197 
GetOutputRegisterListOperand(RegisterList reg_list)1198 uint32_t BytecodeArrayBuilder::GetOutputRegisterListOperand(
1199     RegisterList reg_list) {
1200   DCHECK(RegisterListIsValid(reg_list));
1201   if (register_optimizer_)
1202     register_optimizer_->PrepareOutputRegisterList(reg_list);
1203   return static_cast<uint32_t>(reg_list.first_register().ToOperand());
1204 }
1205 
1206 }  // namespace interpreter
1207 }  // namespace internal
1208 }  // namespace v8
1209