| OLD | NEW |
| 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 '../closure.dart' hide ClosureScope; | 7 import '../closure.dart' as closure; |
| 8 import '../common.dart'; | 8 import '../common.dart'; |
| 9 import '../common/names.dart' show | 9 import '../common/names.dart' show |
| 10 Names, | 10 Names, |
| 11 Selectors; | 11 Selectors; |
| 12 import '../compile_time_constants.dart' show | 12 import '../compile_time_constants.dart' show |
| 13 BackendConstantEnvironment; | 13 BackendConstantEnvironment; |
| 14 import '../constants/constant_system.dart'; | 14 import '../constants/constant_system.dart'; |
| 15 import '../constants/values.dart' show | 15 import '../constants/values.dart' show |
| 16 ConstantValue, | 16 ConstantValue, |
| 17 PrimitiveConstantValue; | 17 PrimitiveConstantValue; |
| (...skipping 2442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2460 getMutableVariable(variableElement), | 2460 getMutableVariable(variableElement), |
| 2461 initialValue)); | 2461 initialValue)); |
| 2462 } else { | 2462 } else { |
| 2463 initialValue.useElementAsHint(variableElement); | 2463 initialValue.useElementAsHint(variableElement); |
| 2464 environment.extend(variableElement, initialValue); | 2464 environment.extend(variableElement, initialValue); |
| 2465 } | 2465 } |
| 2466 } | 2466 } |
| 2467 | 2467 |
| 2468 /// Add [functionElement] to the environment with provided [definition]. | 2468 /// Add [functionElement] to the environment with provided [definition]. |
| 2469 void declareLocalFunction(LocalFunctionElement functionElement, | 2469 void declareLocalFunction(LocalFunctionElement functionElement, |
| 2470 ClosureClassElement classElement, | 2470 closure.ClosureClassElement classElement, |
| 2471 SourceInformation sourceInformation) { | 2471 SourceInformation sourceInformation) { |
| 2472 ir.Primitive closure = | 2472 ir.Primitive closure = |
| 2473 buildFunctionExpression(classElement, sourceInformation); | 2473 buildFunctionExpression(classElement, sourceInformation); |
| 2474 declareLocalVariable(functionElement, initialValue: closure); | 2474 declareLocalVariable(functionElement, initialValue: closure); |
| 2475 } | 2475 } |
| 2476 | 2476 |
| 2477 ir.Primitive buildFunctionExpression(ClosureClassElement classElement, | 2477 ir.Primitive buildFunctionExpression(closure.ClosureClassElement classElement, |
| 2478 SourceInformation sourceInformation) { | 2478 SourceInformation sourceInformation) { |
| 2479 List<ir.Primitive> arguments = <ir.Primitive>[]; | 2479 List<ir.Primitive> arguments = <ir.Primitive>[]; |
| 2480 for (ClosureFieldElement field in classElement.closureFields) { | 2480 for (closure.ClosureFieldElement field in classElement.closureFields) { |
| 2481 // Captured 'this' and type variables are not always available as locals | 2481 // Captured 'this' and type variables are not always available as locals |
| 2482 // in the environment, so treat those specially. | 2482 // in the environment, so treat those specially. |
| 2483 ir.Primitive value; | 2483 ir.Primitive value; |
| 2484 if (field.local is ThisLocal) { | 2484 if (field.local is closure.ThisLocal) { |
| 2485 value = buildThis(); | 2485 value = buildThis(); |
| 2486 } else if (field.local is TypeVariableLocal) { | 2486 } else if (field.local is closure.TypeVariableLocal) { |
| 2487 TypeVariableLocal variable = field.local; | 2487 closure.TypeVariableLocal variable = field.local; |
| 2488 value = buildTypeVariableAccess(variable.typeVariable); | 2488 value = buildTypeVariableAccess(variable.typeVariable); |
| 2489 } else { | 2489 } else { |
| 2490 value = environment.lookup(field.local); | 2490 value = environment.lookup(field.local); |
| 2491 } | 2491 } |
| 2492 arguments.add(value); | 2492 arguments.add(value); |
| 2493 } | 2493 } |
| 2494 return addPrimitive(new ir.CreateInstance( | 2494 return addPrimitive(new ir.CreateInstance( |
| 2495 classElement, arguments, const <ir.Primitive>[], sourceInformation)); | 2495 classElement, arguments, const <ir.Primitive>[], sourceInformation)); |
| 2496 } | 2496 } |
| 2497 | 2497 |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2682 /// | 2682 /// |
| 2683 /// The value of [variable] is taken from the current receiver object, or | 2683 /// The value of [variable] is taken from the current receiver object, or |
| 2684 /// if we are currently building a constructor field initializer, from the | 2684 /// if we are currently building a constructor field initializer, from the |
| 2685 /// corresponding type argument (field initializers are evaluated before the | 2685 /// corresponding type argument (field initializers are evaluated before the |
| 2686 /// receiver object is created). | 2686 /// receiver object is created). |
| 2687 ir.Primitive buildTypeVariableAccess(TypeVariableType variable, | 2687 ir.Primitive buildTypeVariableAccess(TypeVariableType variable, |
| 2688 {SourceInformation sourceInformation}) { | 2688 {SourceInformation sourceInformation}) { |
| 2689 // If the local exists in the environment, use that. | 2689 // If the local exists in the environment, use that. |
| 2690 // This is put here when we are inside a constructor or field initializer, | 2690 // This is put here when we are inside a constructor or field initializer, |
| 2691 // (or possibly a closure inside one of these). | 2691 // (or possibly a closure inside one of these). |
| 2692 Local local = new TypeVariableLocal(variable, state.currentElement); | 2692 Local local = new closure.TypeVariableLocal(variable, state.currentElement); |
| 2693 if (environment.contains(local)) { | 2693 if (environment.contains(local)) { |
| 2694 return environment.lookup(local); | 2694 return environment.lookup(local); |
| 2695 } | 2695 } |
| 2696 | 2696 |
| 2697 // If the type variable is not in a local, read its value from the | 2697 // If the type variable is not in a local, read its value from the |
| 2698 // receiver object. | 2698 // receiver object. |
| 2699 ir.Primitive target = buildThis(); | 2699 ir.Primitive target = buildThis(); |
| 2700 return addPrimitive( | 2700 return addPrimitive( |
| 2701 new ir.ReadTypeVariable(variable, target, sourceInformation)); | 2701 new ir.ReadTypeVariable(variable, target, sourceInformation)); |
| 2702 } | 2702 } |
| 2703 | 2703 |
| 2704 /// Make the given type variable accessible through the local environment | 2704 /// Make the given type variable accessible through the local environment |
| 2705 /// with the value of [binding]. | 2705 /// with the value of [binding]. |
| 2706 void declareTypeVariable(TypeVariableType variable, DartType binding) { | 2706 void declareTypeVariable(TypeVariableType variable, DartType binding) { |
| 2707 environment.extend( | 2707 environment.extend( |
| 2708 new TypeVariableLocal(variable, state.currentElement), | 2708 new closure.TypeVariableLocal(variable, state.currentElement), |
| 2709 buildTypeExpression(binding)); | 2709 buildTypeExpression(binding)); |
| 2710 } | 2710 } |
| 2711 | 2711 |
| 2712 /// Reifies the value of [variable] on the current receiver object. | 2712 /// Reifies the value of [variable] on the current receiver object. |
| 2713 ir.Primitive buildReifyTypeVariable(TypeVariableType variable, | 2713 ir.Primitive buildReifyTypeVariable(TypeVariableType variable, |
| 2714 SourceInformation sourceInformation) { | 2714 SourceInformation sourceInformation) { |
| 2715 ir.Primitive typeArgument = | 2715 ir.Primitive typeArgument = |
| 2716 buildTypeVariableAccess(variable, sourceInformation: sourceInformation); | 2716 buildTypeVariableAccess(variable, sourceInformation: sourceInformation); |
| 2717 return addPrimitive( | 2717 return addPrimitive( |
| 2718 new ir.ReifyRuntimeType(typeArgument, sourceInformation)); | 2718 new ir.ReifyRuntimeType(typeArgument, sourceInformation)); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2845 return addPrimitive(new ir.Refinement(value, type)); | 2845 return addPrimitive(new ir.Refinement(value, type)); |
| 2846 } | 2846 } |
| 2847 } | 2847 } |
| 2848 | 2848 |
| 2849 /// Location of a variable relative to a given closure. | 2849 /// Location of a variable relative to a given closure. |
| 2850 class ClosureLocation { | 2850 class ClosureLocation { |
| 2851 /// If not `null`, this location is [box].[field]. | 2851 /// If not `null`, this location is [box].[field]. |
| 2852 /// The location of [box] can be obtained separately from an | 2852 /// The location of [box] can be obtained separately from an |
| 2853 /// enclosing [ClosureEnvironment] or [ClosureScope]. | 2853 /// enclosing [ClosureEnvironment] or [ClosureScope]. |
| 2854 /// If `null`, then the location is [field] on the enclosing function object. | 2854 /// If `null`, then the location is [field] on the enclosing function object. |
| 2855 final BoxLocal box; | 2855 final closure.BoxLocal box; |
| 2856 | 2856 |
| 2857 /// The field in which the variable is stored. | 2857 /// The field in which the variable is stored. |
| 2858 final Entity field; | 2858 final Entity field; |
| 2859 | 2859 |
| 2860 bool get isBox => box != null; | 2860 bool get isBox => box != null; |
| 2861 | 2861 |
| 2862 ClosureLocation(this.box, this.field); | 2862 ClosureLocation(this.box, this.field); |
| 2863 |
| 2864 /// Converts a map containing closure.dart's [CapturedVariable]s into one |
| 2865 /// containing [ClosureLocation]s. |
| 2866 /// |
| 2867 /// There is a 1:1 corresponce between these; we do this because the |
| 2868 /// IR builder should not depend on synthetic elements. |
| 2869 static Map<Local, ClosureLocation> mapFrom( |
| 2870 Map<Local, closure.CapturedVariable> map) { |
| 2871 Map result = {}; |
| 2872 map.forEach((Local k, closure.CapturedVariable v) { |
| 2873 closure.BoxLocal box = v is closure.BoxFieldElement ? v.box : null; |
| 2874 result[k] = new ClosureLocation(box, v); |
| 2875 }); |
| 2876 return result; |
| 2877 } |
| 2863 } | 2878 } |
| 2864 | 2879 |
| 2865 /// Introduces a new box and binds local variables to this box. | 2880 /// Introduces a new box and binds local variables to this box. |
| 2866 /// | 2881 /// |
| 2867 /// A [ClosureScope] may exist for each function and for each loop. | 2882 /// A [ClosureScope] may exist for each function and for each loop. |
| 2868 /// Generally, one may pass `null` to the [IrBuilder] instead of a | 2883 /// Generally, one may pass `null` to the [IrBuilder] instead of a |
| 2869 /// [ClosureScope] when a given scope has no boxed variables. | 2884 /// [ClosureScope] when a given scope has no boxed variables. |
| 2870 class ClosureScope { | 2885 class ClosureScope { |
| 2871 /// This box is now in scope and [capturedVariables] may use it. | 2886 /// This box is now in scope and [capturedVariables] may use it. |
| 2872 final BoxLocal box; | 2887 final closure.BoxLocal box; |
| 2873 | 2888 |
| 2874 /// Maps [LocalElement]s to their location. | 2889 /// Maps [LocalElement]s to their location. |
| 2875 final Map<Local, ClosureLocation> capturedVariables; | 2890 final Map<Local, ClosureLocation> capturedVariables; |
| 2876 | 2891 |
| 2877 /// If this is the scope of a for-loop, [boxedLoopVariables] is the list | 2892 /// If this is the scope of a for-loop, [boxedLoopVariables] is the list |
| 2878 /// of boxed variables that are declared in the initializer. | 2893 /// of boxed variables that are declared in the initializer. |
| 2879 final List<VariableElement> boxedLoopVariables; | 2894 final List<VariableElement> boxedLoopVariables; |
| 2880 | 2895 |
| 2881 ClosureScope(this.box, this.capturedVariables, this.boxedLoopVariables); | 2896 factory ClosureScope(closure.ClosureScope scope) { |
| 2897 return scope == null ? null : new ClosureScope._internal(scope); |
| 2898 } |
| 2899 |
| 2900 ClosureScope._internal(closure.ClosureScope scope) |
| 2901 : box = scope.boxElement, |
| 2902 capturedVariables = ClosureLocation.mapFrom(scope.capturedVariables), |
| 2903 boxedLoopVariables = scope.boxedLoopVariables; |
| 2882 } | 2904 } |
| 2883 | 2905 |
| 2884 /// Environment passed when building a nested function, describing how | 2906 /// Environment passed when building a nested function, describing how |
| 2885 /// to access variables from the enclosing scope. | 2907 /// to access variables from the enclosing scope. |
| 2886 class ClosureEnvironment { | 2908 class ClosureEnvironment { |
| 2887 /// References to this local should be treated as recursive self-reference. | 2909 /// References to this local should be treated as recursive self-reference. |
| 2888 /// (This is *not* in [freeVariables]). | 2910 /// (This is *not* in [freeVariables]). |
| 2889 final LocalFunctionElement selfReference; | 2911 final LocalFunctionElement selfReference; |
| 2890 | 2912 |
| 2891 /// If non-null, [thisLocal] has an entry in [freeVariables] describing where | 2913 /// If non-null, [thisLocal] has an entry in [freeVariables] describing where |
| 2892 /// to find the captured value of `this`. | 2914 /// to find the captured value of `this`. |
| 2893 final ThisLocal thisLocal; | 2915 final closure.ThisLocal thisLocal; |
| 2894 | 2916 |
| 2895 /// Maps [LocalElement]s, [BoxLocal]s and [ThisLocal] to their location. | 2917 /// Maps [LocalElement]s, [BoxLocal]s and [ThisLocal] to their location. |
| 2896 final Map<Local, ClosureLocation> freeVariables; | 2918 final Map<Local, ClosureLocation> freeVariables; |
| 2897 | 2919 |
| 2898 ClosureEnvironment(this.selfReference, this.thisLocal, this.freeVariables); | 2920 factory ClosureEnvironment(closure.ClosureClassMap closureClassMap) { |
| 2921 if (closureClassMap.closureElement == null) return null; |
| 2922 return new ClosureEnvironment._internal(closureClassMap); |
| 2923 } |
| 2924 |
| 2925 ClosureEnvironment._internal(closure.ClosureClassMap closureClassMap) |
| 2926 : selfReference = closureClassMap.closureElement, |
| 2927 thisLocal = closureClassMap.thisLocal, |
| 2928 freeVariables = |
| 2929 ClosureLocation.mapFrom(closureClassMap.freeVariableMap); |
| 2899 } | 2930 } |
| 2900 | 2931 |
| 2901 class TryStatementInfo { | 2932 class TryStatementInfo { |
| 2902 final Set<LocalVariableElement> declared = new Set<LocalVariableElement>(); | 2933 final Set<LocalVariableElement> declared = new Set<LocalVariableElement>(); |
| 2903 final Set<LocalVariableElement> boxedOnEntry = | 2934 final Set<LocalVariableElement> boxedOnEntry = |
| 2904 new Set<LocalVariableElement>(); | 2935 new Set<LocalVariableElement>(); |
| 2905 } | 2936 } |
| 2906 | 2937 |
| 2907 class CatchClauseInfo { | 2938 class CatchClauseInfo { |
| 2908 final DartType type; | 2939 final DartType type; |
| 2909 final LocalVariableElement exceptionVariable; | 2940 final LocalVariableElement exceptionVariable; |
| 2910 final LocalVariableElement stackTraceVariable; | 2941 final LocalVariableElement stackTraceVariable; |
| 2911 final SubbuildFunction buildCatchBlock; | 2942 final SubbuildFunction buildCatchBlock; |
| 2912 | 2943 |
| 2913 CatchClauseInfo({this.type, | 2944 CatchClauseInfo({this.type, |
| 2914 this.exceptionVariable, | 2945 this.exceptionVariable, |
| 2915 this.stackTraceVariable, | 2946 this.stackTraceVariable, |
| 2916 this.buildCatchBlock}); | 2947 this.buildCatchBlock}); |
| 2917 } | 2948 } |
| 2918 | 2949 |
| 2919 class SwitchCaseInfo { | 2950 class SwitchCaseInfo { |
| 2920 final List<ir.Primitive> constants = <ir.Primitive>[]; | 2951 final List<ir.Primitive> constants = <ir.Primitive>[]; |
| 2921 final SubbuildFunction buildBody; | 2952 final SubbuildFunction buildBody; |
| 2922 | 2953 |
| 2923 SwitchCaseInfo(this.buildBody); | 2954 SwitchCaseInfo(this.buildBody); |
| 2924 | 2955 |
| 2925 void addConstant(ir.Primitive constant) => constants.add(constant); | 2956 void addConstant(ir.Primitive constant) => constants.add(constant); |
| 2926 } | 2957 } |
| OLD | NEW |