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 ®ister_allocator_; 568 } register_allocator()569 const BytecodeRegisterAllocator* register_allocator() const { 570 return ®ister_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