1// Copyright (c) 2017, 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_KERNEL_BINARY_FLOWGRAPH_H_
6#define RUNTIME_VM_COMPILER_FRONTEND_KERNEL_BINARY_FLOWGRAPH_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/frontend/bytecode_reader.h"
13#include "vm/compiler/frontend/constant_reader.h"
14#include "vm/compiler/frontend/kernel_to_il.h"
15#include "vm/compiler/frontend/kernel_translation_helper.h"
16#include "vm/compiler/frontend/scope_builder.h"
17#include "vm/kernel.h"
18#include "vm/kernel_binary.h"
19#include "vm/object.h"
20
21namespace dart {
22namespace kernel {
23
24class StreamingFlowGraphBuilder : public KernelReaderHelper {
25 public:
26 StreamingFlowGraphBuilder(FlowGraphBuilder* flow_graph_builder,
27 const ExternalTypedData& data,
28 intptr_t data_program_offset)
29 : KernelReaderHelper(
30 flow_graph_builder->zone_,
31 &flow_graph_builder->translation_helper_,
32 Script::Handle(
33 flow_graph_builder->zone_,
34 flow_graph_builder->parsed_function_->function().script()),
35 data,
36 data_program_offset),
37 flow_graph_builder_(flow_graph_builder),
38 active_class_(&flow_graph_builder->active_class_),
39 constant_reader_(this, active_class_),
40 type_translator_(this,
41 &constant_reader_,
42 active_class_,
43 /* finalize= */ true),
44 bytecode_metadata_helper_(this, active_class_),
45 direct_call_metadata_helper_(this),
46 inferred_type_metadata_helper_(this, &constant_reader_),
47 procedure_attributes_metadata_helper_(this),
48 call_site_attributes_metadata_helper_(this, &type_translator_),
49 closure_owner_(Object::Handle(flow_graph_builder->zone_)) {}
50
51 virtual ~StreamingFlowGraphBuilder() {}
52
53 FlowGraph* BuildGraph();
54
55 void ReportUnexpectedTag(const char* variant, Tag tag) override;
56
57 Fragment BuildStatementAt(intptr_t kernel_offset);
58
59 private:
60 Thread* thread() const { return flow_graph_builder_->thread_; }
61
62 void ParseKernelASTFunction();
63 void ReadForwardingStubTarget(const Function& function);
64 void EvaluateConstFieldValue(const Field& field);
65 void SetupDefaultParameterValues();
66 void ReadDefaultFunctionTypeArguments(const Function& function);
67
68 FlowGraph* BuildGraphOfFieldInitializer();
69 Fragment BuildFieldInitializer(const Field& field,
70 bool only_for_side_effects);
71 Fragment BuildLateFieldInitializer(const Field& field, bool has_initializer);
72 Fragment BuildInitializers(const Class& parent_class);
73 FlowGraph* BuildGraphOfFunction(bool constructor);
74
75 Fragment BuildExpression(TokenPosition* position = NULL);
76 Fragment BuildStatement();
77
78 // Kernel offset:
79 // start of function expression -> end of function body statement
80 Fragment BuildFunctionBody(const Function& dart_function,
81 LocalVariable* first_parameter,
82 bool constructor);
83
84 // Pieces of the prologue. They are all agnostic to the current Kernel offset.
85 Fragment BuildEveryTimePrologue(const Function& dart_function,
86 TokenPosition token_position,
87 intptr_t type_parameters_offset);
88 Fragment BuildFirstTimePrologue(const Function& dart_function,
89 LocalVariable* first_parameter,
90 intptr_t type_parameters_offset);
91 Fragment ClearRawParameters(const Function& dart_function);
92 Fragment DebugStepCheckInPrologue(const Function& dart_function,
93 TokenPosition position);
94 Fragment SetAsyncStackTrace(const Function& dart_function);
95 Fragment CheckStackOverflowInPrologue(const Function& dart_function);
96 Fragment SetupCapturedParameters(const Function& dart_function);
97 Fragment ShortcutForUserDefinedEquals(const Function& dart_function,
98 LocalVariable* first_parameter);
99 Fragment TypeArgumentsHandling(const Function& dart_function);
100 void CheckArgumentTypesAsNecessary(const Function& dart_function,
101 intptr_t type_parameters_offset,
102 Fragment* explicit_checks,
103 Fragment* implicit_checks,
104 Fragment* implicit_redefinitions);
105 Fragment CompleteBodyWithYieldContinuations(Fragment body);
106
107 static UncheckedEntryPointStyle ChooseEntryPointStyle(
108 const Function& dart_function,
109 const Fragment& implicit_type_checks,
110 const Fragment& first_time_prologue,
111 const Fragment& every_time_prologue,
112 const Fragment& type_args_handling);
113
114 void loop_depth_inc();
115 void loop_depth_dec();
116 intptr_t for_in_depth();
117 void for_in_depth_inc();
118 void for_in_depth_dec();
119 void catch_depth_inc();
120 void catch_depth_dec();
121 void try_depth_inc();
122 void try_depth_dec();
123 intptr_t block_expression_depth();
124 void block_expression_depth_inc();
125 void block_expression_depth_dec();
126 intptr_t CurrentTryIndex();
127 intptr_t AllocateTryIndex();
128 LocalVariable* CurrentException();
129 LocalVariable* CurrentStackTrace();
130 CatchBlock* catch_block();
131 ActiveClass* active_class();
132 ScopeBuildingResult* scopes();
133 void set_scopes(ScopeBuildingResult* scope);
134 ParsedFunction* parsed_function();
135 TryFinallyBlock* try_finally_block();
136 SwitchBlock* switch_block();
137 BreakableBlock* breakable_block();
138 GrowableArray<YieldContinuation>& yield_continuations();
139 Value* stack();
140 void Push(Definition* definition);
141 Value* Pop();
142 Class& GetSuperOrDie();
143
144 Tag PeekArgumentsFirstPositionalTag();
145 const TypeArguments& PeekArgumentsInstantiatedType(const Class& klass);
146 intptr_t PeekArgumentsCount();
147
148 // See BaseFlowGraphBuilder::MakeTemporary.
149 LocalVariable* MakeTemporary();
150
151 LocalVariable* LookupVariable(intptr_t kernel_offset);
152 Function& FindMatchingFunction(const Class& klass,
153 const String& name,
154 int type_args_len,
155 int argument_count,
156 const Array& argument_names);
157
158 bool NeedsDebugStepCheck(const Function& function, TokenPosition position);
159 bool NeedsDebugStepCheck(Value* value, TokenPosition position);
160
161 void InlineBailout(const char* reason);
162 Fragment DebugStepCheck(TokenPosition position);
163 Fragment LoadLocal(LocalVariable* variable);
164 Fragment Return(
165 TokenPosition position,
166 intptr_t yield_index = PcDescriptorsLayout::kInvalidYieldIndex);
167 Fragment EvaluateAssertion();
168 Fragment RethrowException(TokenPosition position, int catch_try_index);
169 Fragment ThrowNoSuchMethodError(const Function& target);
170 Fragment Constant(const Object& value);
171 Fragment IntConstant(int64_t value);
172 Fragment LoadStaticField(const Field& field, bool calls_initializer);
173 Fragment RedefinitionWithType(const AbstractType& type);
174 Fragment CheckNull(TokenPosition position,
175 LocalVariable* receiver,
176 const String& function_name,
177 bool clear_the_temp = true);
178 Fragment StaticCall(TokenPosition position,
179 const Function& target,
180 intptr_t argument_count,
181 ICData::RebindRule rebind_rule);
182 Fragment StaticCall(TokenPosition position,
183 const Function& target,
184 intptr_t argument_count,
185 const Array& argument_names,
186 ICData::RebindRule rebind_rule,
187 const InferredTypeMetadata* result_type = NULL,
188 intptr_t type_args_len = 0,
189 bool use_unchecked_entry = false);
190 Fragment InstanceCall(TokenPosition position,
191 const String& name,
192 Token::Kind kind,
193 intptr_t argument_count,
194 intptr_t checked_argument_count = 1);
195 Fragment InstanceCall(
196 TokenPosition position,
197 const String& name,
198 Token::Kind kind,
199 intptr_t type_args_len,
200 intptr_t argument_count,
201 const Array& argument_names,
202 intptr_t checked_argument_count,
203 const Function& interface_target,
204 const Function& tearoff_interface_target,
205 const InferredTypeMetadata* result_type = nullptr,
206 bool use_unchecked_entry = false,
207 const CallSiteAttributesMetadata* call_site_attrs = nullptr,
208 bool receiver_is_not_smi = false);
209
210 Fragment ThrowException(TokenPosition position);
211 Fragment BooleanNegate();
212 Fragment TranslateInstantiatedTypeArguments(
213 const TypeArguments& type_arguments);
214 Fragment StrictCompare(TokenPosition position,
215 Token::Kind kind,
216 bool number_check = false);
217 Fragment AllocateObject(TokenPosition position,
218 const Class& klass,
219 intptr_t argument_count);
220 Fragment AllocateObject(const Class& klass, const Function& closure_function);
221 Fragment AllocateContext(const ZoneGrowableArray<const Slot*>& context_slots);
222 Fragment LoadNativeField(const Slot& field);
223 Fragment StoreLocal(TokenPosition position, LocalVariable* variable);
224 Fragment StoreStaticField(TokenPosition position, const Field& field);
225 Fragment StringInterpolate(TokenPosition position);
226 Fragment StringInterpolateSingle(TokenPosition position);
227 Fragment ThrowTypeError();
228 Fragment ThrowLateInitializationError(TokenPosition position,
229 const String& name);
230 Fragment LoadInstantiatorTypeArguments();
231 Fragment LoadFunctionTypeArguments();
232 Fragment InstantiateType(const AbstractType& type);
233 Fragment CreateArray();
234 Fragment StoreIndexed(intptr_t class_id);
235 Fragment CheckStackOverflow(TokenPosition position);
236 Fragment CloneContext(const ZoneGrowableArray<const Slot*>& context_slots);
237 Fragment TranslateFinallyFinalizers(TryFinallyBlock* outer_finally,
238 intptr_t target_context_depth);
239 Fragment BranchIfTrue(TargetEntryInstr** then_entry,
240 TargetEntryInstr** otherwise_entry,
241 bool negate);
242 Fragment BranchIfEqual(TargetEntryInstr** then_entry,
243 TargetEntryInstr** otherwise_entry,
244 bool negate);
245 Fragment BranchIfNull(TargetEntryInstr** then_entry,
246 TargetEntryInstr** otherwise_entry,
247 bool negate = false);
248 Fragment CatchBlockEntry(const Array& handler_types,
249 intptr_t handler_index,
250 bool needs_stacktrace,
251 bool is_synthesized);
252 Fragment TryCatch(int try_handler_index);
253 Fragment Drop();
254
255 // Drop given number of temps from the stack but preserve top of the stack.
256 Fragment DropTempsPreserveTop(intptr_t num_temps_to_drop);
257
258 Fragment MakeTemp();
259 Fragment NullConstant();
260 JoinEntryInstr* BuildJoinEntry();
261 JoinEntryInstr* BuildJoinEntry(intptr_t try_index);
262 Fragment Goto(JoinEntryInstr* destination);
263 Fragment BuildImplicitClosureCreation(const Function& target);
264 Fragment CheckBoolean(TokenPosition position);
265 Fragment CheckArgumentType(LocalVariable* variable, const AbstractType& type);
266 Fragment EnterScope(intptr_t kernel_offset,
267 const LocalScope** scope = nullptr);
268 Fragment ExitScope(intptr_t kernel_offset);
269
270 TestFragment TranslateConditionForControl();
271
272 const TypeArguments& BuildTypeArguments();
273 Fragment BuildArguments(Array* argument_names,
274 intptr_t* argument_count,
275 intptr_t* positional_argument_count);
276 Fragment BuildArgumentsFromActualArguments(Array* argument_names);
277
278 Fragment BuildInvalidExpression(TokenPosition* position);
279 Fragment BuildVariableGet(TokenPosition* position);
280 Fragment BuildVariableGet(uint8_t payload, TokenPosition* position);
281 Fragment BuildVariableGetImpl(intptr_t variable_kernel_position,
282 TokenPosition position);
283 Fragment BuildVariableSet(TokenPosition* position);
284 Fragment BuildVariableSet(uint8_t payload, TokenPosition* position);
285 Fragment BuildVariableSetImpl(TokenPosition position,
286 intptr_t variable_kernel_position);
287 Fragment BuildPropertyGet(TokenPosition* position);
288 Fragment BuildPropertySet(TokenPosition* position);
289 Fragment BuildAllocateInvocationMirrorCall(TokenPosition position,
290 const String& name,
291 intptr_t num_type_arguments,
292 intptr_t num_arguments,
293 const Array& argument_names,
294 LocalVariable* actuals_array,
295 Fragment build_rest_of_actuals);
296 Fragment BuildSuperPropertyGet(TokenPosition* position);
297 Fragment BuildSuperPropertySet(TokenPosition* position);
298 Fragment BuildDirectPropertyGet(TokenPosition* position);
299 Fragment BuildDirectPropertySet(TokenPosition* position);
300 Fragment BuildStaticGet(TokenPosition* position);
301 Fragment BuildStaticSet(TokenPosition* position);
302 Fragment BuildMethodInvocation(TokenPosition* position);
303 Fragment BuildDirectMethodInvocation(TokenPosition* position);
304 Fragment BuildSuperMethodInvocation(TokenPosition* position);
305 Fragment BuildStaticInvocation(TokenPosition* position);
306 Fragment BuildConstructorInvocation(TokenPosition* position);
307 Fragment BuildNot(TokenPosition* position);
308 Fragment BuildNullCheck(TokenPosition* position);
309 Fragment BuildLogicalExpression(TokenPosition* position);
310 Fragment TranslateLogicalExpressionForValue(bool negated,
311 TestFragment* side_exits);
312 Fragment BuildConditionalExpression(TokenPosition* position);
313 Fragment BuildStringConcatenation(TokenPosition* position);
314 Fragment BuildIsExpression(TokenPosition* position);
315 Fragment BuildAsExpression(TokenPosition* position);
316 Fragment BuildTypeLiteral(TokenPosition* position);
317 Fragment BuildThisExpression(TokenPosition* position);
318 Fragment BuildRethrow(TokenPosition* position);
319 Fragment BuildThrow(TokenPosition* position);
320 Fragment BuildListLiteral(TokenPosition* position);
321 Fragment BuildMapLiteral(TokenPosition* position);
322 Fragment BuildFunctionExpression();
323 Fragment BuildLet(TokenPosition* position);
324 Fragment BuildBlockExpression();
325 Fragment BuildBigIntLiteral(TokenPosition* position);
326 Fragment BuildStringLiteral(TokenPosition* position);
327 Fragment BuildIntLiteral(uint8_t payload, TokenPosition* position);
328 Fragment BuildIntLiteral(bool is_negative, TokenPosition* position);
329 Fragment BuildDoubleLiteral(TokenPosition* position);
330 Fragment BuildBoolLiteral(bool value, TokenPosition* position);
331 Fragment BuildNullLiteral(TokenPosition* position);
332 Fragment BuildFutureNullValue(TokenPosition* position);
333 Fragment BuildConstantExpression(TokenPosition* position, Tag tag);
334 Fragment BuildPartialTearoffInstantiation(TokenPosition* position);
335 Fragment BuildLibraryPrefixAction(TokenPosition* position,
336 const String& selector);
337
338 Fragment BuildExpressionStatement();
339 Fragment BuildBlock();
340 Fragment BuildEmptyStatement();
341 Fragment BuildAssertBlock();
342 Fragment BuildAssertStatement();
343 Fragment BuildLabeledStatement();
344 Fragment BuildBreakStatement();
345 Fragment BuildWhileStatement();
346 Fragment BuildDoStatement();
347 Fragment BuildForStatement();
348 Fragment BuildForInStatement(bool async);
349 Fragment BuildSwitchStatement();
350 Fragment BuildContinueSwitchStatement();
351 Fragment BuildIfStatement();
352 Fragment BuildReturnStatement();
353 Fragment BuildTryCatch();
354 Fragment BuildTryFinally();
355 Fragment BuildYieldStatement();
356 Fragment BuildVariableDeclaration();
357 Fragment BuildFunctionDeclaration();
358 Fragment BuildFunctionNode(TokenPosition parent_position,
359 StringIndex name_index);
360
361 // Build build FG for '_asFunctionInternal'. Reads an Arguments from the
362 // Kernel buffer and pushes the resulting closure.
363 Fragment BuildFfiAsFunctionInternal();
364
365 // Build build FG for '_nativeCallbackFunction'. Reads an Arguments from the
366 // Kernel buffer and pushes the resulting Function object.
367 Fragment BuildFfiNativeCallbackFunction();
368
369 FlowGraphBuilder* flow_graph_builder_;
370 ActiveClass* const active_class_;
371 ConstantReader constant_reader_;
372 TypeTranslator type_translator_;
373 BytecodeMetadataHelper bytecode_metadata_helper_;
374 DirectCallMetadataHelper direct_call_metadata_helper_;
375 InferredTypeMetadataHelper inferred_type_metadata_helper_;
376 ProcedureAttributesMetadataHelper procedure_attributes_metadata_helper_;
377 CallSiteAttributesMetadataHelper call_site_attributes_metadata_helper_;
378 Object& closure_owner_;
379
380 friend class KernelLoader;
381
382 DISALLOW_COPY_AND_ASSIGN(StreamingFlowGraphBuilder);
383};
384
385} // namespace kernel
386} // namespace dart
387
388#endif // RUNTIME_VM_COMPILER_FRONTEND_KERNEL_BINARY_FLOWGRAPH_H_
389