bytecode-array-builder.h 28.4 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_
#define V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_

8
#include "src/ast/ast.h"
9 10
#include "src/base/compiler-specific.h"
#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 22 23

namespace v8 {
namespace internal {

24
class FeedbackVectorSpec;
25 26 27 28
class Isolate;

namespace interpreter {

29
class BytecodeLabel;
30
class BytecodeNode;
31
class BytecodeRegisterOptimizer;
32
class BytecodeJumpTable;
33 34
class Register;

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 41
      SourcePositionTableBuilder::RecordingMode source_position_mode =
          SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS);
42

43
  Handle<BytecodeArray> ToBytecodeArray(Isolate* isolate);
44

45
  // Get the number of parameters expected by function.
46 47 48 49
  int parameter_count() const {
    DCHECK_GE(parameter_count_, 0);
    return parameter_count_;
  }
50

51
  // Get the number of locals required for bytecode array.
52 53 54 55
  int locals_count() const {
    DCHECK_GE(local_register_count_, 0);
    return local_register_count_;
  }
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 62 63 64
  int total_register_count() const {
    DCHECK_LE(fixed_register_count(),
              register_allocator()->maximum_register_count());
    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(Smi value);
74
  BytecodeArrayBuilder& LoadLiteral(double value);
75 76
  BytecodeArrayBuilder& LoadLiteral(const AstRawString* raw_string);
  BytecodeArrayBuilder& LoadLiteral(const Scope* scope);
77 78
  BytecodeArrayBuilder& LoadLiteral(AstBigInt bigint);
  BytecodeArrayBuilder& LoadLiteral(AstSymbol symbol);
79 80 81 82 83
  BytecodeArrayBuilder& LoadUndefined();
  BytecodeArrayBuilder& LoadNull();
  BytecodeArrayBuilder& LoadTheHole();
  BytecodeArrayBuilder& LoadTrue();
  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 90
  BytecodeArrayBuilder& StoreGlobal(const AstRawString* name,
                                    int feedback_slot);
91

92 93
  // Load the object at |slot_index| at |depth| in the context chain starting
  // with |context| into the accumulator.
94
  enum ContextSlotMutability { kImmutableSlot, kMutableSlot };
95
  BytecodeArrayBuilder& LoadContextSlot(Register context, int slot_index,
96 97
                                        int depth,
                                        ContextSlotMutability immutable);
98 99 100 101 102

  // Stores the object in the accumulator into |slot_index| at |depth| in the
  // context chain starting with |context|.
  BytecodeArrayBuilder& StoreContextSlot(Register context, int slot_index,
                                         int depth);
103

104 105 106 107 108 109 110 111
  // Load from a module variable into the accumulator. |depth| is the depth of
  // the current context relative to the module context.
  BytecodeArrayBuilder& LoadModuleVariable(int cell_index, int depth);

  // Store from the accumulator into a module variable. |depth| is the depth of
  // the current context relative to the module context.
  BytecodeArrayBuilder& StoreModuleVariable(int cell_index, int depth);

112 113 114
  // Register-accumulator transfers.
  BytecodeArrayBuilder& LoadAccumulatorWithRegister(Register reg);
  BytecodeArrayBuilder& StoreAccumulatorInRegister(Register reg);
115

116 117 118
  // Register-register transfer.
  BytecodeArrayBuilder& MoveRegister(Register from, Register to);

119
  // Named load property.
120
  BytecodeArrayBuilder& LoadNamedProperty(Register object,
121
                                          const AstRawString* name,
122
                                          int feedback_slot);
123 124 125 126
  // Named load property without feedback
  BytecodeArrayBuilder& LoadNamedPropertyNoFeedback(Register object,
                                                    const AstRawString* name);

127
  // Keyed load property. The key should be in the accumulator.
128
  BytecodeArrayBuilder& LoadKeyedProperty(Register object, int feedback_slot);
129 130 131
  // Named load property of the @@iterator symbol.
  BytecodeArrayBuilder& LoadIteratorProperty(Register object,
                                             int feedback_slot);
132 133 134
  // Named load property of the @@asyncIterator symbol.
  BytecodeArrayBuilder& LoadAsyncIteratorProperty(Register object,
                                                  int feedback_slot);
135

136 137
  // Store properties. Flag for NeedsSetFunctionName() should
  // be in the accumulator.
138
  BytecodeArrayBuilder& StoreDataPropertyInLiteral(
139 140
      Register object, Register name, DataPropertyInLiteralFlags flags,
      int feedback_slot);
141

142 143
  // Collect type information for developer tools. The value for which we
  // record the type is stored in the accumulator.
144
  BytecodeArrayBuilder& CollectTypeProfile(int position);
145

146 147 148 149 150 151
  // Store a property named by a property name. The value to be stored should be
  // in the accumulator.
  BytecodeArrayBuilder& StoreNamedProperty(Register object,
                                           const AstRawString* name,
                                           int feedback_slot,
                                           LanguageMode language_mode);
152 153 154 155 156 157

  // Store a property named by a property name without feedback slot. The value
  // to be stored should be in the accumulator.
  BytecodeArrayBuilder& StoreNamedPropertyNoFeedback(
      Register object, const AstRawString* name, LanguageMode language_mode);

158 159
  // Store a property named by a constant from the constant pool. The value to
  // be stored should be in the accumulator.
160
  BytecodeArrayBuilder& StoreNamedProperty(Register object,
161
                                           size_t constant_pool_entry,
162 163
                                           int feedback_slot,
                                           LanguageMode language_mode);
164 165 166 167 168
  // Store an own property named by a constant from the constant pool. The
  // value to be stored should be in the accumulator.
  BytecodeArrayBuilder& StoreNamedOwnProperty(Register object,
                                              const AstRawString* name,
                                              int feedback_slot);
169 170
  // Store a property keyed by a value in a register. The value to be stored
  // should be in the accumulator.
171 172 173
  BytecodeArrayBuilder& StoreKeyedProperty(Register object, Register key,
                                           int feedback_slot,
                                           LanguageMode language_mode);
174 175 176 177
  // Store an own element in an array literal. The value to be stored should be
  // in the accumulator.
  BytecodeArrayBuilder& StoreInArrayLiteral(Register array, Register index,
                                            int feedback_slot);
178 179 180 181 182
  // Store the home object property. The value to be stored should be in the
  // accumulator.
  BytecodeArrayBuilder& StoreHomeObjectProperty(Register object,
                                                int feedback_slot,
                                                LanguageMode language_mode);
183

184 185 186 187 188 189 190 191 192
  // Store the class fields property. The initializer to be stored should
  // be in the accumulator.
  BytecodeArrayBuilder& StoreClassFieldsInitializer(Register constructor,
                                                    int feedback_slot);

  // Load class fields property.
  BytecodeArrayBuilder& LoadClassFieldsInitializer(Register constructor,
                                                   int feedback_slot);

193
  // Lookup the variable with |name|.
194
  BytecodeArrayBuilder& LoadLookupSlot(const AstRawString* name,
195 196
                                       TypeofMode typeof_mode);

197 198 199
  // Lookup the variable with |name|, which is known to be at |slot_index| at
  // |depth| in the context chain if not shadowed by a context extension
  // somewhere in that context chain.
200
  BytecodeArrayBuilder& LoadLookupContextSlot(const AstRawString* name,
201 202 203
                                              TypeofMode typeof_mode,
                                              int slot_index, int depth);

204 205 206
  // Lookup the variable with |name|, which has its feedback in |feedback_slot|
  // and is known to be global if not shadowed by a context extension somewhere
  // up to |depth| in that context chain.
207
  BytecodeArrayBuilder& LoadLookupGlobalSlot(const AstRawString* name,
208 209 210
                                             TypeofMode typeof_mode,
                                             int feedback_slot, int depth);

211
  // Store value in the accumulator into the variable with |name|.
212 213 214
  BytecodeArrayBuilder& StoreLookupSlot(
      const AstRawString* name, LanguageMode language_mode,
      LookupHoistingMode lookup_hoisting_mode);
215

216
  // Create a new closure for a SharedFunctionInfo which will be inserted at
217 218 219
  // constant pool index |shared_function_info_entry|.
  BytecodeArrayBuilder& CreateClosure(size_t shared_function_info_entry,
                                      int slot, int flags);
220

221
  // Create a new local context for a |scope|.
222
  BytecodeArrayBuilder& CreateBlockContext(const Scope* scope);
223

224
  // Create a new context for a catch block with |exception| and |scope|.
225
  BytecodeArrayBuilder& CreateCatchContext(Register exception,
226
                                           const Scope* scope);
227

228 229
  // Create a new context with the given |scope| and size |slots|.
  BytecodeArrayBuilder& CreateFunctionContext(const Scope* scope, int slots);
230

231 232
  // Create a new eval context with the given |scope| and size |slots|.
  BytecodeArrayBuilder& CreateEvalContext(const Scope* scope, int slots);
233

234
  // Creates a new context with the given |scope| for a with-statement
235
  // with the |object| in a register.
236
  BytecodeArrayBuilder& CreateWithContext(Register object, const Scope* scope);
237

238 239 240
  // Create a new arguments object in the accumulator.
  BytecodeArrayBuilder& CreateArguments(CreateArgumentsType type);

241
  // Literals creation.  Constant elements should be in the accumulator.
242
  BytecodeArrayBuilder& CreateRegExpLiteral(const AstRawString* pattern,
243
                                            int literal_index, int flags);
244 245
  BytecodeArrayBuilder& CreateArrayLiteral(size_t constant_elements_entry,
                                           int literal_index, int flags);
246
  BytecodeArrayBuilder& CreateEmptyArrayLiteral(int literal_index);
247
  BytecodeArrayBuilder& CreateArrayFromIterable();
248
  BytecodeArrayBuilder& CreateObjectLiteral(size_t constant_properties_entry,
249
                                            int literal_index, int flags);
250
  BytecodeArrayBuilder& CreateEmptyObjectLiteral();
251 252
  BytecodeArrayBuilder& CloneObject(Register source, int flags,
                                    int feedback_slot);
253

254 255 256
  // Gets or creates the template for a TemplateObjectDescription which will
  // be inserted at constant pool index |template_object_description_entry|.
  BytecodeArrayBuilder& GetTemplateObject(
257
      size_t template_object_description_entry, int feedback_slot);
258

259 260 261
  // Push the context in accumulator as the new context, and store in register
  // |context|.
  BytecodeArrayBuilder& PushContext(Register context);
262

263 264 265
  // Pop the current context and replace with |context|.
  BytecodeArrayBuilder& PopContext(Register context);

266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
  // Call a JS function which is known to be a property of a JS object. The
  // JSFunction or Callable to be called should be in |callable|. The arguments
  // should be in |args|, with the receiver in |args[0]|. The call type of the
  // expression is in |call_type|. Type feedback is recorded in the
  // |feedback_slot| in the type feedback vector.
  BytecodeArrayBuilder& CallProperty(Register callable, RegisterList args,
                                     int feedback_slot);

  // Call a JS function with an known undefined receiver. The JSFunction or
  // Callable to be called should be in |callable|. The arguments should be in
  // |args|, with no receiver as it is implicitly set to undefined. Type
  // feedback is recorded in the |feedback_slot| in the type feedback vector.
  BytecodeArrayBuilder& CallUndefinedReceiver(Register callable,
                                              RegisterList args,
                                              int feedback_slot);

  // Call a JS function with an any receiver, possibly (but not necessarily)
  // undefined. The JSFunction or Callable to be called should be in |callable|.
  // The arguments should be in |args|, with the receiver in |args[0]|. Type
  // feedback is recorded in the |feedback_slot| in the type feedback vector.
  BytecodeArrayBuilder& CallAnyReceiver(Register callable, RegisterList args,
                                        int feedback_slot);

289 290 291 292 293
  // Call a JS function with an any receiver, possibly (but not necessarily)
  // undefined. The JSFunction or Callable to be called should be in |callable|.
  // The arguments should be in |args|, with the receiver in |args[0]|.
  BytecodeArrayBuilder& CallNoFeedback(Register callable, RegisterList args);

294 295 296 297 298 299
  // Tail call into a JS function. The JSFunction or Callable to be called
  // should be in |callable|. The arguments should be in |args|, with the
  // receiver in |args[0]|. Type feedback is recorded in the |feedback_slot| in
  // the type feedback vector.
  BytecodeArrayBuilder& TailCall(Register callable, RegisterList args,
                                 int feedback_slot);
300

301
  // Call a JS function. The JSFunction or Callable to be called should be in
302
  // |callable|, the receiver in |args[0]| and the arguments in |args[1]|
303
  // onwards. The final argument must be a spread.
304 305
  BytecodeArrayBuilder& CallWithSpread(Register callable, RegisterList args,
                                       int feedback_slot);
306

307
  // Call the Construct operator. The accumulator holds the |new_target|.
308
  // The |constructor| is in a register and arguments are in |args|.
309 310
  BytecodeArrayBuilder& Construct(Register constructor, RegisterList args,
                                  int feedback_slot);
311

312 313
  // Call the Construct operator for use with a spread. The accumulator holds
  // the |new_target|. The |constructor| is in a register and arguments are in
314
  // |args|. The final argument must be a spread.
315
  BytecodeArrayBuilder& ConstructWithSpread(Register constructor,
316 317
                                            RegisterList args,
                                            int feedback_slot);
318

319
  // Call the runtime function with |function_id| and arguments |args|.
320
  BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id,
321 322 323 324 325 326
                                    RegisterList args);
  // Call the runtime function with |function_id| with single argument |arg|.
  BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id,
                                    Register arg);
  // Call the runtime function with |function_id| with no arguments.
  BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id);
