[vm/aot/tfa] Add missing visitor methods for call site instrumentation.

Some visitor methods were missing in the TFA transformation, causing
some call sites (such as PropertySet) to not be instrumented with
metadata communicating the analysis results.

Visiting all instance call sites (including PropertySet) is also needed
by table dispatch to collect correct summary information on selectors.

Change-Id: I488d5cd10700666dab05bd5c5304010aa90b1943
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135319
Reviewed-by: Samir Jindel <sjindel@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
Aske Simon Christensen 2020-02-13 15:32:48 +00:00 committed by commit-bot@chromium.org
parent e75c9192a1
commit 022b362e84
6 changed files with 38 additions and 8 deletions

View file

@ -162,6 +162,12 @@ class _DirectInvocation extends _Invocation {
if (selector.member.function != null) {
typeChecksNeeded = selector.member.function.typeParameters
.any((t) => t.isGenericCovariantImpl);
} else {
Field field = selector.member;
if (selector.callKind == CallKind.PropertySet) {
// TODO(dartbug.com/40615): Use TFA results to improve this criterion.
typeChecksNeeded = field.isGenericCovariantImpl;
}
}
}

View file

@ -340,6 +340,12 @@ class AnnotateKernel extends RecursiveVisitor<Null> {
super.visitPropertyGet(node);
}
@override
visitPropertySet(PropertySet node) {
_annotateCallSite(node, node.interfaceTarget);
super.visitPropertySet(node);
}
@override
visitDirectMethodInvocation(DirectMethodInvocation node) {
_annotateCallSite(node, node.target);
@ -352,6 +358,12 @@ class AnnotateKernel extends RecursiveVisitor<Null> {
super.visitDirectPropertyGet(node);
}
@override
visitDirectPropertySet(DirectPropertySet node) {
_annotateCallSite(node, node.target);
super.visitDirectPropertySet(node);
}
@override
visitSuperMethodInvocation(SuperMethodInvocation node) {
_annotateCallSite(node, node.interfaceTarget);
@ -364,6 +376,12 @@ class AnnotateKernel extends RecursiveVisitor<Null> {
super.visitSuperPropertyGet(node);
}
@override
visitSuperPropertySet(SuperPropertySet node) {
_annotateCallSite(node, node.interfaceTarget);
super.visitSuperPropertySet(node);
}
@override
visitStaticInvocation(StaticInvocation node) {
_annotateCallSite(node, node.target);
@ -375,6 +393,12 @@ class AnnotateKernel extends RecursiveVisitor<Null> {
_annotateCallSite(node, node.target);
super.visitStaticGet(node);
}
@override
visitStaticSet(StaticSet node) {
_annotateCallSite(node, node.target);
super.visitStaticSet(node);
}
}
/// Tree shaking based on results of type flow analysis (TFA).

View file

@ -53,7 +53,7 @@ static method use2([@vm.inferred-type.metadata=#lib::DeepCaller2] self::DeepCall
static method getDynamic() → dynamic
return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function*] self::unknown.call();
static method setField2([@vm.inferred-type.metadata=#lib::A] self::A* aa, [@vm.inferred-type.metadata=#lib::T2] dynamic value) → void {
[@vm.direct-call.metadata=#lib::A::field2] aa.{self::A::field2} = value;
[@vm.direct-call.metadata=#lib::A::field2] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::field2} = value;
}
static method main(core::List<core::String*>* args) → dynamic {
new self::A::•();

View file

@ -20,7 +20,7 @@ class A1 extends core::Object {
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=#lib::T1?] dynamic a5 = #C1]) → void {
[@vm.direct-call.metadata=#lib::A1::foo] this.{self::A1::foo} = _in::unsafeCast<self::T1*>(a5);
[@vm.direct-call.metadata=#lib::A1::foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A1::foo} = _in::unsafeCast<self::T1*>(a5);
}
}
class B1 extends core::Object {
@ -43,7 +43,7 @@ class A2 extends core::Object {
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=#lib::T2?] dynamic a6 = #C1]) → void {
[@vm.direct-call.metadata=#lib::A2::foo] this.{self::A2::foo} = a6;
[@vm.direct-call.metadata=#lib::A2::foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A2::foo} = a6;
}
}
abstract class B2Base extends core::Object {
@ -76,7 +76,7 @@ class A3 extends core::Object {
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = #C1, [@vm.inferred-type.metadata=#lib::T3?] dynamic a7 = #C1]) → void {
[@vm.direct-call.metadata=#lib::A3::foo] this.{self::A3::foo} = a7;
[@vm.direct-call.metadata=#lib::A3::foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A3::foo} = a7;
}
}
class B3 extends core::Object {
@ -99,7 +99,7 @@ class A4 extends core::Object {
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a7 = #C1, [@vm.inferred-type.metadata=#lib::T4?] dynamic a8 = #C1]) → void {
[@vm.direct-call.metadata=#lib::A4::foo] this.{self::A4::foo} = a8;
[@vm.direct-call.metadata=#lib::A4::foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A4::foo} = a8;
}
}
class B4 extends core::Object {

View file

@ -16,5 +16,5 @@ class C extends core::Object {
}
static method main() → void {
null;
[@vm.direct-call.metadata=#lib::C::instanceField] new self::C::•().{self::C::instanceField} = null;
[@vm.direct-call.metadata=#lib::C::instanceField] [@vm.inferred-type.metadata=!? (skip check)] new self::C::•().{self::C::instanceField} = null;
}

View file

@ -9,7 +9,7 @@ class A extends core::Object {
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method use() → dynamic {
[@vm.direct-call.metadata=#lib::A::x] this.{self::A::x} = 3;
[@vm.direct-call.metadata=#lib::A::x] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A::x} = 3;
}
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3] set /*isNullableByDefault*/ x(core::int value) → void;
}
@ -19,7 +19,7 @@ class B extends core::Object {
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method use() → dynamic {
this.{self::B::x} = 3;
[@vm.inferred-type.metadata=!? (skip check)] this.{self::B::x} = 3;
}
}
[@vm.inferred-type.metadata=dart.core::_Smi?]late static final field core::int staticLateB;