Skip to content

Commit

Permalink
[vm] Re-land use of multiple entrypoints for closure calls.
Browse files Browse the repository at this point in the history
Original patchset is in revision 1.

Change-Id: I29ab0dbc3711f99895fd4f04a49d4185463a1602
Cq-Include-Trybots: luci.dart.try:vm-kernel-win-release-x64-try,vm-kernel-optcounter-threshold-linux-release-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-linux-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/71241
Commit-Queue: Samir Jindel <[email protected]>
Reviewed-by: Vyacheslav Egorov <[email protected]>
  • Loading branch information
sjindel-google authored and [email protected] committed Aug 23, 2018
1 parent a94e43a commit 2beb05b
Show file tree
Hide file tree
Showing 37 changed files with 260 additions and 135 deletions.
7 changes: 5 additions & 2 deletions pkg/vm/lib/transformations/call_site_annotator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,12 @@ class AnnotateWithStaticTypes extends RecursiveVisitor<Null> {
}

// TODO(vegorov) handle setters as well.
// TODO(34162): We don't need to save the type here, just whether or not it's
// a statically-checked call.
static bool shouldAnnotate(MethodInvocation node) =>
node.interfaceTarget != null &&
hasGenericCovariantParameters(node.interfaceTarget);
(node.interfaceTarget != null &&
hasGenericCovariantParameters(node.interfaceTarget)) ||
node.name.name == "call";

