Line data Source code
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 AstNodeSourceRanges;
18 : class AstStringConstants;
19 : class CompilationInfo;
20 : enum class SourceRangeKind;
21 :
22 : namespace interpreter {
23 :
24 : class GlobalDeclarationsBuilder;
25 : class LoopBuilder;
26 : class BlockCoverageBuilder;
27 : class BytecodeJumpTable;
28 :
29 : class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
30 : public:
31 : explicit BytecodeGenerator(CompilationInfo* info);
32 :
33 : void GenerateBytecode(uintptr_t stack_limit);
34 : Handle<BytecodeArray> FinalizeBytecode(Isolate* isolate,
35 : Handle<Script> script);
36 :
37 : #define DECLARE_VISIT(type) void Visit##type(type* node);
38 : AST_NODE_LIST(DECLARE_VISIT)
39 : #undef DECLARE_VISIT
40 :
41 : // Visiting function for declarations list and statements are overridden.
42 : void VisitDeclarations(Declaration::List* declarations);
43 : void VisitStatements(ZoneList<Statement*>* statments);
44 :
45 : private:
46 : class ContextScope;
47 : class ControlScope;
48 : class ControlScopeForBreakable;
49 : class ControlScopeForIteration;
50 : class ControlScopeForTopLevel;
51 : class ControlScopeForTryCatch;
52 : class ControlScopeForTryFinally;
53 : class CurrentScope;
54 : class ExpressionResultScope;
55 : class EffectResultScope;
56 : class FeedbackSlotCache;
57 : class GlobalDeclarationsBuilder;
58 : class RegisterAllocationScope;
59 : class TestResultScope;
60 : class ValueResultScope;
61 :
62 : using ToBooleanMode = BytecodeArrayBuilder::ToBooleanMode;
63 :
64 : enum class TestFallthrough { kThen, kElse, kNone };
65 : enum class TypeHint { kAny, kBoolean };
66 :
67 : void GenerateBytecodeBody();
68 : void AllocateDeferredConstants(Isolate* isolate, Handle<Script> script);
69 :
70 254962439 : DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
71 :
72 : // Dispatched from VisitBinaryOperation.
73 : void VisitArithmeticExpression(BinaryOperation* binop);
74 : void VisitCommaExpression(BinaryOperation* binop);
75 : void VisitLogicalOrExpression(BinaryOperation* binop);
76 : void VisitLogicalAndExpression(BinaryOperation* binop);
77 :
78 : // Dispatched from VisitUnaryOperation.
79 : void VisitVoid(UnaryOperation* expr);
80 : void VisitTypeOf(UnaryOperation* expr);
81 : void VisitNot(UnaryOperation* expr);
82 : void VisitDelete(UnaryOperation* expr);
83 :
84 : // Visits a typeof expression for the value on which to perform the typeof.
85 : void VisitForTypeOfValue(Expression* expr);
86 :
87 : // Used by flow control routines to evaluate loop condition.
88 : void VisitCondition(Expression* expr);
89 :
90 : // Visit the arguments expressions in |args| and store them in |args_regs|,
91 : // growing |args_regs| for each argument visited.
92 : void VisitArguments(ZoneList<Expression*>* args, RegisterList* arg_regs);
93 :
94 : // Visit a keyed super property load. The optional
95 : // |opt_receiver_out| register will have the receiver stored to it
96 : // if it's a valid register. The loaded value is placed in the
97 : // accumulator.
98 : void VisitKeyedSuperPropertyLoad(Property* property,
99 : Register opt_receiver_out);
100 :
101 : // Visit a named super property load. The optional
102 : // |opt_receiver_out| register will have the receiver stored to it
103 : // if it's a valid register. The loaded value is placed in the
104 : // accumulator.
105 : void VisitNamedSuperPropertyLoad(Property* property,
106 : Register opt_receiver_out);
107 :
108 : void VisitPropertyLoad(Register obj, Property* expr);
109 : void VisitPropertyLoadForRegister(Register obj, Property* expr,
110 : Register destination);
111 :
112 : void BuildVariableLoad(Variable* variable, HoleCheckMode hole_check_mode,
113 : TypeofMode typeof_mode = NOT_INSIDE_TYPEOF);
114 : void BuildVariableLoadForAccumulatorValue(
115 : Variable* variable, HoleCheckMode hole_check_mode,
116 : TypeofMode typeof_mode = NOT_INSIDE_TYPEOF);
117 : void BuildVariableAssignment(
118 : Variable* variable, Token::Value op, HoleCheckMode hole_check_mode,
119 : LookupHoistingMode lookup_hoisting_mode = LookupHoistingMode::kNormal);
120 : void BuildLiteralCompareNil(Token::Value compare_op, NilValue nil);
121 : void BuildReturn(int source_position = kNoSourcePosition);
122 : void BuildAsyncReturn(int source_position = kNoSourcePosition);
123 : void BuildAsyncGeneratorReturn();
124 : void BuildReThrow();
125 : void BuildHoleCheckForVariableAssignment(Variable* variable, Token::Value op);
126 : void BuildThrowIfHole(Variable* variable);
127 :
128 : // Build jump to targets[value], where
129 : // start_index <= value < start_index + size.
130 : void BuildIndexedJump(Register value, size_t start_index, size_t size,
131 : ZoneVector<BytecodeLabel>& targets);
132 :
133 : void BuildNewLocalActivationContext();
134 : void BuildLocalActivationContextInitialization();
135 : void BuildNewLocalBlockContext(Scope* scope);
136 : void BuildNewLocalCatchContext(Scope* scope);
137 : void BuildNewLocalWithContext(Scope* scope);
138 :
139 : void BuildGeneratorPrologue();
140 : void BuildSuspendPoint(int suspend_id);
141 :
142 : void BuildAwait(int suspend_id);
143 :
144 : void BuildGetIterator(Expression* iterable, IteratorType hint);
145 :
146 : void AllocateTopLevelRegisters();
147 : void VisitArgumentsObject(Variable* variable);
148 : void VisitRestArgumentsArray(Variable* rest);
149 : void VisitCallSuper(Call* call);
150 : void VisitClassLiteralProperties(ClassLiteral* expr, Register constructor,
151 : Register prototype);
152 : void BuildClassLiteralNameProperty(ClassLiteral* expr, Register constructor);
153 : void BuildClassLiteral(ClassLiteral* expr);
154 : void VisitNewTargetVariable(Variable* variable);
155 : void VisitThisFunctionVariable(Variable* variable);
156 : void BuildGeneratorObjectVariableInitialization();
157 : void VisitBlockDeclarationsAndStatements(Block* stmt);
158 : void VisitFunctionClosureForContext();
159 : void VisitSetHomeObject(Register value, Register home_object,
160 : LiteralProperty* property);
161 : void VisitObjectLiteralAccessor(Register home_object,
162 : ObjectLiteralProperty* property,
163 : Register value_out);
164 : void VisitForInAssignment(Expression* expr);
165 : void VisitModuleNamespaceImports();
166 :
167 : // Builds a logical OR/AND within a test context by rewiring the jumps based
168 : // on the expression values.
169 : void BuildLogicalTest(Token::Value token, Expression* left,
170 : Expression* right);
171 :
172 : // Visit the header/body of a loop iteration.
173 : void VisitIterationHeader(IterationStatement* stmt,
174 : LoopBuilder* loop_builder);
175 : void VisitIterationHeader(int first_suspend_id, int suspend_count,
176 : LoopBuilder* loop_builder);
177 : void VisitIterationBody(IterationStatement* stmt, LoopBuilder* loop_builder);
178 :
179 : // Visit a statement and switch scopes, the context is in the accumulator.
180 : void VisitInScope(Statement* stmt, Scope* scope);
181 :
182 : void BuildPushUndefinedIntoRegisterList(RegisterList* reg_list);
183 :
184 : void BuildLoadPropertyKey(LiteralProperty* property, Register out_reg);
185 :
186 : int AllocateBlockCoverageSlotIfEnabled(AstNode* node, SourceRangeKind kind);
187 : void BuildIncrementBlockCoverageCounterIfEnabled(AstNode* node,
188 : SourceRangeKind kind);
189 : void BuildIncrementBlockCoverageCounterIfEnabled(int coverage_array_slot);
190 :
191 : void BuildTest(ToBooleanMode mode, BytecodeLabels* then_labels,
192 : BytecodeLabels* else_labels, TestFallthrough fallthrough);
193 :
194 : // Visitors for obtaining expression result in the accumulator, in a
195 : // register, or just getting the effect. Some visitors return a TypeHint which
196 : // specifies the type of the result of the visited expression.
197 : TypeHint VisitForAccumulatorValue(Expression* expr);
198 : void VisitForAccumulatorValueOrTheHole(Expression* expr);
199 : MUST_USE_RESULT Register VisitForRegisterValue(Expression* expr);
200 : INLINE(void VisitForRegisterValue(Expression* expr, Register destination));
201 : void VisitAndPushIntoRegisterList(Expression* expr, RegisterList* reg_list);
202 : void VisitForEffect(Expression* expr);
203 : void VisitForTest(Expression* expr, BytecodeLabels* then_labels,
204 : BytecodeLabels* else_labels, TestFallthrough fallthrough);
205 :
206 : void VisitInSameTestExecutionScope(Expression* expr);
207 :
208 : Register GetRegisterForLocalVariable(Variable* variable);
209 :
210 : // Returns the runtime function id for a store to super for the function's
211 : // language mode.
212 : inline Runtime::FunctionId StoreToSuperRuntimeId();
213 : inline Runtime::FunctionId StoreKeyedToSuperRuntimeId();
214 :
215 : // Returns a cached slot, or create and cache a new slot if one doesn't
216 : // already exists.
217 : FeedbackSlot GetCachedLoadGlobalICSlot(TypeofMode typeof_mode,
218 : Variable* variable);
219 : FeedbackSlot GetCachedCreateClosureSlot(FunctionLiteral* literal);
220 :
221 : static constexpr ToBooleanMode ToBooleanModeFromTypeHint(TypeHint type_hint) {
222 : return type_hint == TypeHint::kBoolean ? ToBooleanMode::kAlreadyBoolean
223 1416584 : : ToBooleanMode::kConvertToBoolean;
224 : }
225 :
226 : inline Register generator_object() const;
227 :
228 1543408 : inline BytecodeArrayBuilder* builder() const { return builder_; }
229 : inline Zone* zone() const { return zone_; }
230 : inline DeclarationScope* closure_scope() const { return closure_scope_; }
231 : inline CompilationInfo* info() const { return info_; }
232 : inline const AstStringConstants* ast_string_constants() const {
233 : return ast_string_constants_;
234 : }
235 :
236 : inline Scope* current_scope() const { return current_scope_; }
237 631034 : inline void set_current_scope(Scope* scope) { current_scope_ = scope; }
238 :
239 : inline ControlScope* execution_control() const { return execution_control_; }
240 : inline void set_execution_control(ControlScope* scope) {
241 15312392 : execution_control_ = scope;
242 : }
243 : inline ContextScope* execution_context() const { return execution_context_; }
244 : inline void set_execution_context(ContextScope* context) {
245 4938115 : execution_context_ = context;
246 : }
247 : inline void set_execution_result(ExpressionResultScope* execution_result) {
248 84764771 : execution_result_ = execution_result;
249 : }
250 : ExpressionResultScope* execution_result() const { return execution_result_; }
251 171323842 : BytecodeRegisterAllocator* register_allocator() const {
252 : return builder()->register_allocator();
253 : }
254 :
255 : GlobalDeclarationsBuilder* globals_builder() {
256 : DCHECK_NOT_NULL(globals_builder_);
257 : return globals_builder_;
258 : }
259 : inline LanguageMode language_mode() const;
260 : inline FunctionKind function_kind() const;
261 : inline FeedbackVectorSpec* feedback_spec();
262 : inline int feedback_index(FeedbackSlot slot) const;
263 :
264 : inline FeedbackSlotCache* feedback_slot_cache() {
265 : return feedback_slot_cache_;
266 : }
267 :
268 : inline HandlerTable::CatchPrediction catch_prediction() const {
269 : return catch_prediction_;
270 : }
271 : inline void set_catch_prediction(HandlerTable::CatchPrediction value) {
272 204244 : catch_prediction_ = value;
273 : }
274 :
275 : Zone* zone_;
276 : BytecodeArrayBuilder* builder_;
277 : CompilationInfo* info_;
278 : const AstStringConstants* ast_string_constants_;
279 : DeclarationScope* closure_scope_;
280 : Scope* current_scope_;
281 :
282 : FeedbackSlotCache* feedback_slot_cache_;
283 :
284 : GlobalDeclarationsBuilder* globals_builder_;
285 : BlockCoverageBuilder* block_coverage_builder_;
286 : ZoneVector<GlobalDeclarationsBuilder*> global_declarations_;
287 : ZoneVector<std::pair<FunctionLiteral*, size_t>> function_literals_;
288 : ZoneVector<std::pair<NativeFunctionLiteral*, size_t>>
289 : native_function_literals_;
290 : ZoneVector<std::pair<ObjectLiteral*, size_t>> object_literals_;
291 : ZoneVector<std::pair<ArrayLiteral*, size_t>> array_literals_;
292 : ZoneVector<std::pair<GetTemplateObject*, size_t>> template_objects_;
293 :
294 : ControlScope* execution_control_;
295 : ContextScope* execution_context_;
296 : ExpressionResultScope* execution_result_;
297 :
298 : Register incoming_new_target_or_generator_;
299 :
300 : BytecodeJumpTable* generator_jump_table_;
301 : Register generator_state_;
302 : int loop_depth_;
303 :
304 : HandlerTable::CatchPrediction catch_prediction_;
305 : };
306 :
307 : } // namespace interpreter
308 : } // namespace internal
309 : } // namespace v8
310 :
311 : #endif // V8_INTERPRETER_BYTECODE_GENERATOR_H_
|