• 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 LocalIsolate>
50   EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
51   Handle<BytecodeArray> ToBytecodeArray(LocalIsolate* isolate);
52   template <typename LocalIsolate>
53   EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
54   Handle<ByteArray> ToSourcePositionTable(LocalIsolate* 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& LoadLiteral(AstSymbol symbol);
94   BytecodeArrayBuilder& LoadUndefined();
95   BytecodeArrayBuilder& LoadNull();
96   BytecodeArrayBuilder& LoadTheHole();
97   BytecodeArrayBuilder& LoadTrue();
98   BytecodeArrayBuilder& LoadFalse();
99   BytecodeArrayBuilder& LoadBoolean(bool value);
100 
101   // Global loads to the accumulator and stores from the accumulator.
102   BytecodeArrayBuilder& LoadGlobal(const AstRawString* name, int feedback_slot,
103                                    TypeofMode typeof_mode);
104   BytecodeArrayBuilder& StoreGlobal(const AstRawString* name,
105                                     int feedback_slot);
106 
107   // Load the object at |slot_index| at |depth| in the context chain starting
108   // with |context| into the accumulator.
109   enum ContextSlotMutability { kImmutableSlot, kMutableSlot };
110   BytecodeArrayBuilder& LoadContextSlot(Register context, int slot_index,
111                                         int depth,
112                                         ContextSlotMutability immutable);
113 
114   // Stores the object in the accumulator into |slot_index| at |depth| in the
115   // context chain starting with |context|.
116   BytecodeArrayBuilder& StoreContextSlot(Register context, int slot_index,
117                                          int depth);
118 
119   // Load from a module variable into the accumulator. |depth| is the depth of
120   // the current context relative to the module context.
121   BytecodeArrayBuilder& LoadModuleVariable(int cell_index, int depth);
122 
123   // Store from the accumulator into a module variable. |depth| is the depth of
124   // the current context relative to the module context.
125   BytecodeArrayBuilder& StoreModuleVariable(int cell_index, int depth);
126 
127   // Register-accumulator transfers.
128   BytecodeArrayBuilder& LoadAccumulatorWithRegister(Register reg);
129   BytecodeArrayBuilder& StoreAccumulatorInRegister(Register reg);
130 
131   // Register-register transfer.
132   BytecodeArrayBuilder& MoveRegister(Register from, Register to);
133 
134   // Named load property.
135   BytecodeArrayBuilder& LoadNamedProperty(Register object,
136                                           const AstRawString* name,
137                                           int feedback_slot);
138   // Named load property without feedback
139   BytecodeArrayBuilder& LoadNamedPropertyNoFeedback(Register object,
140                                                     const AstRawString* name);
141 
142   BytecodeArrayBuilder& LoadNamedPropertyFromSuper(Register object,
143                                                    const AstRawString* name,
144                                                    int feedback_slot);
145 
146   // Keyed load property. The key should be in the accumulator.
147   BytecodeArrayBuilder& LoadKeyedProperty(Register object, int feedback_slot);
148 
149   // Named load property of the @@iterator symbol.
150   BytecodeArrayBuilder& LoadIteratorProperty(Register object,
151                                              int feedback_slot);
152 
153   // Load and call property of the @@iterator symbol
154   BytecodeArrayBuilder& GetIterator(Register object, int load_feedback_slot,
155                                     int call_feedback_slot);
156 
157   // Named load property of the @@asyncIterator symbol.
158   BytecodeArrayBuilder& LoadAsyncIteratorProperty(Register object,
159                                                   int feedback_slot);
160 
161   // Store properties. Flag for NeedsSetFunctionName() should
162   // be in the accumulator.
163   BytecodeArrayBuilder& StoreDataPropertyInLiteral(
164       Register object, Register name, DataPropertyInLiteralFlags flags,
165       int feedback_slot);
166 
167   // Collect type information for developer tools. The value for which we
168   // record the type is stored in the accumulator.
169   BytecodeArrayBuilder& CollectTypeProfile(int position);
170 
171   // Store a property named by a property name. The value to be stored should be
172   // in the accumulator.
173   BytecodeArrayBuilder& StoreNamedProperty(Register object,
174                                            const AstRawString* name,
175                                            int feedback_slot,
176                                            LanguageMode language_mode);
177 
178   // Store a property named by a property name without feedback slot. The value
179   // to be stored should be in the accumulator.
180   BytecodeArrayBuilder& StoreNamedPropertyNoFeedback(
181       Register object, const AstRawString* name, LanguageMode language_mode);
182 
183   // Store a property named by a constant from the constant pool. The value to
184   // be stored should be in the accumulator.
185   BytecodeArrayBuilder& StoreNamedProperty(Register object,
186                                            size_t constant_pool_entry,
187                                            int feedback_slot,
188                                            LanguageMode language_mode);
189   // Store an own property named by a constant from the constant pool. The
190   // value to be stored should be in the accumulator.
191   BytecodeArrayBuilder& StoreNamedOwnProperty(Register object,
192                                               const AstRawString* name,
193                                               int feedback_slot);
194   // Store a property keyed by a value in a register. The value to be stored
195   // should be in the accumulator.
196   BytecodeArrayBuilder& StoreKeyedProperty(Register object, Register key,
197                                            int feedback_slot,
198                                            LanguageMode language_mode);
199   // Store an own element in an array literal. The value to be stored should be
200   // in the accumulator.
201   BytecodeArrayBuilder& StoreInArrayLiteral(Register array, Register index,
202                                             int feedback_slot);
203   // Store the home object property. The value to be stored should be in the
204   // accumulator.
205   BytecodeArrayBuilder& StoreHomeObjectProperty(Register object,
206                                                 int feedback_slot,
207                                                 LanguageMode language_mode);
208 
209   // Store the class fields property. The initializer to be stored should
210   // be in the accumulator.
211   BytecodeArrayBuilder& StoreClassFieldsInitializer(Register constructor,
212                                                     int feedback_slot);
213 
214   // Load class fields property.
215   BytecodeArrayBuilder& LoadClassFieldsInitializer(Register constructor,
216                                                    int feedback_slot);
217 
218   // Lookup the variable with |name|.
219   BytecodeArrayBuilder& LoadLookupSlot(const AstRawString* name,
220                                        TypeofMode typeof_mode);
221 
222   // Lookup the variable with |name|, which is known to be at |slot_index| at
223   // |depth| in the context chain if not shadowed by a context extension
224   // somewhere in that context chain.
225   BytecodeArrayBuilder& LoadLookupContextSlot(const AstRawString* name,
226                                               TypeofMode typeof_mode,
227                                               int slot_index, int depth);
228 
229   // Lookup the variable with |name|, which has its feedback in |feedback_slot|
230   // and is known to be global if not shadowed by a context extension somewhere
231   // up to |depth| in that context chain.
232   BytecodeArrayBuilder& LoadLookupGlobalSlot(const AstRawString* name,
233                                              TypeofMode typeof_mode,
234                                              int feedback_slot, int depth);
235 
236   // Store value in the accumulator into the variable with |name|.
237   BytecodeArrayBuilder& StoreLookupSlot(
238       const AstRawString* name, LanguageMode language_mode,
239       LookupHoistingMode lookup_hoisting_mode);
240 
241   // Create a new closure for a SharedFunctionInfo which will be inserted at
242   // constant pool index |shared_function_info_entry|.
243   BytecodeArrayBuilder& CreateClosure(size_t shared_function_info_entry,
244                                       int slot, int flags);
245 
246   // Create a new local context for a |scope|.
247   BytecodeArrayBuilder& CreateBlockContext(const Scope* scope);
248 
249   // Create a new context for a catch block with |exception| and |scope|.
250   BytecodeArrayBuilder& CreateCatchContext(Register exception,
251                                            const Scope* scope);
252 
253   // Create a new context with the given |scope| and size |slots|.
254   BytecodeArrayBuilder& CreateFunctionContext(const Scope* scope, int slots);
255 
256   // Create a new eval context with the given |scope| and size |slots|.
257   BytecodeArrayBuilder& CreateEvalContext(const Scope* scope, int slots);
258 
259   // Creates a new context with the given |scope| for a with-statement
260   // with the |object| in a register.
261   BytecodeArrayBuilder& CreateWithContext(Register object, const Scope* scope);
262 
263   // Create a new arguments object in the accumulator.
264   BytecodeArrayBuilder& CreateArguments(CreateArgumentsType type);
265 
266   // Literals creation.  Constant elements should be in the accumulator.
267   BytecodeArrayBuilder& CreateRegExpLiteral(const AstRawString* pattern,
268                                             int literal_index, int flags);
269   BytecodeArrayBuilder& CreateArrayLiteral(size_t constant_elements_entry,
270                                            int literal_index, int flags);
271   BytecodeArrayBuilder& CreateEmptyArrayLiteral(int literal_index);
272   BytecodeArrayBuilder& CreateArrayFromIterable();
273   BytecodeArrayBuilder& CreateObjectLiteral(size_t constant_properties_entry,
274                                             int literal_index, int flags);
275   BytecodeArrayBuilder& CreateEmptyObjectLiteral();
276   BytecodeArrayBuilder& CloneObject(Register source, int flags,
277                                     int feedback_slot);
278 
279   // Gets or creates the template for a TemplateObjectDescription which will
280   // be inserted at constant pool index |template_object_description_entry|.
281   BytecodeArrayBuilder& GetTemplateObject(
282       size_t template_object_description_entry, int feedback_slot);
283 
284   // Push the context in accumulator as the new context, and store in register
285   // |context|.
286   BytecodeArrayBuilder& PushContext(Register context);
287 
288   // Pop the current context and replace with |context|.
289   BytecodeArrayBuilder& PopContext(Register context);
290 
291   // Call a JS function which is known to be a property of a JS object. The
292   // JSFunction or Callable to be called should be in |callable|. The arguments
293   // should be in |args|, with the receiver in |args[0]|. The call type of the
294   // expression is in |call_type|. Type feedback is recorded in the
295   // |feedback_slot| in the type feedback vector.
296   BytecodeArrayBuilder& CallProperty(Register callable, RegisterList args,
297                                      int feedback_slot);
298 
299   // Call a JS function with an known undefined receiver. The JSFunction or
300   // Callable to be called should be in |callable|. The arguments should be in
301   // |args|, with no receiver as it is implicitly set to undefined. Type
302   // feedback is recorded in the |feedback_slot| in the type feedback vector.
303   BytecodeArrayBuilder& CallUndefinedReceiver(Register callable,
304                                               RegisterList args,
305                                               int feedback_slot);
306 
307   // Call a JS function with an any receiver, possibly (but not necessarily)
308   // undefined. The JSFunction or Callable to be called should be in |callable|.
309   // The arguments should be in |args|, with the receiver in |args[0]|. Type
310   // feedback is recorded in the |feedback_slot| in the type feedback vector.
311   BytecodeArrayBuilder& CallAnyReceiver(Register callable, RegisterList args,
312                                         int feedback_slot);
313 
314   // Call a JS function with an any receiver, possibly (but not necessarily)
315   // undefined. The JSFunction or Callable to be called should be in |callable|.
316   // The arguments should be in |args|, with the receiver in |args[0]|.
317   BytecodeArrayBuilder& CallNoFeedback(Register callable, RegisterList args);
318 
319   // Tail call into a JS function. The JSFunction or Callable to be called
320   // should be in |callable|. The arguments should be in |args|, with the
321   // receiver in |args[0]|. Type feedback is recorded in the |feedback_slot| in
322   // the type feedback vector.
323   BytecodeArrayBuilder& TailCall(Register callable, RegisterList args,
324                                  int feedback_slot);
325 
326   // Call a JS function. The JSFunction or Callable to be called should be in
327   // |callable|, the receiver in |args[0]| and the arguments in |args[1]|
328   // onwards. The final argument must be a spread.
329   BytecodeArrayBuilder& CallWithSpread(Register callable, RegisterList args,
330                                        int feedback_slot);
331 
332   // Call the Construct operator. The accumulator holds the |new_target|.
333   // The |constructor| is in a register and arguments are in |args|.
334   BytecodeArrayBuilder& Construct(Register constructor, RegisterList args,
335                                   int feedback_slot);
336 
337   // Call the Construct operator for use with a spread. The accumulator holds
338   // the |new_target|. The |constructor| is in a register and arguments are in
339   // |args|. The final argument must be a spread.
340   BytecodeArrayBuilder& ConstructWithSpread(Register constructor,
341                                             RegisterList args,
342                                             int feedback_slot);
343 
344   // Call the runtime function with |function_id| and arguments |args|.
345   BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id,
346                                     RegisterList args);
347   // Call the runtime function with |function_id| with single argument |arg|.
348   BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id,
349                                     Register arg);
350   // Call the runtime function with |function_id| with no arguments.
351   BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id);
352 
353   // Call the runtime function with |function_id| and arguments |args|, that
354   // returns a pair of values. The return values will be returned in
355   // |return_pair|.
356   BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id,
357                                            RegisterList args,
358                                            RegisterList return_pair);
359   // Call the runtime function with |function_id| with single argument |arg|
360   // that returns a pair of values. The return values will be returned in
361   // |return_pair|.
362   BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id,
363                                            Register arg,
364                                            RegisterList return_pair);
365 
366   // Call the JS runtime function with |context_index| and arguments |args|,
367   // with no receiver as it is implicitly set to undefined.
368   BytecodeArrayBuilder& CallJSRuntime(int context_index, RegisterList args);
369 
370   // Operators (register holds the lhs value, accumulator holds the rhs value).
371   // Type feedback will be recorded in the |feedback_slot|
372   BytecodeArrayBuilder& BinaryOperation(Token::Value binop, Register reg,
373                                         int feedback_slot);
374   // Same as above, but lhs in the accumulator and rhs in |literal|.
375   BytecodeArrayBuilder& BinaryOperationSmiLiteral(Token::Value binop,
376                                                   Smi literal,
377                                                   int feedback_slot);
378 
379   // Unary and Count Operators (value stored in accumulator).
380   // Type feedback will be recorded in the |feedback_slot|
381   BytecodeArrayBuilder& UnaryOperation(Token::Value op, int feedback_slot);
382 
383   enum class ToBooleanMode {
384     kConvertToBoolean,  // Perform ToBoolean conversion on accumulator.
385     kAlreadyBoolean,    // Accumulator is already a Boolean.
386   };
387 
388   // Unary Operators.
389   BytecodeArrayBuilder& LogicalNot(ToBooleanMode mode);
390   BytecodeArrayBuilder& TypeOf();
391 
392   // Expects a heap object in the accumulator. Returns its super constructor in
393   // the register |out| if it passes the IsConstructor test. Otherwise, it
394   // throws a TypeError exception.
395   BytecodeArrayBuilder& GetSuperConstructor(Register out);
396 
397   // Deletes property from an object. This expects that accumulator contains
398   // the key to be deleted and the register contains a reference to the object.
399   BytecodeArrayBuilder& Delete(Register object, LanguageMode language_mode);
400 
401   // JavaScript defines two kinds of 'nil'.
402   enum NilValue { kNullValue, kUndefinedValue };
403 
404   // Tests.
405   BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg,
406                                          int feedback_slot);
407   BytecodeArrayBuilder& CompareReference(Register reg);
408   BytecodeArrayBuilder& CompareUndetectable();
409   BytecodeArrayBuilder& CompareUndefined();
410   BytecodeArrayBuilder& CompareNull();
411   BytecodeArrayBuilder& CompareNil(Token::Value op, NilValue nil);
412   BytecodeArrayBuilder& CompareTypeOf(
413       TestTypeOfFlags::LiteralFlag literal_flag);
414 
415   // Converts accumulator and stores result in register |out|.
416   BytecodeArrayBuilder& ToObject(Register out);
417   BytecodeArrayBuilder& ToName(Register out);
418   BytecodeArrayBuilder& ToString();
419 
420   // Converts accumulator and stores result back in accumulator.
421   BytecodeArrayBuilder& ToNumber(int feedback_slot);
422   BytecodeArrayBuilder& ToNumeric(int feedback_slot);
423 
424   // Exception handling.
425   BytecodeArrayBuilder& MarkHandler(int handler_id,
426                                     HandlerTable::CatchPrediction will_catch);
427   BytecodeArrayBuilder& MarkTryBegin(int handler_id, Register context);
428   BytecodeArrayBuilder& MarkTryEnd(int handler_id);
429 
430   // Flow Control.
431   BytecodeArrayBuilder& Bind(BytecodeLabel* label);
432   BytecodeArrayBuilder& Bind(BytecodeLoopHeader* label);
433   BytecodeArrayBuilder& Bind(BytecodeJumpTable* jump_table, int case_value);
434 
435   BytecodeArrayBuilder& Jump(BytecodeLabel* label);
436   BytecodeArrayBuilder& JumpLoop(BytecodeLoopHeader* loop_header,
437                                  int loop_depth, int position);
438 
439   BytecodeArrayBuilder& JumpIfTrue(ToBooleanMode mode, BytecodeLabel* label);
440   BytecodeArrayBuilder& JumpIfFalse(ToBooleanMode mode, BytecodeLabel* label);
441   BytecodeArrayBuilder& JumpIfJSReceiver(BytecodeLabel* label);
442   BytecodeArrayBuilder& JumpIfNull(BytecodeLabel* label);
443   BytecodeArrayBuilder& JumpIfNotNull(BytecodeLabel* label);
444   BytecodeArrayBuilder& JumpIfUndefined(BytecodeLabel* label);
445   BytecodeArrayBuilder& JumpIfUndefinedOrNull(BytecodeLabel* label);
446   BytecodeArrayBuilder& JumpIfNotUndefined(BytecodeLabel* label);
447   BytecodeArrayBuilder& JumpIfNil(BytecodeLabel* label, Token::Value op,
448                                   NilValue nil);
449   BytecodeArrayBuilder& JumpIfNotNil(BytecodeLabel* label, Token::Value op,
450                                      NilValue nil);
451 
452   BytecodeArrayBuilder& SwitchOnSmiNoFeedback(BytecodeJumpTable* jump_table);
453 
454   // Sets the pending message to the value in the accumulator, and returns the
455   // previous pending message in the accumulator.
456   BytecodeArrayBuilder& SetPendingMessage();
457 
458   BytecodeArrayBuilder& Throw();
459   BytecodeArrayBuilder& ReThrow();
460   BytecodeArrayBuilder& Abort(AbortReason reason);
461   BytecodeArrayBuilder& Return();
462   BytecodeArrayBuilder& ThrowReferenceErrorIfHole(const AstRawString* name);
463   BytecodeArrayBuilder& ThrowSuperNotCalledIfHole();
464   BytecodeArrayBuilder& ThrowSuperAlreadyCalledIfNotHole();
465   BytecodeArrayBuilder& ThrowIfNotSuperConstructor(Register constructor);
466 
467   // Debugger.
468   BytecodeArrayBuilder& Debugger();
469 
470   // Increment the block counter at the given slot (block code coverage).
471   BytecodeArrayBuilder& IncBlockCounter(int slot);
472 
473   // Complex flow control.
474   BytecodeArrayBuilder& ForInEnumerate(Register receiver);
475   BytecodeArrayBuilder& ForInPrepare(RegisterList cache_info_triple,
476                                      int feedback_slot);
477   BytecodeArrayBuilder& ForInContinue(Register index, Register cache_length);
478   BytecodeArrayBuilder& ForInNext(Register receiver, Register index,
479                                   RegisterList cache_type_array_pair,
480                                   int feedback_slot);
481   BytecodeArrayBuilder& ForInStep(Register index);
482 
483   // Generators.
484   BytecodeArrayBuilder& SuspendGenerator(Register generator,
485                                          RegisterList registers,
486                                          int suspend_id);
487   BytecodeArrayBuilder& SwitchOnGeneratorState(Register generator,
488                                                BytecodeJumpTable* jump_table);
489   BytecodeArrayBuilder& ResumeGenerator(Register generator,
490                                         RegisterList registers);
491 
492   // Creates a new handler table entry and returns a {hander_id} identifying the
493   // entry, so that it can be referenced by above exception handling support.
NewHandlerEntry()494   int NewHandlerEntry() { return handler_table_builder()->NewHandlerEntry(); }
495 
496   // Allocates a new jump table of given |size| and |case_value_base| in the
497   // constant pool.
498   BytecodeJumpTable* AllocateJumpTable(int size, int case_value_base);
499 
500   // Gets a constant pool entry.
501   size_t GetConstantPoolEntry(const AstRawString* raw_string);
502   size_t GetConstantPoolEntry(AstBigInt bigint);
503   size_t GetConstantPoolEntry(const Scope* scope);
504   size_t GetConstantPoolEntry(double number);
505 #define ENTRY_GETTER(NAME, ...) size_t NAME##ConstantPoolEntry();
506   SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)
507 #undef ENTRY_GETTER
508 
509   // Allocates a slot in the constant pool which can later be set.
510   size_t AllocateDeferredConstantPoolEntry();
511   // Sets the deferred value into an allocated constant pool entry.
512   void SetDeferredConstantPoolEntry(size_t entry, Handle<Object> object);
513 
514   void InitializeReturnPosition(FunctionLiteral* literal);
515 
SetStatementPosition(Statement * stmt)516   void SetStatementPosition(Statement* stmt) {
517     if (stmt->position() == kNoSourcePosition) return;
518     latest_source_info_.MakeStatementPosition(stmt->position());
519   }
520 
SetExpressionPosition(Expression * expr)521   void SetExpressionPosition(Expression* expr) {
522     SetExpressionPosition(expr->position());
523   }
524 
SetExpressionPosition(int position)525   void SetExpressionPosition(int position) {
526     if (position == kNoSourcePosition) return;
527     if (!latest_source_info_.is_statement()) {
528       // Ensure the current expression position is overwritten with the
529       // latest value.
530       latest_source_info_.MakeExpressionPosition(position);
531     }
532   }
533 
SetExpressionAsStatementPosition(Expression * expr)534   void SetExpressionAsStatementPosition(Expression* expr) {
535     if (expr->position() == kNoSourcePosition) return;
536     latest_source_info_.MakeStatementPosition(expr->position());
537   }
538 
SetReturnPosition(int source_position,FunctionLiteral * literal)539   void SetReturnPosition(int source_position, FunctionLiteral* literal) {
540     if (source_position != kNoSourcePosition) {
541       latest_source_info_.MakeStatementPosition(source_position);
542     } else if (literal->return_position() != kNoSourcePosition) {
543       latest_source_info_.MakeStatementPosition(literal->return_position());
544     }
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, AccumulatorUse accumulator_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, AccumulatorUse accumulator_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