| 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 | 5 |
| 6 /** | 6 /** |
| 7 * If true, print a warning for each method that was resolved, but not | 7 * If true, print a warning for each method that was resolved, but not |
| 8 * compiled. | 8 * compiled. |
| 9 */ | 9 */ |
| 10 final bool REPORT_EXCESS_RESOLUTION = false; | 10 final bool REPORT_EXCESS_RESOLUTION = false; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 Collection<LibraryElement> libraries) { | 103 Collection<LibraryElement> libraries) { |
| 104 native.processNativeClasses(world, emitter, libraries); | 104 native.processNativeClasses(world, emitter, libraries); |
| 105 } | 105 } |
| 106 | 106 |
| 107 void assembleProgram() { | 107 void assembleProgram() { |
| 108 emitter.assembleProgram(); | 108 emitter.assembleProgram(); |
| 109 } | 109 } |
| 110 | 110 |
| 111 void updateFieldInitializers(Element field, HType propagatedType) { | 111 void updateFieldInitializers(Element field, HType propagatedType) { |
| 112 assert(field.isField()); | 112 assert(field.isField()); |
| 113 assert(field.enclosingElement.isClass()); | 113 assert(field.isMember()); |
| 114 Map<Element, HType> fields = | 114 Map<Element, HType> fields = |
| 115 fieldInitializers.putIfAbsent( | 115 fieldInitializers.putIfAbsent( |
| 116 field.enclosingElement, () => new Map<Element, HType>()); | 116 field.getEnclosingClass(), () => new Map<Element, HType>()); |
| 117 if (!fields.containsKey(field)) { | 117 if (!fields.containsKey(field)) { |
| 118 fields[field] = propagatedType; | 118 fields[field] = propagatedType; |
| 119 } else { | 119 } else { |
| 120 fields[field] = fields[field].union(propagatedType); | 120 fields[field] = fields[field].union(propagatedType); |
| 121 } | 121 } |
| 122 } | 122 } |
| 123 | 123 |
| 124 HType typeFromInitializersSoFar(Element field) { | 124 HType typeFromInitializersSoFar(Element field) { |
| 125 assert(field.isField()); | 125 assert(field.isField()); |
| 126 assert(field.enclosingElement.isClass()); | 126 assert(field.isMember()); |
| 127 if (!fieldInitializers.containsKey(field.enclosingElement)) { | 127 if (!fieldInitializers.containsKey(field.getEnclosingClass())) { |
| 128 return HType.CONFLICTING; | 128 return HType.CONFLICTING; |
| 129 } | 129 } |
| 130 Map<Element, HType> fields = fieldInitializers[field.enclosingElement]; | 130 Map<Element, HType> fields = fieldInitializers[field.getEnclosingClass()]; |
| 131 return fields[field]; | 131 return fields[field]; |
| 132 } | 132 } |
| 133 | 133 |
| 134 void updateFieldConstructorSetters(Element field, HType type) { | 134 void updateFieldConstructorSetters(Element field, HType type) { |
| 135 assert(field.isField()); | 135 assert(field.isField()); |
| 136 assert(field.enclosingElement.isClass()); | 136 assert(field.isMember()); |
| 137 Map<Element, HType> fields = | 137 Map<Element, HType> fields = |
| 138 fieldConstructorSetters.putIfAbsent( | 138 fieldConstructorSetters.putIfAbsent( |
| 139 field.enclosingElement, () => new Map<Element, HType>()); | 139 field.getEnclosingClass(), () => new Map<Element, HType>()); |
| 140 if (!fields.containsKey(field)) { | 140 if (!fields.containsKey(field)) { |
| 141 fields[field] = type; | 141 fields[field] = type; |
| 142 } else { | 142 } else { |
| 143 fields[field] = fields[field].union(type); | 143 fields[field] = fields[field].union(type); |
| 144 } | 144 } |
| 145 } | 145 } |
| 146 | 146 |
| 147 // Check if this field is set in the constructor body. | 147 // Check if this field is set in the constructor body. |
| 148 bool hasConstructorBodyFieldSetter(Element field) { | 148 bool hasConstructorBodyFieldSetter(Element field) { |
| 149 if (!fieldConstructorSetters.containsKey(field.enclosingElement)) { | 149 ClassElement enclosingClass = field.getEnclosingClass(); |
| 150 if (!fieldConstructorSetters.containsKey(enclosingClass)) { |
| 150 return false; | 151 return false; |
| 151 } | 152 } |
| 152 return fieldConstructorSetters[field.enclosingElement][field] != null; | 153 return fieldConstructorSetters[enclosingClass][field] != null; |
| 153 } | 154 } |
| 154 | 155 |
| 155 // Provide an optimistic estimate of the type of a field after construction. | 156 // Provide an optimistic estimate of the type of a field after construction. |
| 156 // If the constructor body has setters for fields returns HType.UNKNOWN. | 157 // If the constructor body has setters for fields returns HType.UNKNOWN. |
| 157 // This only takes the initializer lists and field assignments in the | 158 // This only takes the initializer lists and field assignments in the |
| 158 // constructor body into account. The constructor body might have method calls | 159 // constructor body into account. The constructor body might have method calls |
| 159 // that could alter the field. | 160 // that could alter the field. |
| 160 HType optimisticFieldTypeAfterConstruction(Element field) { | 161 HType optimisticFieldTypeAfterConstruction(Element field) { |
| 161 assert(field.isField()); | 162 assert(field.isField()); |
| 162 assert(field.enclosingElement.isClass()); | 163 assert(field.isMember()); |
| 163 | 164 |
| 165 ClassElement classElement = field.getEnclosingClass(); |
| 164 if (hasConstructorBodyFieldSetter(field)) { | 166 if (hasConstructorBodyFieldSetter(field)) { |
| 165 // If there are field setters but there is only constructor then the type | 167 // If there are field setters but there is only constructor then the type |
| 166 // of the field is determined by the assignments in the constructor | 168 // of the field is determined by the assignments in the constructor |
| 167 // body. | 169 // body. |
| 168 ClassElement classElement = field.enclosingElement; | |
| 169 if (classElement.constructors.length == 1) { | 170 if (classElement.constructors.length == 1) { |
| 170 return fieldConstructorSetters[field.enclosingElement][field]; | 171 return fieldConstructorSetters[classElement][field]; |
| 171 } else { | 172 } else { |
| 172 return HType.UNKNOWN; | 173 return HType.UNKNOWN; |
| 173 } | 174 } |
| 174 } else if (fieldInitializers.containsKey(field.enclosingElement)) { | 175 } else if (fieldInitializers.containsKey(classElement)) { |
| 175 HType type = fieldInitializers[field.enclosingElement][field]; | 176 HType type = fieldInitializers[classElement][field]; |
| 176 return type == null ? HType.CONFLICTING : type; | 177 return type == null ? HType.CONFLICTING : type; |
| 177 } else { | 178 } else { |
| 178 return HType.CONFLICTING; | 179 return HType.CONFLICTING; |
| 179 } | 180 } |
| 180 } | 181 } |
| 181 | 182 |
| 182 void updateFieldSetters(Element field, HType type) { | 183 void updateFieldSetters(Element field, HType type) { |
| 183 assert(field.isField()); | 184 assert(field.isField()); |
| 184 assert(field.enclosingElement.isClass()); | 185 assert(field.isMember()); |
| 185 Map<Element, HType> fields = | 186 Map<Element, HType> fields = |
| 186 fieldSettersType.putIfAbsent( | 187 fieldSettersType.putIfAbsent( |
| 187 field.enclosingElement, () => new Map<Element, HType>()); | 188 field.getEnclosingClass(), () => new Map<Element, HType>()); |
| 188 if (!fields.containsKey(field)) { | 189 if (!fields.containsKey(field)) { |
| 189 fields[field] = type; | 190 fields[field] = type; |
| 190 } else { | 191 } else { |
| 191 fields[field] = fields[field].union(type); | 192 fields[field] = fields[field].union(type); |
| 192 } | 193 } |
| 193 } | 194 } |
| 194 | 195 |
| 195 // Returns the type that field setters are setting the field to based on what | 196 // Returns the type that field setters are setting the field to based on what |
| 196 // have been seen during compilation so far. | 197 // have been seen during compilation so far. |
| 197 HType fieldSettersTypeSoFar(Element field) { | 198 HType fieldSettersTypeSoFar(Element field) { |
| 198 assert(field.isField()); | 199 assert(field.isField()); |
| 199 assert(field.enclosingElement.isClass()); | 200 assert(field.isMember()); |
| 200 if (!fieldSettersType.containsKey(field.enclosingElement)) { | 201 ClassElement enclosingClass = field.getEnclosingClass(); |
| 202 if (!fieldSettersType.containsKey(enclosingClass)) { |
| 201 return HType.CONFLICTING; | 203 return HType.CONFLICTING; |
| 202 } | 204 } |
| 203 Map<Element, HType> fields = fieldSettersType[field.enclosingElement]; | 205 Map<Element, HType> fields = fieldSettersType[enclosingClass]; |
| 204 if (!fields.containsKey(field)) return HType.CONFLICTING; | 206 if (!fields.containsKey(field)) return HType.CONFLICTING; |
| 205 return fields[field]; | 207 return fields[field]; |
| 206 } | 208 } |
| 207 } | 209 } |
| 208 | 210 |
| 209 class Compiler implements DiagnosticListener { | 211 class Compiler implements DiagnosticListener { |
| 210 final Map<String, LibraryElement> libraries; | 212 final Map<String, LibraryElement> libraries; |
| 211 int nextFreeClassId = 0; | 213 int nextFreeClassId = 0; |
| 212 World world; | 214 World world; |
| 213 String assembledCode; | 215 String assembledCode; |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 return false; | 407 return false; |
| 406 } | 408 } |
| 407 tracer.close(); | 409 tracer.close(); |
| 408 log('compilation succeeded'); | 410 log('compilation succeeded'); |
| 409 return true; | 411 return true; |
| 410 } | 412 } |
| 411 | 413 |
| 412 void enableNoSuchMethod(Element element) { | 414 void enableNoSuchMethod(Element element) { |
| 413 // TODO(ahe): Move this method to Enqueuer. | 415 // TODO(ahe): Move this method to Enqueuer. |
| 414 if (enabledNoSuchMethod) return; | 416 if (enabledNoSuchMethod) return; |
| 415 if (element.enclosingElement === objectClass) { | 417 if (element.getEnclosingClass() === objectClass) { |
| 416 enqueuer.resolution.registerDynamicInvocationOf(element); | 418 enqueuer.resolution.registerDynamicInvocationOf(element); |
| 417 return; | 419 return; |
| 418 } | 420 } |
| 419 enabledNoSuchMethod = true; | 421 enabledNoSuchMethod = true; |
| 420 enqueuer.resolution.registerInvocation(NO_SUCH_METHOD, | 422 enqueuer.resolution.registerInvocation(NO_SUCH_METHOD, |
| 421 Selector.INVOCATION_2); | 423 Selector.INVOCATION_2); |
| 422 enqueuer.codegen.registerInvocation(NO_SUCH_METHOD, | 424 enqueuer.codegen.registerInvocation(NO_SUCH_METHOD, |
| 423 Selector.INVOCATION_2); | 425 Selector.INVOCATION_2); |
| 424 } | 426 } |
| 425 | 427 |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 813 } | 815 } |
| 814 for (Element e in new Set.from(resolved)) { | 816 for (Element e in new Set.from(resolved)) { |
| 815 if (e.isClass() || | 817 if (e.isClass() || |
| 816 e.isField() || | 818 e.isField() || |
| 817 e.isTypeVariable() || | 819 e.isTypeVariable() || |
| 818 e.isTypedef() || | 820 e.isTypedef() || |
| 819 e.kind === ElementKind.ABSTRACT_FIELD) { | 821 e.kind === ElementKind.ABSTRACT_FIELD) { |
| 820 resolved.remove(e); | 822 resolved.remove(e); |
| 821 } | 823 } |
| 822 if (e.kind === ElementKind.GENERATIVE_CONSTRUCTOR) { | 824 if (e.kind === ElementKind.GENERATIVE_CONSTRUCTOR) { |
| 823 ClassElement enclosingClass = e.enclosingElement; | 825 ClassElement enclosingClass = e.getEnclosingClass(); |
| 824 if (enclosingClass.isInterface()) { | 826 if (enclosingClass.isInterface()) { |
| 825 resolved.remove(e); | 827 resolved.remove(e); |
| 826 } | 828 } |
| 827 resolved.remove(e); | 829 resolved.remove(e); |
| 828 | 830 |
| 829 } | 831 } |
| 830 if (e.getLibrary() === jsHelperLibrary) { | 832 if (e.getLibrary() === jsHelperLibrary) { |
| 831 resolved.remove(e); | 833 resolved.remove(e); |
| 832 } | 834 } |
| 833 if (e.getLibrary() === interceptorsLibrary) { | 835 if (e.getLibrary() === interceptorsLibrary) { |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1101 final endOffset = end.charOffset + end.slowCharCount; | 1103 final endOffset = end.charOffset + end.slowCharCount; |
| 1102 | 1104 |
| 1103 // [begin] and [end] might be the same for the same empty token. This | 1105 // [begin] and [end] might be the same for the same empty token. This |
| 1104 // happens for instance when scanning '$$'. | 1106 // happens for instance when scanning '$$'. |
| 1105 assert(endOffset >= beginOffset); | 1107 assert(endOffset >= beginOffset); |
| 1106 return f(beginOffset, endOffset); | 1108 return f(beginOffset, endOffset); |
| 1107 } | 1109 } |
| 1108 | 1110 |
| 1109 String toString() => 'SourceSpan($uri, $begin, $end)'; | 1111 String toString() => 'SourceSpan($uri, $begin, $end)'; |
| 1110 } | 1112 } |
| OLD | NEW |