327

328 329
  // Call the runtime function with |function_id| and arguments |args|, that
  // returns a pair of values. The return values will be returned in
330
  // |return_pair|.
331
  BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id,
332
                                           RegisterList args,
333 334 335 336
                                           RegisterList return_pair);
  // Call the runtime function with |function_id| with single argument |arg|
  // that returns a pair of values. The return values will be returned in
  // |return_pair|.
337
  BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id,
338 339
                                           Register arg,
                                           RegisterList return_pair);
340

341 342
  // Call the JS runtime function with |context_index| and arguments |args|,
  // with no receiver as it is implicitly set to undefined.
343
  BytecodeArrayBuilder& CallJSRuntime(int context_index, RegisterList args);
344

345
  // Operators (register holds the lhs value, accumulator holds the rhs value).
346 347 348
  // Type feedback will be recorded in the |feedback_slot|
  BytecodeArrayBuilder& BinaryOperation(Token::Value binop, Register reg,
                                        int feedback_slot);
349
  // Same as above, but lhs in the accumulator and rhs in |literal|.
350
  BytecodeArrayBuilder& BinaryOperationSmiLiteral(Token::Value binop,
351
                                                  Smi literal,
352
                                                  int feedback_slot);
353

354
  // Unary and Count Operators (value stored in accumulator).
