1 | // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file |
2 | // for details. All rights reserved. Use of this source code is governed by a |
3 | // BSD-style license that can be found in the LICENSE file. |
4 | |
5 | #ifndef RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_FLOW_GRAPH_BUILDER_H_ |
6 | #define RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_FLOW_GRAPH_BUILDER_H_ |
7 | |
8 | #if defined(DART_PRECOMPILED_RUNTIME) |
9 | #error "AOT runtime should not use compiler sources (including header files)" |
10 | #endif // defined(DART_PRECOMPILED_RUNTIME) |
11 | |
12 | #include "vm/compiler/backend/il.h" |
13 | #include "vm/compiler/frontend/base_flow_graph_builder.h" |
14 | #include "vm/compiler/frontend/kernel_translation_helper.h" // For InferredTypeMetadata |
15 | #include "vm/constants_kbc.h" |
16 | |
17 | namespace dart { |
18 | namespace kernel { |
19 | |
20 | class BytecodeLocalVariablesIterator; |
21 | |
22 | // This class builds flow graph from bytecode. It is used either to compile |
23 | // from bytecode, or generate bytecode interpreter (the latter is not |
24 | // fully implemented yet). |
25 | // TODO(alexmarkov): extend this class and IL to generate an interpreter in |
26 | // addition to compiling bytecode. |
27 | class BytecodeFlowGraphBuilder { |
28 | public: |
29 | BytecodeFlowGraphBuilder(BaseFlowGraphBuilder* flow_graph_builder, |
30 | ParsedFunction* parsed_function, |
31 | ZoneGrowableArray<const ICData*>* ic_data_array) |
32 | : flow_graph_builder_(flow_graph_builder), |
33 | zone_(flow_graph_builder->zone_), |
34 | is_generating_interpreter_( |
35 | false), // TODO(alexmarkov): pass as argument |
36 | parsed_function_(parsed_function), |
37 | ic_data_array_(ic_data_array), |
38 | object_pool_(ObjectPool::Handle(zone_)), |
39 | bytecode_length_(0), |
40 | pc_(0), |
41 | position_(TokenPosition::kNoSource), |
42 | local_vars_(zone_, 0), |
43 | parameters_(zone_, 0), |
44 | exception_var_(nullptr), |
45 | stacktrace_var_(nullptr), |
46 | scratch_var_(nullptr), |
47 | prologue_info_(-1, -1), |
48 | throw_no_such_method_(nullptr), |
49 | inferred_types_attribute_(Array::Handle(zone_)) {} |
50 | |
51 | FlowGraph* BuildGraph(); |
52 | |
53 | // Create parameter variables without building a flow graph. |
54 | void CreateParameterVariables(); |
55 | |
56 | protected: |
57 | // Returns `true` if building a flow graph for a bytecode interpreter, or |
58 | // `false` if compiling a function from bytecode. |
59 | bool is_generating_interpreter() const { return is_generating_interpreter_; } |
60 | |
61 | private: |
62 | // Operand of bytecode instruction, either intptr_t value (if compiling |
63 | // bytecode) or Definition (if generating interpreter). |
64 | class Operand { |
65 | public: |
66 | explicit Operand(Definition* definition) |
67 | : definition_(definition), value_(0) { |
68 | ASSERT(definition != nullptr); |
69 | } |
70 | |
71 | explicit Operand(intptr_t value) : definition_(nullptr), value_(value) {} |
72 | |
73 | Definition* definition() const { |
74 | ASSERT(definition_ != nullptr); |
75 | return definition_; |
76 | } |
77 | |
78 | intptr_t value() const { |
79 | ASSERT(definition_ == nullptr); |
80 | return value_; |
81 | } |
82 | |
83 | private: |
84 | Definition* definition_; |
85 | intptr_t value_; |
86 | }; |
87 | |
88 | // Constant from a constant pool. |
89 | // It is either Object (if compiling bytecode) or Definition |
90 | // (if generating interpreter). |
91 | class Constant { |
92 | public: |
93 | explicit Constant(Definition* definition) |
94 | : definition_(definition), value_(Object::null_object()) { |
95 | ASSERT(definition != nullptr); |
96 | } |
97 | |
98 | explicit Constant(Zone* zone, const Object& value) |
99 | : definition_(nullptr), value_(value) {} |
100 | |
101 | Definition* definition() const { |
102 | ASSERT(definition_ != nullptr); |
103 | return definition_; |
104 | } |
105 | |
106 | const Object& value() const { |
107 | ASSERT(definition_ == nullptr); |
108 | return value_; |
109 | } |
110 | |
111 | private: |
112 | Definition* definition_; |
113 | const Object& value_; |
114 | }; |
115 | |
116 | // Scope declared in bytecode local variables information. |
117 | class BytecodeScope : public ZoneAllocated { |
118 | public: |
119 | BytecodeScope(Zone* zone, |
120 | intptr_t end_pc, |
121 | intptr_t context_level, |
122 | BytecodeScope* parent) |
123 | : end_pc_(end_pc), |
124 | context_level_(context_level), |
125 | parent_(parent), |
126 | hidden_vars_(zone, 4) {} |
127 | |
128 | const intptr_t end_pc_; |
129 | const intptr_t context_level_; |
130 | BytecodeScope* const parent_; |
131 | ZoneGrowableArray<LocalVariable*> hidden_vars_; |
132 | }; |
133 | |
134 | Operand DecodeOperandA(); |
135 | Operand DecodeOperandB(); |
136 | Operand DecodeOperandC(); |
137 | Operand DecodeOperandD(); |
138 | Operand DecodeOperandE(); |
139 | Operand DecodeOperandF(); |
140 | Operand DecodeOperandX(); |
141 | Operand DecodeOperandY(); |
142 | Operand DecodeOperandT(); |
143 | Constant ConstantAt(Operand entry_index, intptr_t add_index = 0); |
144 | void PushConstant(Constant constant); |
145 | Constant PopConstant(); |
146 | void LoadStackSlots(intptr_t num_slots); |
147 | void AllocateLocalVariables(Operand frame_size, |
148 | intptr_t num_param_locals = 0); |
149 | LocalVariable* AllocateParameter(intptr_t param_index, |
150 | VariableIndex var_index); |
151 | void AllocateFixedParameters(); |
152 | |
153 | // Allocates parameters and local variables in case of EntryOptional. |
154 | // Returns pointer to the instruction after EntryOptional/LoadConstant/Frame |
155 | // bytecodes. |
156 | const KBCInstr* AllocateParametersAndLocalsForEntryOptional(); |
157 | |
158 | LocalVariable* LocalVariableAt(intptr_t local_index); |
159 | void StoreLocal(Operand local_index); |
160 | void LoadLocal(Operand local_index); |
161 | Value* Pop(); |
162 | intptr_t GetStackDepth() const; |
163 | bool IsStackEmpty() const; |
164 | InferredTypeMetadata GetInferredType(intptr_t pc); |
165 | void PropagateStackState(intptr_t target_pc); |
166 | void DropUnusedValuesFromStack(); |
167 | void BuildJumpIfStrictCompare(Token::Kind cmp_kind); |
168 | void BuildPrimitiveOp(const String& name, |
169 | Token::Kind token_kind, |
170 | const AbstractType& static_receiver_type, |
171 | int num_args); |
172 | void BuildIntOp(const String& name, Token::Kind token_kind, int num_args); |
173 | void BuildDoubleOp(const String& name, Token::Kind token_kind, int num_args); |
174 | void BuildDirectCallCommon(bool is_unchecked_call); |
175 | void BuildInterfaceCallCommon(bool is_unchecked_call, |
176 | bool is_instantiated_call); |
177 | |
178 | void BuildInstruction(KernelBytecode::Opcode opcode); |
179 | void BuildFfiAsFunction(); |
180 | void BuildFfiNativeCallbackFunction(); |
181 | void BuildDebugStepCheck(); |
182 | |
183 | #define DECLARE_BUILD_METHOD(name, encoding, kind, op1, op2, op3) \ |
184 | void Build##name(); |
185 | KERNEL_BYTECODES_LIST(DECLARE_BUILD_METHOD) |
186 | #undef DECLARE_BUILD_METHOD |
187 | |
188 | intptr_t GetTryIndex(const PcDescriptors& descriptors, intptr_t pc); |
189 | JoinEntryInstr* EnsureControlFlowJoin(const PcDescriptors& descriptors, |
190 | intptr_t pc); |
191 | bool RequiresScratchVar(const KBCInstr* instr); |
192 | void CollectControlFlow(const PcDescriptors& descriptors, |
193 | const ExceptionHandlers& handlers, |
194 | GraphEntryInstr* graph_entry); |
195 | |
196 | // Update current scope, context level and local variables for the given PC. |
197 | // Returns next PC where scope might need an update. |
198 | intptr_t UpdateScope(BytecodeLocalVariablesIterator* iter, intptr_t pc); |
199 | |
200 | // Figure out entry points style. |
201 | UncheckedEntryPointStyle ChooseEntryPointStyle( |
202 | const KBCInstr* jump_if_unchecked); |
203 | |
204 | Thread* thread() const { return flow_graph_builder_->thread_; } |
205 | Isolate* isolate() const { return thread()->isolate(); } |
206 | |
207 | ParsedFunction* parsed_function() const { |
208 | ASSERT(!is_generating_interpreter()); |
209 | return parsed_function_; |
210 | } |
211 | const Function& function() const { return parsed_function()->function(); } |
212 | |
213 | BaseFlowGraphBuilder* flow_graph_builder_; |
214 | Zone* zone_; |
215 | bool is_generating_interpreter_; |
216 | |
217 | // The following members are available only when compiling bytecode. |
218 | |
219 | ParsedFunction* parsed_function_; |
220 | ZoneGrowableArray<const ICData*>* ic_data_array_; |
221 | ObjectPool& object_pool_; |
222 | const KBCInstr* raw_bytecode_ = nullptr; |
223 | intptr_t bytecode_length_; |
224 | intptr_t pc_; |
225 | intptr_t next_pc_ = -1; |
226 | const KBCInstr* bytecode_instr_ = nullptr; |
227 | TokenPosition position_; |
228 | intptr_t last_yield_point_pc_ = 0; |
229 | intptr_t last_yield_point_index_ = 0; |
230 | Fragment code_; |
231 | ZoneGrowableArray<LocalVariable*> local_vars_; |
232 | ZoneGrowableArray<LocalVariable*> parameters_; |
233 | LocalVariable* exception_var_; |
234 | LocalVariable* stacktrace_var_; |
235 | LocalVariable* scratch_var_; |
236 | IntMap<JoinEntryInstr*> jump_targets_; |
237 | IntMap<Value*> stack_states_; |
238 | PrologueInfo prologue_info_; |
239 | JoinEntryInstr* throw_no_such_method_; |
240 | GraphEntryInstr* graph_entry_ = nullptr; |
241 | UncheckedEntryPointStyle entry_point_style_ = UncheckedEntryPointStyle::kNone; |
242 | bool build_debug_step_checks_ = false; |
243 | bool seen_parameters_scope_ = false; |
244 | BytecodeScope* current_scope_ = nullptr; |
245 | Array& inferred_types_attribute_; |
246 | intptr_t inferred_types_index_ = 0; |
247 | }; |
248 | |
249 | } // namespace kernel |
250 | } // namespace dart |
251 | |
252 | #endif // RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_FLOW_GRAPH_BUILDER_H_ |
253 | |