Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 81c3208

Browse files
fishythefishcommit-bot@chromium.org
authored andcommitted
[dart2js] Special case null is T.
Change-Id: Iec5212db2d4493797257753f9eaa63799d047253 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/138574 Reviewed-by: Sigmund Cherem <[email protected]> Commit-Queue: Mayank Patke <[email protected]>
1 parent de0fcd7 commit 81c3208

29 files changed

+332
-251
lines changed

pkg/compiler/lib/src/common_elements.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,9 @@ abstract class CommonElements {
513513
FunctionEntity get generalAsCheckImplementation;
514514
FunctionEntity get generalTypeCheckImplementation;
515515

516+
FunctionEntity get specializedIsObject;
517+
FunctionEntity get specializedAsObject;
518+
FunctionEntity get specializedCheckObject;
516519
FunctionEntity get specializedIsTop;
517520
FunctionEntity get specializedAsTop;
518521
FunctionEntity get specializedIsBool;
@@ -1976,6 +1979,21 @@ class CommonElementsImpl
19761979
_generalTypeCheckImplementation ??=
19771980
_findRtiFunction('_generalTypeCheckImplementation');
19781981

1982+
FunctionEntity _specializedIsObject;
1983+
@override
1984+
FunctionEntity get specializedIsObject =>
1985+
_specializedIsObject ??= _findRtiFunction('_isObject');
1986+
1987+
FunctionEntity _specializedAsObject;
1988+
@override
1989+
FunctionEntity get specializedAsObject =>
1990+
_specializedAsObject ??= _findRtiFunction('_asObject');
1991+
1992+
FunctionEntity _specializedCheckObject;
1993+
@override
1994+
FunctionEntity get specializedCheckObject =>
1995+
_specializedCheckObject ??= _findRtiFunction('_checkObject');
1996+
19791997
@override
19801998
FunctionEntity get specializedIsTop => _findRtiFunction('_isTop');
19811999

pkg/compiler/lib/src/inferrer/type_graph_nodes.dart

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2248,42 +2248,36 @@ abstract class TypeInformationVisitor<T> {
22482248
T visitYieldTypeInformation(YieldTypeInformation info);
22492249
}
22502250

2251-
AbstractValue _intersection(AbstractValue type, AbstractValue otherType,
2252-
AbstractValueDomain abstractValueDomain, bool isNullable) {
2253-
if (isNullable) {
2254-
otherType = abstractValueDomain.includeNull(otherType);
2255-
}
2256-
return type == null
2257-
? otherType
2258-
: abstractValueDomain.intersection(type, otherType);
2259-
}
2260-
22612251
AbstractValue _narrowType(
22622252
JClosedWorld closedWorld, AbstractValue type, DartType annotation,
22632253
{bool isNullable: true}) {
2264-
annotation = annotation.withoutNullability;
22652254
AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
2255+
2256+
AbstractValue _intersectionWith(AbstractValue otherType) {
2257+
if (isNullable) {
2258+
otherType = abstractValueDomain.includeNull(otherType);
2259+
}
2260+
return type == null
2261+
? otherType
2262+
: abstractValueDomain.intersection(type, otherType);
2263+
}
2264+
22662265
// TODO(joshualitt): FutureOrType, TypeVariableType, and FunctionTypeVariable
22672266
// can be narrowed.
2267+
// TODO(fishythefish): Use nullability.
2268+
annotation = annotation.withoutNullability;
22682269
if (closedWorld.dartTypes.isTopType(annotation) ||
2269-
annotation is VoidType ||
2270-
annotation is NeverType ||
22712270
annotation is FutureOrType ||
22722271
annotation is TypeVariableType ||
22732272
annotation is FunctionTypeVariable) {
22742273
return type;
2274+
} else if (annotation is NeverType) {
2275+
return _intersectionWith(abstractValueDomain.emptyType);
22752276
} else if (annotation is InterfaceType) {
2276-
if (annotation.element == closedWorld.commonElements.objectClass) {
2277-
return type;
2278-
}
2279-
return _intersection(
2280-
type,
2281-
abstractValueDomain.createNonNullSubtype(annotation.element),
2282-
abstractValueDomain,
2283-
isNullable);
2277+
return _intersectionWith(
2278+
abstractValueDomain.createNonNullSubtype(annotation.element));
22842279
} else if (annotation is FunctionType) {
2285-
return _intersection(type, closedWorld.abstractValueDomain.functionType,
2286-
abstractValueDomain, isNullable);
2280+
return _intersectionWith(abstractValueDomain.functionType);
22872281
} else {
22882282
throw 'Unexpected annotation type $annotation';
22892283
}

pkg/compiler/lib/src/inferrer/type_system.dart

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -317,43 +317,42 @@ class TypeSystem {
317317
/// type.
318318
TypeInformation narrowType(TypeInformation type, DartType annotation,
319319
{bool isNullable: true}) {
320+
TypeInformation _narrowTo(AbstractValue otherType) {
321+
if (_abstractValueDomain.isExact(type.type).isDefinitelyTrue) return type;
322+
if (isNullable) {
323+
otherType = _abstractValueDomain.includeNull(otherType);
324+
}
325+
TypeInformation newType =
326+
new NarrowTypeInformation(_abstractValueDomain, type, otherType);
327+
allocatedTypes.add(newType);
328+
return newType;
329+
}
330+
331+
// TODO(fishythefish): Use nullability.
320332
annotation = annotation.withoutNullability;
321-
AbstractValue otherType;
322333
if (annotation is VoidType) return type;
323334
if (_closedWorld.dartTypes.isTopType(annotation)) {
324335
if (isNullable) return type;
325336
// If the input is already narrowed to be not-null, there is no value
326337
// in adding another narrowing node.
327338
if (_isNonNullNarrow(type)) return type;
328-
otherType = _abstractValueDomain.excludeNull(dynamicType.type);
339+
return _narrowTo(_abstractValueDomain.excludeNull(dynamicType.type));
340+
} else if (annotation is NeverType) {
341+
return _narrowTo(_abstractValueDomain.emptyType);
329342
} else if (annotation is InterfaceType) {
330-
InterfaceType interface = annotation;
331-
if (interface.element == _closedWorld.commonElements.objectClass) {
332-
if (isNullable) return type;
333-
if (_isNonNullNarrow(type)) return type;
334-
otherType = _abstractValueDomain.excludeNull(dynamicType.type);
335-
} else {
336-
otherType =
337-
_abstractValueDomain.createNonNullSubtype(interface.element);
338-
}
343+
return _narrowTo(
344+
_abstractValueDomain.createNonNullSubtype(annotation.element));
339345
} else if (annotation is FunctionType) {
340-
otherType = functionType.type;
346+
return _narrowTo(functionType.type);
341347
} else if (annotation is FutureOrType) {
342348
// TODO(johnniwinther): Support narrowing of FutureOr.
343349
return type;
344-
} else {
345-
assert(annotation is TypeVariableType);
350+
} else if (annotation is TypeVariableType) {
346351
// TODO(ngeoffray): Narrow to bound.
347352
return type;
353+
} else {
354+
throw 'Unexpected annotation type $annotation';
348355
}
349-
if (isNullable) {
350-
otherType = _abstractValueDomain.includeNull(otherType);
351-
}
352-
if (_abstractValueDomain.isExact(type.type).isDefinitelyTrue) return type;
353-
TypeInformation newType =
354-
new NarrowTypeInformation(_abstractValueDomain, type, otherType);
355-
allocatedTypes.add(newType);
356-
return newType;
357356
}
358357

359358
ParameterTypeInformation getInferredTypeOfParameter(Local parameter) {

pkg/compiler/lib/src/js_backend/backend_impact.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,9 @@ class BackendImpacts {
832832
_commonElements.specializedIsTop,
833833
_commonElements.specializedAsTop,
834834
// no specializedCheckTop
835+
_commonElements.specializedIsObject,
836+
_commonElements.specializedAsObject,
837+
_commonElements.specializedCheckObject,
835838
], globalClasses: [
836839
_commonElements.closureClass, // instanceOrFunctionType uses this.
837840
])

pkg/compiler/lib/src/js_backend/namer.dart

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2599,16 +2599,6 @@ abstract class ModularNamer {
25992599
return runtimeTypeName(_commonElements.jsJavaScriptFunctionClass);
26002600
case JsGetName.FUTURE_CLASS_TYPE_NAME:
26012601
return runtimeTypeName(_commonElements.futureClass);
2602-
case JsGetName.BOOL_RECIPE:
2603-
return runtimeTypeName(_commonElements.boolClass);
2604-
case JsGetName.DOUBLE_RECIPE:
2605-
return runtimeTypeName(_commonElements.doubleClass);
2606-
case JsGetName.INT_RECIPE:
2607-
return runtimeTypeName(_commonElements.intClass);
2608-
case JsGetName.NUM_RECIPE:
2609-
return runtimeTypeName(_commonElements.numClass);
2610-
case JsGetName.STRING_RECIPE:
2611-
return runtimeTypeName(_commonElements.stringClass);
26122602
case JsGetName.RTI_FIELD_IS:
26132603
return instanceFieldPropertyName(_commonElements.rtiIsField);
26142604
default:

pkg/compiler/lib/src/ssa/nodes.dart

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4543,8 +4543,9 @@ class HIsTest extends HInstruction {
45434543
HInstruction get typeInput => inputs[0];
45444544
HInstruction get checkedInput => inputs[1];
45454545

4546-
AbstractBool evaluate(JClosedWorld closedWorld) =>
4547-
_isTestResult(checkedInput, dartType, checkedAbstractValue, closedWorld);
4546+
AbstractBool evaluate(JClosedWorld closedWorld, bool useNullSafety) =>
4547+
_isTestResult(checkedInput, dartType, checkedAbstractValue, closedWorld,
4548+
useNullSafety);
45484549

45494550
@override
45504551
accept(HVisitor visitor) => visitor.visitIsTest(this);
@@ -4577,8 +4578,9 @@ class HIsTestSimple extends HInstruction {
45774578

45784579
HInstruction get checkedInput => inputs[0];
45794580

4580-
AbstractBool evaluate(JClosedWorld closedWorld) =>
4581-
_isTestResult(checkedInput, dartType, checkedAbstractValue, closedWorld);
4581+
AbstractBool evaluate(JClosedWorld closedWorld, bool useNullSafety) =>
4582+
_isTestResult(checkedInput, dartType, checkedAbstractValue, closedWorld,
4583+
useNullSafety);
45824584

45834585
@override
45844586
accept(HVisitor visitor) => visitor.visitIsTestSimple(this);
@@ -4596,11 +4598,36 @@ class HIsTestSimple extends HInstruction {
45964598
String toString() => 'HIsTestSimple()';
45974599
}
45984600

4599-
AbstractBool _isTestResult(HInstruction expression, DartType dartType,
4600-
AbstractValueWithPrecision checkedAbstractValue, JClosedWorld closedWorld) {
4601+
AbstractBool _isTestResult(
4602+
HInstruction expression,
4603+
DartType dartType,
4604+
AbstractValueWithPrecision checkedAbstractValue,
4605+
JClosedWorld closedWorld,
4606+
bool useNullSafety) {
46014607
AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
46024608
AbstractValue subsetType = expression.instructionType;
46034609
AbstractValue supersetType = checkedAbstractValue.abstractValue;
4610+
4611+
if (useNullSafety &&
4612+
expression.isNull(abstractValueDomain).isDefinitelyTrue) {
4613+
if (closedWorld.dartTypes.isTopType(dartType) ||
4614+
dartType is NullableType ||
4615+
dartType.isNull) {
4616+
return AbstractBool.True;
4617+
}
4618+
if (dartType is TypeVariableType || dartType is FunctionTypeVariable) {
4619+
return AbstractBool.Maybe;
4620+
}
4621+
if (dartType is LegacyType) {
4622+
DartType baseType = dartType.baseType;
4623+
if (baseType is NeverType) return AbstractBool.True;
4624+
if (baseType is TypeVariableType || baseType is FunctionTypeVariable) {
4625+
return AbstractBool.Maybe;
4626+
}
4627+
}
4628+
return AbstractBool.False;
4629+
}
4630+
46044631
if (checkedAbstractValue.isPrecise &&
46054632
abstractValueDomain.isIn(subsetType, supersetType).isDefinitelyTrue) {
46064633
return AbstractBool.True;

pkg/compiler/lib/src/ssa/optimize.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2123,6 +2123,9 @@ class SsaInstructionSimplifier extends HBaseVisitor
21232123

21242124
@override
21252125
HInstruction visitAsCheck(HAsCheck node) {
2126+
// TODO(fishythefish): Correctly constant fold `null as T` (also in
2127+
// [visitAsCheckSimple]) when running with strong NNBD. We might get this
2128+
// for free if nullability is precisely propagated to the typemasks.
21262129
if (node.isRedundant(_closedWorld)) return node.checkedInput;
21272130

21282131
// See if this check can be lowered to a simple one.
@@ -2153,7 +2156,7 @@ class SsaInstructionSimplifier extends HBaseVisitor
21532156

21542157
@override
21552158
HInstruction visitIsTest(HIsTest node) {
2156-
AbstractBool result = node.evaluate(_closedWorld);
2159+
AbstractBool result = node.evaluate(_closedWorld, _options.useNullSafety);
21572160
if (result.isDefinitelyFalse) {
21582161
return _graph.addConstantBool(false, _closedWorld);
21592162
}
@@ -2199,7 +2202,7 @@ class SsaInstructionSimplifier extends HBaseVisitor
21992202

22002203
@override
22012204
HInstruction visitIsTestSimple(HIsTestSimple node) {
2202-
AbstractBool result = node.evaluate(_closedWorld);
2205+
AbstractBool result = node.evaluate(_closedWorld, _options.useNullSafety);
22032206
if (result.isDefinitelyFalse) {
22042207
return _graph.addConstantBool(false, _closedWorld);
22052208
}

0 commit comments

Comments
 (0)