355
  // Type feedback will be recorded in the |feedback_slot|
356
  BytecodeArrayBuilder& UnaryOperation(Token::Value op, int feedback_slot);
357

358 359 360 361 362
  enum class ToBooleanMode {
    kConvertToBoolean,  // Perform ToBoolean conversion on accumulator.
    kAlreadyBoolean,    // Accumulator is already a Boolean.
  };

363
  // Unary Operators.
364
  BytecodeArrayBuilder& LogicalNot(ToBooleanMode mode);
365 366
  BytecodeArrayBuilder& TypeOf();

367 368 369 370 371
  // Expects a heap object in the accumulator. Returns its super constructor in
  // the register |out| if it passes the IsConstructor test. Otherwise, it
  // throws a TypeError exception.
  BytecodeArrayBuilder& GetSuperConstructor(Register out);

372 373 374 375
  // Deletes property from an object. This expects that accumulator contains
  // the key to be deleted and the register contains a reference to the object.
  BytecodeArrayBuilder& Delete(Register object, LanguageMode language_mode);

376 377 378
  // JavaScript defines two kinds of 'nil'.
  enum NilValue { kNullValue, kUndefinedValue };

379
  // Tests.
380
  BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg,
381 382
                                         int feedback_slot);
  BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg);
383
  BytecodeArrayBuilder& CompareReference(Register reg);
