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

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

Issue 10824234: Reapply "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: 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
« no previous file with comments | « no previous file | lib/compiler/implementation/enqueue.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 {
55 int parameterCount;
56 List<HType> providedTypes;
57 List<Element> compiledFunctions;
58
59 InvocationInfo(List<HType> types)
60 : parameterCount = types != null ? types.length : -1,
61 providedTypes = types,
62 compiledFunctions = new List<Element>();
63
64 addCompiledFunction(FunctionElement function) =>
65 compiledFunctions.add(function);
66
67 void clearTypeInformation() => providedTypes = null;
68 bool get hasTypeInformation() => providedTypes != null;
69
70 }
71
54 class JavaScriptBackend extends Backend { 72 class JavaScriptBackend extends Backend {
55 SsaBuilderTask builder; 73 SsaBuilderTask builder;
56 SsaOptimizerTask optimizer; 74 SsaOptimizerTask optimizer;
57 SsaCodeGeneratorTask generator; 75 SsaCodeGeneratorTask generator;
58 CodeEmitterTask emitter; 76 CodeEmitterTask emitter;
59 final Map<Element, Map<Element, HType>> fieldInitializers; 77 final Map<Element, Map<Element, HType>> fieldInitializers;
60 final Map<Element, Map<Element, HType>> fieldConstructorSetters; 78 final Map<Element, Map<Element, HType>> fieldConstructorSetters;
61 final Map<Element, Map<Element, HType>> fieldSettersType; 79 final Map<Element, Map<Element, HType>> fieldSettersType;
62 80
81 final Map<SourceString, Map<Selector, InvocationInfo>> invocationInfo;
82
63 List<CompilerTask> get tasks() { 83 List<CompilerTask> get tasks() {
64 return <CompilerTask>[builder, optimizer, generator, emitter]; 84 return <CompilerTask>[builder, optimizer, generator, emitter];
65 } 85 }
66 86
67 JavaScriptBackend(Compiler compiler, bool generateSourceMap) 87 JavaScriptBackend(Compiler compiler, bool generateSourceMap)
68 : emitter = new CodeEmitterTask(compiler, generateSourceMap), 88 : emitter = new CodeEmitterTask(compiler, generateSourceMap),
69 fieldInitializers = new Map<Element, Map<Element, HType>>(), 89 fieldInitializers = new Map<Element, Map<Element, HType>>(),
70 fieldConstructorSetters = new Map<Element, Map<Element, HType>>(), 90 fieldConstructorSetters = new Map<Element, Map<Element, HType>>(),
71 fieldSettersType = new Map<Element, Map<Element, HType>>(), 91 fieldSettersType = new Map<Element, Map<Element, HType>>(),
92 invocationInfo = new Map<SourceString, Map<Selector, InvocationInfo>>(),
72 super(compiler) { 93 super(compiler) {
73 builder = new SsaBuilderTask(this); 94 builder = new SsaBuilderTask(this);
74 optimizer = new SsaOptimizerTask(this); 95 optimizer = new SsaOptimizerTask(this);
75 generator = new SsaCodeGeneratorTask(this); 96 generator = new SsaCodeGeneratorTask(this);
76 } 97 }
77 98
78 void enqueueHelpers(Enqueuer world) { 99 void enqueueHelpers(Enqueuer world) {
79 enqueueAllTopLevelFunctions(compiler.jsHelperLibrary, world); 100 enqueueAllTopLevelFunctions(compiler.jsHelperLibrary, world);
80 enqueueAllTopLevelFunctions(compiler.interceptorsLibrary, world); 101 enqueueAllTopLevelFunctions(compiler.interceptorsLibrary, world);
81 for (var helper in [const SourceString('Closure'), 102 for (var helper in [const SourceString('Closure'),
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 HType fieldSettersTypeSoFar(Element field) { 218 HType fieldSettersTypeSoFar(Element field) {
198 assert(field.isField()); 219 assert(field.isField());
199 assert(field.enclosingElement.isClass()); 220 assert(field.enclosingElement.isClass());
200 if (!fieldSettersType.containsKey(field.enclosingElement)) { 221 if (!fieldSettersType.containsKey(field.enclosingElement)) {
201 return HType.CONFLICTING; 222 return HType.CONFLICTING;
202 } 223 }
203 Map<Element, HType> fields = fieldSettersType[field.enclosingElement]; 224 Map<Element, HType> fields = fieldSettersType[field.enclosingElement];
204 if (!fields.containsKey(field)) return HType.CONFLICTING; 225 if (!fields.containsKey(field)) return HType.CONFLICTING;
205 return fields[field]; 226 return fields[field];
206 } 227 }
228
229 /**
230 * Register a dynamic invocation and collect the provided types for the
231 * named selector.
232 */
233 void registerDynamicInvocation(HInvokeDynamicMethod node, Selector selector) {
234 Map<Selector, InvocationInfo> invocationInfos =
235 invocationInfo.putIfAbsent(node.name,
236 () => new Map<Selector, InvocationInfo>());
237 InvocationInfo info = invocationInfos[selector];
238 if (info != null) {
239 // If we don't know anything useful about the types adding more
240 // information will not help.
241 if (!info.hasTypeInformation) return;
242
243 // Update the type information with the provided types.
244 bool typesChanged = false;
245 List<HType> types = info.providedTypes;
246 bool allUnknown = true;
247 for (int i = 0; i < types.length; i++) {
248 HType newType = types[i].union(node.inputs[i + 1].propagatedType);
249 if (newType != types[i]) {
250 typesChanged = true;
251 types[i] = newType;
252 }
253 if (types[i] != HType.UNKNOWN) allUnknown = false;
254 }
255 // If the provided types change we need to recompile all functions which
256 // have been compiled under the now invalidated assumptions.
257 if (typesChanged && info.compiledFunctions.length != 0) {
258 if (compiler.phase == Compiler.PHASE_COMPILING) {
259 info.compiledFunctions.forEach(
260 compiler.enqueuer.codegen.eagerRecompile);
261 info.compiledFunctions.clear();
262 }
263 }
264 // If all information is lost no need to keep it around.
265 if (allUnknown) info.clearTypeInformation();
266 } else {
267 // Gather the type information provided. If the types contains no useful
268 // information there is no need to actually store them.
269 bool allUnknown = true;
270 for (int i = 1; i < node.inputs.length; i++) {
271 if (node.inputs[i].propagatedType != HType.UNKNOWN) {
272 allUnknown = false;
273 break;
274 }
275 }
276 List<HType> types = null;
277 if (!allUnknown) {
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 /**
289 * Retreive the types of the parameters used for calling the [element]
290 * function. The types are optimistic in the sense as they are based on the
291 * possible invocations of the function seen so far. As compiling more
292 * code can invalidate this asumption the function is registered for being
293 * re-compiled if new possible invocations of this function invalidate these
294 * asumptions.
295 */
296 List<HType> optimisticParameterTypesWithRecompilationOnTypeChange(
297 FunctionElement element) {
298 Map<Selector, InvocationInfo> invocationInfos =
299 invocationInfo[element.name];
300 if (invocationInfos == null) return null;
301
302 int foundCount = 0;
303 InvocationInfo found = null;
304 invocationInfos.forEach((Selector selector, InvocationInfo info) {
305 if (selector.applies(element, compiler)) {
306 found = info;
307 foundCount++;
308 }
309 });
310
311 if (foundCount == 1 && found.hasTypeInformation) {
312 FunctionSignature signature = element.computeSignature(compiler);
313 if (signature.parameterCount == found.parameterCount) {
314 found.addCompiledFunction(element);
315 return found.providedTypes;
316 }
317 }
318 return null;
319 }
207 } 320 }
208 321
209 class Compiler implements DiagnosticListener { 322 class Compiler implements DiagnosticListener {
210 final Map<String, LibraryElement> libraries; 323 final Map<String, LibraryElement> libraries;
211 int nextFreeClassId = 0; 324 int nextFreeClassId = 0;
212 World world; 325 World world;
213 String assembledCode; 326 String assembledCode;
214 Namer namer; 327 Namer namer;
215 Types types; 328 Types types;
216 final bool enableTypeAssertions; 329 final bool enableTypeAssertions;
(...skipping 884 matching lines...) Expand 10 before | Expand all | Expand 10 after
1101 final endOffset = end.charOffset + end.slowCharCount; 1214 final endOffset = end.charOffset + end.slowCharCount;
1102 1215
1103 // [begin] and [end] might be the same for the same empty token. This 1216 // [begin] and [end] might be the same for the same empty token. This
1104 // happens for instance when scanning '$$'. 1217 // happens for instance when scanning '$$'.
1105 assert(endOffset >= beginOffset); 1218 assert(endOffset >= beginOffset);
1106 return f(beginOffset, endOffset); 1219 return f(beginOffset, endOffset);
1107 } 1220 }
1108 1221
1109 String toString() => 'SourceSpan($uri, $begin, $end)'; 1222 String toString() => 'SourceSpan($uri, $begin, $end)';
1110 } 1223 }
OLDNEW
« no previous file with comments | « no previous file | lib/compiler/implementation/enqueue.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698