Home | History | Annotate | Download | only in interpreter
      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.
     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.
     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.
     58   int fixed_register_count() const { return locals_count(); }
     59 
     60   // Returns the number of fixed and temporary registers.
     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.
    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 
    477   void SetStatementPosition(Statement* stmt) {
    478     if (stmt->position() == kNoSourcePosition) return;
    479     latest_source_info_.MakeStatementPosition(stmt->position());
    480   }
    481 
    482   void SetExpressionPosition(Expression* expr) {
    483     SetExpressionPosition(expr->position());
    484   }
    485 
    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 
    495   void SetExpressionAsStatementPosition(Expression* expr) {
    496     if (expr->position() == kNoSourcePosition) return;
    497     latest_source_info_.MakeStatementPosition(expr->position());
    498   }
    499 
    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 
    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
    523   BytecodeRegisterAllocator* register_allocator() {
    524     return &register_allocator_;
    525   }
    526   const BytecodeRegisterAllocator* register_allocator() const {
    527     return &register_allocator_;
    528   }
    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 
    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 
    579   void LeaveBasicBlock() { return_seen_in_block_ = false; }
    580 
    581   BytecodeArrayWriter* bytecode_array_writer() {
    582     return &bytecode_array_writer_;
    583   }
    584   ConstantArrayBuilder* constant_array_builder() {
    585     return &constant_array_builder_;
    586   }
    587   const ConstantArrayBuilder* constant_array_builder() const {
    588     return &constant_array_builder_;
    589   }
    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