384 385 386 387
  BytecodeArrayBuilder& CompareUndetectable();
  BytecodeArrayBuilder& CompareUndefined();
  BytecodeArrayBuilder& CompareNull();
  BytecodeArrayBuilder& CompareNil(Token::Value op, NilValue nil);
388 389
  BytecodeArrayBuilder& CompareTypeOf(
      TestTypeOfFlags::LiteralFlag literal_flag);
390

391
  // Converts accumulator and stores result in register |out|.
392 393
  BytecodeArrayBuilder& ToObject(Register out);
  BytecodeArrayBuilder& ToName(Register out);
394
  BytecodeArrayBuilder& ToString();
395 396 397

  // Converts accumulator and stores result back in accumulator.
  BytecodeArrayBuilder& ToNumber(int feedback_slot);
398
  BytecodeArrayBuilder& ToNumeric(int feedback_slot);
399

400
  // Flow Control.
401
  BytecodeArrayBuilder& Bind(BytecodeLabel* label);
402
  BytecodeArrayBuilder& Bind(const BytecodeLabel& target, BytecodeLabel* label);
403
  BytecodeArrayBuilder& Bind(BytecodeJumpTable* jump_table, int case_value);
404

405
  BytecodeArrayBuilder& Jump(BytecodeLabel* label);
