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