| Index: pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
|
| diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
|
| index b84a3786c9f7e2776b3731a97ca3d1d63889649b..717bc066de9e57009f9b8ca12f1e1c682cae61b2 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
|
| @@ -466,9 +466,10 @@ abstract class IrBuilder {
|
| /// closure fields in order to access the receiver from the enclosing method.
|
| ir.Primitive buildThis();
|
|
|
| - /// In JS-mode, gets an interceptor for [value].
|
| - /// In Dart-mode, simply returns [value].
|
| - ir.Primitive buildGetInterceptor(ir.Primitive value);
|
| + /// Creates a type test or type cast of [value] against [type].
|
| + ir.Primitive buildTypeOperator(ir.Primitive value,
|
| + DartType type,
|
| + {bool isTypeTest});
|
|
|
| // TODO(johnniwinther): Make these field final and remove the default values
|
| // when [IrBuilder] is a property of [IrBuilderVisitor] instead of a mixin.
|
| @@ -1801,7 +1802,6 @@ abstract class IrBuilder {
|
| // handler parameter.
|
| ir.Parameter exceptionParameter =
|
| new ir.Parameter(catchClauseInfos.first.exceptionVariable);
|
| - ir.Primitive exceptionInterceptor = new ir.Parameter(null);
|
| LocalVariableElement traceVariable;
|
| CatchClauseInfo catchAll;
|
| for (int i = 0; i < catchClauseInfos.length; ++i) {
|
| @@ -1848,24 +1848,23 @@ abstract class IrBuilder {
|
| ir.Continuation elseContinuation = new ir.Continuation([]);
|
| elseContinuation.body = catchBody;
|
|
|
| - ir.Parameter typeMatches = new ir.Parameter(null);
|
| - ir.Continuation checkType = new ir.Continuation([typeMatches]);
|
| - checkType.body =
|
| - new ir.LetCont.many([thenContinuation, elseContinuation],
|
| - new ir.Branch(new ir.IsTrue(typeMatches),
|
| - thenContinuation,
|
| - elseContinuation));
|
| - catchBody =
|
| - new ir.LetCont(checkType,
|
| - new ir.TypeOperator(exceptionInterceptor, clause.type, checkType,
|
| - isTypeTest: true));
|
| + // Build the type test guarding this clause. We can share the environment
|
| + // with the nested builder because this part cannot mutate it.
|
| + IrBuilder checkBuilder = catchBuilder.makeDelimitedBuilder(environment);
|
| + ir.Primitive typeMatches =
|
| + checkBuilder.buildTypeOperator(exceptionParameter,
|
| + clause.type,
|
| + isTypeTest: true);
|
| + checkBuilder.add(new ir.LetCont.many([thenContinuation, elseContinuation],
|
| + new ir.Branch(new ir.IsTrue(typeMatches),
|
| + thenContinuation,
|
| + elseContinuation)));
|
| + catchBody = checkBuilder._root;
|
| }
|
|
|
| List<ir.Parameter> catchParameters =
|
| <ir.Parameter>[exceptionParameter, traceParameter];
|
| ir.Continuation catchContinuation = new ir.Continuation(catchParameters);
|
| - catchBuilder.buildGetInterceptor(exceptionParameter)
|
| - .substituteFor(exceptionInterceptor);
|
| catchBuilder.add(catchBody);
|
| catchContinuation.body = catchBuilder._root;
|
|
|
| @@ -2014,15 +2013,6 @@ abstract class IrBuilder {
|
| return resultParameter;
|
| }
|
|
|
| - /// Creates a type test or type cast of [receiver] against [type].
|
| - ///
|
| - /// Set [isTypeTest] to `true` to create a type test and furthermore set
|
| - /// [isNotCheck] to `true` to create a negated type test.
|
| - ir.Primitive buildTypeOperator(ir.Primitive receiver,
|
| - DartType type,
|
| - {bool isTypeTest: false,
|
| - bool isNotCheck: false});
|
| -
|
| /// Create a lazy and/or expression. [leftValue] is the value of the left
|
| /// operand and [buildRightValue] is called to process the value of the right
|
| /// operand in the context of its own [IrBuilder].
|
| @@ -2291,8 +2281,6 @@ class DartIrBuilder extends IrBuilder {
|
| return state.enclosingMethodThisParameter;
|
| }
|
|
|
| - ir.Primitive buildGetInterceptor(ir.Primitive value) => value;
|
| -
|
| @override
|
| ir.Primitive buildConstructorInvocation(ConstructorElement element,
|
| CallStructure callStructure,
|
| @@ -2312,16 +2300,15 @@ class DartIrBuilder extends IrBuilder {
|
| }
|
|
|
| @override
|
| - ir.Primitive buildTypeOperator(ir.Primitive receiver,
|
| + ir.Primitive buildTypeOperator(ir.Primitive value,
|
| DartType type,
|
| - {bool isTypeTest: false,
|
| - bool isNotCheck: false}) {
|
| + {bool isTypeTest}) {
|
| assert(isOpen);
|
| assert(isTypeTest != null);
|
| - assert(!isNotCheck || isTypeTest);
|
| ir.Primitive check = _continueWithExpression(
|
| - (k) => new ir.TypeOperator(receiver, type, k, isTypeTest: isTypeTest));
|
| - return isNotCheck ? buildNegation(check) : check;
|
| + (k) => new ir.TypeOperator(value, type,
|
| + const <ir.Primitive>[], k, isTypeTest: isTypeTest));
|
| + return check;
|
| }
|
| }
|
|
|
| @@ -2558,10 +2545,6 @@ class JsIrBuilder extends IrBuilder {
|
| return state.thisParameter;
|
| }
|
|
|
| - ir.Primitive buildGetInterceptor(ir.Primitive value) {
|
| - return addPrimitive(new ir.Interceptor(value, program.interceptedClasses));
|
| - }
|
| -
|
| @override
|
| ir.Primitive buildSuperFieldGet(FieldElement target) {
|
| return addPrimitive(new ir.GetField(buildThis(), target));
|
| @@ -2636,6 +2619,8 @@ class JsIrBuilder extends IrBuilder {
|
| arguments.add(value);
|
| });
|
| return addPrimitive(new ir.TypeExpression(type, arguments));
|
| + } else if (type is DynamicType) {
|
| + return buildNullConstant();
|
| } else {
|
| // TypedefType can reach here, and possibly other things.
|
| throw 'unimplemented translation of type expression $type';
|
| @@ -2680,21 +2665,33 @@ class JsIrBuilder extends IrBuilder {
|
| }
|
|
|
| @override
|
| - ir.Primitive buildTypeOperator(ir.Primitive receiver,
|
| + ir.Primitive buildTypeOperator(ir.Primitive value,
|
| DartType type,
|
| - {bool isTypeTest: false,
|
| - bool isNotCheck: false}) {
|
| + {bool isTypeTest}) {
|
| assert(isOpen);
|
| assert(isTypeTest != null);
|
| - assert(!isNotCheck || isTypeTest);
|
| - ir.Primitive interceptor =
|
| - addPrimitive(new ir.Interceptor(receiver, program.interceptedClasses));
|
| + if (isTypeTest) {
|
| + // The TypeOperator node does not allow the Object, dynamic, and Null types,
|
| + // because the null value satisfies them. These must be handled here.
|
| + if (type.isObject || type.isDynamic) {
|
| + // `x is Object` and `x is dynamic` are always true, even if x is null.
|
| + return buildBooleanConstant(true);
|
| + }
|
| + if (type is InterfaceType && type.element == program.nullClass) {
|
| + // `x is Null` is true if and only if x is null.
|
| + return addPrimitive(new ir.Identical(value, buildNullConstant()));
|
| + }
|
| + }
|
| + // Null cannot not satisfy the check. Use a standard subtype check.
|
| + List<ir.Primitive> typeArguments = const <ir.Primitive>[];
|
| + if (type is GenericType && type.typeArguments.isNotEmpty) {
|
| + typeArguments = type.typeArguments.map(buildTypeExpression).toList();
|
| + }
|
| ir.Primitive check = _continueWithExpression(
|
| - (k) => new ir.TypeOperator(interceptor, type, k,
|
| - isTypeTest: isTypeTest));
|
| - return isNotCheck ? buildNegation(check) : check;
|
| + (k) => new ir.TypeOperator(value,
|
| + type, typeArguments, k, isTypeTest: isTypeTest));
|
| + return check;
|
| }
|
| -
|
| }
|
|
|
|
|
|
|