dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.03k stars 1.55k forks source link

[dart2js] Clean up processing of `@pragma('dart2js:...')` annotations #49475

Open rakudrama opened 2 years ago

rakudrama commented 2 years ago

We should rework the processing of @pragma annotations to address the following problems.

There are additional comments in the code-base referencing this issue.

MemberEntities only

dart2js's @pragma annotation processing is (mostly) keyed on MemberEntitys.

J-model annotations

In lowering from the K-model to the J-model, we sometimes generate two (or more) J-entities for a K-entity. For example, a K-generative-constructor may be lowered to a J-generative-constructor-factory and a J-constructor-body.

Some annotations on the K-entity should apply to all the corresponding J-elements, others should apply to only one. For example, noInline applied to a K-constructor reasonably applies to the J-generative-constructor-factory, but not the J-constructor-body that is called from the generative-constructor-factory. This happens by accident today, because the annotations are copied to only the primary J-entity. For noInline this is desirable - it would likely be bad for code size to reduce the number of calls to the constructor body and then prevent inlining at the reduced number of calls. By comparison, disable-inlining, which applies not to the method but to call sites inside the method, it is likely that the user intends to disable inlining inside the constructor's initializers and body.

To address the above example, we need to be able to say what the annotations mean in the J-model. I think a first try at this should probably formalize annotations as either an attribute of an entity, or an directive to be applied within an entity. The second kind are more naturally scoped.

Using pragmas in processing impacts

Pragmas that might naturally be scoped are used in places where the scope is not available. One of these is in processing impacts. Another is in some ssa optimizations (invoke_dynamic_specializer).

Rather than querying the annotations on the basis of an approximate representative member entity, we should find a way to flow the annotation scope to the place where the annotations are queried.

It is infeasible to use the Kernel AST node as a token for the scope of an operation where the annotations might have an effect - it deserializes too much of the .dill file. We should investigate whether we could instead query the annotations at the beginning of the impact chain, in resolution where the Kernel AST is available, and propagate the answer rather than the index for the query (i.e. MemberEntity). For example, today we have a TypeUse for a parametric covariant parameter type, perhaps this should become a TypeUse for a parametric covariant parameter type and whether the type has been 'trusted'.

pragmas and command-line settings

The default value of some pragma annotation queries is a bool property of the command-line options. It would be cleaner if these options imputed a set of scoped pragma annotations that apply to the 'whole program' scope. We could then explain that, e.g. -O3 is the same as a set of @pragma annotations applied to every file.

mnordine commented 2 years ago

@rakudrama Are the @pragma annotations documented anywhere?

rakudrama commented 1 year ago

@mnordine, after your question I wrote some documentation at pkg/compiler/doc/pragmas.md. I apologize for forgetting to let you know.

mnordine commented 1 year ago

No worries! I seen it at the time.