• 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 #ifndef V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_
6 #define V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_
7 
8 #include "src/ast/ast.h"
9 #include "src/base/compiler-specific.h"
10 #include "src/globals.h"
11 #include "src/interpreter/bytecode-array-writer.h"
12 #include "src/interpreter/bytecode-flags.h"
13 #include "src/interpreter/bytecode-register-allocator.h"
14 #include "src/interpreter/bytecode-register.h"
15 #include "src/interpreter/bytecode-source-info.h"
16 #include "src/interpreter/bytecodes.h"
17 #include "src/interpreter/constant-array-builder.h"
18 #include "src/interpreter/handler-table-builder.h"
19 #include "src/zone/zone-containers.h"
20 
21 namespace v8 {
22 namespace internal {
23 
24 class FeedbackVectorSpec;
25 class Isolate;
26 
27 namespace interpreter {
28 
29 class BytecodeLabel;
30 class BytecodeNode;
31 class BytecodeRegisterOptimizer;
32 class BytecodeJumpTable;
33 class Register;
34 
35 class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
36  public:
37   BytecodeArrayBuilder(
38       Zone* zone, int parameter_count, int locals_count,
39       FeedbackVectorSpec* feedback_vector_spec = nullptr,
40       SourcePositionTableBuilder::RecordingMode source_position_mode =
41           SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS);
42 
43   Handle<BytecodeArray> ToBytecodeArray(Isolate* isolate);
44 
45   // Get the number of parameters expected by function.
parameter_count()46   int parameter_count() const {
47     DCHECK_GE(parameter_count_, 0);
48     return parameter_count_;
49   }
50 
51   // Get the number of locals required for bytecode array.
locals_count()52   int locals_count() const {
53     DCHECK_GE(local_register_count_, 0);
54     return local_register_count_;
55   }
56 
57   // Returns the number of fixed (non-temporary) registers.
fixed_register_count()58   int fixed_register_count() const { return locals_count(); }
59 
60   // Returns the number of fixed and temporary registers.
total_register_count()61   int total_register_count() const {
62     DCHECK_LE(fixed_register_count(),
63               register_allocator()->maximum_register_count());
64     return register_allocator()->maximum_register_count();
65   }
66 
67   Register Local(int index) const;
68   Register Parameter(int parameter_index) const;
69   Register Receiver() const;
70 
71   // Constant loads to accumulator.
72   BytecodeArrayBuilder& LoadConstantPoolEntry(size_t entry);
73   BytecodeArrayBuilder& LoadLiteral(v8::internal::Smi* value);
74   BytecodeArrayBuilder& LoadLiteral(double value);
75   BytecodeArrayBuilder& LoadLiteral(const AstRawString* raw_string);
76   BytecodeArrayBuilder& LoadLiteral(const Scope* scope);
77   BytecodeArrayBuilder& LoadLiteral(AstBigInt bigint);
78   BytecodeArrayBuilder& LoadLiteral(AstSymbol symbol);
79   BytecodeArrayBuilder& LoadUndefined();
80   BytecodeArrayBuilder& LoadNull();
81   BytecodeArrayBuilder& LoadTheHole();
82   BytecodeArrayBuilder& LoadTrue();
83   BytecodeArrayBuilder& LoadFalse();
84   BytecodeArrayBuilder& LoadBoolean(bool value);
85 
86   // Global loads to the accumulator and stores from the accumulator.
87   BytecodeArrayBuilder& LoadGlobal(const AstRawString* name, int feedback_slot,
88                                    TypeofMode typeof_mode);
89   BytecodeArrayBuilder& StoreGlobal(const AstRawString* name,
90                                     int feedback_slot);
91 
92   // Load the object at |slot_index| at |depth| in the context chain starting
93   // with |context| into the accumulator.
94   enum ContextSlotMutability { kImmutableSlot, kMutableSlot };
95   BytecodeArrayBuilder& LoadContextSlot(Register context, int slot_index,
96                                         int depth,
97                                         ContextSlotMutability immutable);
98 
99   // Stores the object in the accumulator into |slot_index| at |depth| in the
100   // context chain starting with |context|.
101   BytecodeArrayBuilder& StoreContextSlot(Register context, int slot_index,
102                                          int depth);
103 
104   // Load from a module variable into the accumulator. |depth| is the depth of
105   // the current context relative to the module context.
106   BytecodeArrayBuilder& LoadModuleVariable(int cell_index, int depth);
107 
108   // Store from the accumulator into a module variable. |depth| is the depth of
109   // the current context relative to the module context.
110   BytecodeArrayBuilder& StoreModuleVariable(int cell_index, int depth);
111 
112   // Register-accumulator transfers.
113   BytecodeArrayBuilder& LoadAccumulatorWithRegister(Register reg);
114   BytecodeArrayBuilder& StoreAccumulatorInRegister(Register reg);
115 
116   // Register-register transfer.
117   BytecodeArrayBuilder& MoveRegister(Register from, Register to);
118 
119   // Named load property.
120   BytecodeArrayBuilder& LoadNamedProperty(Register object,
121                                           const AstRawString* name,
122                                           int feedback_slot);
123   // Keyed load property. The key should be in the accumulator.
124   BytecodeArrayBuilder& LoadKeyedProperty(Register object, int feedback_slot);
125   // Named load property of the @@iterator symbol.
126   BytecodeArrayBuilder& LoadIteratorProperty(Register object,
127                                              int feedback_slot);
128   // Named load property of the @@asyncIterator symbol.
129   BytecodeArrayBuilder& LoadAsyncIteratorProperty(Register object,
130                                                   int feedback_slot);
131 
132   // Store properties. Flag for NeedsSetFunctionName() should
133   // be in the accumulator.
134   BytecodeArrayBuilder& StoreDataPropertyInLiteral(
135       Register object, Register name, DataPropertyInLiteralFlags flags,
136       int feedback_slot);
137 
138   // Collect type information for developer tools. The value for which we
139   // record the type is stored in the accumulator.
140   BytecodeArrayBuilder& CollectTypeProfile(int position);
141 
142   // Store a property named by a property name. The value to be stored should be
143   // in the accumulator.
144   BytecodeArrayBuilder& StoreNamedProperty(Register object,
145                                            const AstRawString* name,
146                                            int feedback_slot,
147                                            LanguageMode language_mode);
148   // Store a property named by a constant from the constant pool. The value to
149   // be stored should be in the accumulator.
150   BytecodeArrayBuilder& StoreNamedProperty(Register object,
151                                            size_t constant_pool_entry,
152                                            int feedback_slot,
153                                            LanguageMode language_mode);
154   // Store an own property named by a constant from the constant pool. The
155   // value to be stored should be in the accumulator.
156   BytecodeArrayBuilder& StoreNamedOwnProperty(Register object,
157                                               const AstRawString* name,
158                                               int feedback_slot);
159   // Store a property keyed by a value in a register. The value to be stored
160   // should be in the accumulator.
161   BytecodeArrayBuilder& StoreKeyedProperty(Register object, Register key,
162                                            int feedback_slot,
163                                            LanguageMode language_mode);
164   // Store an own element in an array literal. The value to be stored should be
165   // in the accumulator.
166   BytecodeArrayBuilder& StoreInArrayLiteral(Register array, Register index,
167                                             int feedback_slot);
168   // Store the home object property. The value to be stored should be in the
169   // accumulator.
170   BytecodeArrayBuilder& StoreHomeObjectProperty(Register object,
171                                                 int feedback_slot,
172                                                 LanguageMode language_mode);
173 
174   // Store the class fields property. The initializer to be stored should
175   // be in the accumulator.
176   BytecodeArrayBuilder& StoreClassFieldsInitializer(Register constructor,
177                                                     int feedback_slot);
178 
179   // Load class fields property.
180   BytecodeArrayBuilder& LoadClassFieldsInitializer(Register constructor,
181                                                    int feedback_slot);
182 
183   // Lookup the variable with |name|.
184   BytecodeArrayBuilder& LoadLookupSlot(const AstRawString* name,
185                                        TypeofMode typeof_mode);
186 
187   // Lookup the variable with |name|, which is known to be at |slot_index| at
188   // |depth| in the context chain if not shadowed by a context extension
189   // somewhere in that context chain.
190   BytecodeArrayBuilder& LoadLookupContextSlot(const AstRawString* name,
191                                               TypeofMode typeof_mode,
192                                               int slot_index, int depth);
193 
194   // Lookup the variable with |name|, which has its feedback in |feedback_slot|
195   // and is known to be global if not shadowed by a context extension somewhere
196   // up to |depth| in that context chain.
197   BytecodeArrayBuilder& LoadLookupGlobalSlot(const AstRawString* name,
198                                              TypeofMode typeof_mode,
199                                              int feedback_slot, int depth);
200 
201   // Store value in the accumulator into the variable with |name|.
202   BytecodeArrayBuilder& StoreLookupSlot(
203       const AstRawString* name, LanguageMode language_mode,
204       LookupHoistingMode lookup_hoisting_mode);
205 
206   // Create a new closure for a SharedFunctionInfo which will be inserted at
207   // constant pool index |shared_function_info_entry|.
208   BytecodeArrayBuilder& CreateClosure(size_t shared_function_info_entry,
209                                       int slot, int flags);
210 
211   // Create a new local context for a |scope|.
212   BytecodeArrayBuilder& CreateBlockContext(const Scope* scope);
213 
214   // Create a new context for a catch block with |exception| and |scope|.
215   BytecodeArrayBuilder& CreateCatchContext(Register exception,
216                                            const Scope* scope);
217 
218   // Create a new context with the given |scope| and size |slots|.
219   BytecodeArrayBuilder& CreateFunctionContext(const Scope* scope, int slots);
220 
221   // Create a new eval context with the given |scope| and size |slots|.
222   BytecodeArrayBuilder& CreateEvalContext(const Scope* scope, int slots);
223 
224   // Creates a new context with the given |scope| for a with-statement
225   // with the |object| in a register.
226   BytecodeArrayBuilder& CreateWithContext(Register object, const Scope* scope);
227 
228   // Create a new arguments object in the accumulator.
229   BytecodeArrayBuilder& CreateArguments(CreateArgumentsType type);
230 
231   // Literals creation.  Constant elements should be in the accumulator.
232   BytecodeArrayBuilder& CreateRegExpLiteral(const AstRawString* pattern,
233                                             int literal_index, int flags);
234   BytecodeArrayBuilder& CreateArrayLiteral(size_t constant_elements_entry,
235                                            int literal_index, int flags);
236   BytecodeArrayBuilder& CreateEmptyArrayLiteral(int literal_index);
237   BytecodeArrayBuilder& CreateObjectLiteral(size_t constant_properties_entry,
238                                             int literal_index, int flags,
239                                             Register output);
240   BytecodeArrayBuilder& CreateEmptyObjectLiteral();
241   BytecodeArrayBuilder& CloneObject(Register source, int flags,
242                                     int feedback_slot);
243 
244   // Gets or creates the template for a TemplateObjectDescription which will
245   // be inserted at constant pool index |template_object_description_entry|.
246   BytecodeArrayBuilder& GetTemplateObject(
247       size_t template_object_description_entry, int feedback_slot);
248 
249   // Push the context in accumulator as the new context, and store in register
250   // |context|.
251   BytecodeArrayBuilder& PushContext(Register context);
252 
253   // Pop the current context and replace with |context|.
254   BytecodeArrayBuilder& PopContext(Register context);
255 
256   // Call a JS function which is known to be a property of a JS object. The
257   // JSFunction or Callable to be called should be in |callable|. The arguments
258   // should be in |args|, with the receiver in |args[0]|. The call type of the
259   // expression is in |call_type|. Type feedback is recorded in the
260   // |feedback_slot| in the type feedback vector.
261   BytecodeArrayBuilder& CallProperty(Register callable, RegisterList args,
262                                      int feedback_slot);
263 
264   // Call a JS function with an known undefined receiver. The JSFunction or
265   // Callable to be called should be in |callable|. The arguments should be in
266   // |args|, with no receiver as it is implicitly set to undefined. Type
267   // feedback is recorded in the |feedback_slot| in the type feedback vector.
268   BytecodeArrayBuilder& CallUndefinedReceiver(Register callable,
269                                               RegisterList args,
270                                               int feedback_slot);
271 
272   // Call a JS function with an any receiver, possibly (but not necessarily)
273   // undefined. The JSFunction or Callable to be called should be in |callable|.
274   // The arguments should be in |args|, with the receiver in |args[0]|. Type
275   // feedback is recorded in the |feedback_slot| in the type feedback vector.
276   BytecodeArrayBuilder& CallAnyReceiver(Register callable, RegisterList args,
277                                         int feedback_slot);
278 
279   // Tail call into a JS function. The JSFunction or Callable to be called
280   // should be in |callable|. The arguments should be in |args|, with the
281   // receiver in |args[0]|. Type feedback is recorded in the |feedback_slot| in
282   // the type feedback vector.
283   BytecodeArrayBuilder& TailCall(Register callable, RegisterList args,
284                                  int feedback_slot);
285 
286   // Call a JS function. The JSFunction or Callable to be called should be in
287   // |callable|, the receiver in |args[0]| and the arguments in |args[1]|
288   // onwards. The final argument must be a spread.
289   BytecodeArrayBuilder& CallWithSpread(Register callable, RegisterList args,
290                                        int feedback_slot);
291 
292   // Call the Construct operator. The accumulator holds the |new_target|.
293   // The |constructor| is in a register and arguments are in |args|.
294   BytecodeArrayBuilder& Construct(Register constructor, RegisterList args,
295                                   int feedback_slot);
296 
297   // Call the Construct operator for use with a spread. The accumulator holds
298   // the |new_target|. The |constructor| is in a register and arguments are in
299   // |args|. The final argument must be a spread.
300   BytecodeArrayBuilder& ConstructWithSpread(Register constructor,
301                                             RegisterList args,
302                                             int feedback_slot);
303 
304   // Call the runtime function with |function_id| and arguments |args|.
305   BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id,
306                                     RegisterList args);
307   // Call the runtime function with |function_id| with single argument |arg|.
308   BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id,
309                                     Register arg);
310   // Call the runtime function with |function_id| with no arguments.
311   BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id);
312 
313   // Call the runtime function with |function_id| and arguments |args|, that
314   // returns a pair of values. The return values will be returned in
315   // |return_pair|.
316   BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id,
317                                            RegisterList args,
318                                            RegisterList return_pair);
319   // Call the runtime function with |function_id| with single argument |arg|
320   // that returns a pair of values. The return values will be returned in
321   // |return_pair|.
322   BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id,
323                                            Register arg,
324                                            RegisterList return_pair);
325 
326   // Call the JS runtime function with |context_index| and arguments |args|,
327   // with no receiver as it is implicitly set to undefined.
328   BytecodeArrayBuilder& CallJSRuntime(int context_index, RegisterList args);
329 
330   // Operators (register holds the lhs value, accumulator holds the rhs value).
331   // Type feedback will be recorded in the |feedback_slot|
332   BytecodeArrayBuilder& BinaryOperation(Token::Value binop, Register reg,
333                                         int feedback_slot);
334   // Same as above, but lhs in the accumulator and rhs in |literal|.
335   BytecodeArrayBuilder& BinaryOperationSmiLiteral(Token::Value binop,
336                                                   Smi* literal,
337                                                   int feedback_slot);
338 
339   // Unary and Count Operators (value stored in accumulator).
340   // Type feedback will be recorded in the |feedback_slot|
341   BytecodeArrayBuilder& UnaryOperation(Token::Value op, int feedback_slot);
342 
343   enum class ToBooleanMode {
344     kConvertToBoolean,  // Perform ToBoolean conversion on accumulator.
345     kAlreadyBoolean,    // Accumulator is already a Boolean.
346   };
347 
348   // Unary Operators.
349   BytecodeArrayBuilder& LogicalNot(ToBooleanMode mode);
350   BytecodeArrayBuilder& TypeOf();
351 
352   // Expects a heap object in the accumulator. Returns its super constructor in
353   // the register |out| if it passes the IsConstructor test. Otherwise, it
354   // throws a TypeError exception.
355   BytecodeArrayBuilder& GetSuperConstructor(Register out);
356 
357   // Deletes property from an object. This expects that accumulator contains
358   // the key to be deleted and the register contains a reference to the object.
359   BytecodeArrayBuilder& Delete(Register object, LanguageMode language_mode);
360 
361   // JavaScript defines two kinds of 'nil'.
362   enum NilValue { kNullValue, kUndefinedValue };
363 
364   // Tests.
365   BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg,
366                                          int feedback_slot);
367   BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg);
368   BytecodeArrayBuilder& CompareReference(Register reg);
369   BytecodeArrayBuilder& CompareUndetectable();
370   BytecodeArrayBuilder& CompareUndefined();
371   BytecodeArrayBuilder& CompareNull();
372   BytecodeArrayBuilder& CompareNil(Token::Value op, NilValue nil);
373   BytecodeArrayBuilder& CompareTypeOf(
374       TestTypeOfFlags::LiteralFlag literal_flag);
375 
376   // Converts accumulator and stores result in register |out|.
377   BytecodeArrayBuilder& ToObject(Register out);
378   BytecodeArrayBuilder& ToName(Register out);
379   BytecodeArrayBuilder& ToString();
380 
381   // Converts accumulator and stores result back in accumulator.
382   BytecodeArrayBuilder& ToNumber(int feedback_slot);
383   BytecodeArrayBuilder& ToNumeric(int feedback_slot);
384 
385   // Flow Control.
386   BytecodeArrayBuilder& Bind(BytecodeLabel* label);
387   BytecodeArrayBuilder& Bind(const BytecodeLabel& target, BytecodeLabel* label);
388   BytecodeArrayBuilder& Bind(BytecodeJumpTable* jump_table, int case_value);
389 
390   BytecodeArrayBuilder& Jump(BytecodeLabel* label);
391   BytecodeArrayBuilder& JumpLoop(BytecodeLabel* label, int loop_depth);
392 
393   BytecodeArrayBuilder& JumpIfTrue(ToBooleanMode mode, BytecodeLabel* label);
394   BytecodeArrayBuilder& JumpIfFalse(ToBooleanMode mode, BytecodeLabel* label);
395   BytecodeArrayBuilder& JumpIfNotHole(BytecodeLabel* label);
396   BytecodeArrayBuilder& JumpIfJSReceiver(BytecodeLabel* label);
397   BytecodeArrayBuilder& JumpIfNull(BytecodeLabel* label);
398   BytecodeArrayBuilder& JumpIfNotNull(BytecodeLabel* label);
399   BytecodeArrayBuilder& JumpIfUndefined(BytecodeLabel* label);
400   BytecodeArrayBuilder& JumpIfNotUndefined(BytecodeLabel* label);
401   BytecodeArrayBuilder& JumpIfNil(BytecodeLabel* label, Token::Value op,
402                                   NilValue nil);
403   BytecodeArrayBuilder& JumpIfNotNil(BytecodeLabel* label, Token::Value op,
404                                      NilValue nil);
405 
406   BytecodeArrayBuilder& SwitchOnSmiNoFeedback(BytecodeJumpTable* jump_table);
407 
408   BytecodeArrayBuilder& StackCheck(int position);
409 
410   // Sets the pending message to the value in the accumulator, and returns the
411   // previous pending message in the accumulator.
412   BytecodeArrayBuilder& SetPendingMessage();
413 
414   BytecodeArrayBuilder& Throw();
415   BytecodeArrayBuilder& ReThrow();
416   BytecodeArrayBuilder& Abort(AbortReason reason);
417   BytecodeArrayBuilder& Return();
418   BytecodeArrayBuilder& ThrowReferenceErrorIfHole(const AstRawString* name);
419   BytecodeArrayBuilder& ThrowSuperNotCalledIfHole();
420   BytecodeArrayBuilder& ThrowSuperAlreadyCalledIfNotHole();
421 
422   // Debugger.
423   BytecodeArrayBuilder& Debugger();
424 
425   // Increment the block counter at the given slot (block code coverage).
426   BytecodeArrayBuilder& IncBlockCounter(int slot);
427 
428   // Complex flow control.
429   BytecodeArrayBuilder& ForInEnumerate(Register receiver);
430   BytecodeArrayBuilder& ForInPrepare(RegisterList cache_info_triple,
431                                      int feedback_slot);
432   BytecodeArrayBuilder& ForInContinue(Register index, Register cache_length);
433   BytecodeArrayBuilder& ForInNext(Register receiver, Register index,
434                                   RegisterList cache_type_array_pair,
435                                   int feedback_slot);
436   BytecodeArrayBuilder& ForInStep(Register index);
437 
438   // Generators.
439   BytecodeArrayBuilder& SuspendGenerator(Register generator,
440                                          RegisterList registers,
441                                          int suspend_id);
442   BytecodeArrayBuilder& SwitchOnGeneratorState(Register generator,
443                                                BytecodeJumpTable* jump_table);
444   BytecodeArrayBuilder& ResumeGenerator(Register generator,
445                                         RegisterList registers);
446 
447   // Exception handling.
448   BytecodeArrayBuilder& MarkHandler(int handler_id,
449                                     HandlerTable::CatchPrediction will_catch);
450   BytecodeArrayBuilder& MarkTryBegin(int handler_id, Register context);
451   BytecodeArrayBuilder& MarkTryEnd(int handler_id);
452 
453   // Creates a new handler table entry and returns a {hander_id} identifying the
454   // entry, so that it can be referenced by above exception handling support.
NewHandlerEntry()455   int NewHandlerEntry() { return handler_table_builder()->NewHandlerEntry(); }
456 
457   // Allocates a new jump table of given |size| and |case_value_base| in the
458   // constant pool.
459   BytecodeJumpTable* AllocateJumpTable(int size, int case_value_base);
460 
461   // Gets a constant pool entry.
462   size_t GetConstantPoolEntry(const AstRawString* raw_string);
463   size_t GetConstantPoolEntry(AstBigInt bigint);
464   size_t GetConstantPoolEntry(const Scope* scope);
465   size_t GetConstantPoolEntry(double number);
466 #define ENTRY_GETTER(NAME, ...) size_t NAME##ConstantPoolEntry();
467   SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)
468 #undef ENTRY_GETTER
469 
470   // Allocates a slot in the constant pool which can later be set.
471   size_t AllocateDeferredConstantPoolEntry();
472   // Sets the deferred value into an allocated constant pool entry.
473   void SetDeferredConstantPoolEntry(size_t entry, Handle<Object> object);
474 
475   void InitializeReturnPosition(FunctionLiteral* literal);
476 
SetStatementPosition(Statement * stmt)477   void SetStatementPosition(Statement* stmt) {
478     if (stmt->position() == kNoSourcePosition) return;
479     latest_source_info_.MakeStatementPosition(stmt->position());
480   }
481 
SetExpressionPosition(Expression * expr)482   void SetExpressionPosition(Expression* expr) {
483     SetExpressionPosition(expr->position());
484   }
485 
SetExpressionPosition(int position)486   void SetExpressionPosition(int position) {
487     if (position == kNoSourcePosition) return;
488     if (!latest_source_info_.is_statement()) {
489       // Ensure the current expression position is overwritten with the
490       // latest value.
491       latest_source_info_.MakeExpressionPosition(position);
492     }
493   }
494 
SetExpressionAsStatementPosition(Expression * expr)495   void SetExpressionAsStatementPosition(Expression* expr) {
496     if (expr->position() == kNoSourcePosition) return;
497     latest_source_info_.MakeStatementPosition(expr->position());
498   }
499 
SetReturnPosition(int source_position,FunctionLiteral * literal)500   void SetReturnPosition(int source_position, FunctionLiteral* literal) {
501     if (source_position != kNoSourcePosition) {
502       latest_source_info_.MakeStatementPosition(source_position);
503     } else if (literal->return_position() != kNoSourcePosition) {
504       latest_source_info_.MakeStatementPosition(literal->return_position());
505     }
506   }
507 
RequiresImplicitReturn()508   bool RequiresImplicitReturn() const { return !return_seen_in_block_; }
509 
510   // Returns the raw operand value for the given register or register list.
511   uint32_t GetInputRegisterOperand(Register reg);
512   uint32_t GetOutputRegisterOperand(Register reg);
513   uint32_t GetInputRegisterListOperand(RegisterList reg_list);
514   uint32_t GetOutputRegisterListOperand(RegisterList reg_list);
515 
516   // Outputs raw register transfer bytecodes without going through the register
517   // optimizer.
518   void OutputLdarRaw(Register reg);
519   void OutputStarRaw(Register reg);
520   void OutputMovRaw(Register src, Register dest);
521 
522   // Accessors
register_allocator()523   BytecodeRegisterAllocator* register_allocator() {
524     return &register_allocator_;
525   }
register_allocator()526   const BytecodeRegisterAllocator* register_allocator() const {
527     return &register_allocator_;
528   }
zone()529   Zone* zone() const { return zone_; }
530 
531  private:
532   friend class BytecodeRegisterAllocator;
533   template <Bytecode bytecode, AccumulatorUse accumulator_use,
534             OperandType... operand_types>
535   friend class BytecodeNodeBuilder;
536 
feedback_vector_spec()537   const FeedbackVectorSpec* feedback_vector_spec() const {
538     return feedback_vector_spec_;
539   }
540 
541   // Returns the current source position for the given |bytecode|.
542   V8_INLINE BytecodeSourceInfo CurrentSourcePosition(Bytecode bytecode);
543 
544 #define DECLARE_BYTECODE_OUTPUT(Name, ...)                         \
545   template <typename... Operands>                                  \
546   V8_INLINE BytecodeNode Create##Name##Node(Operands... operands); \
547   template <typename... Operands>                                  \
548   V8_INLINE void Output##Name(Operands... operands);               \
549   template <typename... Operands>                                  \
550   V8_INLINE void Output##Name(BytecodeLabel* label, Operands... operands);
551   BYTECODE_LIST(DECLARE_BYTECODE_OUTPUT)
552 #undef DECLARE_OPERAND_TYPE_INFO
553 
554   V8_INLINE void OutputSwitchOnSmiNoFeedback(BytecodeJumpTable* jump_table);
555 
556   bool RegisterIsValid(Register reg) const;
557   bool RegisterListIsValid(RegisterList reg_list) const;
558 
559   // Sets a deferred source info which should be emitted before any future
560   // source info (either attached to a following bytecode or as a nop).
561   void SetDeferredSourceInfo(BytecodeSourceInfo source_info);
562   // Either attach deferred source info to node, or emit it as a nop bytecode
563   // if node already have valid source info.
564   void AttachOrEmitDeferredSourceInfo(BytecodeNode* node);
565 
566   // Write bytecode to bytecode array.
567   void Write(BytecodeNode* node);
568   void WriteJump(BytecodeNode* node, BytecodeLabel* label);
569   void WriteSwitch(BytecodeNode* node, BytecodeJumpTable* label);
570 
571   // Not implemented as the illegal bytecode is used inside internally
572   // to indicate a bytecode field is not valid or an error has occurred
573   // during bytecode generation.
574   BytecodeArrayBuilder& Illegal();
575 
576   template <Bytecode bytecode, AccumulatorUse accumulator_use>
577   void PrepareToOutputBytecode();
578 
LeaveBasicBlock()579   void LeaveBasicBlock() { return_seen_in_block_ = false; }
580 
bytecode_array_writer()581   BytecodeArrayWriter* bytecode_array_writer() {
582     return &bytecode_array_writer_;
583   }
constant_array_builder()584   ConstantArrayBuilder* constant_array_builder() {
585     return &constant_array_builder_;
586   }
constant_array_builder()587   const ConstantArrayBuilder* constant_array_builder() const {
588     return &constant_array_builder_;
589   }
handler_table_builder()590   HandlerTableBuilder* handler_table_builder() {
591     return &handler_table_builder_;
592   }
593 
594   Zone* zone_;
595   FeedbackVectorSpec* feedback_vector_spec_;
596   bool bytecode_generated_;
597   ConstantArrayBuilder constant_array_builder_;
598   HandlerTableBuilder handler_table_builder_;
599   bool return_seen_in_block_;
600   int parameter_count_;
601   int local_register_count_;
602   BytecodeRegisterAllocator register_allocator_;
603   BytecodeArrayWriter bytecode_array_writer_;
604   BytecodeRegisterOptimizer* register_optimizer_;
605   BytecodeSourceInfo latest_source_info_;
606   BytecodeSourceInfo deferred_source_info_;
607 
608   DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBuilder);
609 };
610 
611 V8_EXPORT_PRIVATE std::ostream& operator<<(
612     std::ostream& os, const BytecodeArrayBuilder::ToBooleanMode& mode);
613 
614 }  // namespace interpreter
615 }  // namespace internal
616 }  // namespace v8
617 
618 #endif  // V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_
619