Chromium Code Reviews| 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 50 abstract void assembleProgram(); | 50 abstract void assembleProgram(); |
| 51 abstract List<CompilerTask> get tasks(); | 51 abstract List<CompilerTask> get tasks(); |
| 52 } | 52 } |
| 53 | 53 |
| 54 class JavaScriptBackend extends Backend { | 54 class JavaScriptBackend extends Backend { |
| 55 SsaBuilderTask builder; | 55 SsaBuilderTask builder; |
| 56 SsaOptimizerTask optimizer; | 56 SsaOptimizerTask optimizer; |
| 57 SsaCodeGeneratorTask generator; | 57 SsaCodeGeneratorTask generator; |
| 58 CodeEmitterTask emitter; | 58 CodeEmitterTask emitter; |
| 59 final Map<Element, Map<Element, HType>> fieldInitializers; | 59 final Map<Element, Map<Element, HType>> fieldInitializers; |
| 60 final Map<Element, Map<Element, HType>> fieldConstructorSetters; | |
|
floitsch
2012/06/22 08:18:12
Do we need this two-stage approach? Shouldn't it b
Søren Gjesse
2012/06/22 09:22:36
The reason for this is that we know that field wil
| |
| 60 final Map<Element, Map<Element, bool>> fieldIntegerSetters; | 61 final Map<Element, Map<Element, bool>> fieldIntegerSetters; |
| 61 | 62 |
| 62 List<CompilerTask> get tasks() { | 63 List<CompilerTask> get tasks() { |
| 63 return <CompilerTask>[builder, optimizer, generator, emitter]; | 64 return <CompilerTask>[builder, optimizer, generator, emitter]; |
| 64 } | 65 } |
| 65 | 66 |
| 66 JavaScriptBackend(Compiler compiler, bool generateSourceMap) | 67 JavaScriptBackend(Compiler compiler, bool generateSourceMap) |
| 67 : emitter = new CodeEmitterTask(compiler, generateSourceMap), | 68 : emitter = new CodeEmitterTask(compiler, generateSourceMap), |
| 68 fieldInitializers = new Map<Element, Map<Element, HType>>(), | 69 fieldInitializers = new Map<Element, Map<Element, HType>>(), |
| 70 fieldConstructorSetters = new Map<Element, Map<Element, HType>>(), | |
| 69 fieldIntegerSetters = new Map<Element, Map<Element, bool>>(), | 71 fieldIntegerSetters = new Map<Element, Map<Element, bool>>(), |
| 70 super(compiler) { | 72 super(compiler) { |
| 71 builder = new SsaBuilderTask(this); | 73 builder = new SsaBuilderTask(this); |
| 72 optimizer = new SsaOptimizerTask(this); | 74 optimizer = new SsaOptimizerTask(this); |
| 73 generator = new SsaCodeGeneratorTask(this); | 75 generator = new SsaCodeGeneratorTask(this); |
| 74 } | 76 } |
| 75 | 77 |
| 76 void enqueueHelpers(Enqueuer world) { | 78 void enqueueHelpers(Enqueuer world) { |
| 77 enqueueAllTopLevelFunctions(compiler.jsHelperLibrary, world); | 79 enqueueAllTopLevelFunctions(compiler.jsHelperLibrary, world); |
| 78 enqueueAllTopLevelFunctions(compiler.interceptorsLibrary, world); | 80 enqueueAllTopLevelFunctions(compiler.interceptorsLibrary, world); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 135 bool hasFieldSingleTypeInitializers(Element field, HType requestedType) { | 137 bool hasFieldSingleTypeInitializers(Element field, HType requestedType) { |
| 136 assert(field.isField()); | 138 assert(field.isField()); |
| 137 assert(field.enclosingElement.isClass()); | 139 assert(field.enclosingElement.isClass()); |
| 138 if (!fieldInitializers.containsKey(field.enclosingElement)) return false; | 140 if (!fieldInitializers.containsKey(field.enclosingElement)) return false; |
| 139 Map<Element, HType> fields = fieldInitializers[field.enclosingElement]; | 141 Map<Element, HType> fields = fieldInitializers[field.enclosingElement]; |
| 140 HType propagatedType = fields[field]; | 142 HType propagatedType = fields[field]; |
| 141 if (propagatedType == null) return false; | 143 if (propagatedType == null) return false; |
| 142 return propagatedType == requestedType; | 144 return propagatedType == requestedType; |
| 143 } | 145 } |
| 144 | 146 |
| 147 void updateFieldConstructorSetters(Element field, HType type) { | |
| 148 assert(field.isField()); | |
| 149 assert(field.enclosingElement.isClass()); | |
| 150 Map<Element, HType> fields = | |
| 151 fieldConstructorSetters.putIfAbsent( | |
| 152 field.enclosingElement, () => new Map<Element, HType>()); | |
| 153 if (!fields.containsKey(field)) { | |
| 154 fields[field] = type; | |
| 155 } else { | |
| 156 fields[field] = fields[field].union(type); | |
| 157 } | |
| 158 } | |
| 159 | |
| 160 // Check if this field set in the constructor body. | |
|
floitsch
2012/06/22 08:18:12
is set
Søren Gjesse
2012/06/22 09:22:36
Done.
| |
| 161 bool hasConstructorBodyFieldSetter(Element field) { | |
| 162 if (!fieldConstructorSetters.containsKey(field.enclosingElement)) { | |
| 163 return false; | |
| 164 } | |
| 165 return fieldConstructorSetters[field.enclosingElement][field] != null; | |
| 166 } | |
| 167 | |
| 168 // Provide an optimistic estimate of the type of a field after construction. | |
| 169 // This only takes the initializer lists and field assignments in the | |
| 170 // constructor body into account. The constructor body might have method calls | |
| 171 // that could alter the field. | |
| 172 HType optimisticFieldTypeAfterConstruction(Element field) { | |
| 173 assert(field.isField()); | |
| 174 assert(field.enclosingElement.isClass()); | |
| 175 | |
| 176 if (hasConstructorBodyFieldSetter(field)) { | |
| 177 // If there are field setters for this field in some constructor only one | |
| 178 // constructor then the type set will be the field type after | |
| 179 // construction. | |
| 180 if (field.enclosingElement.constructors.length == 1) { | |
| 181 return fieldConstructorSetters[field.enclosingElement][field]; | |
| 182 } else { | |
| 183 return HType.UNKNOWN; | |
| 184 } | |
| 185 } else if (fieldInitializers.containsKey(field.enclosingElement)) { | |
| 186 HType type = fieldInitializers[field.enclosingElement][field]; | |
| 187 return type == null ? HType.UNKNOWN : type; | |
| 188 } else { | |
| 189 return HType.UNKNOWN; | |
| 190 } | |
| 191 } | |
| 192 | |
| 145 void updateFieldIntegerSetters(Element field, bool isInteger) { | 193 void updateFieldIntegerSetters(Element field, bool isInteger) { |
| 146 assert(field.isField()); | 194 assert(field.isField()); |
| 147 assert(field.enclosingElement.isClass()); | 195 assert(field.enclosingElement.isClass()); |
| 148 Map<Element, bool> fields = | 196 Map<Element, bool> fields = |
| 149 fieldIntegerSetters.putIfAbsent( | 197 fieldIntegerSetters.putIfAbsent( |
| 150 field.enclosingElement, () => new Map<Element, bool>()); | 198 field.enclosingElement, () => new Map<Element, bool>()); |
| 151 if (!fields.containsKey(field)) { | 199 if (!fields.containsKey(field)) { |
| 152 fields[field] = isInteger; | 200 fields[field] = isInteger; |
| 153 } else { | 201 } else { |
| 154 fields[field] = fields[field] && isInteger; | 202 fields[field] = fields[field] && isInteger; |
| (...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 834 // invariant that endOffset > beginOffset, but for EOF the | 882 // invariant that endOffset > beginOffset, but for EOF the |
| 835 // charoffset of the next token may be [beginOffset]. This can | 883 // charoffset of the next token may be [beginOffset]. This can |
| 836 // also happen for synthetized tokens that are produced during | 884 // also happen for synthetized tokens that are produced during |
| 837 // error handling. | 885 // error handling. |
| 838 final endOffset = | 886 final endOffset = |
| 839 Math.max((end.next !== null) ? end.next.charOffset : 0, beginOffset + 1); | 887 Math.max((end.next !== null) ? end.next.charOffset : 0, beginOffset + 1); |
| 840 assert(endOffset > beginOffset); | 888 assert(endOffset > beginOffset); |
| 841 return f(beginOffset, endOffset); | 889 return f(beginOffset, endOffset); |
| 842 } | 890 } |
| 843 } | 891 } |
| OLD | NEW |