/// Return [true] if the given list of [VariableDeclaration] contains
/// any annotated with generic-covariant-impl.
Expand Down
2 changes: 1 addition & 1 deletion pkg/vm/testcases/bytecode/asserts.dart.expect
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ ConstantPool {
[7] = Null
}
]static method test2(() → core::bool condition, () → core::String message) → void {
assert(condition.call(), message.call());
assert([@vm.call-site-attributes.metadata=receiverType:() → dart.core::bool] condition.call(), [@vm.call-site-attributes.metadata=receiverType:() → dart.core::String] message.call());
}
[@vm.bytecode=
Bytecode {
Expand Down
2 changes: 1 addition & 1 deletion pkg/vm/testcases/bytecode/bootstrapping.dart.expect
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ ConstantPool {
}
] static get platformScript() → dynamic {
if(self::VMLibraryHooks::_cachedScript.{core::Object::==}(null) && !self::VMLibraryHooks::_computeScriptUri.{core::Object::==}(null)) {
self::VMLibraryHooks::_cachedScript = self::VMLibraryHooks::_computeScriptUri.call();
self::VMLibraryHooks::_cachedScript = [@vm.call-site-attributes.metadata=receiverType:dynamic] self::VMLibraryHooks::_computeScriptUri.call();
}
return self::VMLibraryHooks::_cachedScript;
}
Expand Down
22 changes: 11 additions & 11 deletions pkg/vm/testcases/bytecode/closures.dart.expect
Original file line number Diff line number Diff line change
Expand Up @@ -474,13 +474,13 @@ Closure CP#0 {
core::print(<core::Type>[self::A::T1, self::A::T2, self::A::foo::T3, self::A::foo::T4, T5, T6, T7, T8]);
self::callWithArgs<self::A::T1, self::A::T2, self::A::foo::T3, self::A::foo::T4, T5, T6, T7, T8>();
};
nested3.call();
[@vm.call-site-attributes.metadata=receiverType:() → dart.core::Null] nested3.call();
}
nested2.call<self::C7, self::C8>();
nested2.call<core::List<self::C7>, core::List<self::C8>>();
[@vm.call-site-attributes.metadata=receiverType:<T7 extends dart.core::Object = dynamic, T8 extends dart.core::Object = dynamic>() → void] nested2.call<self::C7, self::C8>();
[@vm.call-site-attributes.metadata=receiverType:<T7 extends dart.core::Object = dynamic, T8 extends dart.core::Object = dynamic>() → void] nested2.call<core::List<self::C7>, core::List<self::C8>>();
}
nested1.call<self::C5, self::C6>();
nested1.call<core::List<self::C5>, core::List<self::C6>>();
[@vm.call-site-attributes.metadata=receiverType:<T5 extends dart.core::Object = dynamic, T6 extends dart.core::Object = dynamic>() → void] nested1.call<self::C5, self::C6>();
[@vm.call-site-attributes.metadata=receiverType:<T5 extends dart.core::Object = dynamic, T6 extends dart.core::Object = dynamic>() → void] nested1.call<core::List<self::C5>, core::List<self::C6>>();
}
}
class B extends core::Object {
Expand Down Expand Up @@ -768,12 +768,12 @@ Closure CP#43 {
z = x.{core::num::+}(2);
w = this.{self::B::foo}.{core::num::+}(y);
}
closure2.call();
[@vm.call-site-attributes.metadata=receiverType:() → void] closure2.call();
core::print(w);
}
};
closure1.call(10);
closure1.call(11);
[@vm.call-site-attributes.metadata=receiverType:(dart.core::int) → dart.core::Null] closure1.call(10);
[@vm.call-site-attributes.metadata=receiverType:(dart.core::int) → dart.core::Null] closure1.call(11);
core::print(y);
core::print(z);
}
Expand All @@ -784,7 +784,7 @@ Closure CP#43 {
() → core::Null closure3 = () → core::Null {
this.{self::B::foo} = x;
};
closure3.call();
[@vm.call-site-attributes.metadata=receiverType:() → dart.core::Null] closure3.call();
}
}
}
Expand Down Expand Up @@ -1118,7 +1118,7 @@ Closure CP#9 {
() → core::Null inc = () → core::Null {
i = i.{core::num::+}(1);
};
inc.call();
[@vm.call-site-attributes.metadata=receiverType:() → dart.core::Null] inc.call();
core::print(i);
}
}
Expand Down Expand Up @@ -1313,7 +1313,7 @@ Closure CP#1 {
(core::int) → core::Null inc = (core::int y) → core::Null {
x = x.{core::num::+}(y);
};
inc.call(3);
[@vm.call-site-attributes.metadata=receiverType:(dart.core::int) → dart.core::Null] inc.call(3);
return x;
}
[@vm.bytecode=
Expand Down
4 changes: 2 additions & 2 deletions pkg/vm/testcases/bytecode/super_calls.dart.expect
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ ConstantPool {
[6] = Null
}
] method testSuperCallViaGetter() → dynamic
return super.{self::Base1::bar}.call<core::int>("param");
return [@vm.call-site-attributes.metadata=receiverType:dynamic] super.{self::Base1::bar}.call<core::int>("param");
[@vm.bytecode=
Bytecode {
Entry 1
Expand Down Expand Up @@ -467,7 +467,7 @@ ConstantPool {
[14] = Null
}
] method testSuperCallViaGetter() → dynamic
return super.{self::Base2::bar}.call<core::int>("param");
return [@vm.call-site-attributes.metadata=receiverType:dynamic] super.{self::Base2::bar}.call<core::int>("param");
[@vm.bytecode=
Bytecode {
Entry 1
Expand Down
6 changes: 3 additions & 3 deletions pkg/vm/testcases/bytecode/try_blocks.dart.expect
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ L1:
y = 3;
}
}
foo.call();
[@vm.call-site-attributes.metadata=receiverType:() → void] foo.call();
core::print(y);
}
on dynamic catch(final dynamic e, final core::StackTrace st) {
Expand Down Expand Up @@ -968,7 +968,7 @@ Closure CP#12 {
core::print(x);
core::print(y);
}
foo.call();
[@vm.call-site-attributes.metadata=receiverType:() → void] foo.call();
continue #L4;
}
finally {
Expand Down Expand Up @@ -1293,7 +1293,7 @@ L8:
}
finally {
core::print(x);
y.call();
[@vm.call-site-attributes.metadata=receiverType:dynamic] y.call();
}
}
[@vm.bytecode=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ static method foo2([@vm.inferred-type.metadata=dart.async::_Future?] asy::Future
self::foo2_a4(a4);
}
static method getDynamic() → dynamic
return self::unknown.call();
return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call();
static method main(core::List<core::String> args) → dynamic {
self::foo1([@vm.inferred-type.metadata=dart.async::_Future] asy::Future::value<self::B>(new self::B::•()), new self::B::•(), [@vm.inferred-type.metadata=dart.async::_Future] asy::Future::value<self::B>(new self::B::•()), new self::B::•());
self::foo2(self::getDynamic() as{TypeError} asy::Future<self::A>, self::getDynamic() as{TypeError} self::A, self::getDynamic() as{TypeError} asy::FutureOr<self::A>, self::getDynamic() as{TypeError} asy::FutureOr<self::A>);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class DeepCaller2 extends core::Object {
[@vm.inferred-type.metadata=dart.core::Null?]static field core::Function unknown;
static field core::Object field1 = [@vm.inferred-type.metadata=!] self::getValue();
static method getDynamic() → dynamic
return self::unknown.call();
return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call();
static method getValue() → core::Object {
self::A aa = self::getDynamic() as{TypeError} self::A;
return [@vm.inferred-type.metadata=!] aa.{self::A::foo}();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ static method use1([@vm.inferred-type.metadata=#lib::Intermediate] self::Interme
static method use2([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, [@vm.inferred-type.metadata=#lib::B?] self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::Intermediate::bar] [@vm.inferred-type.metadata=#lib::T1] i.{self::Intermediate::bar}(aa);
static method getDynamic() → dynamic
return self::unknown.call();
return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call();
static method allocateB() → dynamic {
new self::B::•();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ static method use2([@vm.inferred-type.metadata=#lib::Intermediate] self::Interme
static method use3([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::Intermediate::bar] [@vm.inferred-type.metadata=!] i.{self::Intermediate::bar}(aa);
static method getDynamic() → dynamic
return self::unknown.call();
return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call();
static method allocateB() → dynamic {
new self::B::•();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ static method use_bar(dynamic x) → dynamic
static method use_bazz(dynamic x) → dynamic
return [@vm.inferred-type.metadata=#lib::T3] x.bazz();
static method getDynamic() → dynamic
return self::unknown.call();
return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call();
static method allocateA() → dynamic {
new self::A::•();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ static method use1([@vm.inferred-type.metadata=#lib::DeepCaller1] self::DeepCall
static method use2([@vm.inferred-type.metadata=#lib::DeepCaller2] self::DeepCaller2 x, [@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::DeepCaller2::barL1] [@vm.inferred-type.metadata=!] x.{self::DeepCaller2::barL1}(aa);
static method getDynamic() → dynamic
return self::unknown.call();
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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class H extends core::Object {
[@vm.inferred-type.metadata=#lib::D?]static field self::A dd = new self::D::•();
[@vm.inferred-type.metadata=dart.core::Null?]static field core::Function unknown;
static method getDynamic() → dynamic
return self::unknown.call();
return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call();
static method main(core::List<core::String> args) → dynamic {
core::print([@vm.direct-call.metadata=#lib::B::foo??] [@vm.inferred-type.metadata=#lib::T1] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::foo}());
core::print([@vm.direct-call.metadata=#lib::B::bar??] [@vm.inferred-type.metadata=#lib::T1] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::bar});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ static method func2(self::T0 t0) → void {
[@vm.direct-call.metadata=#lib::T2::foo??] t0.{self::T0::foo}();
}
static method getDynamic() → dynamic
return self::unknown.call();
return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call();
static method use(dynamic x) → dynamic
return self::unknown.call(x);
return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call(x);
static method main(core::List<core::String> args) → dynamic {
self::func1(self::getDynamic() as{TypeError} self::T0);
self::use(self::func2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class B2 extends self::B2Base {
: super self::B2Base::•()
;
method doSuperCall() → void {
[@vm.direct-call.metadata=#lib::A2::call] [@vm.inferred-type.metadata=#lib::A2] super.{self::B2Base::aa2}.call(1, 2, 3, 4, 5, new self::T2::•());
[@vm.call-site-attributes.metadata=receiverType:dynamic] [@vm.direct-call.metadata=#lib::A2::call] [@vm.inferred-type.metadata=#lib::A2] super.{self::B2Base::aa2}.call(1, 2, 3, 4, 5, new self::T2::•());
}
}
class T3 extends core::Object {
Expand Down Expand Up @@ -127,15 +127,15 @@ static method test2() → void {
exp::Expect::isTrue([@vm.inferred-type.metadata=dart.core::bool?] self::ok);
}
static method getDynamic3() → dynamic
return self::unknown3.call();
return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown3.call();
static method test3() → void {
self::getDynamic3().aa3(1, 2, 3, 4, 5, 6, new self::T3::•());
self::ok = false;
[@vm.direct-call.metadata=#lib::T3::doTest3??] [@vm.direct-call.metadata=#lib::A3::foo] [@vm.inferred-type.metadata=#lib::T3?] [@vm.direct-call.metadata=#lib::B3::aa3??] [@vm.inferred-type.metadata=#lib::A3] [@vm.inferred-type.metadata=#lib::B3?] self::bb3.aa3.foo.doTest3();
exp::Expect::isTrue([@vm.inferred-type.metadata=dart.core::bool?] self::ok);
}
static method getDynamic4() → dynamic
return self::unknown4.call();
return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown4.call();
static method test4() → void {
self::getDynamic4().aa4(1, 2, 3, 4, 5, 6, 7, new self::T4::•());
self::ok = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ static method knownResult() → dynamic
return new self::B::•();
static method main(core::List<core::String> args) → dynamic {
core::Function closure = () → self::B => new self::B::•();
new self::TearOffDynamicMethod::•(closure.call());
new self::TearOffDynamicMethod::•([@vm.call-site-attributes.metadata=receiverType:dart.core::Function] closure.call());
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ abstract class Base extends core::Object {
method foo() → core::int
return [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] [@vm.inferred-type.metadata=int?] 3.{core::num::+}([@vm.direct-call.metadata=#lib::B::foo] [@vm.inferred-type.metadata=int?] [@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError} core::num) as{TypeError} core::int;
method doCall(dynamic x) → core::int
return x.call() as{TypeError} core::int;
return [@vm.call-site-attributes.metadata=receiverType:dynamic] x.call() as{TypeError} core::int;
}
class TearOffSuperMethod extends self::Base {
synthetic constructor •() → void
Expand Down
37 changes: 37 additions & 0 deletions runtime/tests/vm/dart/entrypoints/tearoff.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) 2018, 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.

// Test that typed calls against tearoffs go into the unchecked entrypoint.

import "package:expect/expect.dart";
import "common.dart";

class C<T> {
@NeverInline
@pragma("vm:testing.unsafe.trace-entrypoints-fn", validateTearoff)
void target1(T x, String y) {
Expect.notEquals(x, -1);
Expect.equals(y, "foo");
}
}

test(List<String> args) {
var f = (new C<int>()).target1;

// Warmup.
expectedEntryPoint = -1;
expectedTearoffEntryPoint = -1;
for (int i = 0; i < 100; ++i) {
f(i, "foo");
}

expectedEntryPoint = 0;
expectedTearoffEntryPoint = 1;
const int iterations = benchmarkMode ? 100000000 : 100;
for (int i = 0; i < iterations; ++i) {
f(i, "foo");
}

Expect.isTrue(validateRan);
}
9 changes: 9 additions & 0 deletions runtime/tests/vm/dart/entrypoints/tearoff_inline_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) 2018, 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.

// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10 -Denable_inlining=true

import "tearoff.dart";

main(args) => test(args);
9 changes: 9 additions & 0 deletions runtime/tests/vm/dart/entrypoints/tearoff_noinline_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) 2018, 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.

// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10

import "tearoff.dart";

main(args) => test(args);
35 changes: 35 additions & 0 deletions runtime/tests/vm/dart/entrypoints/tearoff_prologue.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// No type checks are removed here, but we can skip the argument count check.

import "package:expect/expect.dart";
import "common.dart";

class C<T> {
@NeverInline
@pragma("vm:testing.unsafe.trace-entrypoints-fn", validateTearoff)
void samir1(T x) {
if (x == -1) {
throw "oh no";
}
}
}

test(List<String> args) {
var c = new C<int>();
var f = c.samir1;

// Warmup.
expectedEntryPoint = -1;
expectedTearoffEntryPoint = -1;
for (int i = 0; i < 100; ++i) {
f(i);
}

expectedEntryPoint = 0;
expectedTearoffEntryPoint = 1;
int iterations = benchmarkMode ? 100000000 : 100;
for (int i = 0; i < iterations; ++i) {
f(i);
}

Expect.isTrue(validateRan);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10 -Denable_inlining=true

import "tearoff_prologue.dart";

main(args) => test(args);
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10

import "tearoff_prologue.dart";

main(args) => test(args);
Loading

0 comments on commit 2beb05b

Please sign in to comment.