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

Side by Side Diff: lib/compiler/implementation/compiler.dart

Issue 10638013: Improve tracking of the type of fields after object construction (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 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 | Annotate | Revision Log
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | lib/compiler/implementation/elements/elements.dart » ('j') | lib/compiler/implementation/ssa/codegen.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698