Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(810)

Unified Diff: pkg/compiler/lib/src/ssa/types_propagation.dart

Issue 2275853002: Protect types_propagation receiver type strengthening against many users. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: rebase Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/compiler/lib/src/ssa/nodes.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/ssa/types_propagation.dart
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index 756417621fe38ddd4cb6ae024aacc2d4ad1f5ee2..298d928f756c1df1e6c35382004fc0a8cd041a5c 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -361,31 +361,47 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
TypeMask receiverType = receiver.instructionType;
instruction.mask = receiverType;
- // Try to specialize the receiver after this call.
- if (receiver.dominatedUsers(instruction).length != 1 &&
- !instruction.selector.isClosureCall) {
- TypeMask newType = compiler.world.allFunctions
- .receiverType(instruction.selector, instruction.mask);
- newType = newType.intersection(receiverType, classWorld);
+ // Try to specialize the receiver after this call by instering a refinement
+ // node (HTypeKnown). There are two potentially expensive tests - are there
+ // any uses of the receiver dominated by and following this call?, and what
+ // is the refined type? The first is expensive if the receiver has many
+ // uses, the second is expensive if many classes implement the selector. So
+ // we try to do the least expensive test first.
+ const int _MAX_QUICK_USERS = 50;
+ if (!instruction.selector.isClosureCall) {
+ TypeMask newType;
+ TypeMask computeNewType() {
+ newType = compiler.world.allFunctions
+ .receiverType(instruction.selector, instruction.mask);
+ newType = newType.intersection(receiverType, classWorld);
+ return newType;
+ }
+
var next = instruction.next;
if (next is HTypeKnown && next.checkedInput == receiver) {
- // We already have refined [receiver]. We still update the
- // type of the [HTypeKnown] instruction because it may have
- // been refined with a correct type at the time, but
- // incorrect now.
- if (next.instructionType != newType) {
+ // On a previous pass or iteration we already refined [receiver] by
+ // inserting a [HTypeKnown] instruction. That replaced several dominated
+ // uses with the refinement. We update the type of the [HTypeKnown]
+ // instruction because it may have been refined with a correct type at
+ // the time, but incorrect now.
+ if (next.instructionType != computeNewType()) {
next.knownType = next.instructionType = newType;
addDependentInstructionsToWorkList(next);
}
- } else if (newType != receiverType) {
- // Insert a refinement node after the call and update all
- // users dominated by the call to use that node instead of
- // [receiver].
- HTypeKnown converted =
- new HTypeKnown.witnessed(newType, receiver, instruction);
- instruction.block.addBefore(instruction.next, converted);
- receiver.replaceAllUsersDominatedBy(converted.next, converted);
- addDependentInstructionsToWorkList(converted);
+ } else {
+ bool hasCandidates() => receiver.dominatedUsers(instruction).length > 1;
+
+ if ((receiver.usedBy.length <= _MAX_QUICK_USERS)
+ ? (hasCandidates() && computeNewType() != receiverType)
+ : (computeNewType() != receiverType && hasCandidates())) {
+ // Insert a refinement node after the call and update all users
+ // dominated by the call to use that node instead of [receiver].
+ HTypeKnown converted =
+ new HTypeKnown.witnessed(newType, receiver, instruction);
+ instruction.block.addBefore(instruction.next, converted);
+ receiver.replaceAllUsersDominatedBy(converted.next, converted);
+ addDependentInstructionsToWorkList(converted);
+ }
}
}
« no previous file with comments | « pkg/compiler/lib/src/ssa/nodes.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698