406 407 408 409
  BytecodeArrayBuilder& JumpLoop(BytecodeLabel* label, int loop_depth);

  BytecodeArrayBuilder& JumpIfTrue(ToBooleanMode mode, BytecodeLabel* label);
  BytecodeArrayBuilder& JumpIfFalse(ToBooleanMode mode, BytecodeLabel* label);
410
  BytecodeArrayBuilder& JumpIfJSReceiver(BytecodeLabel* label);
411
  BytecodeArrayBuilder& JumpIfNull(BytecodeLabel* label);
412
  BytecodeArrayBuilder& JumpIfNotNull(BytecodeLabel* label);
413
  BytecodeArrayBuilder& JumpIfUndefined(BytecodeLabel* label);
414 415 416 417 418
  BytecodeArrayBuilder& JumpIfNotUndefined(BytecodeLabel* label);
  BytecodeArrayBuilder& JumpIfNil(BytecodeLabel* label, Token::Value op,
                                  NilValue nil);
  BytecodeArrayBuilder& JumpIfNotNil(BytecodeLabel* label, Token::Value op,
                                     NilValue nil);
419

420 421
  BytecodeArrayBuilder& SwitchOnSmiNoFeedback(BytecodeJumpTable* jump_table);

422
  BytecodeArrayBuilder& StackCheck(int position);
423

424 425 426 427
  // Sets the pending message to the value in the accumulator, and returns the
  // previous pending message in the accumulator.
  BytecodeArrayBuilder& SetPendingMessage();

428
  BytecodeArrayBuilder& Throw();
429
  BytecodeArrayBuilder& ReThrow();
430
  BytecodeArrayBuilder& Abort(AbortReason reason);
431
  BytecodeArrayBuilder& Return();
432 433 434
  BytecodeArrayBuilder& ThrowReferenceErrorIfHole(const AstRawString* name);
  BytecodeArrayBuilder& ThrowSuperNotCalledIfHole();
  BytecodeArrayBuilder& ThrowSuperAlreadyCalledIfNotHole();
435

436 437 438
  // Debugger.
  BytecodeArrayBuilder& Debugger();

439 440 441
  // Increment the block counter at the given slot (block code coverage).
  BytecodeArrayBuilder& IncBlockCounter(int slot);

442
  // Complex flow control.
443 444 445
  BytecodeArrayBuilder& ForInEnumerate(Register receiver);
  BytecodeArrayBuilder& ForInPrepare(RegisterList cache_info_triple,
                                     int feedback_slot);
446
  BytecodeArrayBuilder& ForInContinue(Register index, Register cache_length);
447
  BytecodeArrayBuilder& ForInNext(Register receiver, Register index,
448
                                  RegisterList cache_type_array_pair,
449
                                  int feedback_slot);
450
  BytecodeArrayBuilder& ForInStep(Register index);
451

452
  // Generators.
