From 03e504e5fa51731ebda1677d05f4d4702a3e9521 Mon Sep 17 00:00:00 2001 From: Stephen Adams Date: Tue, 12 May 2020 18:05:04 +0000 Subject: [PATCH] [dart2js] Specialize strong 'is Object' - o is Object --> o != null. - Avoid specializing 'is Object' to instanceof. Change-Id: Id882666d547ee2e06c6b92dec5a8070302dd9415 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/147686 Reviewed-by: Joshua Litt Commit-Queue: Stephen Adams --- .../lib/src/js_backend/specialized_checks.dart | 17 +++++++++++++---- pkg/compiler/lib/src/ssa/codegen.dart | 7 ++++--- pkg/compiler/lib/src/ssa/optimize.dart | 9 +++++++-- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/pkg/compiler/lib/src/js_backend/specialized_checks.dart b/pkg/compiler/lib/src/js_backend/specialized_checks.dart index ca83fd16e57..25156d2bdf1 100644 --- a/pkg/compiler/lib/src/js_backend/specialized_checks.dart +++ b/pkg/compiler/lib/src/js_backend/specialized_checks.dart @@ -12,7 +12,8 @@ import '../universe/class_hierarchy.dart' show ClassHierarchy; import '../world.dart' show JClosedWorld; enum IsTestSpecialization { - null_, + isNull, + notNull, string, bool, num, @@ -27,8 +28,7 @@ class SpecializedChecks { if (dartType is LegacyType) { DartType base = dartType.baseType; // `Never*` accepts only `null`. - if (base is NeverType) return IsTestSpecialization.null_; - // TODO(sra): Handle strong checking 'x is Object' --> `x != null`. + if (base is NeverType) return IsTestSpecialization.isNull; // `Object*` is top and should be handled by constant folding. if (base.isObject) return null; return _findIsTestSpecialization(base, graph, closedWorld); @@ -44,7 +44,7 @@ class SpecializedChecks { if (element == commonElements.nullClass || element == commonElements.jsNullClass) { - return IsTestSpecialization.null_; + return IsTestSpecialization.isNull; } if (element == commonElements.jsStringClass || @@ -73,6 +73,9 @@ class SpecializedChecks { } DartTypes dartTypes = closedWorld.dartTypes; + // Top types (here it could be Object in non-NNBD mode) should be constant + // folded outside the specializer. This test protects logic below. + if (dartTypes.isTopType(dartType)) return null; ElementEnvironment elementEnvironment = closedWorld.elementEnvironment; if (!dartTypes.isSubtype( elementEnvironment.getClassInstantiationToBounds(element), @@ -84,6 +87,11 @@ class SpecializedChecks { return IsTestSpecialization.arrayTop; } + if (dartType.isObject) { + assert(!dartTypes.isTopType(dartType)); // Checked above. + return IsTestSpecialization.notNull; + } + ClassHierarchy classHierarchy = closedWorld.classHierarchy; InterceptorData interceptorData = closedWorld.interceptorData; OutputUnitData outputUnitData = closedWorld.outputUnitData; @@ -92,6 +100,7 @@ class SpecializedChecks { !interceptorData.isInterceptedClass(element) && outputUnitData.hasOnlyNonDeferredImportPathsToClass( graph.element, element)) { + assert(!dartType.isObject); // Checked above. return IsTestSpecialization.instanceof; } } diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart index 781976ae691..db213caae65 100644 --- a/pkg/compiler/lib/src/ssa/codegen.dart +++ b/pkg/compiler/lib/src/ssa/codegen.dart @@ -3492,9 +3492,10 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { js.Expression test; switch (node.specialization) { - case IsTestSpecialization.null_: - // This case should be lowered to [HIdentity] during optimization. - test = js.Binary(relation, value, js.LiteralNull()); + case IsTestSpecialization.isNull: + case IsTestSpecialization.notNull: + // These cases should be lowered using [HIdentity] during optimization. + failedAt(node, 'Missing lowering'); break; case IsTestSpecialization.string: diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart index cce21ad75e3..8b38f2f575c 100644 --- a/pkg/compiler/lib/src/ssa/optimize.dart +++ b/pkg/compiler/lib/src/ssa/optimize.dart @@ -2176,12 +2176,17 @@ class SsaInstructionSimplifier extends HBaseVisitor SpecializedChecks.findIsTestSpecialization( dartType, _graph, _closedWorld); - if (specialization == IsTestSpecialization.null_) { - return HIdentity( + if (specialization == IsTestSpecialization.isNull || + specialization == IsTestSpecialization.notNull) { + HInstruction nullTest = HIdentity( node.checkedInput, _graph.addConstantNull(_closedWorld), null, _abstractValueDomain.boolType); + if (specialization == IsTestSpecialization.isNull) return nullTest; + nullTest.sourceInformation = node.sourceInformation; + node.block.addBefore(node, nullTest); + return HNot(nullTest, _abstractValueDomain.boolType); } if (specialization != null) {