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 
14 namespace v8 {
15 namespace internal {
16 
17 class CompilationInfo;
18 
19 namespace interpreter {
20 
21 class LoopBuilder;
22 
23 class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
24  public:
25   explicit BytecodeGenerator(CompilationInfo* info);
26 
27   void GenerateBytecode(uintptr_t stack_limit);
28   Handle<BytecodeArray> FinalizeBytecode(Isolate* isolate);
29 
30 #define DECLARE_VISIT(type) void Visit##type(type* node);
31   AST_NODE_LIST(DECLARE_VISIT)
32 #undef DECLARE_VISIT
33 
34   // Visiting function for declarations list and statements are overridden.
35   void VisitDeclarations(Declaration::List* declarations);
36   void VisitStatements(ZoneList<Statement*>* statments);
37 
38  private:
39   class ContextScope;
40   class ControlScope;
41   class ControlScopeForBreakable;
42   class ControlScopeForIteration;
43   class ControlScopeForTopLevel;
44   class ControlScopeForTryCatch;
45   class ControlScopeForTryFinally;
46   class ExpressionResultScope;
47   class EffectResultScope;
48   class GlobalDeclarationsBuilder;
49   class RegisterAllocationScope;
50   class TestResultScope;
51   class ValueResultScope;
52 
53   enum class TestFallthrough { kThen, kElse, kNone };
54 
55   void GenerateBytecodeBody();
56   void AllocateDeferredConstants();
57 
58   DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
59 
60   // Dispatched from VisitBinaryOperation.
61   void VisitArithmeticExpression(BinaryOperation* binop);
62   void VisitCommaExpression(BinaryOperation* binop);
63   void VisitLogicalOrExpression(BinaryOperation* binop);
64   void VisitLogicalAndExpression(BinaryOperation* binop);
65 
66   // Dispatched from VisitUnaryOperation.
67   void VisitVoid(UnaryOperation* expr);
68   void VisitTypeOf(UnaryOperation* expr);
69   void VisitNot(UnaryOperation* expr);
70   void VisitDelete(UnaryOperation* expr);
71 
72   // Used by flow control routines to evaluate loop condition.
73   void VisitCondition(Expression* expr);
74 
75   // Visit the arguments expressions in |args| and store them in |args_regs|,
76   // growing |args_regs| for each argument visited.
77   void VisitArguments(ZoneList<Expression*>* args, RegisterList* arg_regs);
78 
79   // Visit a keyed super property load. The optional
80   // |opt_receiver_out| register will have the receiver stored to it
81   // if it's a valid register. The loaded value is placed in the
82   // accumulator.
83   void VisitKeyedSuperPropertyLoad(Property* property,
84                                    Register opt_receiver_out);
85 
86   // Visit a named super property load. The optional
87   // |opt_receiver_out| register will have the receiver stored to it
88   // if it's a valid register. The loaded value is placed in the
89   // accumulator.
90   void VisitNamedSuperPropertyLoad(Property* property,
91                                    Register opt_receiver_out);
92 
93   void VisitPropertyLoad(Register obj, Property* expr);
94   void VisitPropertyLoadForRegister(Register obj, Property* expr,
95                                     Register destination);
96 
97   void BuildVariableLoad(Variable* variable, FeedbackVectorSlot slot,
98                          HoleCheckMode hole_check_mode,
99                          TypeofMode typeof_mode = NOT_INSIDE_TYPEOF);
100   void BuildVariableLoadForAccumulatorValue(
101       Variable* variable, FeedbackVectorSlot slot,
102       HoleCheckMode hole_check_mode,
103       TypeofMode typeof_mode = NOT_INSIDE_TYPEOF);
104   void BuildVariableAssignment(Variable* variable, Token::Value op,
105                                FeedbackVectorSlot slot,
106                                HoleCheckMode hole_check_mode);
107 
108   void BuildReturn();
109   void BuildReThrow();
110   void BuildAbort(BailoutReason bailout_reason);
111   void BuildThrowIfHole(Handle<String> name);
112   void BuildThrowIfNotHole(Handle<String> name);
113   void BuildThrowReferenceError(Handle<String> name);
114   void BuildHoleCheckForVariableAssignment(Variable* variable, Token::Value op);
115 
116   // Build jump to targets[value], where
117   // start_index <= value < start_index + size.
118   void BuildIndexedJump(Register value, size_t start_index, size_t size,
119                         ZoneVector<BytecodeLabel>& targets);
120 
121   void BuildNewLocalActivationContext();
122   void BuildLocalActivationContextInitialization();
123   void BuildNewLocalBlockContext(Scope* scope);
124   void BuildNewLocalCatchContext(Variable* variable, Scope* scope);
125   void BuildNewLocalWithContext(Scope* scope);
126 
127   void VisitGeneratorPrologue();
128 
129   void VisitArgumentsObject(Variable* variable);
130   void VisitRestArgumentsArray(Variable* rest);
131   void VisitCallSuper(Call* call);
132   void VisitClassLiteralForRuntimeDefinition(ClassLiteral* expr);
133   void VisitClassLiteralProperties(ClassLiteral* expr, Register literal,
134                                    Register prototype);
135   void VisitThisFunctionVariable(Variable* variable);
136   void VisitNewTargetVariable(Variable* variable);
137   void VisitBlockDeclarationsAndStatements(Block* stmt);
138   void VisitFunctionClosureForContext();
139   void VisitSetHomeObject(Register value, Register home_object,
140                           LiteralProperty* property, int slot_number = 0);
141   void VisitObjectLiteralAccessor(Register home_object,
142                                   ObjectLiteralProperty* property,
143                                   Register value_out);
144   void VisitForInAssignment(Expression* expr, FeedbackVectorSlot slot);
145   void VisitModuleNamespaceImports();
146 
147   // Visit the header/body of a loop iteration.
148   void VisitIterationHeader(IterationStatement* stmt,
149                             LoopBuilder* loop_builder);
150   void VisitIterationBody(IterationStatement* stmt, LoopBuilder* loop_builder);
151 
152   // Visit a statement and switch scopes, the context is in the accumulator.
153   void VisitInScope(Statement* stmt, Scope* scope);
154 
155   void BuildPushUndefinedIntoRegisterList(RegisterList* reg_list);
156 
157   // Visitors for obtaining expression result in the accumulator, in a
158   // register, or just getting the effect.
159   void VisitForAccumulatorValue(Expression* expr);
160   void VisitForAccumulatorValueOrTheHole(Expression* expr);
161   MUST_USE_RESULT Register VisitForRegisterValue(Expression* expr);
162   void VisitForRegisterValue(Expression* expr, Register destination);
163   void VisitAndPushIntoRegisterList(Expression* expr, RegisterList* reg_list);
164   void VisitForEffect(Expression* expr);
165   void VisitForTest(Expression* expr, BytecodeLabels* then_labels,
166                     BytecodeLabels* else_labels, TestFallthrough fallthrough);
167 
168   // Returns the runtime function id for a store to super for the function's
169   // language mode.
170   inline Runtime::FunctionId StoreToSuperRuntimeId();
171   inline Runtime::FunctionId StoreKeyedToSuperRuntimeId();
172 
builder()173   inline BytecodeArrayBuilder* builder() const { return builder_; }
zone()174   inline Zone* zone() const { return zone_; }
scope()175   inline DeclarationScope* scope() const { return scope_; }
info()176   inline CompilationInfo* info() const { return info_; }
177 
execution_control()178   inline ControlScope* execution_control() const { return execution_control_; }
set_execution_control(ControlScope * scope)179   inline void set_execution_control(ControlScope* scope) {
180     execution_control_ = scope;
181   }
execution_context()182   inline ContextScope* execution_context() const { return execution_context_; }
set_execution_context(ContextScope * context)183   inline void set_execution_context(ContextScope* context) {
184     execution_context_ = context;
185   }
set_execution_result(ExpressionResultScope * execution_result)186   inline void set_execution_result(ExpressionResultScope* execution_result) {
187     execution_result_ = execution_result;
188   }
execution_result()189   ExpressionResultScope* execution_result() const { return execution_result_; }
register_allocator()190   BytecodeRegisterAllocator* register_allocator() const {
191     return builder()->register_allocator();
192   }
193 
globals_builder()194   GlobalDeclarationsBuilder* globals_builder() { return globals_builder_; }
195   inline LanguageMode language_mode() const;
196   int feedback_index(FeedbackVectorSlot slot) const;
197 
home_object_symbol()198   Handle<Name> home_object_symbol() const { return home_object_symbol_; }
prototype_string()199   Handle<Name> prototype_string() const { return prototype_string_; }
empty_fixed_array()200   Handle<FixedArray> empty_fixed_array() const { return empty_fixed_array_; }
201 
202   Zone* zone_;
203   BytecodeArrayBuilder* builder_;
204   CompilationInfo* info_;
205   DeclarationScope* scope_;
206 
207   GlobalDeclarationsBuilder* globals_builder_;
208   ZoneVector<GlobalDeclarationsBuilder*> global_declarations_;
209   ZoneVector<std::pair<FunctionLiteral*, size_t>> function_literals_;
210   ZoneVector<std::pair<NativeFunctionLiteral*, size_t>>
211       native_function_literals_;
212 
213   ControlScope* execution_control_;
214   ContextScope* execution_context_;
215   ExpressionResultScope* execution_result_;
216 
217   ZoneVector<BytecodeLabel> generator_resume_points_;
218   Register generator_state_;
219   int loop_depth_;
220 
221   Handle<Name> home_object_symbol_;
222   Handle<Name> prototype_string_;
223   Handle<FixedArray> empty_fixed_array_;
224 };
225 
226 }  // namespace interpreter
227 }  // namespace internal
228 }  // namespace v8
229 
230 #endif  // V8_INTERPRETER_BYTECODE_GENERATOR_H_
231