Index: pkg/compiler/lib/src/ssa/builder.dart |
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart |
index abd5e29594869b5486b149f52854b583ddcb859b..aa3b7f098766afe850e43dfd89691adfbd52c189 100644 |
--- a/pkg/compiler/lib/src/ssa/builder.dart |
+++ b/pkg/compiler/lib/src/ssa/builder.dart |
@@ -1006,6 +1006,9 @@ class SsaBuilder extends ResolvedVisitor { |
// implementation/declaration distinction. |
Element get sourceElement => sourceElementStack.last; |
+ bool get _checkOrTrustTypes => |
+ compiler.enableTypeAssertions || compiler.trustTypeAnnotations; |
+ |
HBasicBlock addNewBlock() { |
HBasicBlock block = graph.addNewBlock(); |
// If adding a new block during building of an expression, it is due to |
@@ -1483,8 +1486,7 @@ class SsaBuilder extends ResolvedVisitor { |
// If the method is intercepted, we want the actual receiver |
// to be the first parameter. |
graph.entry.addBefore(graph.entry.last, parameter); |
- HInstruction value = |
- potentiallyCheckType(parameter, field.type); |
+ HInstruction value = potentiallyCheckOrTrustType(parameter, field.type); |
add(new HFieldSet(field, thisInstruction, value)); |
return closeFunction(); |
} |
@@ -1495,7 +1497,7 @@ class SsaBuilder extends ResolvedVisitor { |
assert(variable.initializer != null); |
visit(variable.initializer); |
HInstruction value = pop(); |
- value = potentiallyCheckType(value, variable.type); |
+ value = potentiallyCheckOrTrustType(value, variable.type); |
closeAndGotoExit(new HReturn(value)); |
return closeFunction(); |
} |
@@ -1658,12 +1660,12 @@ class SsaBuilder extends ResolvedVisitor { |
* function. |
*/ |
void potentiallyCheckInlinedParameterTypes(FunctionElement function) { |
- if (!compiler.enableTypeAssertions) return; |
+ if (!_checkOrTrustTypes) return; |
FunctionSignature signature = function.functionSignature; |
signature.orderedForEachParameter((ParameterElement parameter) { |
HInstruction argument = localsHandler.readLocal(parameter); |
- potentiallyCheckType(argument, parameter.type); |
+ potentiallyCheckOrTrustType(argument, parameter.type); |
}); |
} |
@@ -1974,7 +1976,7 @@ class SsaBuilder extends ResolvedVisitor { |
} else { |
fields.add(member); |
DartType type = localsHandler.substInContext(member.type); |
- constructorArguments.add(potentiallyCheckType(value, type)); |
+ constructorArguments.add(potentiallyCheckOrTrustType(value, type)); |
} |
}, |
includeSuperAndInjectedMembers: true); |
@@ -2219,7 +2221,7 @@ class SsaBuilder extends ResolvedVisitor { |
// |
// Only the final target is allowed to check for the argument types. |
newParameter = |
- potentiallyCheckType(newParameter, parameterElement.type); |
+ potentiallyCheckOrTrustType(newParameter, parameterElement.type); |
} |
localsHandler.directLocals[parameterElement] = newParameter; |
}); |
@@ -2296,25 +2298,43 @@ class SsaBuilder extends ResolvedVisitor { |
} |
} |
- HInstruction potentiallyBuildTypeHint(HInstruction original, DartType type) { |
- if (!compiler.trustTypeAnnotations || type == null) return original; |
+ HInstruction _trustType(HInstruction original, DartType type) { |
+ assert(compiler.trustTypeAnnotations); |
+ assert(type != null); |
type = localsHandler.substInContext(type); |
+ type = type.unalias(compiler); |
+ if (type.isDynamic) return original; |
if (!type.isInterfaceType) return original; |
- TypeMask mask = new TypeMask.subtype(type.element, compiler.world); |
- var result = new HTypeKnown.pinned(mask, original); |
- return result; |
+ // The type element is either a class or the void element. |
+ Element element = type.element; |
+ if (element == compiler.objectClass) return original; |
+ TypeMask mask = new TypeMask.subtype(element, compiler.world); |
+ return new HTypeKnown.pinned(mask, original); |
} |
- HInstruction potentiallyCheckType(HInstruction original, DartType type, |
- { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { |
- if (!compiler.enableTypeAssertions) return original; |
+ HInstruction _checkType(HInstruction original, DartType type, int kind) { |
+ assert(compiler.enableTypeAssertions); |
+ assert(type != null); |
type = localsHandler.substInContext(type); |
HInstruction other = buildTypeConversion(original, type, kind); |
- if (other != original) add(other); |
registry.registerIsCheck(type); |
return other; |
} |
+ HInstruction potentiallyCheckOrTrustType(HInstruction original, DartType type, |
+ { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { |
+ if (type == null) return original; |
+ HInstruction checkedOrTrusted = original; |
+ if (compiler.trustTypeAnnotations) { |
+ checkedOrTrusted = _trustType(original, type); |
+ } else if (compiler.enableTypeAssertions) { |
+ checkedOrTrusted = _checkType(original, type, kind); |
+ } |
+ if (checkedOrTrusted == original) return original; |
+ add(checkedOrTrusted); |
+ return checkedOrTrusted; |
+ } |
+ |
void assertIsSubtype(ast.Node node, DartType subtype, DartType supertype, |
String message) { |
HInstruction subtypeInstruction = |
@@ -2358,8 +2378,8 @@ class SsaBuilder extends ResolvedVisitor { |
HInstruction popBoolified() { |
HInstruction value = pop(); |
- if (compiler.enableTypeAssertions) { |
- return potentiallyCheckType( |
+ if (_checkOrTrustTypes) { |
+ return potentiallyCheckOrTrustType( |
value, |
compiler.boolClass.rawType, |
kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); |
@@ -3186,8 +3206,7 @@ class SsaBuilder extends ResolvedVisitor { |
pop(); |
} else { |
VariableElement field = element; |
- value = |
- potentiallyCheckType(value, field.type); |
+ value = potentiallyCheckOrTrustType(value, field.type); |
addWithPosition(new HStaticStore(element, value), location); |
} |
stack.add(value); |
@@ -3205,20 +3224,14 @@ class SsaBuilder extends ResolvedVisitor { |
if (value.sourceElement == null) { |
value.sourceElement = local; |
} |
- HInstruction checked = |
- potentiallyCheckType(value, local.type); |
- if (!identical(checked, value)) { |
- pop(); |
- stack.add(checked); |
- } |
- HInstruction trusted = |
- potentiallyBuildTypeHint(checked, local.type); |
- if (!identical(trusted, checked)) { |
+ HInstruction checkedOrTrusted = |
+ potentiallyCheckOrTrustType(value, local.type); |
+ if (!identical(checkedOrTrusted, value)) { |
pop(); |
- push(trusted); |
+ stack.add(checkedOrTrusted); |
} |
- localsHandler.updateLocal(local, trusted); |
+ localsHandler.updateLocal(local, checkedOrTrusted); |
} |
} |
@@ -4304,7 +4317,7 @@ class SsaBuilder extends ResolvedVisitor { |
// Finally, if we called a redirecting factory constructor, check the type. |
if (isRedirected) { |
- HInstruction checked = potentiallyCheckType(newInstance, type); |
+ HInstruction checked = potentiallyCheckOrTrustType(newInstance, type); |
if (checked != newInstance) { |
pop(); |
stack.add(checked); |
@@ -5042,7 +5055,7 @@ class SsaBuilder extends ResolvedVisitor { |
} else { |
visit(node.expression); |
value = pop(); |
- value = potentiallyCheckType(value, returnType); |
+ value = potentiallyCheckOrTrustType(value, returnType); |
} |
handleInTryStatement(); |