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