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