Flutter Engine
The Flutter Engine
kernel_binary_flowgraph.h
Go to the documentation of this file.
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
16#include "vm/kernel.h"
17#include "vm/kernel_binary.h"
18#include "vm/object.h"
19
20namespace dart {
21namespace kernel {
22
24 public:
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(flow_graph_builder->zone_)) {}
44
46
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 const AbstractType* emitted_value_type);
90 Fragment ShortcutForUserDefinedEquals(const Function& dart_function,
91 LocalVariable* first_parameter);
92 Fragment TypeArgumentsHandling(const Function& dart_function);
93
94 ScriptPtr Script() {
95 if (active_class_ != nullptr) {
96 return active_class_->ActiveScript();
97 }
98 return Script::null();
99 }
100
101 static UncheckedEntryPointStyle ChooseEntryPointStyle(
102 const Function& dart_function,
103 const Fragment& implicit_type_checks,
104 const Fragment& regular_function_prologue,
105 const Fragment& type_args_handling);
106
107 void loop_depth_inc();
108 void loop_depth_dec();
109 void catch_depth_inc();
110 void catch_depth_dec();
111 void try_depth_inc();
112 void try_depth_dec();
113 intptr_t block_expression_depth();
114 void block_expression_depth_inc();
115 void block_expression_depth_dec();
116 void synthetic_error_handler_depth_inc();
117 void synthetic_error_handler_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 TokenPosition ReadPosition();
141
142 // See BaseFlowGraphBuilder::MakeTemporary.
143 LocalVariable* MakeTemporary(const char* suffix = nullptr);
144 Fragment DropTemporary(LocalVariable** variable);
145
146 LocalVariable* LookupVariable(intptr_t kernel_offset);
147 Function& FindMatchingFunction(const Class& klass,
148 const String& name,
149 int type_args_len,
150 int argument_count,
151 const Array& argument_names);
152
153 bool NeedsDebugStepCheck(const Function& function, TokenPosition position);
154 bool NeedsDebugStepCheck(Value* value, TokenPosition position);
155
156 void InlineBailout(const char* reason);
157 Fragment DebugStepCheck(TokenPosition position);
158 Fragment LoadLocal(LocalVariable* variable);
159 IndirectGotoInstr* IndirectGoto(intptr_t target_count);
160 Fragment Return(TokenPosition position);
161 Fragment EvaluateAssertion();
162 Fragment RethrowException(TokenPosition position, int catch_try_index);
163 Fragment ThrowNoSuchMethodError(TokenPosition position,
164 const Function& target,
165 bool incompatible_arguments);
166 Fragment Constant(const Object& value);
167 Fragment IntConstant(int64_t value);
168 Fragment LoadStaticField(const Field& field, bool calls_initializer);
169 Fragment RedefinitionWithType(const AbstractType& type);
170 Fragment CheckNull(TokenPosition position,
171 LocalVariable* receiver,
172 const String& function_name);
173 Fragment StaticCall(TokenPosition position,
174 const Function& target,
175 intptr_t argument_count,
176 ICData::RebindRule rebind_rule);
177 Fragment StaticCall(TokenPosition position,
178 const Function& target,
179 intptr_t argument_count,
180 const Array& argument_names,
181 ICData::RebindRule rebind_rule,
182 const InferredTypeMetadata* result_type = nullptr,
183 intptr_t type_args_len = 0,
184 bool use_unchecked_entry = false);
185 Fragment StaticCallMissing(TokenPosition position,
186 const String& selector,
187 intptr_t argument_count,
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 bool is_call_on_this = false);
210
211 Fragment ThrowException(TokenPosition position);
212 Fragment BooleanNegate();
213 Fragment TranslateInstantiatedTypeArguments(
214 const TypeArguments& type_arguments);
215 Fragment StrictCompare(TokenPosition position,
216 Token::Kind kind,
217 bool number_check = false);
218 Fragment AllocateObject(TokenPosition position,
219 const Class& klass,
220 intptr_t argument_count);
221 Fragment AllocateContext(const ZoneGrowableArray<const Slot*>& context_slots);
222 Fragment LoadNativeField(const Slot& field,
223 InnerPointerAccess loads_inner_pointer =
225 Fragment StoreLocal(TokenPosition position, LocalVariable* variable);
226 Fragment StoreStaticField(TokenPosition position, const Field& field);
227 Fragment StringInterpolate(TokenPosition position);
228 Fragment StringInterpolateSingle(TokenPosition position);
229 Fragment ThrowTypeError();
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 = false);
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 Fragment DropArguments(intptr_t argument_count, intptr_t type_args_count);
255
256 // Drop given number of temps from the stack but preserve top of the stack.
257 Fragment DropTempsPreserveTop(intptr_t num_temps_to_drop);
258
259 Fragment MakeTemp();
260 Fragment NullConstant();
261 JoinEntryInstr* BuildJoinEntry();
262 JoinEntryInstr* BuildJoinEntry(intptr_t try_index);
263 Fragment Goto(JoinEntryInstr* destination);
264 Fragment CheckBoolean(TokenPosition position);
265 Fragment CheckArgumentType(LocalVariable* variable, const AbstractType& type);
266 Fragment RecordCoverage(TokenPosition position);
267 Fragment EnterScope(intptr_t kernel_offset,
268 const LocalScope** scope = nullptr);
269 Fragment ExitScope(intptr_t kernel_offset);
270
271 TestFragment TranslateConditionForControl();
272
273 const TypeArguments& BuildTypeArguments();
274 Fragment BuildArguments(Array* argument_names,
275 intptr_t* argument_count,
276 intptr_t* positional_argument_count);
277 Fragment BuildArgumentsFromActualArguments(Array* argument_names);
278
279 Fragment BuildInvalidExpression(TokenPosition* position);
280 Fragment BuildVariableGet(TokenPosition* position);
281 Fragment BuildVariableGet(uint8_t payload, TokenPosition* position);
282 Fragment BuildVariableGetImpl(intptr_t variable_kernel_position,
283 TokenPosition position);
284 Fragment BuildVariableSet(TokenPosition* position);
285 Fragment BuildVariableSet(uint8_t payload, TokenPosition* position);
286 Fragment BuildVariableSetImpl(TokenPosition position,
287 intptr_t variable_kernel_position);
288 Fragment BuildInstanceGet(TokenPosition* position);
289 Fragment BuildDynamicGet(TokenPosition* position);
290 Fragment BuildInstanceTearOff(TokenPosition* position);
291 Fragment BuildInstanceSet(TokenPosition* position);
292 Fragment BuildDynamicSet(TokenPosition* position);
293 Fragment BuildAllocateInvocationMirrorCall(TokenPosition position,
294 const String& name,
295 intptr_t num_type_arguments,
296 intptr_t num_arguments,
297 const Array& argument_names,
298 LocalVariable* actuals_array,
299 Fragment build_rest_of_actuals);
300 Fragment BuildSuperPropertyGet(TokenPosition* position);
301 Fragment BuildSuperPropertySet(TokenPosition* position);
302 Fragment BuildStaticGet(TokenPosition* position);
303 Fragment BuildStaticSet(TokenPosition* position);
304 Fragment BuildMethodInvocation(TokenPosition* position, bool is_dynamic);
305 Fragment BuildLocalFunctionInvocation(TokenPosition* position);
306 Fragment BuildFunctionInvocation(TokenPosition* position);
307 Fragment BuildEqualsCall(TokenPosition* position);
308 Fragment BuildEqualsNull(TokenPosition* position);
309 Fragment BuildSuperMethodInvocation(TokenPosition* position);
310 Fragment BuildStaticInvocation(TokenPosition* position);
311 Fragment BuildConstructorInvocation(TokenPosition* position);
312 Fragment BuildNot(TokenPosition* position);
313 Fragment BuildNullCheck(TokenPosition* position);
314 Fragment BuildLogicalExpression(TokenPosition* position);
315 Fragment TranslateLogicalExpressionForValue(bool negated,
316 TestFragment* side_exits);
317 Fragment BuildConditionalExpression(TokenPosition* position);
318 Fragment BuildStringConcatenation(TokenPosition* position);
319 Fragment BuildIsTest(TokenPosition position, const AbstractType& type);
320 Fragment BuildRecordIsTest(TokenPosition position, const RecordType& type);
321 Fragment BuildIsExpression(TokenPosition* position);
322 Fragment BuildAsExpression(TokenPosition* position);
323 Fragment BuildTypeLiteral(TokenPosition* position);
324 Fragment BuildThisExpression(TokenPosition* position);
325 Fragment BuildRethrow(TokenPosition* position);
326 Fragment BuildThrow(TokenPosition* position);
327 Fragment BuildListLiteral(TokenPosition* position);
328 Fragment BuildMapLiteral(TokenPosition* position);
329 Fragment BuildRecordLiteral(TokenPosition* position);
330 Fragment BuildRecordFieldGet(TokenPosition* position, bool is_named);
331 Fragment BuildFunctionExpression();
332 Fragment BuildLet(TokenPosition* position);
333 Fragment BuildBlockExpression();
334 Fragment BuildBigIntLiteral(TokenPosition* position);
335 Fragment BuildStringLiteral(TokenPosition* position);
336 Fragment BuildIntLiteral(uint8_t payload, TokenPosition* position);
337 Fragment BuildIntLiteral(bool is_negative, TokenPosition* position);
338 Fragment BuildDoubleLiteral(TokenPosition* position);
339 Fragment BuildBoolLiteral(bool value, TokenPosition* position);
340 Fragment BuildNullLiteral(TokenPosition* position);
341 Fragment BuildFutureNullValue(TokenPosition* position);
342 Fragment BuildConstantExpression(TokenPosition* position, Tag tag);
343 Fragment BuildPartialTearoffInstantiation(TokenPosition* position);
344 Fragment BuildLibraryPrefixAction(TokenPosition* position,
345 const String& selector);
346 Fragment BuildAwaitExpression(TokenPosition* position);
347 Fragment BuildFileUriExpression(TokenPosition* position);
348
349 Fragment BuildExpressionStatement(TokenPosition* position);
350 Fragment BuildBlock(TokenPosition* position);
351 Fragment BuildEmptyStatement();
352 Fragment BuildAssertBlock(TokenPosition* position);
353 Fragment BuildAssertStatement(TokenPosition* position);
354 Fragment BuildLabeledStatement(TokenPosition* position);
355 Fragment BuildBreakStatement(TokenPosition* position);
356 Fragment BuildWhileStatement(TokenPosition* position);
357 Fragment BuildDoStatement(TokenPosition* position);
358 Fragment BuildForStatement(TokenPosition* position);
359 Fragment BuildSwitchStatement(TokenPosition* position);
360 Fragment BuildSwitchCase(SwitchHelper* helper, intptr_t case_index);
361 Fragment BuildLinearScanSwitch(SwitchHelper* helper);
362 Fragment BuildOptimizedSwitchPrelude(SwitchHelper* helper,
363 JoinEntryInstr* join);
364 Fragment BuildBinarySearchSwitch(SwitchHelper* helper);
365 Fragment BuildJumpTableSwitch(SwitchHelper* helper);
366 Fragment BuildContinueSwitchStatement(TokenPosition* position);
367 Fragment BuildIfStatement(TokenPosition* position);
368 Fragment BuildReturnStatement(TokenPosition* position);
369 Fragment BuildTryCatch(TokenPosition* position);
370 Fragment BuildTryFinally(TokenPosition* position);
371 Fragment BuildYieldStatement(TokenPosition* position);
372 Fragment BuildVariableDeclaration(TokenPosition* position);
373 Fragment BuildFunctionDeclaration(TokenPosition* position);
374 Fragment BuildFunctionNode(intptr_t func_decl_offset);
375
376 // Build flow graph for '_nativeEffect'.
377 Fragment BuildNativeEffect();
378
379 // Build the call-site manually, to avoid doing initialization checks
380 // for late fields.
381 Fragment BuildReachabilityFence();
382
383 // Build flow graph for '_loadAbiSpecificInt' and
384 // '_loadAbiSpecificIntAtIndex', '_storeAbiSpecificInt', and
385 // '_storeAbiSpecificIntAtIndex' call sites.
386 Fragment BuildLoadStoreAbiSpecificInt(bool is_store, bool at_index);
387
388 // Build FG for FFI call.
389 Fragment BuildFfiCall();
390
391 // Build FG for '_nativeCallbackFunction'. Reads an Arguments from the
392 // Kernel buffer and pushes the resulting Function object.
393 Fragment BuildFfiNativeCallbackFunction(FfiCallbackKind kind);
394
395 Fragment BuildFfiNativeAddressOf();
396
397 Fragment BuildArgumentsCachableIdempotentCall(intptr_t* argument_count);
398 Fragment BuildCachableIdempotentCall(TokenPosition position,
399 const Function& target);
400
401 // Piece of a StringConcatenation.
402 // Represents either a StringLiteral, or a Reader offset to the expression.
403 struct ConcatPiece {
404 intptr_t offset;
405 const String* literal;
406 };
407
408 // Collector that automatically concatenates adjacent string ConcatPieces.
409 struct PiecesCollector {
410 explicit PiecesCollector(Zone* z, TranslationHelper* translation_helper)
411 : pieces(5),
412 literal_run(z, 1),
413 translation_helper(translation_helper) {}
414
415 GrowableArray<ConcatPiece> pieces;
416 GrowableHandlePtrArray<const String> literal_run;
417 TranslationHelper* translation_helper;
418
419 void Add(const ConcatPiece& piece) {
420 if (piece.literal != nullptr) {
421 literal_run.Add(*piece.literal);
422 } else {
423 FlushRun();
424 pieces.Add(piece);
425 }
426 }
427
428 void FlushRun() {
429 switch (literal_run.length()) {
430 case 0:
431 return;
432 case 1:
433 pieces.Add({-1, &literal_run[0]});
434 break;
435 default:
436 pieces.Add({-1, &translation_helper->DartString(literal_run)});
437 }
438 literal_run.Clear();
439 }
440 };
441
442 // Flattens and collects pieces of StringConcatenations such that:
443 // ["a", "", "b"] => ["ab"]
444 // ["a", StringConcat("b", "c")] => ["abc"]
445 // ["a", "", StringConcat("b", my_var), "c"] => ["ab", my_var, "c"]
446 void FlattenStringConcatenation(PiecesCollector* collector);
447
448 FlowGraphBuilder* flow_graph_builder_;
449 ActiveClass* const active_class_;
450 ConstantReader constant_reader_;
451 TypeTranslator type_translator_;
452 DirectCallMetadataHelper direct_call_metadata_helper_;
453 InferredTypeMetadataHelper inferred_type_metadata_helper_;
454 ProcedureAttributesMetadataHelper procedure_attributes_metadata_helper_;
455 CallSiteAttributesMetadataHelper call_site_attributes_metadata_helper_;
456 Object& closure_owner_;
457 intptr_t num_ast_nodes_ = 0;
458 intptr_t synthetic_error_handler_depth_ = 0;
459
460 friend class KernelLoader;
461
463};
464
465} // namespace kernel
466} // namespace dart
467
468#endif // RUNTIME_VM_COMPILER_FRONTEND_KERNEL_BINARY_FLOWGRAPH_H_
GLenum type
static ObjectPtr null()
Definition: object.h:433
void ReportUnexpectedTag(const char *variant, Tag tag) override
StreamingFlowGraphBuilder(FlowGraphBuilder *flow_graph_builder, const TypedDataView &data, intptr_t data_program_offset)
Fragment BuildStatementAt(intptr_t kernel_offset)
uint8_t value
uint32_t * target
Dart_NativeFunction function
Definition: fuchsia.cc:51
int argument_count
Definition: fuchsia.cc:52
Definition: dart_vm.cc:33
const char *const name
InnerPointerAccess
Definition: il.h:6295
FfiCallbackKind
Definition: object.h:2984
const char *const function_name
static int8_t data[kExtLength]
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: globals.h:581
static SkString join(const CommandLineFlags::StringArray &)
Definition: skpbench.cpp:741
SeparatedVector2 offset