| 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 717bc066de9e57009f9b8ca12f1e1c682cae61b2..b84a3786c9f7e2776b3731a97ca3d1d63889649b 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
|
| @@ -466,10 +466,9 @@ abstract class IrBuilder {
|
| /// closure fields in order to access the receiver from the enclosing method.
|
| ir.Primitive buildThis();
|
|
|
| - /// Creates a type test or type cast of [value] against [type].
|
| - ir.Primitive buildTypeOperator(ir.Primitive value,
|
| - DartType type,
|
| - {bool isTypeTest});
|
| + /// In JS-mode, gets an interceptor for [value].
|
| + /// In Dart-mode, simply returns [value].
|
| + ir.Primitive buildGetInterceptor(ir.Primitive value);
|
|
|
| // TODO(johnniwinther): Make these field final and remove the default values
|
| // when [IrBuilder] is a property of [IrBuilderVisitor] instead of a mixin.
|
| @@ -1802,6 +1801,7 @@ 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,23 +1848,24 @@ abstract class IrBuilder {
|
| ir.Continuation elseContinuation = new ir.Continuation([]);
|
| elseContinuation.body = catchBody;
|
|
|
| - // 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;
|
| + 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));
|
| }
|
|
|
| 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;
|
|
|
| @@ -2013,6 +2014,15 @@ 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].
|
| @@ -2281,6 +2291,8 @@ class DartIrBuilder extends IrBuilder {
|
| return state.enclosingMethodThisParameter;
|
| }
|
|
|
| + ir.Primitive buildGetInterceptor(ir.Primitive value) => value;
|
| +
|
| @override
|
| ir.Primitive buildConstructorInvocation(ConstructorElement element,
|
| CallStructure callStructure,
|
| @@ -2300,15 +2312,16 @@ class DartIrBuilder extends IrBuilder {
|
| }
|
|
|
| @override
|
| - ir.Primitive buildTypeOperator(ir.Primitive value,
|
| + ir.Primitive buildTypeOperator(ir.Primitive receiver,
|
| DartType type,
|
| - {bool isTypeTest}) {
|
| + {bool isTypeTest: false,
|
| + bool isNotCheck: false}) {
|
| assert(isOpen);
|
| assert(isTypeTest != null);
|
| + assert(!isNotCheck || isTypeTest);
|
| ir.Primitive check = _continueWithExpression(
|
| - (k) => new ir.TypeOperator(value, type,
|
| - const <ir.Primitive>[], k, isTypeTest: isTypeTest));
|
| - return check;
|
| + (k) => new ir.TypeOperator(receiver, type, k, isTypeTest: isTypeTest));
|
| + return isNotCheck ? buildNegation(check) : check;
|
| }
|
| }
|
|
|
| @@ -2545,6 +2558,10 @@ 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));
|
| @@ -2619,8 +2636,6 @@ 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';
|
| @@ -2665,33 +2680,21 @@ class JsIrBuilder extends IrBuilder {
|
| }
|
|
|
| @override
|
| - ir.Primitive buildTypeOperator(ir.Primitive value,
|
| + ir.Primitive buildTypeOperator(ir.Primitive receiver,
|
| DartType type,
|
| - {bool isTypeTest}) {
|
| + {bool isTypeTest: false,
|
| + bool isNotCheck: false}) {
|
| assert(isOpen);
|
| assert(isTypeTest != null);
|
| - 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();
|
| - }
|
| + assert(!isNotCheck || isTypeTest);
|
| + ir.Primitive interceptor =
|
| + addPrimitive(new ir.Interceptor(receiver, program.interceptedClasses));
|
| ir.Primitive check = _continueWithExpression(
|
| - (k) => new ir.TypeOperator(value,
|
| - type, typeArguments, k, isTypeTest: isTypeTest));
|
| - return check;
|
| + (k) => new ir.TypeOperator(interceptor, type, k,
|
| + isTypeTest: isTypeTest));
|
| + return isNotCheck ? buildNegation(check) : check;
|
| }
|
| +
|
| }
|
|
|
|
|
|
|