-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[vm/aot/tfa] Improve handling of recursive calls in TFA
In general case, TFA approximates results of recursive calls using static types. However, if result type of a function does not depend on the flow inside its body, it cannot change and it can be used in case of recursive calls instead of a static type. This improves micro-benchmark from #37455: Before: 0m11.506s After: 0m7.324s Issue: #37455 Change-Id: I967d7add906c8dbd59dbbea1b993e1b4e1733514 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108500 Commit-Queue: Alexander Markov <[email protected]> Reviewed-by: Martin Kustermann <[email protected]>
- Loading branch information
1 parent
016061d
commit 318a482
Showing
4 changed files
with
124 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
pkg/vm/testcases/transformations/type_flow/transformer/regress_37455.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Copyright (c) 2019, 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. | ||
|
||
// Regression test for https://github.com/dart-lang/sdk/issues/37455 | ||
// Verifies that TFA can infer type of a recursive call if it doesn't depend | ||
// on the flow. | ||
|
||
class A { | ||
// Should be inferred as _GrowableList. | ||
final List afield; | ||
|
||
A(this.afield); | ||
|
||
String toString() => afield.toString(); | ||
} | ||
|
||
class B { | ||
List _foo(Iterator<int> iter) { | ||
List result = []; | ||
while (iter.moveNext()) { | ||
if (iter.current < 0) { | ||
return result; | ||
} | ||
// Do a recursive call with the same arguments. | ||
result.add(new A(_foo(iter))); | ||
} | ||
return result; | ||
} | ||
} | ||
|
||
void main() { | ||
var list = new B()._foo([1, 2, 3].iterator); | ||
print(list); | ||
} |
31 changes: 31 additions & 0 deletions
31
pkg/vm/testcases/transformations/type_flow/transformer/regress_37455.dart.expect
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
library #lib; | ||
import self as self; | ||
import "dart:core" as core; | ||
|
||
class A extends core::Object { | ||
[@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] [@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false] final field core::List<dynamic> afield; | ||
constructor •([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::List<dynamic> afield) → self::A | ||
: self::A::afield = afield, super core::Object::•() | ||
; | ||
[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false] method toString() → core::String | ||
return [@vm.direct-call.metadata=dart.core::_GrowableList::toString] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::A::afield] [@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] this.{self::A::afield}.{core::Object::toString}(); | ||
} | ||
class B extends core::Object { | ||
synthetic constructor •() → self::B | ||
: super core::Object::•() | ||
; | ||
[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasTearOffUses:false] method _foo([@vm.inferred-type.metadata=dart._internal::ListIterator<dart.core::int>] core::Iterator<core::int> iter) → core::List<dynamic> { | ||
core::List<dynamic> result = <dynamic>[]; | ||
while ([@vm.direct-call.metadata=dart._internal::ListIterator::moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] iter.{core::Iterator::moveNext}()) { | ||
if([@vm.inferred-type.metadata=dart.core::bool?] [@vm.direct-call.metadata=dart._internal::ListIterator::current] iter.{core::Iterator::current}.{core::num::<}(0)) { | ||
return result; | ||
} | ||
[@vm.call-site-attributes.metadata=receiverType:dart.core::List<dynamic>] [@vm.direct-call.metadata=dart.core::_GrowableList::add] [@vm.inferred-type.metadata=!? (skip check)] result.{core::List::add}(new self::A::•([@vm.direct-call.metadata=#lib::B::_foo] [@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic> (skip check)] this.{self::B::_foo}(iter))); | ||
} | ||
return result; | ||
} | ||
} | ||
static method main() → void { | ||
core::List<dynamic> list = [@vm.direct-call.metadata=#lib::B::_foo] [@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic> (skip check)] new self::B::•().{self::B::_foo}([@vm.direct-call.metadata=dart.core::_GrowableList::iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<dart.core::int>]<core::int>[1, 2, 3].{core::Iterable::iterator}); | ||
core::print(list); | ||
} |