mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 21:50:11 +00:00
[vm/aot] Keep pragmas on VariableDeclaration nodes in tree shaker
VM can use pragmas on local functions, which are actually put on VariableDeclaration nodes. This change teaches TFA tree shaker to keep such pragmas. TEST=pkg/vm/testcases/transformations/type_flow/transformer/pragmas.dart Issue: https://github.com/dart-lang/sdk/issues/45987 Change-Id: Ic2db375a93b539a131eca2431bef0e317a4d1b2b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/199520 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
parent
b1c961233d
commit
d39e794cc3
|
@ -774,8 +774,6 @@ class SummaryCollector extends RecursiveResultVisitor<TypeExpr> {
|
|||
_summary.result = _returnValue;
|
||||
}
|
||||
|
||||
// Visit annotations on members, classes and libraries.
|
||||
// Other nodes currently do not have annotations used by the VM.
|
||||
member.annotations.forEach(_visit);
|
||||
member.enclosingClass?.annotations?.forEach(_visit);
|
||||
member.enclosingLibrary?.annotations?.forEach(_visit);
|
||||
|
@ -2136,6 +2134,7 @@ class SummaryCollector extends RecursiveResultVisitor<TypeExpr> {
|
|||
@override
|
||||
TypeExpr visitFunctionDeclaration(FunctionDeclaration node) {
|
||||
// TODO(alexmarkov): support function types.
|
||||
node.variable.annotations.forEach(_visit);
|
||||
_declareVariableWithStaticType(node.variable);
|
||||
_handleNestedFunctionNode(node.function);
|
||||
return null;
|
||||
|
@ -2248,6 +2247,7 @@ class SummaryCollector extends RecursiveResultVisitor<TypeExpr> {
|
|||
|
||||
@override
|
||||
TypeExpr visitVariableDeclaration(VariableDeclaration node) {
|
||||
node.annotations.forEach(_visit);
|
||||
final TypeExpr initialValue =
|
||||
node.initializer == null ? _nullType : _visit(node.initializer);
|
||||
_declareVariable(node, initialValue);
|
||||
|
|
|
@ -122,8 +122,8 @@ Component transformComponent(
|
|||
}
|
||||
|
||||
// Pass which removes all annotations except @ExternalName and @pragma
|
||||
// on members, classes and libraries. May also keep @TagNumber which is used
|
||||
// by protobuf handler.
|
||||
// on variables, members, classes and libraries.
|
||||
// May also keep @TagNumber which is used by protobuf handler.
|
||||
class CleanupAnnotations extends RecursiveVisitor {
|
||||
final Class externalNameClass;
|
||||
final Class pragmaClass;
|
||||
|
@ -152,7 +152,10 @@ class CleanupAnnotations extends RecursiveVisitor {
|
|||
}
|
||||
|
||||
void _cleanupAnnotations(Node node, List<Expression> annotations) {
|
||||
if (node is Member || node is Class || node is Library) {
|
||||
if (node is VariableDeclaration ||
|
||||
node is Member ||
|
||||
node is Class ||
|
||||
node is Library) {
|
||||
annotations.removeWhere((a) => !_keepAnnotation(a));
|
||||
} else {
|
||||
annotations.clear();
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
class A {
|
||||
final int x;
|
||||
const A(this.x);
|
||||
}
|
||||
|
||||
class B {
|
||||
final int y;
|
||||
const B(this.y);
|
||||
}
|
||||
|
||||
class C {
|
||||
final int z;
|
||||
const C(this.z);
|
||||
}
|
||||
|
||||
@pragma("test1", A(10))
|
||||
class Foo {
|
||||
@pragma("test2", {3: B(11), 4: 'hey'})
|
||||
void bar() {
|
||||
@pragma("test3", C(12))
|
||||
void bazz() {}
|
||||
|
||||
bazz();
|
||||
}
|
||||
}
|
||||
|
||||
main() {
|
||||
Foo().bar();
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
library #lib;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
class A extends core::Object /*hasConstConstructor*/ {
|
||||
[@vm.inferred-type.metadata=dart.core::_Smi (value: 10)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i] final field core::int* x;
|
||||
}
|
||||
class B extends core::Object /*hasConstConstructor*/ {
|
||||
[@vm.inferred-type.metadata=dart.core::_Smi (value: 11)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] final field core::int* y;
|
||||
}
|
||||
class C extends core::Object /*hasConstConstructor*/ {
|
||||
[@vm.inferred-type.metadata=dart.core::_Smi (value: 12)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] [@vm.unboxing-info.metadata=()->i] final field core::int* z;
|
||||
}
|
||||
@#C4
|
||||
class Foo extends core::Object {
|
||||
synthetic constructor •() → self::Foo*
|
||||
: super core::Object::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] @#C13
|
||||
method bar() → void {
|
||||
@#C17
|
||||
function bazz() → void {}
|
||||
[@vm.call-site-attributes.metadata=receiverType:void Function()*] bazz.call();
|
||||
}
|
||||
}
|
||||
static method main() → dynamic {
|
||||
[@vm.direct-call.metadata=#lib::Foo.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::Foo::•().{self::Foo::bar}();
|
||||
}
|
Loading…
Reference in a new issue