Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 2c9e7eb

Browse files
author
Dart CI
committed
Version 2.19.0-29.0.dev
Merge commit 'd6d9924b2609ce647e981e4bc7ebecf1567a96d2' into 'dev'
2 parents 88d7794 + d6d9924 commit 2c9e7eb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+809
-520
lines changed

pkg/compiler/doc/pragmas.md

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
# Pragma Annotations understood by dart2js
2+
3+
## Pragmas for general use
4+
5+
| Pragma | Meaning |
6+
| --- | --- |
7+
| `dart2js:noInline` | [Never inline a function or method](#requesting-a-function-never-be-inlined) |
8+
| `dart2js:never-inline` | Alias for `dart2js:noInline` |
9+
| `dart2js:tryInline` | [Inline a function or method when possible](#requesting-a-function-be-inlined) |
10+
| `dart2js:prefer-inline` | Alias for `dart2js:tryInline` |
11+
| `dart2js:disable-inlining` | [Disable inlining within a method](#disabling-inlining) |
12+
| `dart2js:noElision` | Disables an optimization whereby unused fields or unused parameters are removed |
13+
14+
## Unsafe pragmas for general use
15+
16+
These pragmas are available for use in third-party code but are potentially
17+
unsafe. The use of these pragmas is discouraged unless the developer fully
18+
understands potential repercussions.
19+
20+
| Pragma | Meaning |
21+
| --- | --- |
22+
| `dart2js:as:check` | [Check `as` casts](#casts) |
23+
| `dart2js:as:trust` | [Trust `as` casts](#casts) |
24+
| `dart2js:downcast:check` | [Check downcasts](#downcasts) |
25+
| `dart2js:downcast:trust` | [Trust downcasts](#downcasts) |
26+
| `dart2js:index-bounds:check` | TBD |
27+
| `dart2js:index-bounds:trust` | TBD |
28+
| `dart2js:late:check` | [Check late fields are used correctly](#late-checks) |
29+
| `dart2js:late:trust` | [Trust late fields are used correctly](#late-checks) |
30+
| `dart2js:parameter:check` | TBD |
31+
| `dart2js:parameter:trust` | TBD |
32+
| `dart2js:types:check` | TBD |
33+
| `dart2js:types:trust` | TBD |
34+
35+
## Pragmas for internal use
36+
37+
These pragmas can cause unsound behavior if used incorrectly and therefore are
38+
only allowed within the core SDK libraries.
39+
40+
| Pragma | Meaning |
41+
| --- | --- |
42+
| `dart2js:assumeDynamic` | TBD |
43+
| `dart2js:disableFinal` | TBD |
44+
| `dart2js:noSideEffects` | Requires `dart2js:noInline` to work properly |
45+
| `dart2js:noThrows` | Requires `dart2js:noInline` to work properly |
46+
47+
## Detailed descriptions
48+
49+
### Annotations related to function inlining
50+
51+
Function (method) inlining is a compiler optimization where a call to a function
52+
is replaced with the body of the function. To perform function inlining, the
53+
compiler needs to determine that the call site calls exactly one function, the
54+
target. This is trivial for top-level methods, static methods and
55+
constructors. For calls to instance methods, the compiler does an analysis of
56+
the possible types of the receiver and uses that to reduce the set of potential
57+
targets. If there is a single target, it can potentially be inlined.
58+
59+
Not all functions can be inlined. For example, a recursive function cannot be
60+
expanded by inlining indefinitely. `dart2js` will not inline functions complex
61+
control flow, such as methods with exception handling (`try`-`catch`-`finally`)
62+
or many return or throw exit points.
63+
64+
We say a function is a _viable inlining candidate_ when it is the single target
65+
and it is possible to perform the inlining.
66+
67+
One benefit of inlining is that the execution cost of performing the call is
68+
avoided, which can be a substantial part of the total cost of the call when the
69+
body of the callee is simple. Copying instructions from the callee into the
70+
caller can create more opportunities for optimization, for example, it becomes
71+
possible to recognize and remove repeated operations.
72+
73+
The compiler automatically makes a decision whether or not to inline a function
74+
or method based on heuristics. One heuristic is to inline if the the inlined
75+
code is likely to be smaller that the call, as this results in a smaller _and_
76+
faster program. Another heuristic is to inline even if the code is likely to be
77+
slightly larger when the call is in a loop, as loops here is a chance that some
78+
of the code can be hoisted out of the loop.
79+
80+
The annotations described below allow the developer to override the default
81+
decisions. They should be used sparingly since it is likely that over time
82+
manual overrides will become increasingly out of date and mismatched with the
83+
evolving capabilities of the compiler.
84+
85+
#### Requesting a function be inlined
86+
87+
```dart
88+
@pragma('dart2js:tryInline')
89+
```
90+
91+
```dart
92+
@pragma('dart2js:prefer-inline) // Alias for the above annotation.
93+
```
94+
95+
This annotation may be placed on a function or method.
96+
97+
The compiler will inline the annotated function wherever it is a viable inlining
98+
candidate.
99+
100+
101+
#### Requesting a function never be inlined
102+
103+
```dart
104+
@pragma('dart2js:noInline')
105+
```
106+
107+
```dart
108+
@pragma('dart2js:never-inline) // Alias for the above annotation.
109+
```
110+
111+
This annotation may be placed on a function or method to prevent the function
112+
from being inlined.
113+
114+
#### Disabling inlining
115+
116+
```dart
117+
@pragma('dart2js:disable-inlining')
118+
```
119+
120+
This annotation may be placed on a function or method.
121+
122+
Function inlining is disabled at call sites within the annotated function.
123+
Inlining is disabled even when the call site has a viable inlining candidate
124+
that is annotated with `@pragma('dart2js:tryInline')`.
125+
126+
127+
### Annotations related to run-time checks
128+
129+
The Dart language and runtime libraries mandate checks in various places. Checks
130+
result in some kind of `Error` exception being thrown. If a program has a high
131+
degree of test coverage, the developer might have some confidence that the
132+
checks will never fail. If this is the case, the checks can be disabled via
133+
command line options or annotations. Annotations override the command line
134+
settings.
135+
136+
Trusting (i.e. disabling) checks can lead to a smaller and faster program. The
137+
cost is highly confusing unspecified behavior in place of the `Error`s that
138+
would otherwise have been thrown. The unspecified behavior is not necessarily
139+
consistent between runs and includes the program execution reaching statements
140+
that are 'impossible' to reach and variables being assigned values of an
141+
'impossible' type.
142+
143+
#### Casts
144+
145+
```dart
146+
@pragma('dart2js:as:check')
147+
@pragma('dart2js:as:trust')
148+
```
149+
150+
These annotations may be placed on a function or method to control whether `as`
151+
casts in the body of the function are checked.
152+
153+
One use of `dart2js:as:trust` is to construct an `unsafeCast` method.
154+
155+
```dart
156+
@pragma('dart2js:tryInline')
157+
@pragma('dart2js:as:trust')
158+
T unsafeCast<T>(Object? o) => o as T;
159+
```
160+
161+
The `tryInline` pragma ensures that the function is inlined, removing the cost
162+
of the call and passing the type parameter `T`, and the `as:trust` pragma
163+
removes the code that does the check.
164+
165+
#### Downcasts
166+
167+
```dart
168+
@pragma('dart2js:downcast:check')
169+
@pragma('dart2js:downcast:trust')
170+
```
171+
172+
These annotations may be placed on a function or method to control whether
173+
implicit downcasts in the body of the function are checked.
174+
175+
This is similar to the `dart2js:as:check` and `dart2js:as:trust` pragmas except
176+
it applies to implicit downcasts. Implicit downcasts are `as` checks that are
177+
inserted to cast from `dynamic`.
178+
179+
The `unsafeCast` method described above could also be written by trusting
180+
implicit downcasts.
181+
182+
```dart
183+
@pragma('dart2js:tryInline')
184+
@pragma('dart2js:downcast:trust')
185+
T unsafeCast<T>(dynamic o) => o; // implicit downcast `as T`.
186+
```
187+
188+
Trusting implicit downcasts is part of the `-O3` and `-O4` optimization level
189+
command line options. `dart2js:downcast:check` can be used to enable checking of
190+
implicit downcasts in a method when it would otherwise be trusted due to the
191+
command line options.
192+
193+
#### Late checks
194+
195+
Late checks - checking whether a late variable has been initialized - occur on
196+
all late variables. The checks on late instance variables (i.e. late fields)
197+
can be controlled via the following annotations.
198+
199+
```dart
200+
@pragma('dart2js:late:check')
201+
@pragma('dart2js:late:trust')
202+
```
203+
204+
These annotations may be placed on the declaration of a late field, class, or
205+
library. When placed on a class, the annotation applies to all late fields of
206+
the class. When placed on a library, the annotation applies to all late fields
207+
of all classes in the library. `dart2js:late` annotations are _scoped_: when
208+
there are multiple annotations, the one nearest the late field wins.
209+
210+
In the future this annotation might be extended to apply to `late` local
211+
variables, static variables, and top-level variables.

pkg/compiler/lib/src/inferrer/engine.dart

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,6 @@ class InferrerEngine implements interfaces.InferrerEngine {
225225
case CallType.access:
226226
data.setReceiverTypeMask(node, mask);
227227
break;
228-
case CallType.indirectAccess:
229-
// indirect access is not diretly recorded in the result data.
230-
break;
231228
case CallType.forIn:
232229
if (selector == Selectors.iterator) {
233230
data.setIteratorTypeMask(node, mask);
@@ -1126,57 +1123,6 @@ class InferrerEngine implements interfaces.InferrerEngine {
11261123
}
11271124
}
11281125

1129-
/// Indirect calls share the same dynamic call site information node. This
1130-
/// cache holds that shared dynamic call node for a given selector.
1131-
final Map<Selector, DynamicCallSiteTypeInformation> _sharedCalls = {};
1132-
1133-
/// For a given selector, return a shared dynamic call site that will be used
1134-
/// to combine the results of multiple dynamic calls in the program via
1135-
/// [IndirectDynamicCallSiteTypeInformation].
1136-
///
1137-
/// This is used only for scalability reasons: if there are too many targets
1138-
/// and call sites, we may have a quadratic number of edges in the graph, so
1139-
/// we add a level of indirection to merge the information and keep the graph
1140-
/// smaller.
1141-
// TODO(sigmund): start using or delete indirection logic.
1142-
// ignore: unused_element
1143-
DynamicCallSiteTypeInformation _typeOfSharedDynamicCall(
1144-
Selector selector, CallStructure structure) {
1145-
DynamicCallSiteTypeInformation info = _sharedCalls[selector];
1146-
if (info != null) return info;
1147-
1148-
TypeInformation receiverType =
1149-
IndirectParameterTypeInformation(abstractValueDomain, 'receiver');
1150-
List<TypeInformation> positional = [];
1151-
for (int i = 0; i < structure.positionalArgumentCount; i++) {
1152-
positional
1153-
.add(IndirectParameterTypeInformation(abstractValueDomain, '$i'));
1154-
}
1155-
Map<String, TypeInformation> named = {};
1156-
if (structure.namedArgumentCount > 0) {
1157-
for (var name in structure.namedArguments) {
1158-
named[name] =
1159-
IndirectParameterTypeInformation(abstractValueDomain, name);
1160-
}
1161-
}
1162-
1163-
info = _sharedCalls[selector] = DynamicCallSiteTypeInformation(
1164-
abstractValueDomain,
1165-
null,
1166-
CallType.indirectAccess,
1167-
null,
1168-
null,
1169-
selector,
1170-
null,
1171-
receiverType,
1172-
ArgumentsTypes(positional, named),
1173-
false,
1174-
false);
1175-
info.addToGraph(this);
1176-
types.allocatedCalls.add(info);
1177-
return info;
1178-
}
1179-
11801126
/// Returns true if global optimizations such as type inferencing can apply to
11811127
/// the field [element].
11821128
///

pkg/compiler/lib/src/inferrer/node_tracer.dart

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,6 @@ abstract class TracerVisitor implements TypeInformationVisitor {
272272
}
273273
}
274274

275-
@override
276-
visitIndirectDynamicCallSiteTypeInformation(
277-
IndirectDynamicCallSiteTypeInformation info) {
278-
if (info.dynamicCall == currentUser) {
279-
addNewEscapeInformation(info);
280-
}
281-
}
282-
283275
void analyzeStoredIntoList(ListTypeInformation list) {
284276
inferrer.analyzeListAndEnqueue(list);
285277
if (list.bailedOut) {
@@ -557,10 +549,4 @@ abstract class TracerVisitor implements TypeInformationVisitor {
557549
}
558550
addNewEscapeInformation(info);
559551
}
560-
561-
@override
562-
void visitIndirectParameterTypeInformation(
563-
IndirectParameterTypeInformation info) {
564-
addNewEscapeInformation(info);
565-
}
566552
}

pkg/compiler/lib/src/inferrer/type_graph_dump.dart

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -415,12 +415,6 @@ class _GraphGenerator extends TypeInformationVisitor {
415415
handleCall(info, 'StaticCallSite', {});
416416
}
417417

418-
@override
419-
void visitIndirectDynamicCallSiteTypeInformation(
420-
IndirectDynamicCallSiteTypeInformation info) {
421-
handleCall(info, 'IndirectDynamicCallSite', {});
422-
}
423-
424418
@override
425419
void visitDynamicCallSiteTypeInformation(
426420
DynamicCallSiteTypeInformation info) {
@@ -437,12 +431,6 @@ class _GraphGenerator extends TypeInformationVisitor {
437431
addNode(info, 'Parameter ${info.debugName}');
438432
}
439433

440-
@override
441-
void visitIndirectParameterTypeInformation(
442-
IndirectParameterTypeInformation info) {
443-
addNode(info, 'IndirectParameter ${info.debugName}');
444-
}
445-
446434
@override
447435
void visitClosureTypeInformation(ClosureTypeInformation info) {
448436
String text = shorten('${info.debugName}');

0 commit comments

Comments
 (0)