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_GENERATOR_H_ 6 #define V8_INTERPRETER_BYTECODE_GENERATOR_H_ 7 8 #include "src/ast/ast.h" 9 #include "src/interpreter/bytecode-array-builder.h" 10 #include "src/interpreter/bytecode-label.h" 11 #include "src/interpreter/bytecode-register.h" 12 #include "src/interpreter/bytecodes.h" 13 #include "src/objects/feedback-vector.h" 14 #include "src/objects/function-kind.h" 15 16 namespace v8 { 17 namespace internal { 18 19 class AstNodeSourceRanges; 20 class AstStringConstants; 21 class BytecodeArray; 22 class UnoptimizedCompilationInfo; 23 enum class SourceRangeKind; 24 25 namespace interpreter { 26 27 class TopLevelDeclarationsBuilder; 28 class LoopBuilder; 29 class BlockCoverageBuilder; 30 class BytecodeJumpTable; 31 32 class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> { 33 public: 34 explicit BytecodeGenerator( 35 LocalIsolate* local_isolate, Zone* zone, UnoptimizedCompilationInfo* info, 36 const AstStringConstants* ast_string_constants, 37 std::vector<FunctionLiteral*>* eager_inner_literals, 38 Handle<Script> script); 39 40 void GenerateBytecode(uintptr_t stack_limit); 41 template <typename IsolateT> 42 Handle<BytecodeArray> FinalizeBytecode(IsolateT* isolate, 43 Handle<Script> script); 44 template <typename IsolateT> 45 Handle<ByteArray> FinalizeSourcePositionTable(IsolateT* isolate); 46 47 #ifdef DEBUG 48 int CheckBytecodeMatches(BytecodeArray bytecode); 49 #endif 50 51 #define DECLARE_VISIT(type) void Visit##type(type* node); 52 AST_NODE_LIST(DECLARE_VISIT) 53 #undef DECLARE_VISIT 54 55 // Visiting function for declarations list and statements are overridden. 56 void VisitModuleDeclarations(Declaration::List* declarations); 57 void VisitGlobalDeclarations(Declaration::List* declarations); 58 void VisitDeclarations(Declaration::List* declarations); 59 void VisitStatements(const ZonePtrList<Statement>* statments); 60 61 private: 62 class AccumulatorPreservingScope; 63 class ContextScope; 64 class ControlScope; 65 class ControlScopeForBreakable; 66 class ControlScopeForIteration; 67 class ControlScopeForTopLevel; 68 class ControlScopeForTryCatch; 69 class ControlScopeForTryFinally; 70 class CurrentScope; 71 class EffectResultScope; 72 class ExpressionResultScope; 73 class FeedbackSlotCache; 74 class IteratorRecord; 75 class MultipleEntryBlockContextScope; 76 class LoopScope; 77 class NaryCodeCoverageSlots; 78 class OptionalChainNullLabelScope; 79 class RegisterAllocationScope; 80 class TestResultScope; 81 class TopLevelDeclarationsBuilder; 82 class ValueResultScope; 83 84 using ToBooleanMode = BytecodeArrayBuilder::ToBooleanMode; 85 86 enum class TestFallthrough { kThen, kElse, kNone }; 87 enum class TypeHint { kAny, kBoolean, kString }; 88 enum class AccumulatorPreservingMode { kNone, kPreserve }; 89 90 // An assignment has to evaluate its LHS before its RHS, but has to assign to 91 // the LHS after both evaluations are done. This class stores the data 92 // computed in the LHS evaulation that has to live across the RHS evaluation, 93 // and is used in the actual LHS assignment. 94 class AssignmentLhsData { 95 public: 96 static AssignmentLhsData NonProperty(Expression* expr); 97 static AssignmentLhsData NamedProperty(Expression* object_expr, 98 Register object, 99 const AstRawString* name); 100 static AssignmentLhsData KeyedProperty(Register object, Register key); 101 static AssignmentLhsData PrivateMethodOrAccessor(AssignType type, 102 Property* property, 103 Register object, 104 Register key); 105 static AssignmentLhsData NamedSuperProperty( 106 RegisterList super_property_args); 107 static AssignmentLhsData KeyedSuperProperty( 108 RegisterList super_property_args); 109 assign_type()110 AssignType assign_type() const { return assign_type_; } expr()111 Expression* expr() const { 112 DCHECK(assign_type_ == NON_PROPERTY || assign_type_ == PRIVATE_METHOD || 113 assign_type_ == PRIVATE_GETTER_ONLY || 114 assign_type_ == PRIVATE_SETTER_ONLY || 115 assign_type_ == PRIVATE_GETTER_AND_SETTER); 116 return expr_; 117 } object_expr()118 Expression* object_expr() const { 119 DCHECK_EQ(assign_type_, NAMED_PROPERTY); 120 return object_expr_; 121 } object()122 Register object() const { 123 DCHECK(assign_type_ == NAMED_PROPERTY || assign_type_ == KEYED_PROPERTY || 124 assign_type_ == PRIVATE_METHOD || 125 assign_type_ == PRIVATE_GETTER_ONLY || 126 assign_type_ == PRIVATE_SETTER_ONLY || 127 assign_type_ == PRIVATE_GETTER_AND_SETTER); 128 return object_; 129 } key()130 Register key() const { 131 DCHECK(assign_type_ == KEYED_PROPERTY || assign_type_ == PRIVATE_METHOD || 132 assign_type_ == PRIVATE_GETTER_ONLY || 133 assign_type_ == PRIVATE_SETTER_ONLY || 134 assign_type_ == PRIVATE_GETTER_AND_SETTER); 135 return key_; 136 } name()137 const AstRawString* name() const { 138 DCHECK(assign_type_ == NAMED_PROPERTY); 139 return name_; 140 } super_property_args()141 RegisterList super_property_args() const { 142 DCHECK(assign_type_ == NAMED_SUPER_PROPERTY || 143 assign_type_ == KEYED_SUPER_PROPERTY); 144 return super_property_args_; 145 } 146 147 private: AssignmentLhsData(AssignType assign_type,Expression * expr,RegisterList super_property_args,Register object,Register key,Expression * object_expr,const AstRawString * name)148 AssignmentLhsData(AssignType assign_type, Expression* expr, 149 RegisterList super_property_args, Register object, 150 Register key, Expression* object_expr, 151 const AstRawString* name) 152 : assign_type_(assign_type), 153 expr_(expr), 154 super_property_args_(super_property_args), 155 object_(object), 156 key_(key), 157 object_expr_(object_expr), 158 name_(name) {} 159 160 AssignType assign_type_; 161 162 // Different assignment types use different fields: 163 // 164 // NON_PROPERTY: expr 165 // NAMED_PROPERTY: object_expr, object, name 166 // KEYED_PROPERTY, PRIVATE_METHOD: object, key 167 // NAMED_SUPER_PROPERTY: super_property_args 168 // KEYED_SUPER_PROPERT: super_property_args 169 Expression* expr_; 170 RegisterList super_property_args_; 171 Register object_; 172 Register key_; 173 Expression* object_expr_; 174 const AstRawString* name_; 175 }; 176 177 void GenerateBytecodeBody(); 178 template <typename IsolateT> 179 void AllocateDeferredConstants(IsolateT* isolate, Handle<Script> script); 180 181 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); 182 183 // Dispatched from VisitBinaryOperation. 184 void VisitArithmeticExpression(BinaryOperation* binop); 185 void VisitCommaExpression(BinaryOperation* binop); 186 void VisitLogicalOrExpression(BinaryOperation* binop); 187 void VisitLogicalAndExpression(BinaryOperation* binop); 188 void VisitNullishExpression(BinaryOperation* binop); 189 190 // Dispatched from VisitNaryOperation. 191 void VisitNaryArithmeticExpression(NaryOperation* expr); 192 void VisitNaryCommaExpression(NaryOperation* expr); 193 void VisitNaryLogicalOrExpression(NaryOperation* expr); 194 void VisitNaryLogicalAndExpression(NaryOperation* expr); 195 void VisitNaryNullishExpression(NaryOperation* expr); 196 197 // Dispatched from VisitUnaryOperation. 198 void VisitVoid(UnaryOperation* expr); 199 void VisitTypeOf(UnaryOperation* expr); 200 void VisitNot(UnaryOperation* expr); 201 void VisitDelete(UnaryOperation* expr); 202 203 // Visits a typeof expression for the value on which to perform the typeof. 204 void VisitForTypeOfValue(Expression* expr); 205 206 // Used by flow control routines to evaluate loop condition. 207 void VisitCondition(Expression* expr); 208 209 // Visit the arguments expressions in |args| and store them in |args_regs|, 210 // growing |args_regs| for each argument visited. 211 void VisitArguments(const ZonePtrList<Expression>* args, 212 RegisterList* arg_regs); 213 214 // Visit a keyed super property load. The optional 215 // |opt_receiver_out| register will have the receiver stored to it 216 // if it's a valid register. The loaded value is placed in the 217 // accumulator. 218 void VisitKeyedSuperPropertyLoad(Property* property, 219 Register opt_receiver_out); 220 221 // Visit a named super property load. The optional 222 // |opt_receiver_out| register will have the receiver stored to it 223 // if it's a valid register. The loaded value is placed in the 224 // accumulator. 225 void VisitNamedSuperPropertyLoad(Property* property, 226 Register opt_receiver_out); 227 228 void VisitPropertyLoad(Register obj, Property* expr); 229 void VisitPropertyLoadForRegister(Register obj, Property* expr, 230 Register destination); 231 232 AssignmentLhsData PrepareAssignmentLhs( 233 Expression* lhs, AccumulatorPreservingMode accumulator_preserving_mode = 234 AccumulatorPreservingMode::kNone); 235 void BuildAssignment(const AssignmentLhsData& data, Token::Value op, 236 LookupHoistingMode lookup_hoisting_mode); 237 238 void BuildThisVariableLoad(); 239 240 void BuildDeclareCall(Runtime::FunctionId id); 241 242 Expression* GetDestructuringDefaultValue(Expression** target); 243 void BuildDestructuringArrayAssignment( 244 ArrayLiteral* pattern, Token::Value op, 245 LookupHoistingMode lookup_hoisting_mode); 246 void BuildDestructuringObjectAssignment( 247 ObjectLiteral* pattern, Token::Value op, 248 LookupHoistingMode lookup_hoisting_mode); 249 250 void BuildLoadNamedProperty(const Expression* object_expr, Register object, 251 const AstRawString* name); 252 void BuildSetNamedProperty(const Expression* object_expr, Register object, 253 const AstRawString* name); 254 void BuildStoreGlobal(Variable* variable); 255 256 void BuildVariableLoad(Variable* variable, HoleCheckMode hole_check_mode, 257 TypeofMode typeof_mode = TypeofMode::kNotInside); 258 void BuildVariableLoadForAccumulatorValue( 259 Variable* variable, HoleCheckMode hole_check_mode, 260 TypeofMode typeof_mode = TypeofMode::kNotInside); 261 void BuildVariableAssignment( 262 Variable* variable, Token::Value op, HoleCheckMode hole_check_mode, 263 LookupHoistingMode lookup_hoisting_mode = LookupHoistingMode::kNormal); 264 void BuildLiteralCompareNil(Token::Value compare_op, 265 BytecodeArrayBuilder::NilValue nil); 266 void BuildReturn(int source_position); 267 void BuildAsyncReturn(int source_position); 268 void BuildAsyncGeneratorReturn(); 269 void BuildReThrow(); 270 void BuildHoleCheckForVariableAssignment(Variable* variable, Token::Value op); 271 void BuildThrowIfHole(Variable* variable); 272 273 void BuildNewLocalActivationContext(); 274 void BuildLocalActivationContextInitialization(); 275 void BuildNewLocalBlockContext(Scope* scope); 276 void BuildNewLocalCatchContext(Scope* scope); 277 void BuildNewLocalWithContext(Scope* scope); 278 279 void BuildGeneratorPrologue(); 280 void BuildSuspendPoint(int position); 281 282 void BuildAwait(int position = kNoSourcePosition); 283 void BuildAwait(Expression* await_expr); 284 285 void BuildFinalizeIteration(IteratorRecord iterator, Register done, 286 Register iteration_continuation_token); 287 288 void BuildGetIterator(IteratorType hint); 289 290 // Create an IteratorRecord with pre-allocated registers holding the next 291 // method and iterator object. 292 IteratorRecord BuildGetIteratorRecord(Register iterator_next, 293 Register iterator_object, 294 IteratorType hint); 295 296 // Create an IteratorRecord allocating new registers to hold the next method 297 // and iterator object. 298 IteratorRecord BuildGetIteratorRecord(IteratorType hint); 299 void BuildIteratorNext(const IteratorRecord& iterator, Register next_result); 300 void BuildIteratorClose(const IteratorRecord& iterator, 301 Expression* expr = nullptr); 302 void BuildCallIteratorMethod(Register iterator, const AstRawString* method, 303 RegisterList receiver_and_args, 304 BytecodeLabel* if_called, 305 BytecodeLabels* if_notcalled); 306 307 void BuildFillArrayWithIterator(IteratorRecord iterator, Register array, 308 Register index, Register value, 309 FeedbackSlot next_value_slot, 310 FeedbackSlot next_done_slot, 311 FeedbackSlot index_slot, 312 FeedbackSlot element_slot); 313 // Create Array literals. |expr| can be nullptr, but if provided, 314 // a boilerplate will be used to create an initial array for elements 315 // before the first spread. 316 void BuildCreateArrayLiteral(const ZonePtrList<Expression>* elements, 317 ArrayLiteral* expr); 318 void BuildCreateObjectLiteral(Register literal, uint8_t flags, size_t entry); 319 void AllocateTopLevelRegisters(); 320 void VisitArgumentsObject(Variable* variable); 321 void VisitRestArgumentsArray(Variable* rest); 322 void VisitCallSuper(Call* call); 323 void BuildInvalidPropertyAccess(MessageTemplate tmpl, Property* property); 324 void BuildPrivateBrandCheck(Property* property, Register object); 325 void BuildPrivateMethodIn(Variable* private_name, 326 Expression* object_expression); 327 void BuildPrivateGetterAccess(Register obj, Register access_pair); 328 void BuildPrivateSetterAccess(Register obj, Register access_pair, 329 Register value); 330 void BuildPrivateMethods(ClassLiteral* expr, bool is_static, 331 Register home_object); 332 void BuildClassProperty(ClassLiteral::Property* property); 333 void BuildClassLiteral(ClassLiteral* expr, Register name); 334 void VisitClassLiteral(ClassLiteral* expr, Register name); 335 void VisitNewTargetVariable(Variable* variable); 336 void VisitThisFunctionVariable(Variable* variable); 337 void BuildPrivateBrandInitialization(Register receiver, Variable* brand); 338 void BuildInstanceMemberInitialization(Register constructor, 339 Register instance); 340 void BuildGeneratorObjectVariableInitialization(); 341 void VisitBlockDeclarationsAndStatements(Block* stmt); 342 void VisitLiteralAccessor(LiteralProperty* property, Register value_out); 343 void VisitForInAssignment(Expression* expr); 344 void VisitModuleNamespaceImports(); 345 346 // Visit a logical OR/AND within a test context, rewiring the jumps based 347 // on the expression values. 348 void VisitLogicalTest(Token::Value token, Expression* left, Expression* right, 349 int right_coverage_slot); 350 void VisitNaryLogicalTest(Token::Value token, NaryOperation* expr, 351 const NaryCodeCoverageSlots* coverage_slots); 352 353 // Visit a (non-RHS) test for a logical op, which falls through if the test 354 // fails or jumps to the appropriate labels if it succeeds. 355 void VisitLogicalTestSubExpression(Token::Value token, Expression* expr, 356 BytecodeLabels* then_labels, 357 BytecodeLabels* else_labels, 358 int coverage_slot); 359 360 // Helpers for binary and nary logical op value expressions. 361 bool VisitLogicalOrSubExpression(Expression* expr, BytecodeLabels* end_labels, 362 int coverage_slot); 363 bool VisitLogicalAndSubExpression(Expression* expr, 364 BytecodeLabels* end_labels, 365 int coverage_slot); 366 367 // Helper for binary and nary nullish op value expressions. 368 bool VisitNullishSubExpression(Expression* expr, BytecodeLabels* end_labels, 369 int coverage_slot); 370 371 // Visit the body of a loop iteration. 372 void VisitIterationBody(IterationStatement* stmt, LoopBuilder* loop_builder); 373 374 // Visit a statement and switch scopes, the context is in the accumulator. 375 void VisitInScope(Statement* stmt, Scope* scope); 376 377 void BuildPushUndefinedIntoRegisterList(RegisterList* reg_list); 378 379 void BuildLoadPropertyKey(LiteralProperty* property, Register out_reg); 380 381 int AllocateBlockCoverageSlotIfEnabled(AstNode* node, SourceRangeKind kind); 382 int AllocateNaryBlockCoverageSlotIfEnabled(NaryOperation* node, size_t index); 383 384 void BuildIncrementBlockCoverageCounterIfEnabled(AstNode* node, 385 SourceRangeKind kind); 386 void BuildIncrementBlockCoverageCounterIfEnabled(int coverage_array_slot); 387 388 void BuildTest(ToBooleanMode mode, BytecodeLabels* then_labels, 389 BytecodeLabels* else_labels, TestFallthrough fallthrough); 390 391 template <typename TryBodyFunc, typename CatchBodyFunc> 392 void BuildTryCatch(TryBodyFunc try_body_func, CatchBodyFunc catch_body_func, 393 HandlerTable::CatchPrediction catch_prediction, 394 TryCatchStatement* stmt_for_coverage = nullptr); 395 template <typename TryBodyFunc, typename FinallyBodyFunc> 396 void BuildTryFinally(TryBodyFunc try_body_func, 397 FinallyBodyFunc finally_body_func, 398 HandlerTable::CatchPrediction catch_prediction, 399 TryFinallyStatement* stmt_for_coverage = nullptr); 400 401 template <typename ExpressionFunc> 402 void BuildOptionalChain(ExpressionFunc expression_func); 403 404 // Visitors for obtaining expression result in the accumulator, in a 405 // register, or just getting the effect. Some visitors return a TypeHint which 406 // specifies the type of the result of the visited expression. 407 TypeHint VisitForAccumulatorValue(Expression* expr); 408 void VisitForAccumulatorValueOrTheHole(Expression* expr); 409 V8_WARN_UNUSED_RESULT Register VisitForRegisterValue(Expression* expr); 410 V8_INLINE void VisitForRegisterValue(Expression* expr, Register destination); 411 void VisitAndPushIntoRegisterList(Expression* expr, RegisterList* reg_list); 412 void VisitForEffect(Expression* expr); 413 void VisitForTest(Expression* expr, BytecodeLabels* then_labels, 414 BytecodeLabels* else_labels, TestFallthrough fallthrough); 415 void VisitForNullishTest(Expression* expr, BytecodeLabels* then_labels, 416 BytecodeLabels* test_next_labels, 417 BytecodeLabels* else_labels); 418 419 void VisitInSameTestExecutionScope(Expression* expr); 420 421 Register GetRegisterForLocalVariable(Variable* variable); 422 423 // Returns the runtime function id for a store to super for the function's 424 // language mode. 425 inline Runtime::FunctionId StoreToSuperRuntimeId(); 426 inline Runtime::FunctionId StoreKeyedToSuperRuntimeId(); 427 428 // Returns a cached slot, or create and cache a new slot if one doesn't 429 // already exists. 430 FeedbackSlot GetCachedLoadGlobalICSlot(TypeofMode typeof_mode, 431 Variable* variable); 432 FeedbackSlot GetCachedStoreGlobalICSlot(LanguageMode language_mode, 433 Variable* variable); 434 FeedbackSlot GetCachedLoadICSlot(const Expression* expr, 435 const AstRawString* name); 436 FeedbackSlot GetCachedLoadSuperICSlot(const AstRawString* name); 437 FeedbackSlot GetCachedStoreICSlot(const Expression* expr, 438 const AstRawString* name); 439 FeedbackSlot GetDummyCompareICSlot(); 440 441 int GetCachedCreateClosureSlot(FunctionLiteral* literal); 442 443 void AddToEagerLiteralsIfEager(FunctionLiteral* literal); 444 ToBooleanModeFromTypeHint(TypeHint type_hint)445 static constexpr ToBooleanMode ToBooleanModeFromTypeHint(TypeHint type_hint) { 446 return type_hint == TypeHint::kBoolean ? ToBooleanMode::kAlreadyBoolean 447 : ToBooleanMode::kConvertToBoolean; 448 } 449 450 inline Register generator_object() const; 451 builder()452 inline BytecodeArrayBuilder* builder() { return &builder_; } zone()453 inline Zone* zone() const { return zone_; } closure_scope()454 inline DeclarationScope* closure_scope() const { return closure_scope_; } info()455 inline UnoptimizedCompilationInfo* info() const { return info_; } ast_string_constants()456 inline const AstStringConstants* ast_string_constants() const { 457 return ast_string_constants_; 458 } 459 current_scope()460 inline Scope* current_scope() const { return current_scope_; } set_current_scope(Scope * scope)461 inline void set_current_scope(Scope* scope) { current_scope_ = scope; } 462 execution_control()463 inline ControlScope* execution_control() const { return execution_control_; } set_execution_control(ControlScope * scope)464 inline void set_execution_control(ControlScope* scope) { 465 execution_control_ = scope; 466 } execution_context()467 inline ContextScope* execution_context() const { return execution_context_; } set_execution_context(ContextScope * context)468 inline void set_execution_context(ContextScope* context) { 469 execution_context_ = context; 470 } set_execution_result(ExpressionResultScope * execution_result)471 inline void set_execution_result(ExpressionResultScope* execution_result) { 472 execution_result_ = execution_result; 473 } execution_result()474 ExpressionResultScope* execution_result() const { return execution_result_; } register_allocator()475 BytecodeRegisterAllocator* register_allocator() { 476 return builder()->register_allocator(); 477 } 478 top_level_builder()479 TopLevelDeclarationsBuilder* top_level_builder() { 480 DCHECK_NOT_NULL(top_level_builder_); 481 return top_level_builder_; 482 } 483 inline LanguageMode language_mode() const; 484 inline FunctionKind function_kind() const; 485 inline FeedbackVectorSpec* feedback_spec(); 486 inline int feedback_index(FeedbackSlot slot) const; 487 feedback_slot_cache()488 inline FeedbackSlotCache* feedback_slot_cache() { 489 return feedback_slot_cache_; 490 } 491 catch_prediction()492 inline HandlerTable::CatchPrediction catch_prediction() const { 493 return catch_prediction_; 494 } set_catch_prediction(HandlerTable::CatchPrediction value)495 inline void set_catch_prediction(HandlerTable::CatchPrediction value) { 496 catch_prediction_ = value; 497 } 498 current_loop_scope()499 LoopScope* current_loop_scope() const { return current_loop_scope_; } set_current_loop_scope(LoopScope * loop_scope)500 void set_current_loop_scope(LoopScope* loop_scope) { 501 current_loop_scope_ = loop_scope; 502 } 503 504 LocalIsolate* local_isolate_; 505 Zone* zone_; 506 BytecodeArrayBuilder builder_; 507 UnoptimizedCompilationInfo* info_; 508 const AstStringConstants* ast_string_constants_; 509 DeclarationScope* closure_scope_; 510 Scope* current_scope_; 511 512 // External vector of literals to be eagerly compiled. 513 std::vector<FunctionLiteral*>* eager_inner_literals_; 514 Handle<Script> script_; 515 516 FeedbackSlotCache* feedback_slot_cache_; 517 518 TopLevelDeclarationsBuilder* top_level_builder_; 519 BlockCoverageBuilder* block_coverage_builder_; 520 ZoneVector<std::pair<FunctionLiteral*, size_t>> function_literals_; 521 ZoneVector<std::pair<NativeFunctionLiteral*, size_t>> 522 native_function_literals_; 523 ZoneVector<std::pair<ObjectLiteralBoilerplateBuilder*, size_t>> 524 object_literals_; 525 ZoneVector<std::pair<ArrayLiteralBoilerplateBuilder*, size_t>> 526 array_literals_; 527 ZoneVector<std::pair<ClassLiteral*, size_t>> class_literals_; 528 ZoneVector<std::pair<GetTemplateObject*, size_t>> template_objects_; 529 530 ControlScope* execution_control_; 531 ContextScope* execution_context_; 532 ExpressionResultScope* execution_result_; 533 534 Register incoming_new_target_or_generator_; 535 536 BytecodeLabels* optional_chaining_null_labels_; 537 538 // Dummy feedback slot for compare operations, where we don't care about 539 // feedback 540 SharedFeedbackSlot dummy_feedback_slot_; 541 542 BytecodeJumpTable* generator_jump_table_; 543 int suspend_count_; 544 // TODO(solanes): assess if we can move loop_depth_ into LoopScope. 545 int loop_depth_; 546 547 LoopScope* current_loop_scope_; 548 549 HandlerTable::CatchPrediction catch_prediction_; 550 }; 551 552 } // namespace interpreter 553 } // namespace internal 554 } // namespace v8 555 556 #endif // V8_INTERPRETER_BYTECODE_GENERATOR_H_ 557