[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 <joshualitt@google.com>
Commit-Queue: Stephen Adams <sra@google.com>
This commit is contained in:
Stephen Adams 2020-05-12 18:05:04 +00:00 committed by commit-bot@chromium.org
parent 83a2b2e51d
commit 03e504e5fa
3 changed files with 24 additions and 9 deletions

View file

@ -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;
}
}

View file

@ -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:

View file

@ -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) {