453
  BytecodeArrayBuilder& SuspendGenerator(Register generator,
454 455
                                         RegisterList registers,
                                         int suspend_id);
456 457
  BytecodeArrayBuilder& SwitchOnGeneratorState(Register generator,
                                               BytecodeJumpTable* jump_table);
458 459
  BytecodeArrayBuilder& ResumeGenerator(Register generator,
                                        RegisterList registers);
460

461
  // Exception handling.
462 463
  BytecodeArrayBuilder& MarkHandler(int handler_id,
                                    HandlerTable::CatchPrediction will_catch);
464 465 466 467 468 469 470
  BytecodeArrayBuilder& MarkTryBegin(int handler_id, Register context);
  BytecodeArrayBuilder& MarkTryEnd(int handler_id);

  // Creates a new handler table entry and returns a {hander_id} identifying the
  // entry, so that it can be referenced by above exception handling support.
  int NewHandlerEntry() { return handler_table_builder()->NewHandlerEntry(); }

471 472 473 474
  // Allocates a new jump table of given |size| and |case_value_base| in the
  // constant pool.
  BytecodeJumpTable* AllocateJumpTable(int size, int case_value_base);

475 476
  // Gets a constant pool entry.
  size_t GetConstantPoolEntry(const AstRawString* raw_string);
477
  size_t GetConstantPoolEntry(AstBigInt bigint);
478
  size_t GetConstantPoolEntry(const Scope* scope);
479
  size_t GetConstantPoolEntry(double number);
480 481 482 483 484 485 486 487
#define ENTRY_GETTER(NAME, ...) size_t NAME##ConstantPoolEntry();
  SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)
#undef ENTRY_GETTER

  // Allocates a slot in the constant pool which can later be set.
  size_t AllocateDeferredConstantPoolEntry();
  // Sets the deferred value into an allocated constant pool entry.
  void SetDeferredConstantPoolEntry(size_t entry, Handle<Object> object);
488

489 490
  void InitializeReturnPosition(FunctionLiteral* literal);

491 492 493 494 495 496
  void SetStatementPosition(Statement* stmt) {
    if (stmt->position() == kNoSourcePosition) return;
    latest_source_info_.MakeStatementPosition(stmt->position());
  }

  void SetExpressionPosition(Expression* expr) {
497 498 499 500 501
    SetExpressionPosition(expr->position());
  }

  void SetExpressionPosition(int position) {
    if (position == kNoSourcePosition) return;
502 503 504
    if (!latest_source_info_.is_statement()) {
      // Ensure the current expression position is overwritten with the
      // latest value.
505
      latest_source_info_.MakeExpressionPosition(position);
506 507 508 509 510 511 512
    }
  }

  void SetExpressionAsStatementPosition(Expression* expr) {
    if (expr->position() == kNoSourcePosition) return;
    latest_source_info_.MakeStatementPosition(expr->position());
  }
513

514 515 516 517 518 519 520 521
  void SetReturnPosition(int source_position, FunctionLiteral* literal) {
    if (source_position != kNoSourcePosition) {
      latest_source_info_.MakeStatementPosition(source_position);
    } else if (literal->return_position() != kNoSourcePosition) {
      latest_source_info_.MakeStatementPosition(literal->return_position());
    }
  }

522
  bool RequiresImplicitReturn() const { return !return_seen_in_block_; }
523 524 525
  bool RemainderOfBlockIsDead() const {
    return bytecode_array_writer_.RemainderOfBlockIsDead();
  }
526

527 528 529 530 531 532
  // Returns the raw operand value for the given register or register list.
  uint32_t GetInputRegisterOperand(Register reg);
  uint32_t GetOutputRegisterOperand(Register reg);
  uint32_t GetInputRegisterListOperand(RegisterList reg_list);
  uint32_t GetOutputRegisterListOperand(RegisterList reg_list);

533 534 535 536 537 538
  // Outputs raw register transfer bytecodes without going through the register
  // optimizer.
  void OutputLdarRaw(Register reg);
  void OutputStarRaw(Register reg);
  void OutputMovRaw(Register src, Register dest);

539 540 541
  // Accessors
  BytecodeRegisterAllocator* register_allocator() {
    return &register_allocator_;
542
  }
