| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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.resolution.members; | 5 library dart2js.resolution.members; |
| 6 | 6 |
| 7 import '../common/names.dart' show | 7 import '../common/names.dart' show |
| 8 Selectors; | 8 Selectors; |
| 9 import '../compiler.dart' show | 9 import '../compiler.dart' show |
| 10 Compiler; | 10 Compiler; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 | 118 |
| 119 /// `true` if a [Send] or [SendSet] is visited as the prefix of member access. | 119 /// `true` if a [Send] or [SendSet] is visited as the prefix of member access. |
| 120 /// For instance `Class` in `Class.staticField` or `prefix.Class` in | 120 /// For instance `Class` in `Class.staticField` or `prefix.Class` in |
| 121 /// `prefix.Class.staticMethod()`. | 121 /// `prefix.Class.staticMethod()`. |
| 122 bool sendIsMemberAccess = false; | 122 bool sendIsMemberAccess = false; |
| 123 | 123 |
| 124 StatementScope statementScope; | 124 StatementScope statementScope; |
| 125 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION | 125 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION |
| 126 | ElementCategory.IMPLIES_TYPE; | 126 | ElementCategory.IMPLIES_TYPE; |
| 127 | 127 |
| 128 /** | |
| 129 * Record of argument nodes to JS_INTERCEPTOR_CONSTANT for deferred | |
| 130 * processing. | |
| 131 */ | |
| 132 Set<Node> argumentsToJsInterceptorConstant = null; | |
| 133 | |
| 134 /// When visiting the type declaration of the variable in a [ForIn] loop, | 128 /// When visiting the type declaration of the variable in a [ForIn] loop, |
| 135 /// the initializer of the variable is implicit and we should not emit an | 129 /// the initializer of the variable is implicit and we should not emit an |
| 136 /// error when verifying that all final variables are initialized. | 130 /// error when verifying that all final variables are initialized. |
| 137 bool allowFinalWithoutInitializer = false; | 131 bool allowFinalWithoutInitializer = false; |
| 138 | 132 |
| 139 /// The nodes for which variable access and mutation must be registered in | 133 /// The nodes for which variable access and mutation must be registered in |
| 140 /// order to determine when the static type of variables types is promoted. | 134 /// order to determine when the static type of variables types is promoted. |
| 141 Link<Node> promotionScope = const Link<Node>(); | 135 Link<Node> promotionScope = const Link<Node>(); |
| 142 | 136 |
| 143 bool isPotentiallyMutableTarget(Element target) { | 137 bool isPotentiallyMutableTarget(Element target) { |
| (...skipping 1907 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2051 // identifier that refers to the class/typedef) as a constant. | 2045 // identifier that refers to the class/typedef) as a constant. |
| 2052 registry.useElement(node.selector, element); | 2046 registry.useElement(node.selector, element); |
| 2053 analyzeConstantDeferred(node.selector, enforceConst: false); | 2047 analyzeConstantDeferred(node.selector, enforceConst: false); |
| 2054 | 2048 |
| 2055 registry.registerSendStructure(node, | 2049 registry.registerSendStructure(node, |
| 2056 new InvokeStructure(semantics, selector)); | 2050 new InvokeStructure(semantics, selector)); |
| 2057 return const NoneResult(); | 2051 return const NoneResult(); |
| 2058 } else { | 2052 } else { |
| 2059 analyzeConstantDeferred(node, enforceConst: false); | 2053 analyzeConstantDeferred(node, enforceConst: false); |
| 2060 | 2054 |
| 2061 // TODO(johnniwinther): Avoid the need for a [Selector] here. | 2055 registry.setConstant(node, semantics.constant); |
| 2062 registry.registerSendStructure(node, new GetStructure(semantics)); | 2056 registry.registerSendStructure(node, new GetStructure(semantics)); |
| 2063 return new ConstantResult(node, semantics.constant); | 2057 return new ConstantResult(node, semantics.constant); |
| 2064 } | 2058 } |
| 2065 } | 2059 } |
| 2066 | 2060 |
| 2067 /// Handle access to a constant type literal of [type]. | 2061 /// Handle access to a constant type literal of [type]. |
| 2068 // TODO(johnniwinther): Remove [name] when [Selector] is not required for the | 2062 // TODO(johnniwinther): Remove [name] when [Selector] is not required for the |
| 2069 // the [GetStructure]. | 2063 // the [GetStructure]. |
| 2070 // TODO(johnniwinther): Remove [element] when it is no longer needed for | 2064 // TODO(johnniwinther): Remove [element] when it is no longer needed for |
| 2071 // evaluating constants. | 2065 // evaluating constants. |
| (...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2750 case AccessKind.TOPLEVEL_METHOD: | 2744 case AccessKind.TOPLEVEL_METHOD: |
| 2751 MethodElement method = semantics.element; | 2745 MethodElement method = semantics.element; |
| 2752 method.computeType(compiler); | 2746 method.computeType(compiler); |
| 2753 if (!callStructure.signatureApplies(method.functionSignature)) { | 2747 if (!callStructure.signatureApplies(method.functionSignature)) { |
| 2754 registry.registerThrowNoSuchMethod(); | 2748 registry.registerThrowNoSuchMethod(); |
| 2755 registry.registerDynamicInvocation( | 2749 registry.registerDynamicInvocation( |
| 2756 new UniverseSelector(selector, null)); | 2750 new UniverseSelector(selector, null)); |
| 2757 isIncompatibleInvoke = true; | 2751 isIncompatibleInvoke = true; |
| 2758 } else { | 2752 } else { |
| 2759 registry.registerStaticUse(semantics.element); | 2753 registry.registerStaticUse(semantics.element); |
| 2760 handleForeignCall(node, semantics.element, selector); | 2754 handleForeignCall(node, semantics.element, callStructure); |
| 2761 if (method == compiler.identicalFunction && | 2755 if (method == compiler.identicalFunction && |
| 2762 argumentsResult.isValidAsConstant) { | 2756 argumentsResult.isValidAsConstant) { |
| 2763 result = new ConstantResult(node, | 2757 result = new ConstantResult(node, |
| 2764 new IdenticalConstantExpression( | 2758 new IdenticalConstantExpression( |
| 2765 argumentsResult.argumentResults[0].constant, | 2759 argumentsResult.argumentResults[0].constant, |
| 2766 argumentsResult.argumentResults[1].constant)); | 2760 argumentsResult.argumentResults[1].constant)); |
| 2767 } | 2761 } |
| 2768 } | 2762 } |
| 2769 break; | 2763 break; |
| 2770 case AccessKind.STATIC_FIELD: | 2764 case AccessKind.STATIC_FIELD: |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3103 if (isPotentiallyMutableTarget(target)) { | 3097 if (isPotentiallyMutableTarget(target)) { |
| 3104 if (enclosingElement != target.enclosingElement) { | 3098 if (enclosingElement != target.enclosingElement) { |
| 3105 for (Node scope in promotionScope) { | 3099 for (Node scope in promotionScope) { |
| 3106 registry.setAccessedByClosureIn(scope, target, node); | 3100 registry.setAccessedByClosureIn(scope, target, node); |
| 3107 } | 3101 } |
| 3108 } | 3102 } |
| 3109 } | 3103 } |
| 3110 } | 3104 } |
| 3111 | 3105 |
| 3112 // TODO(johnniwinther): Move this to the backend resolution callbacks. | 3106 // TODO(johnniwinther): Move this to the backend resolution callbacks. |
| 3113 void handleForeignCall(Send node, Element target, Selector selector) { | 3107 void handleForeignCall(Send node, |
| 3108 Element target, |
| 3109 CallStructure callStructure) { |
| 3114 if (target != null && compiler.backend.isForeign(target)) { | 3110 if (target != null && compiler.backend.isForeign(target)) { |
| 3115 if (selector.name == 'JS') { | 3111 registry.registerForeignCall(node, target, callStructure, this); |
| 3116 registry.registerJsCall(node, this); | |
| 3117 } else if (selector.name == 'JS_EMBEDDED_GLOBAL') { | |
| 3118 registry.registerJsEmbeddedGlobalCall(node, this); | |
| 3119 } else if (selector.name == 'JS_BUILTIN') { | |
| 3120 registry.registerJsBuiltinCall(node, this); | |
| 3121 } else if (selector.name == 'JS_INTERCEPTOR_CONSTANT') { | |
| 3122 if (!node.argumentsNode.isEmpty) { | |
| 3123 Node argument = node.argumentsNode.nodes.head; | |
| 3124 if (argumentsToJsInterceptorConstant == null) { | |
| 3125 argumentsToJsInterceptorConstant = new Set<Node>(); | |
| 3126 } | |
| 3127 argumentsToJsInterceptorConstant.add(argument); | |
| 3128 } | |
| 3129 } | |
| 3130 } | 3112 } |
| 3131 } | 3113 } |
| 3132 | 3114 |
| 3133 /// Callback for native enqueuer to parse a type. Returns [:null:] on error. | 3115 /// Callback for native enqueuer to parse a type. Returns [:null:] on error. |
| 3134 DartType resolveTypeFromString(Node node, String typeName) { | 3116 DartType resolveTypeFromString(Node node, String typeName) { |
| 3135 Element element = lookupInScope(compiler, node, scope, typeName); | 3117 Element element = lookupInScope(compiler, node, scope, typeName); |
| 3136 if (element == null) return null; | 3118 if (element == null) return null; |
| 3137 if (element is! ClassElement) return null; | 3119 if (element is! ClassElement) return null; |
| 3138 ClassElement cls = element; | 3120 ClassElement cls = element; |
| 3139 cls.ensureResolved(compiler); | 3121 cls.ensureResolved(compiler); |
| (...skipping 828 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3968 | 3950 |
| 3969 if (constant == null) { | 3951 if (constant == null) { |
| 3970 assert(invariant(node, compiler.compilationFailed)); | 3952 assert(invariant(node, compiler.compilationFailed)); |
| 3971 return; | 3953 return; |
| 3972 } | 3954 } |
| 3973 | 3955 |
| 3974 ConstantValue value = compiler.constants.getConstantValue(constant); | 3956 ConstantValue value = compiler.constants.getConstantValue(constant); |
| 3975 if (value.isMap) { | 3957 if (value.isMap) { |
| 3976 checkConstMapKeysDontOverrideEquals(node, value); | 3958 checkConstMapKeysDontOverrideEquals(node, value); |
| 3977 } | 3959 } |
| 3978 | |
| 3979 // The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names | |
| 3980 // a class that will be instantiated outside the program by attaching a | |
| 3981 // native class dispatch record referencing the interceptor. | |
| 3982 if (argumentsToJsInterceptorConstant != null && | |
| 3983 argumentsToJsInterceptorConstant.contains(node)) { | |
| 3984 if (value.isType) { | |
| 3985 TypeConstantValue typeConstant = value; | |
| 3986 if (typeConstant.representedType is InterfaceType) { | |
| 3987 registry.registerInstantiatedType(typeConstant.representedType); | |
| 3988 } else { | |
| 3989 compiler.reportErrorMessage( | |
| 3990 node, | |
| 3991 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); | |
| 3992 } | |
| 3993 } else { | |
| 3994 compiler.reportErrorMessage( | |
| 3995 node, | |
| 3996 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); | |
| 3997 } | |
| 3998 } | |
| 3999 } | 3960 } |
| 4000 | 3961 |
| 4001 void analyzeConstantDeferred(Node node, {bool enforceConst: true}) { | 3962 void analyzeConstantDeferred(Node node, {bool enforceConst: true}) { |
| 4002 addDeferredAction(enclosingElement, () { | 3963 addDeferredAction(enclosingElement, () { |
| 4003 analyzeConstant(node, enforceConst: enforceConst); | 3964 analyzeConstant(node, enforceConst: enforceConst); |
| 4004 }); | 3965 }); |
| 4005 } | 3966 } |
| 4006 | 3967 |
| 4007 bool validateSymbol(Node node, String name, {bool reportError: true}) { | 3968 bool validateSymbol(Node node, String name, {bool reportError: true}) { |
| 4008 if (name.isEmpty) return true; | 3969 if (name.isEmpty) return true; |
| (...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4727 } | 4688 } |
| 4728 return const NoneResult(); | 4689 return const NoneResult(); |
| 4729 } | 4690 } |
| 4730 } | 4691 } |
| 4731 | 4692 |
| 4732 /// Looks up [name] in [scope] and unwraps the result. | 4693 /// Looks up [name] in [scope] and unwraps the result. |
| 4733 Element lookupInScope(Compiler compiler, Node node, | 4694 Element lookupInScope(Compiler compiler, Node node, |
| 4734 Scope scope, String name) { | 4695 Scope scope, String name) { |
| 4735 return Elements.unwrap(scope.lookup(name), compiler, node); | 4696 return Elements.unwrap(scope.lookup(name), compiler, node); |
| 4736 } | 4697 } |
| OLD | NEW |