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