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/constant_reader.h"
13#include "vm/compiler/frontend/kernel_to_il.h"
14#include "vm/compiler/frontend/kernel_translation_helper.h"
15#include "vm/compiler/frontend/scope_builder.h"
16#include "vm/kernel.h"
17#include "vm/kernel_binary.h"
18#include "vm/object.h"
19
20namespace dart {
21namespace kernel {
22
23class StreamingFlowGraphBuilder : public KernelReaderHelper {
24 public:
25 StreamingFlowGraphBuilder(FlowGraphBuilder* flow_graph_builder,
26 const TypedDataView& data,
27 intptr_t data_program_offset)
28 : KernelReaderHelper(flow_graph_builder->zone_,
29 &flow_graph_builder->translation_helper_,
30 data,
31 data_program_offset),
32 flow_graph_builder_(flow_graph_builder),
33 active_class_(&flow_graph_builder->active_class_),
34 constant_reader_(this, active_class_),
35 type_translator_(this,
36 &constant_reader_,
37 active_class_,
38 /* finalize= */ true),
39 direct_call_metadata_helper_(this),
40 inferred_type_metadata_helper_(this, &constant_reader_),
41 procedure_attributes_metadata_helper_(this),
42 call_site_attributes_metadata_helper_(this, &type_translator_),
43 closure_owner_(Object::Handle(zone: flow_graph_builder->zone_)) {}
44
45 virtual ~StreamingFlowGraphBuilder() {}
46
47 FlowGraph* BuildGraph();
48
49 void ReportUnexpectedTag(const char* variant, Tag tag) override;
50
51 Fragment BuildStatementAt(intptr_t kernel_offset);
52
53 intptr_t num_ast_nodes() const { return num_ast_nodes_; }
54
55 private:
56 Thread* thread() const { return flow_graph_builder_->thread_; }
57
58 void ParseKernelASTFunction();
59 void ReadForwardingStubTarget(const Function& function);
60 void SetupDefaultParameterValues();
61
62 FlowGraph* BuildGraphOfFieldInitializer();
63 Fragment BuildFieldInitializer(const Field& field,
64 bool only_for_side_effects);
65 Fragment BuildLateFieldInitializer(const Field& field, bool has_initializer);
66 Fragment BuildInitializers(const Class& parent_class);
67 FlowGraph* BuildGraphOfFunction(bool constructor);
68
69 Fragment BuildExpression(TokenPosition* position = nullptr);
70 Fragment BuildStatement(TokenPosition* position = nullptr);
71 Fragment BuildStatementWithBranchCoverage(TokenPosition* position = nullptr);
72
73 // Kernel offset:
74 // start of function expression -> end of function body statement
75 Fragment BuildFunctionBody(const Function& dart_function,
76 LocalVariable* first_parameter,
77 bool constructor);
78
79 // Pieces of the prologue. They are all agnostic to the current Kernel offset.
80 Fragment BuildRegularFunctionPrologue(const Function& dart_function,
81 TokenPosition token_position,
82 LocalVariable* first_parameter);
83 Fragment ClearRawParameters(const Function& dart_function);
84 Fragment DebugStepCheckInPrologue(const Function& dart_function,
85 TokenPosition position);
86 Fragment CheckStackOverflowInPrologue(const Function& dart_function);
87 Fragment SetupCapturedParameters(const Function& dart_function);
88 Fragment InitSuspendableFunction(const Function& dart_function);
89 Fragment ShortcutForUserDefinedEquals(const Function& dart_function,
90 LocalVariable* first_parameter);
91 Fragment TypeArgumentsHandling(const Function& dart_function);
92
93 ScriptPtr Script() {
94 if (active_class_ != nullptr) {
95 return active_class_->ActiveScript();
96 }
97 return Script::null();
98 }
99
100 static UncheckedEntryPointStyle ChooseEntryPointStyle(
101 const Function& dart_function,
102 const Fragment& implicit_type_checks,
103 const Fragment& regular_function_prologue,
104 const Fragment& type_args_handling);
105
106 void loop_depth_inc();
107 void loop_depth_dec();
108 intptr_t for_in_depth();
109 void for_in_depth_inc();
110 void for_in_depth_dec();
111 void catch_depth_inc();
112 void catch_depth_dec();
113 void try_depth_inc();
114 void try_depth_dec();
115 intptr_t block_expression_depth();
116 void block_expression_depth_inc();
117 void block_expression_depth_dec();
118 intptr_t CurrentTryIndex();
119 intptr_t AllocateTryIndex();
120 LocalVariable* CurrentException();
121 LocalVariable* CurrentStackTrace();
122 CatchBlock* catch_block();
123 ActiveClass* active_class();
124 ScopeBuildingResult* scopes();
125 void set_scopes(ScopeBuildingResult* scope);
126 ParsedFunction* parsed_function();
127 TryFinallyBlock* try_finally_block();
128 SwitchBlock* switch_block();
129 BreakableBlock* breakable_block();
130 Value* stack();
131 void set_stack(Value* top);
132 void Push(Definition* definition);
133 Value* Pop();
134 Class& GetSuperOrDie();
135
136 Tag PeekArgumentsFirstPositionalTag();
137 const TypeArguments& PeekArgumentsInstantiatedType(const Class& klass);
138 intptr_t PeekArgumentsCount();
139
140 // See BaseFlowGraphBuilder::MakeTemporary.
141 LocalVariable* MakeTemporary(const char* suffix = nullptr);
142 Fragment DropTemporary(LocalVariable** variable);
143
144 LocalVariable* LookupVariable(intptr_t kernel_offset);
145 Function& FindMatchingFunction(const Class& klass,
146 const String& name,
147 int type_args_len,
148 int argument_count,
149 const Array& argument_names);
150
151 bool NeedsDebugStepCheck(const Function& function, TokenPosition position);
152 bool NeedsDebugStepCheck(Value* value, TokenPosition position);
153
154 void InlineBailout(const char* reason);
155 Fragment DebugStepCheck(TokenPosition position);
156 Fragment LoadLocal(LocalVariable* variable);
157 IndirectGotoInstr* IndirectGoto(intptr_t target_count);
158 Fragment Return(TokenPosition position);
159 Fragment EvaluateAssertion();
160 Fragment RethrowException(TokenPosition position, int catch_try_index);
161 Fragment ThrowNoSuchMethodError(TokenPosition position,
162 const Function& target,
163 bool incompatible_arguments);
164 Fragment Constant(const Object& value);
165 Fragment IntConstant(int64_t value);
166 Fragment LoadStaticField(const Field& field, bool calls_initializer);
167 Fragment RedefinitionWithType(const AbstractType& type);
168 Fragment CheckNull(TokenPosition position,
169 LocalVariable* receiver,
170 const String& function_name);
171 Fragment StaticCall(TokenPosition position,
172 const Function& target,
173 intptr_t argument_count,
174 ICData::RebindRule rebind_rule);
175 Fragment StaticCall(TokenPosition position,
176 const Function& target,
177 intptr_t argument_count,
178 const Array& argument_names,
179 ICData::RebindRule rebind_rule,
180 const InferredTypeMetadata* result_type = nullptr,
181 intptr_t type_args_len = 0,
182 bool use_unchecked_entry = false);
183 Fragment StaticCallMissing(TokenPosition position,
184 const String& selector,
185 intptr_t argument_count,
186 InvocationMirror::Level level,
187 InvocationMirror::Kind kind);
188 Fragment InstanceCall(TokenPosition position,
189 const String& name,
190 Token::Kind kind,
191 intptr_t argument_count,
192 intptr_t checked_argument_count = 1);
193 Fragment InstanceCall(
194 TokenPosition position,
195 const String& name,
196 Token::Kind kind,
197 intptr_t type_args_len,
198 intptr_t argument_count,
199 const Array& argument_names,
200 intptr_t checked_argument_count,
201 const Function& interface_target,
202 const Function& tearoff_interface_target,
203 const InferredTypeMetadata* result_type = nullptr,
204 bool use_unchecked_entry = false,
205 const CallSiteAttributesMetadata* call_site_attrs = nullptr,
206 bool receiver_is_not_smi = false,
207 bool is_call_on_this = false);
208
209 Fragment ThrowException(TokenPosition position);
210 Fragment BooleanNegate();
211 Fragment TranslateInstantiatedTypeArguments(
212 const TypeArguments& type_arguments);
213 Fragment StrictCompare(TokenPosition position,
214 Token::Kind kind,
215 bool number_check = false);
216 Fragment AllocateObject(TokenPosition position,
217 const Class& klass,
218 intptr_t argument_count);
219 Fragment AllocateContext(const ZoneGrowableArray<const Slot*>& context_slots);
220 Fragment LoadNativeField(const Slot& field);
221 Fragment StoreLocal(TokenPosition position, LocalVariable* variable);
222 Fragment StoreStaticField(TokenPosition position, const Field& field);
223 Fragment StringInterpolate(TokenPosition position);
224 Fragment StringInterpolateSingle(TokenPosition position);
225 Fragment ThrowTypeError();
226 Fragment LoadInstantiatorTypeArguments();
227 Fragment LoadFunctionTypeArguments();
228 Fragment InstantiateType(const AbstractType& type);
229 Fragment CreateArray();
230 Fragment StoreIndexed(intptr_t class_id);
231 Fragment CheckStackOverflow(TokenPosition position);
232 Fragment CloneContext(const ZoneGrowableArray<const Slot*>& context_slots);
233 Fragment TranslateFinallyFinalizers(TryFinallyBlock* outer_finally,
234 intptr_t target_context_depth);
235 Fragment BranchIfTrue(TargetEntryInstr** then_entry,
236 TargetEntryInstr** otherwise_entry,
237 bool negate);
238 Fragment BranchIfEqual(TargetEntryInstr** then_entry,
239 TargetEntryInstr** otherwise_entry,
240 bool negate = false);
241 Fragment BranchIfNull(TargetEntryInstr** then_entry,
242 TargetEntryInstr** otherwise_entry,
243 bool negate = false);
244 Fragment CatchBlockEntry(const Array& handler_types,
245 intptr_t handler_index,
246 bool needs_stacktrace,
247 bool is_synthesized);
248 Fragment TryCatch(int try_handler_index);
249 Fragment Drop();
250 Fragment DropArguments(intptr_t argument_count, intptr_t type_args_count);
251
252 // Drop given number of temps from the stack but preserve top of the stack.
253 Fragment DropTempsPreserveTop(intptr_t num_temps_to_drop);
254
255 Fragment MakeTemp();
256 Fragment NullConstant();
257 JoinEntryInstr* BuildJoinEntry();
258 JoinEntryInstr* BuildJoinEntry(intptr_t try_index);
259 Fragment Goto(JoinEntryInstr* destination);
260 Fragment BuildImplicitClosureCreation(const Function& target);
261 Fragment CheckBoolean(TokenPosition position);
262 Fragment CheckArgumentType(LocalVariable* variable, const AbstractType& type);
263 Fragment RecordCoverage(TokenPosition position);
264 Fragment EnterScope(intptr_t kernel_offset,
265 const LocalScope** scope = nullptr);
266 Fragment ExitScope(intptr_t kernel_offset);
267
268 TestFragment TranslateConditionForControl();
269
270 const TypeArguments& BuildTypeArguments();
271 Fragment BuildArguments(Array* argument_names,
272 intptr_t* argument_count,
273 intptr_t* positional_argument_count);
274 Fragment BuildArgumentsFromActualArguments(Array* argument_names);
275
276 Fragment BuildInvalidExpression(TokenPosition* position);
277 Fragment BuildVariableGet(TokenPosition* position);
278 Fragment BuildVariableGet(uint8_t payload, TokenPosition* position);
279 Fragment BuildVariableGetImpl(intptr_t variable_kernel_position,
280 TokenPosition position);
281 Fragment BuildVariableSet(TokenPosition* position);
282 Fragment BuildVariableSet(uint8_t payload, TokenPosition* position);
283 Fragment BuildVariableSetImpl(TokenPosition position,
284 intptr_t variable_kernel_position);
285 Fragment BuildInstanceGet(TokenPosition* position);
286 Fragment BuildDynamicGet(TokenPosition* position);
287 Fragment BuildInstanceTearOff(TokenPosition* position);
288 Fragment BuildFunctionTearOff(TokenPosition* position);
289 Fragment BuildInstanceSet(TokenPosition* position);
290 Fragment BuildDynamicSet(TokenPosition* position);
291 Fragment BuildAllocateInvocationMirrorCall(TokenPosition position,
292 const String& name,
293 intptr_t num_type_arguments,
294 intptr_t num_arguments,
295 const Array& argument_names,
296 LocalVariable* actuals_array,
297 Fragment build_rest_of_actuals);
298 Fragment BuildSuperPropertyGet(TokenPosition* position);
299 Fragment BuildSuperPropertySet(TokenPosition* position);
300 Fragment BuildStaticGet(TokenPosition* position);
301 Fragment BuildStaticSet(TokenPosition* position);
302 Fragment BuildMethodInvocation(TokenPosition* position, bool is_dynamic);
303 Fragment BuildLocalFunctionInvocation(TokenPosition* position);
304 Fragment BuildFunctionInvocation(TokenPosition* position);
305 Fragment BuildEqualsCall(TokenPosition* position);
306 Fragment BuildEqualsNull(TokenPosition* position);
307 Fragment BuildSuperMethodInvocation(TokenPosition* position);
308 Fragment BuildStaticInvocation(TokenPosition* position);
309 Fragment BuildConstructorInvocation(TokenPosition* position);
310 Fragment BuildNot(TokenPosition* position);
311 Fragment BuildNullCheck(TokenPosition* position);
312 Fragment BuildLogicalExpression(TokenPosition* position);
313 Fragment TranslateLogicalExpressionForValue(bool negated,
314 TestFragment* side_exits);
315 Fragment BuildConditionalExpression(TokenPosition* position);
316 Fragment BuildStringConcatenation(TokenPosition* position);
317 Fragment BuildIsTest(TokenPosition position, const AbstractType& type);
318 Fragment BuildRecordIsTest(TokenPosition position, const RecordType& type);
319 Fragment BuildIsExpression(TokenPosition* position);
320 Fragment BuildAsExpression(TokenPosition* position);
321 Fragment BuildTypeLiteral(TokenPosition* position);
322 Fragment BuildThisExpression(TokenPosition* position);
323 Fragment BuildRethrow(TokenPosition* position);
324 Fragment BuildThrow(TokenPosition* position);
325 Fragment BuildListLiteral(TokenPosition* position);
326 Fragment BuildMapLiteral(TokenPosition* position);
327 Fragment BuildRecordLiteral(TokenPosition* position);
328 Fragment BuildRecordFieldGet(TokenPosition* position, bool is_named);
329 Fragment BuildFunctionExpression();
330 Fragment BuildLet(TokenPosition* position);
331 Fragment BuildBlockExpression();
332 Fragment BuildBigIntLiteral(TokenPosition* position);
333 Fragment BuildStringLiteral(TokenPosition* position);
334 Fragment BuildIntLiteral(uint8_t payload, TokenPosition* position);
335 Fragment BuildIntLiteral(bool is_negative, TokenPosition* position);
336 Fragment BuildDoubleLiteral(TokenPosition* position);
337 Fragment BuildBoolLiteral(bool value, TokenPosition* position);
338 Fragment BuildNullLiteral(TokenPosition* position);
339 Fragment BuildFutureNullValue(TokenPosition* position);
340 Fragment BuildConstantExpression(TokenPosition* position, Tag tag);
341 Fragment BuildPartialTearoffInstantiation(TokenPosition* position);
342 Fragment BuildLibraryPrefixAction(TokenPosition* position,
343 const String& selector);
344 Fragment BuildAwaitExpression(TokenPosition* position);
345 Fragment BuildFileUriExpression(TokenPosition* position);
346
347 Fragment BuildExpressionStatement(TokenPosition* position);
348 Fragment BuildBlock(TokenPosition* position);
349 Fragment BuildEmptyStatement();
350 Fragment BuildAssertBlock(TokenPosition* position);
351 Fragment BuildAssertStatement(TokenPosition* position);
352 Fragment BuildLabeledStatement(TokenPosition* position);
353 Fragment BuildBreakStatement(TokenPosition* position);
354 Fragment BuildWhileStatement(TokenPosition* position);
355 Fragment BuildDoStatement(TokenPosition* position);
356 Fragment BuildForStatement(TokenPosition* position);
357 Fragment BuildForInStatement(bool async, TokenPosition* position);
358 Fragment BuildSwitchStatement(TokenPosition* position);
359 Fragment BuildSwitchCase(SwitchHelper* helper, intptr_t case_index);
360 Fragment BuildLinearScanSwitch(SwitchHelper* helper);
361 Fragment BuildOptimizedSwitchPrelude(SwitchHelper* helper,
362 JoinEntryInstr* join);
363 Fragment BuildBinarySearchSwitch(SwitchHelper* helper);
364 Fragment BuildJumpTableSwitch(SwitchHelper* helper);
365 Fragment BuildContinueSwitchStatement(TokenPosition* position);
366 Fragment BuildIfStatement(TokenPosition* position);
367 Fragment BuildReturnStatement(TokenPosition* position);
368 Fragment BuildTryCatch(TokenPosition* position);
369 Fragment BuildTryFinally(TokenPosition* position);
370 Fragment BuildYieldStatement(TokenPosition* position);
371 Fragment BuildVariableDeclaration(TokenPosition* position);
372 Fragment BuildFunctionDeclaration(intptr_t offset, TokenPosition* position);
373 Fragment BuildFunctionNode(TokenPosition parent_position,
374 StringIndex name_index,
375 bool has_valid_annotation,
376 bool has_pragma,
377 intptr_t func_decl_offset);
378
379 // Build flow graph for '_nativeEffect'.
380 Fragment BuildNativeEffect();
381
382 // Build the call-site manually, to avoid doing initialization checks
383 // for late fields.
384 Fragment BuildReachabilityFence();
385
386 // Build flow graph for '_loadAbiSpecificInt' and
387 // '_loadAbiSpecificIntAtIndex', '_storeAbiSpecificInt', and
388 // '_storeAbiSpecificIntAtIndex' call sites.
389 //
390 // The second argument is either offsetInBytes (at_index==false), or
391 // index (at_index==true).
392 Fragment BuildLoadAbiSpecificInt(bool at_index);
393 Fragment BuildStoreAbiSpecificInt(bool at_index);
394
395 // Build FG for '_asFunctionInternal'. Reads an Arguments from the
396 // Kernel buffer and pushes the resulting closure.
397 Fragment BuildFfiAsFunctionInternal();
398
399 // Build FG for '_nativeCallbackFunction'. Reads an Arguments from the
400 // Kernel buffer and pushes the resulting Function object.
401 Fragment BuildFfiNativeCallbackFunction(FfiTrampolineKind kind);
402
403 // Piece of a StringConcatenation.
404 // Represents either a StringLiteral, or a Reader offset to the expression.
405 struct ConcatPiece {
406 intptr_t offset;
407 const String* literal;
408 };
409
410 // Collector that automatically concatenates adjacent string ConcatPieces.
411 struct PiecesCollector {
412 explicit PiecesCollector(Zone* z, TranslationHelper* translation_helper)
413 : pieces(5),
414 literal_run(z, 1),
415 translation_helper(translation_helper) {}
416
417 GrowableArray<ConcatPiece> pieces;
418 GrowableHandlePtrArray<const String> literal_run;
419 TranslationHelper* translation_helper;
420
421 void Add(const ConcatPiece& piece) {
422 if (piece.literal != nullptr) {
423 literal_run.Add(*piece.literal);
424 } else {
425 FlushRun();
426 pieces.Add(piece);
427 }
428 }
429
430 void FlushRun() {
431 switch (literal_run.length()) {
432 case 0:
433 return;
434 case 1:
435 pieces.Add({-1, &literal_run[0]});
436 break;
437 default:
438 pieces.Add({-1, &translation_helper->DartString(literal_run)});
439 }
440 literal_run.Clear();
441 }
442 };
443
444 // Flattens and collects pieces of StringConcatenations such that:
445 // ["a", "", "b"] => ["ab"]
446 // ["a", StringConcat("b", "c")] => ["abc"]
447 // ["a", "", StringConcat("b", my_var), "c"] => ["ab", my_var, "c"]
448 void FlattenStringConcatenation(PiecesCollector* collector);
449
450 FlowGraphBuilder* flow_graph_builder_;
451 ActiveClass* const active_class_;
452 ConstantReader constant_reader_;
453 TypeTranslator type_translator_;
454 DirectCallMetadataHelper direct_call_metadata_helper_;
455 InferredTypeMetadataHelper inferred_type_metadata_helper_;
456 ProcedureAttributesMetadataHelper procedure_attributes_metadata_helper_;
457 CallSiteAttributesMetadataHelper call_site_attributes_metadata_helper_;
458 Object& closure_owner_;
459 intptr_t num_ast_nodes_ = 0;
460
461 friend class KernelLoader;
462
463 DISALLOW_COPY_AND_ASSIGN(StreamingFlowGraphBuilder);
464};
465
466} // namespace kernel
467} // namespace dart
468
469#endif // RUNTIME_VM_COMPILER_FRONTEND_KERNEL_BINARY_FLOWGRAPH_H_
470

source code of dart_sdk/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h