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

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

Issue 10827181: Collect call site information and use that for estimating parameter types (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed review comments Created 8 years, 4 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 } 44 }
45 45
46 abstract void enqueueHelpers(Enqueuer world); 46 abstract void enqueueHelpers(Enqueuer world);
47 abstract CodeBuffer codegen(WorkItem work); 47 abstract CodeBuffer codegen(WorkItem work);
48 abstract void processNativeClasses(Enqueuer world, 48 abstract void processNativeClasses(Enqueuer world,
49 Collection<LibraryElement> libraries); 49 Collection<LibraryElement> libraries);
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 InvocationInfo {
ahe 2012/08/07 11:23:26 I don't think this class belongs in this file.
Søren Gjesse 2012/08/08 10:36:02 I agree. I will move this and the JavaScriptBacken
ahe 2012/08/08 13:00:27 SGTM
55 InvocationInfo(List<HType> types)
56 : parameterCount = types != null ? types.length : -1,
57 providedTypes = types,
58 compiledFunctions = new List<Element>();
59
60 addCompiledFunction(FunctionElement function) =>
61 compiledFunctions.add(function);
62
63 void clearTypeInformation() => providedTypes = null;
64 bool get hasTypeInformation() => providedTypes != null;
65
66 int parameterCount;
ahe 2012/08/07 11:23:26 Please follow this sequence of members: fields, c
Søren Gjesse 2012/08/08 10:36:02 Done.
67 List<HType> providedTypes;
68 List<Element> compiledFunctions;
69 }
70
54 class JavaScriptBackend extends Backend { 71 class JavaScriptBackend extends Backend {
55 SsaBuilderTask builder; 72 SsaBuilderTask builder;
56 SsaOptimizerTask optimizer; 73 SsaOptimizerTask optimizer;
57 SsaCodeGeneratorTask generator; 74 SsaCodeGeneratorTask generator;
58 CodeEmitterTask emitter; 75 CodeEmitterTask emitter;
59 final Map<Element, Map<Element, HType>> fieldInitializers; 76 final Map<Element, Map<Element, HType>> fieldInitializers;
60 final Map<Element, Map<Element, HType>> fieldConstructorSetters; 77 final Map<Element, Map<Element, HType>> fieldConstructorSetters;
61 final Map<Element, Map<Element, HType>> fieldSettersType; 78 final Map<Element, Map<Element, HType>> fieldSettersType;
62 79
80 final Map<SourceString, Map<Selector, InvocationInfo>> invocationInfo;
81
63 List<CompilerTask> get tasks() { 82 List<CompilerTask> get tasks() {
64 return <CompilerTask>[builder, optimizer, generator, emitter]; 83 return <CompilerTask>[builder, optimizer, generator, emitter];
65 } 84 }
66 85
67 JavaScriptBackend(Compiler compiler, bool generateSourceMap) 86 JavaScriptBackend(Compiler compiler, bool generateSourceMap)
68 : emitter = new CodeEmitterTask(compiler, generateSourceMap), 87 : emitter = new CodeEmitterTask(compiler, generateSourceMap),
69 fieldInitializers = new Map<Element, Map<Element, HType>>(), 88 fieldInitializers = new Map<Element, Map<Element, HType>>(),
70 fieldConstructorSetters = new Map<Element, Map<Element, HType>>(), 89 fieldConstructorSetters = new Map<Element, Map<Element, HType>>(),
71 fieldSettersType = new Map<Element, Map<Element, HType>>(), 90 fieldSettersType = new Map<Element, Map<Element, HType>>(),
91 invocationInfo = new Map<SourceString, Map<Selector, InvocationInfo>>(),
72 super(compiler) { 92 super(compiler) {
73 builder = new SsaBuilderTask(this); 93 builder = new SsaBuilderTask(this);
74 optimizer = new SsaOptimizerTask(this); 94 optimizer = new SsaOptimizerTask(this);
75 generator = new SsaCodeGeneratorTask(this); 95 generator = new SsaCodeGeneratorTask(this);
76 } 96 }
77 97
78 void enqueueHelpers(Enqueuer world) { 98 void enqueueHelpers(Enqueuer world) {
79 enqueueAllTopLevelFunctions(compiler.jsHelperLibrary, world); 99 enqueueAllTopLevelFunctions(compiler.jsHelperLibrary, world);
80 enqueueAllTopLevelFunctions(compiler.interceptorsLibrary, world); 100 enqueueAllTopLevelFunctions(compiler.interceptorsLibrary, world);
81 for (var helper in [const SourceString('Closure'), 101 for (var helper in [const SourceString('Closure'),
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 HType fieldSettersTypeSoFar(Element field) { 217 HType fieldSettersTypeSoFar(Element field) {
198 assert(field.isField()); 218 assert(field.isField());
199 assert(field.enclosingElement.isClass()); 219 assert(field.enclosingElement.isClass());
200 if (!fieldSettersType.containsKey(field.enclosingElement)) { 220 if (!fieldSettersType.containsKey(field.enclosingElement)) {
201 return HType.CONFLICTING; 221 return HType.CONFLICTING;
202 } 222 }
203 Map<Element, HType> fields = fieldSettersType[field.enclosingElement]; 223 Map<Element, HType> fields = fieldSettersType[field.enclosingElement];
204 if (!fields.containsKey(field)) return HType.CONFLICTING; 224 if (!fields.containsKey(field)) return HType.CONFLICTING;
205 return fields[field]; 225 return fields[field];
206 } 226 }
227
228 // Register a dynamic invocation and collects the provided types for the
ahe 2012/08/07 11:23:26 collects -> collect.
ahe 2012/08/07 11:23:26 This should be a documentation comment, that is, u
Søren Gjesse 2012/08/08 10:36:02 Done.
Søren Gjesse 2012/08/08 10:36:02 Done.
229 // named selector.
230 void registerDynamicInvocation(HInvokeDynamicMethod node, Selector selector) {
ahe 2012/08/07 11:23:26 It would be great if you could move this out of co
Søren Gjesse 2012/08/08 10:36:02 Will do.
231 Map<Selector, InvocationInfo> invocationInfos =
232 invocationInfo.putIfAbsent(node.name,
233 () => new Map<Selector, InvocationInfo>());
234 InvocationInfo info = invocationInfos[selector];
235 if (info != null) {
236 // If we don't know anything useful about the types adding more
237 // information will not help.
238 if (!info.hasTypeInformation) return;
239
240 // Update the type information with the provided types.
241 bool typesChanged = false;
242 List<HType> types = info.providedTypes;
243 bool allUnknown = true;
244 for (int i = 0; i < types.length; i++) {
245 HType newType = types[i].union(node.inputs[i + 1].propagatedType);
246 if (newType != types[i]) {
247 typesChanged = true;
248 types[i] = newType;
249 }
250 if (types[i] != HType.UNKNOWN) allUnknown = false;
251 }
252 // If the provided types change we need to recompile all functions which
253 // have been compiled under the now invalidated assumptions.
254 if (typesChanged && info.compiledFunctions.length != 0) {
255 if (compiler.phase == Compiler.PHASE_COMPILING) {
256 info.compiledFunctions.forEach(
ahe 2012/08/07 11:23:26 info.compiledFunctions.forEach(compiler.enqueuer.c
Søren Gjesse 2012/08/08 10:36:02 Done.
257 (e) => compiler.enqueuer.codegen.eagerRecompile(e)
258 );
259 info.compiledFunctions.clear();
260 }
261 }
262 // If all information is lost no need to keep it around.
263 if (allUnknown) info.clearTypeInformation();
264 } else {
265 // Gather the type information provided. If the types contains no useful
266 // information there is no need to actually store them.
267 bool allUnknown = true;
268 for (int i = 1; i < node.inputs.length; i++) {
269 if (node.inputs[i].propagatedType != HType.UNKNOWN) {
270 allUnknown = false;
271 break;
272 }
273 }
274 List<HType> types;
275 if (allUnknown) {
276 types == null;
ahe 2012/08/07 11:23:26 This is a no-op.
Søren Gjesse 2012/08/08 10:36:02 Fixed.
277 } else {
278 types = new List<HType>(node.inputs.length - 1);
279 for (int i = 0; i < types.length; i++) {
280 types[i] = node.inputs[i + 1].propagatedType;
281 }
282 }
283 InvocationInfo info = new InvocationInfo(types);
284 invocationInfos[selector] = info;
285 }
286 }
287
288 List<HType> optimisticParameterTypesWithRecompilationOnTypeChange(
ahe 2012/08/07 11:23:26 Please document this method.
Søren Gjesse 2012/08/08 10:36:02 Done.
289 FunctionElement element) {
290 Map<Selector, InvocationInfo> invocationInfos =
291 invocationInfo[element.name];
292 if (invocationInfos == null) return null;
293
294 int foundCount = 0;
295 InvocationInfo found = null;
296 invocationInfos.forEach((Selector selector, InvocationInfo info) {
297 if (selector.applies(element, compiler)) {
298 found = info;
299 foundCount++;
300 }
301 });
302
303 if (foundCount == 1 && found.hasTypeInformation) {
304 FunctionSignature signature = element.computeSignature(compiler);
305 if (signature.parameterCount == found.parameterCount) {
306 found.addCompiledFunction(element);
307 return found.providedTypes;
308 }
309 }
310 return null;
311 }
207 } 312 }
208 313
209 class Compiler implements DiagnosticListener { 314 class Compiler implements DiagnosticListener {
210 final Map<String, LibraryElement> libraries; 315 final Map<String, LibraryElement> libraries;
211 int nextFreeClassId = 0; 316 int nextFreeClassId = 0;
212 World world; 317 World world;
213 String assembledCode; 318 String assembledCode;
214 Namer namer; 319 Namer namer;
215 Types types; 320 Types types;
216 final bool enableTypeAssertions; 321 final bool enableTypeAssertions;
(...skipping 878 matching lines...) Expand 10 before | Expand all | Expand 10 after
1095 final endOffset = end.charOffset + end.slowCharCount; 1200 final endOffset = end.charOffset + end.slowCharCount;
1096 1201
1097 // [begin] and [end] might be the same for the same empty token. This 1202 // [begin] and [end] might be the same for the same empty token. This
1098 // happens for instance when scanning '$$'. 1203 // happens for instance when scanning '$$'.
1099 assert(endOffset >= beginOffset); 1204 assert(endOffset >= beginOffset);
1100 return f(beginOffset, endOffset); 1205 return f(beginOffset, endOffset);
1101 } 1206 }
1102 1207
1103 String toString() => 'SourceSpan($uri, $begin, $end)'; 1208 String toString() => 'SourceSpan($uri, $begin, $end)';
1104 } 1209 }
OLDNEW
« no previous file with comments | « no previous file | lib/compiler/implementation/enqueue.dart » ('j') | lib/compiler/implementation/enqueue.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698