543 544
  const BytecodeRegisterAllocator* register_allocator() const {
    return &register_allocator_;
545
  }
546
  Zone* zone() const { return zone_; }
547

548
 private:
549 550 551 552 553 554
  friend class BytecodeRegisterAllocator;
  template <Bytecode bytecode, AccumulatorUse accumulator_use,
            OperandType... operand_types>
  friend class BytecodeNodeBuilder;

  const FeedbackVectorSpec* feedback_vector_spec() const {
555
    return feedback_vector_spec_;
556 557 558
  }

  // Returns the current source position for the given |bytecode|.
559 560 561 562 563 564 565 566 567
  V8_INLINE BytecodeSourceInfo CurrentSourcePosition(Bytecode bytecode);

#define DECLARE_BYTECODE_OUTPUT(Name, ...)                         \
  template <typename... Operands>                                  \
  V8_INLINE BytecodeNode Create##Name##Node(Operands... operands); \
  template <typename... Operands>                                  \
  V8_INLINE void Output##Name(Operands... operands);               \
  template <typename... Operands>                                  \
  V8_INLINE void Output##Name(BytecodeLabel* label, Operands... operands);
568 569
  BYTECODE_LIST(DECLARE_BYTECODE_OUTPUT)
#undef DECLARE_OPERAND_TYPE_INFO
570

571
  V8_INLINE void OutputSwitchOnSmiNoFeedback(BytecodeJumpTable* jump_table);
572

573
  bool RegisterIsValid(Register reg) const;
574
  bool RegisterListIsValid(RegisterList reg_list) const;
575

576 577 578
  // Sets a deferred source info which should be emitted before any future
  // source info (either attached to a following bytecode or as a nop).
  void SetDeferredSourceInfo(BytecodeSourceInfo source_info);
579 580 581 582 583 584 585 586
  // Either attach deferred source info to node, or emit it as a nop bytecode
  // if node already have valid source info.
  void AttachOrEmitDeferredSourceInfo(BytecodeNode* node);

  // Write bytecode to bytecode array.
  void Write(BytecodeNode* node);
  void WriteJump(BytecodeNode* node, BytecodeLabel* label);
  void WriteSwitch(BytecodeNode* node, BytecodeJumpTable* label);
587

588
  // Not implemented as the illegal bytecode is used inside internally
589
  // to indicate a bytecode field is not valid or an error has occurred
590 591 592
  // during bytecode generation.
  BytecodeArrayBuilder& Illegal();

593
  template <Bytecode bytecode, AccumulatorUse accumulator_use>
594
  void PrepareToOutputBytecode();
595

596
  void LeaveBasicBlock() { return_seen_in_block_ = false; }
597

598 599 600
  BytecodeArrayWriter* bytecode_array_writer() {
    return &bytecode_array_writer_;
  }
601 602 603 604 605 606
  ConstantArrayBuilder* constant_array_builder() {
    return &constant_array_builder_;
  }
  const ConstantArrayBuilder* constant_array_builder() const {
    return &constant_array_builder_;
  }
607 608 609
  HandlerTableBuilder* handler_table_builder() {
    return &handler_table_builder_;
  }
610

611
  Zone* zone_;
612
  FeedbackVectorSpec* feedback_vector_spec_;
613
  bool bytecode_generated_;
614
  ConstantArrayBuilder constant_array_builder_;
615
  HandlerTableBuilder handler_table_builder_;
616 617 618
  bool return_seen_in_block_;
  int parameter_count_;
  int local_register_count_;
619
  BytecodeRegisterAllocator register_allocator_;
620
  BytecodeArrayWriter bytecode_array_writer_;
621
  BytecodeRegisterOptimizer* register_optimizer_;
622
  BytecodeSourceInfo latest_source_info_;
623
  BytecodeSourceInfo deferred_source_info_;
624

625
  DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBuilder);
626 627
};

628 629 630
V8_EXPORT_PRIVATE std::ostream& operator<<(
    std::ostream& os, const BytecodeArrayBuilder::ToBooleanMode& mode);

631 632 633 634 635
}  // namespace interpreter
}  // namespace internal
}  // namespace v8

#endif  // V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_