mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:59:47 +00:00
[dart2js] Union old and new type when refining in type inference.
This change doesn't seem to have a significant impact on most compilation results: - Golem results show no significant difference in microbenchmarks. - For a medium and large app tested, while we see a small change in the actual inference results, the generated code is identical before/after this change. - Timing and memory usage on internal compilations seem comparable before/after this change. Note: This replaces the need for any notion of "invalid" refines so I will clean up that code in a follow up change. Change-Id: I2a293eacd944fc17ee2dab97d3d947c042b4038f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/313720 Commit-Queue: Nate Biggs <natebiggs@google.com> Reviewed-by: Mayank Patke <fishythefish@google.com>
This commit is contained in:
parent
34f0e26d45
commit
acd2ad41b6
|
@ -782,7 +782,17 @@ class InferrerEngine {
|
||||||
_progress.showProgress('Inferred ', _overallRefineCount, ' types.');
|
_progress.showProgress('Inferred ', _overallRefineCount, ' types.');
|
||||||
TypeInformation info = _workQueue.remove();
|
TypeInformation info = _workQueue.remove();
|
||||||
AbstractValue oldType = info.type;
|
AbstractValue oldType = info.type;
|
||||||
AbstractValue newType = info.refine(this);
|
|
||||||
|
// In order to ensure that types are always getting wider we union the old
|
||||||
|
// and new refined types. This ensures that we do not get caught in any
|
||||||
|
// refinement loops that can arise from horizontal or downward
|
||||||
|
// (i.e. narrowing) moves in the type lattice.
|
||||||
|
//
|
||||||
|
// This tends to produce comparable results to not doing the union and
|
||||||
|
// often with fewer refine steps since the natural progression of these
|
||||||
|
// refines is to take us up the lattice anyway.
|
||||||
|
AbstractValue newType =
|
||||||
|
abstractValueDomain.union(oldType, info.refine(this));
|
||||||
// Check that refinement has not accidentally changed the type.
|
// Check that refinement has not accidentally changed the type.
|
||||||
assert(oldType == info.type);
|
assert(oldType == info.type);
|
||||||
if (info.abandonInferencing) info.doNotEnqueue = true;
|
if (info.abandonInferencing) info.doNotEnqueue = true;
|
||||||
|
|
57
tests/web/regress/issue/290868787b_test.dart
Normal file
57
tests/web/regress/issue/290868787b_test.dart
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
// Copyright (c) 2023, 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.
|
||||||
|
|
||||||
|
abstract class A {
|
||||||
|
A get a;
|
||||||
|
}
|
||||||
|
|
||||||
|
class B implements A {
|
||||||
|
@override
|
||||||
|
C get a => C();
|
||||||
|
}
|
||||||
|
|
||||||
|
class C implements A {
|
||||||
|
@override
|
||||||
|
B get a => B();
|
||||||
|
}
|
||||||
|
|
||||||
|
class D implements B, C {
|
||||||
|
@override
|
||||||
|
H get a => H();
|
||||||
|
}
|
||||||
|
|
||||||
|
class E implements B, C {
|
||||||
|
@override
|
||||||
|
H get a => H();
|
||||||
|
}
|
||||||
|
|
||||||
|
class F implements B, C {
|
||||||
|
@override
|
||||||
|
H get a => H();
|
||||||
|
}
|
||||||
|
|
||||||
|
class G implements B, C {
|
||||||
|
@override
|
||||||
|
H get a => H();
|
||||||
|
}
|
||||||
|
|
||||||
|
class H implements B, C {
|
||||||
|
@override
|
||||||
|
H get a => H();
|
||||||
|
}
|
||||||
|
|
||||||
|
void foo(int n, A a) {
|
||||||
|
if (n > 0) {
|
||||||
|
foo(n - 1, E());
|
||||||
|
foo(n - 1, F());
|
||||||
|
foo(n - 1, G());
|
||||||
|
foo(n - 1, a.a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
B();
|
||||||
|
C();
|
||||||
|
foo(2, D());
|
||||||
|
}
|
Loading…
Reference in a new issue