Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(234)

Side by Side Diff: pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart

Issue 1161683002: dart2js cps: 'is' checks on types with type arguments. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart2js.ir_builder; 5 library dart2js.ir_builder;
6 6
7 import '../constants/constant_system.dart'; 7 import '../constants/constant_system.dart';
8 import '../constants/expressions.dart'; 8 import '../constants/expressions.dart';
9 import '../constants/values.dart' show PrimitiveConstantValue; 9 import '../constants/values.dart' show PrimitiveConstantValue;
10 import '../dart_types.dart'; 10 import '../dart_types.dart';
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 459
460 /// Reifies the value of [variable] on the current receiver object. 460 /// Reifies the value of [variable] on the current receiver object.
461 ir.Primitive buildReifyTypeVariable(TypeVariableType variable); 461 ir.Primitive buildReifyTypeVariable(TypeVariableType variable);
462 462
463 /// Creates an access to the receiver from the current (or enclosing) method. 463 /// Creates an access to the receiver from the current (or enclosing) method.
464 /// 464 ///
465 /// If inside a closure class, [buildThis] will redirect access through 465 /// If inside a closure class, [buildThis] will redirect access through
466 /// closure fields in order to access the receiver from the enclosing method. 466 /// closure fields in order to access the receiver from the enclosing method.
467 ir.Primitive buildThis(); 467 ir.Primitive buildThis();
468 468
469 /// In JS-mode, gets an interceptor for [value]. 469 /// Creates a type test or type cast of [value] against [type].
470 /// In Dart-mode, simply returns [value]. 470 ir.Primitive buildTypeOperator(ir.Primitive value,
471 ir.Primitive buildGetInterceptor(ir.Primitive value); 471 DartType type,
472 {bool isTypeTest});
472 473
473 // TODO(johnniwinther): Make these field final and remove the default values 474 // TODO(johnniwinther): Make these field final and remove the default values
474 // when [IrBuilder] is a property of [IrBuilderVisitor] instead of a mixin. 475 // when [IrBuilder] is a property of [IrBuilderVisitor] instead of a mixin.
475 476
476 final List<ir.Parameter> _parameters = <ir.Parameter>[]; 477 final List<ir.Parameter> _parameters = <ir.Parameter>[];
477 478
478 IrBuilderSharedState state; 479 IrBuilderSharedState state;
479 480
480 /// A map from variable indexes to their values. 481 /// A map from variable indexes to their values.
481 /// 482 ///
(...skipping 1312 matching lines...) Expand 10 before | Expand all | Expand 10 after
1794 catchBuilder.removeMutableVariable(variable); 1795 catchBuilder.removeMutableVariable(variable);
1795 catchBuilder.environment.update(variable, value); 1796 catchBuilder.environment.update(variable, value);
1796 } 1797 }
1797 1798
1798 // Handlers are always translated as having both exception and stack trace 1799 // Handlers are always translated as having both exception and stack trace
1799 // parameters. Multiple clauses do not have to use the same names for 1800 // parameters. Multiple clauses do not have to use the same names for
1800 // them. Choose the first of each as the name hint for the respective 1801 // them. Choose the first of each as the name hint for the respective
1801 // handler parameter. 1802 // handler parameter.
1802 ir.Parameter exceptionParameter = 1803 ir.Parameter exceptionParameter =
1803 new ir.Parameter(catchClauseInfos.first.exceptionVariable); 1804 new ir.Parameter(catchClauseInfos.first.exceptionVariable);
1804 ir.Primitive exceptionInterceptor = new ir.Parameter(null);
1805 LocalVariableElement traceVariable; 1805 LocalVariableElement traceVariable;
1806 CatchClauseInfo catchAll; 1806 CatchClauseInfo catchAll;
1807 for (int i = 0; i < catchClauseInfos.length; ++i) { 1807 for (int i = 0; i < catchClauseInfos.length; ++i) {
1808 CatchClauseInfo info = catchClauseInfos[i]; 1808 CatchClauseInfo info = catchClauseInfos[i];
1809 if (info.type == null) { 1809 if (info.type == null) {
1810 catchAll = info; 1810 catchAll = info;
1811 catchClauseInfos.length = i; 1811 catchClauseInfos.length = i;
1812 break; 1812 break;
1813 } 1813 }
1814 if (traceVariable == null) { 1814 if (traceVariable == null) {
(...skipping 26 matching lines...) Expand all
1841 clauseBuilder.declareLocalVariable(clause.stackTraceVariable, 1841 clauseBuilder.declareLocalVariable(clause.stackTraceVariable,
1842 initialValue: traceParameter); 1842 initialValue: traceParameter);
1843 } 1843 }
1844 clause.buildCatchBlock(clauseBuilder); 1844 clause.buildCatchBlock(clauseBuilder);
1845 if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join); 1845 if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join);
1846 ir.Continuation thenContinuation = new ir.Continuation([]); 1846 ir.Continuation thenContinuation = new ir.Continuation([]);
1847 thenContinuation.body = clauseBuilder._root; 1847 thenContinuation.body = clauseBuilder._root;
1848 ir.Continuation elseContinuation = new ir.Continuation([]); 1848 ir.Continuation elseContinuation = new ir.Continuation([]);
1849 elseContinuation.body = catchBody; 1849 elseContinuation.body = catchBody;
1850 1850
1851 ir.Parameter typeMatches = new ir.Parameter(null); 1851 // Build the type test guarding this clause. We can share the environment
1852 ir.Continuation checkType = new ir.Continuation([typeMatches]); 1852 // with the nested builder because this part cannot mutate it.
1853 checkType.body = 1853 IrBuilder checkBuilder = catchBuilder.makeDelimitedBuilder(environment);
1854 new ir.LetCont.many([thenContinuation, elseContinuation], 1854 ir.Primitive typeMatches =
1855 new ir.Branch(new ir.IsTrue(typeMatches), 1855 checkBuilder.buildTypeOperator(exceptionParameter,
1856 thenContinuation, 1856 clause.type,
1857 elseContinuation)); 1857 isTypeTest: true);
1858 catchBody = 1858 checkBuilder.add(new ir.LetCont.many([thenContinuation, elseContinuation],
1859 new ir.LetCont(checkType, 1859 new ir.Branch(new ir.IsTrue(typeMatches),
1860 new ir.TypeOperator(exceptionInterceptor, clause.type, checkType, 1860 thenContinuation,
1861 isTypeTest: true)); 1861 elseContinuation)));
1862 catchBody = checkBuilder._root;
1862 } 1863 }
1863 1864
1864 List<ir.Parameter> catchParameters = 1865 List<ir.Parameter> catchParameters =
1865 <ir.Parameter>[exceptionParameter, traceParameter]; 1866 <ir.Parameter>[exceptionParameter, traceParameter];
1866 ir.Continuation catchContinuation = new ir.Continuation(catchParameters); 1867 ir.Continuation catchContinuation = new ir.Continuation(catchParameters);
1867 catchBuilder.buildGetInterceptor(exceptionParameter)
1868 .substituteFor(exceptionInterceptor);
1869 catchBuilder.add(catchBody); 1868 catchBuilder.add(catchBody);
1870 catchContinuation.body = catchBuilder._root; 1869 catchContinuation.body = catchBuilder._root;
1871 1870
1872 tryCatchBuilder.add( 1871 tryCatchBuilder.add(
1873 new ir.LetHandler(catchContinuation, tryBuilder._root)); 1872 new ir.LetHandler(catchContinuation, tryBuilder._root));
1874 add(new ir.LetCont(join.continuation, tryCatchBuilder._root)); 1873 add(new ir.LetCont(join.continuation, tryCatchBuilder._root));
1875 environment = join.environment; 1874 environment = join.environment;
1876 } 1875 }
1877 1876
1878 /// Create a return statement `return value;` or `return;` if [value] is 1877 /// Create a return statement `return value;` or `return;` if [value] is
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
2007 2006
2008 add(new ir.LetCont(joinContinuation, 2007 add(new ir.LetCont(joinContinuation,
2009 new ir.LetCont.many(<ir.Continuation>[thenContinuation, 2008 new ir.LetCont.many(<ir.Continuation>[thenContinuation,
2010 elseContinuation], 2009 elseContinuation],
2011 new ir.Branch(new ir.IsTrue(condition), 2010 new ir.Branch(new ir.IsTrue(condition),
2012 thenContinuation, 2011 thenContinuation,
2013 elseContinuation)))); 2012 elseContinuation))));
2014 return resultParameter; 2013 return resultParameter;
2015 } 2014 }
2016 2015
2017 /// Creates a type test or type cast of [receiver] against [type].
2018 ///
2019 /// Set [isTypeTest] to `true` to create a type test and furthermore set
2020 /// [isNotCheck] to `true` to create a negated type test.
2021 ir.Primitive buildTypeOperator(ir.Primitive receiver,
2022 DartType type,
2023 {bool isTypeTest: false,
2024 bool isNotCheck: false});
2025
2026 /// Create a lazy and/or expression. [leftValue] is the value of the left 2016 /// Create a lazy and/or expression. [leftValue] is the value of the left
2027 /// operand and [buildRightValue] is called to process the value of the right 2017 /// operand and [buildRightValue] is called to process the value of the right
2028 /// operand in the context of its own [IrBuilder]. 2018 /// operand in the context of its own [IrBuilder].
2029 ir.Primitive buildLogicalOperator( 2019 ir.Primitive buildLogicalOperator(
2030 ir.Primitive leftValue, 2020 ir.Primitive leftValue,
2031 ir.Primitive buildRightValue(IrBuilder builder), 2021 ir.Primitive buildRightValue(IrBuilder builder),
2032 {bool isLazyOr: false}) { 2022 {bool isLazyOr: false}) {
2033 // e0 && e1 is translated as if e0 ? (e1 == true) : false. 2023 // e0 && e1 is translated as if e0 ? (e1 == true) : false.
2034 // e0 || e1 is translated as if e0 ? true : (e1 == true). 2024 // e0 || e1 is translated as if e0 ? true : (e1 == true).
2035 // The translation must convert both e0 and e1 to booleans and handle 2025 // The translation must convert both e0 and e1 to booleans and handle
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
2284 value.useElementAsHint(local); 2274 value.useElementAsHint(local);
2285 environment.update(local, value); 2275 environment.update(local, value);
2286 } 2276 }
2287 return value; 2277 return value;
2288 } 2278 }
2289 2279
2290 ir.Primitive buildThis() { 2280 ir.Primitive buildThis() {
2291 return state.enclosingMethodThisParameter; 2281 return state.enclosingMethodThisParameter;
2292 } 2282 }
2293 2283
2294 ir.Primitive buildGetInterceptor(ir.Primitive value) => value;
2295
2296 @override 2284 @override
2297 ir.Primitive buildConstructorInvocation(ConstructorElement element, 2285 ir.Primitive buildConstructorInvocation(ConstructorElement element,
2298 CallStructure callStructure, 2286 CallStructure callStructure,
2299 DartType type, 2287 DartType type,
2300 List<ir.Primitive> arguments) { 2288 List<ir.Primitive> arguments) {
2301 assert(isOpen); 2289 assert(isOpen);
2302 Selector selector = 2290 Selector selector =
2303 new Selector(SelectorKind.CALL, element.memberName, callStructure); 2291 new Selector(SelectorKind.CALL, element.memberName, callStructure);
2304 return _continueWithExpression( 2292 return _continueWithExpression(
2305 (k) => new ir.InvokeConstructor(type, element, selector, 2293 (k) => new ir.InvokeConstructor(type, element, selector,
2306 arguments, k)); 2294 arguments, k));
2307 } 2295 }
2308 2296
2309 @override 2297 @override
2310 ir.Primitive buildReifyTypeVariable(TypeVariableType variable) { 2298 ir.Primitive buildReifyTypeVariable(TypeVariableType variable) {
2311 return addPrimitive(new ir.ReifyTypeVar(variable.element)); 2299 return addPrimitive(new ir.ReifyTypeVar(variable.element));
2312 } 2300 }
2313 2301
2314 @override 2302 @override
2315 ir.Primitive buildTypeOperator(ir.Primitive receiver, 2303 ir.Primitive buildTypeOperator(ir.Primitive value,
2316 DartType type, 2304 DartType type,
2317 {bool isTypeTest: false, 2305 {bool isTypeTest}) {
2318 bool isNotCheck: false}) {
2319 assert(isOpen); 2306 assert(isOpen);
2320 assert(isTypeTest != null); 2307 assert(isTypeTest != null);
2321 assert(!isNotCheck || isTypeTest);
2322 ir.Primitive check = _continueWithExpression( 2308 ir.Primitive check = _continueWithExpression(
2323 (k) => new ir.TypeOperator(receiver, type, k, isTypeTest: isTypeTest )); 2309 (k) => new ir.TypeOperator(value,
2324 return isNotCheck ? buildNegation(check) : check; 2310 type, [], k, isTypeTest: isTypeTest));
karlklose 2015/05/27 07:38:34 Please add type arguments to list literals (also i
asgerf 2015/05/27 09:19:16 Done.
2311 return check;
2325 } 2312 }
2326 } 2313 }
2327 2314
2328 /// State shared between JsIrBuilders within the same function. 2315 /// State shared between JsIrBuilders within the same function.
2329 /// 2316 ///
2330 /// Note that this is not shared between builders of nested functions. 2317 /// Note that this is not shared between builders of nested functions.
2331 class JsIrBuilderSharedState { 2318 class JsIrBuilderSharedState {
2332 /// Maps boxed locals to their location. These locals are not part of 2319 /// Maps boxed locals to their location. These locals are not part of
2333 /// the environment. 2320 /// the environment.
2334 final Map<Local, ClosureLocation> boxedVariables = {}; 2321 final Map<Local, ClosureLocation> boxedVariables = {};
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
2551 } 2538 }
2552 environment.update(scope.box, newBox); 2539 environment.update(scope.box, newBox);
2553 } 2540 }
2554 2541
2555 ir.Primitive buildThis() { 2542 ir.Primitive buildThis() {
2556 if (jsState.receiver != null) return jsState.receiver; 2543 if (jsState.receiver != null) return jsState.receiver;
2557 assert(state.thisParameter != null); 2544 assert(state.thisParameter != null);
2558 return state.thisParameter; 2545 return state.thisParameter;
2559 } 2546 }
2560 2547
2561 ir.Primitive buildGetInterceptor(ir.Primitive value) {
2562 return addPrimitive(new ir.Interceptor(value, program.interceptedClasses));
2563 }
2564
2565 @override 2548 @override
2566 ir.Primitive buildSuperFieldGet(FieldElement target) { 2549 ir.Primitive buildSuperFieldGet(FieldElement target) {
2567 return addPrimitive(new ir.GetField(buildThis(), target)); 2550 return addPrimitive(new ir.GetField(buildThis(), target));
2568 } 2551 }
2569 2552
2570 @override 2553 @override
2571 ir.Primitive buildSuperFieldSet(FieldElement target, ir.Primitive value) { 2554 ir.Primitive buildSuperFieldSet(FieldElement target, ir.Primitive value) {
2572 add(new ir.SetField(buildThis(), target, value)); 2555 add(new ir.SetField(buildThis(), target, value));
2573 return value; 2556 return value;
2574 } 2557 }
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
2629 ir.Primitive buildTypeExpression(DartType type) { 2612 ir.Primitive buildTypeExpression(DartType type) {
2630 if (type is TypeVariableType) { 2613 if (type is TypeVariableType) {
2631 return buildTypeVariableAccess(type); 2614 return buildTypeVariableAccess(type);
2632 } else if (type is InterfaceType) { 2615 } else if (type is InterfaceType) {
2633 List<ir.Primitive> arguments = <ir.Primitive>[]; 2616 List<ir.Primitive> arguments = <ir.Primitive>[];
2634 type.forEachTypeVariable((TypeVariableType variable) { 2617 type.forEachTypeVariable((TypeVariableType variable) {
2635 ir.Primitive value = buildTypeVariableAccess(variable); 2618 ir.Primitive value = buildTypeVariableAccess(variable);
2636 arguments.add(value); 2619 arguments.add(value);
2637 }); 2620 });
2638 return addPrimitive(new ir.TypeExpression(type, arguments)); 2621 return addPrimitive(new ir.TypeExpression(type, arguments));
2622 } else if (type is DynamicType) {
2623 return buildNullConstant();
2639 } else { 2624 } else {
2640 // TypedefType can reach here, and possibly other things. 2625 // TypedefType can reach here, and possibly other things.
2641 throw 'unimplemented translation of type expression $type'; 2626 throw 'unimplemented translation of type expression $type';
2642 } 2627 }
2643 } 2628 }
2644 2629
2645 /// Obtains the internal type representation of the type held in [variable]. 2630 /// Obtains the internal type representation of the type held in [variable].
2646 /// 2631 ///
2647 /// The value of [variable] is taken from the current receiver object, or 2632 /// The value of [variable] is taken from the current receiver object, or
2648 /// if we are currently building a constructor field initializer, from the 2633 /// if we are currently building a constructor field initializer, from the
(...skipping 24 matching lines...) Expand all
2673 ir.Primitive typeArgument = buildTypeVariableAccess(variable); 2658 ir.Primitive typeArgument = buildTypeVariableAccess(variable);
2674 return addPrimitive(new ir.ReifyRuntimeType(typeArgument)); 2659 return addPrimitive(new ir.ReifyRuntimeType(typeArgument));
2675 } 2660 }
2676 2661
2677 ir.Primitive buildInvocationMirror(Selector selector, 2662 ir.Primitive buildInvocationMirror(Selector selector,
2678 List<ir.Primitive> arguments) { 2663 List<ir.Primitive> arguments) {
2679 return addPrimitive(new ir.CreateInvocationMirror(selector, arguments)); 2664 return addPrimitive(new ir.CreateInvocationMirror(selector, arguments));
2680 } 2665 }
2681 2666
2682 @override 2667 @override
2683 ir.Primitive buildTypeOperator(ir.Primitive receiver, 2668 ir.Primitive buildTypeOperator(ir.Primitive value,
2684 DartType type, 2669 DartType type,
2685 {bool isTypeTest: false, 2670 {bool isTypeTest}) {
2686 bool isNotCheck: false}) {
2687 assert(isOpen); 2671 assert(isOpen);
2688 assert(isTypeTest != null); 2672 assert(isTypeTest != null);
2689 assert(!isNotCheck || isTypeTest); 2673 // The TypeOperator node does not allow the Object, dynamic, and Null types,
2690 ir.Primitive interceptor = 2674 // because the null value satisfies them. These must be handled here.
2691 addPrimitive(new ir.Interceptor(receiver, program.interceptedClasses)); 2675 if (type.isObject || type.isDynamic) {
2676 // `x is Object` and `x is dynamic` are always true, even if x is null.
2677 return buildBooleanConstant(true);
2678 }
2679 if (type is InterfaceType && type.element == program.nullClass) {
2680 // `x is Null` is true if and only if x is null.
2681 return addPrimitive(new ir.Identical(value, buildNullConstant()));
2682 }
2683 // Null cannot not satisfy the check. Use a standard subtype check.
2684 List<ir.Primitive> typeArguments = const [];
2685 if (type is GenericType && type.typeArguments.isNotEmpty) {
2686 typeArguments = type.typeArguments.map(buildTypeExpression).toList();
2687 }
2692 ir.Primitive check = _continueWithExpression( 2688 ir.Primitive check = _continueWithExpression(
2693 (k) => new ir.TypeOperator(interceptor, type, k, 2689 (k) => new ir.TypeOperator(value,
2694 isTypeTest: isTypeTest)); 2690 type, typeArguments, k, isTypeTest: isTypeTest));
2695 return isNotCheck ? buildNegation(check) : check; 2691 return check;
2696 } 2692 }
2697
2698 } 2693 }
2699 2694
2700 2695
2701 /// Location of a variable relative to a given closure. 2696 /// Location of a variable relative to a given closure.
2702 class ClosureLocation { 2697 class ClosureLocation {
2703 /// If not `null`, this location is [box].[field]. 2698 /// If not `null`, this location is [box].[field].
2704 /// The location of [box] can be obtained separately from an 2699 /// The location of [box] can be obtained separately from an
2705 /// enclosing [ClosureEnvironment] or [ClosureScope]. 2700 /// enclosing [ClosureEnvironment] or [ClosureScope].
2706 /// If `null`, then the location is [field] on the enclosing function object. 2701 /// If `null`, then the location is [field] on the enclosing function object.
2707 final BoxLocal box; 2702 final BoxLocal box;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2769 } 2764 }
2770 2765
2771 /// Synthetic parameter to a JavaScript factory method that takes the type 2766 /// Synthetic parameter to a JavaScript factory method that takes the type
2772 /// argument given for the type variable [variable]. 2767 /// argument given for the type variable [variable].
2773 class TypeInformationParameter implements Local { 2768 class TypeInformationParameter implements Local {
2774 final TypeVariableElement variable; 2769 final TypeVariableElement variable;
2775 final ExecutableElement executableContext; 2770 final ExecutableElement executableContext;
2776 TypeInformationParameter(this.variable, this.executableContext); 2771 TypeInformationParameter(this.variable, this.executableContext);
2777 String get name => variable.name; 2772 String get name => variable.name;
2778 } 2773 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698