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

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

Issue 10855170: Track types for arguments passed to calls to static functions (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
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 class InvocationInfo { 5 class InvocationInfo {
6 int parameterCount; 6 int parameterCount = -1;
7 List<HType> providedTypes; 7 List<HType> providedTypes;
8 List<Element> compiledFunctions; 8 List<Element> compiledFunctions;
9 9
10 InvocationInfo(List<HType> types) 10 InvocationInfo(HInvoke node) : compiledFunctions = new List<Element>() {
floitsch 2012/08/15 09:11:59 nit: move the init into a separate line.
Søren Gjesse 2012/08/15 12:17:10 Done.
11 : parameterCount = types != null ? types.length : -1, 11 // If no node is provided this is an invocation info to indicate no type
12 providedTypes = types, 12 // information.
13 compiledFunctions = new List<Element>(); 13 if (node == null) return;
floitsch 2012/08/15 09:11:59 named constructor: InvocationInfo.withoutType() ?
Søren Gjesse 2012/08/15 12:17:10 Good point, done.
14 // Gather the type information provided. If the types contains no useful
15 // information there is no need to actually store them.
16 bool allUnknown = true;
17 for (int i = 1; i < node.inputs.length; i++) {
18 if (node.inputs[i].propagatedType != HType.UNKNOWN) {
19 allUnknown = false;
20 break;
21 }
22 }
23 if (!allUnknown) {
24 providedTypes = new List<HType>(node.inputs.length - 1);
25 for (int i = 0; i < providedTypes.length; i++) {
26 providedTypes[i] = node.inputs[i + 1].propagatedType;
27 }
28 parameterCount = providedTypes.length;
29 }
30 }
31
32 void update(HInvoke node, var recompile) {
33 // If we don't know anything useful about the types adding more
34 // information will not help.
35 if (!hasTypeInformation) return;
36
37 // Update the type information with the provided types.
38 bool typesChanged = false;
39 bool allUnknown = true;
40 for (int i = 0; i < providedTypes.length; i++) {
41 HType newType = providedTypes[i].union(node.inputs[i + 1].propagatedType);
42 if (newType != providedTypes[i]) {
43 typesChanged = true;
44 providedTypes[i] = newType;
45 }
46 if (providedTypes[i] != HType.UNKNOWN) allUnknown = false;
47 }
48 // If the provided types change we need to recompile all functions which
49 // have been compiled under the now invalidated assumptions.
50 if (typesChanged && compiledFunctions.length != 0) {
51 if (recompile != null) {
52 compiledFunctions.forEach(recompile);
53 }
54 compiledFunctions.clear();
55 }
56 // If all information is lost no need to keep it around.
57 if (allUnknown) clearTypeInformation();
58 }
14 59
15 addCompiledFunction(FunctionElement function) => 60 addCompiledFunction(FunctionElement function) =>
16 compiledFunctions.add(function); 61 compiledFunctions.add(function);
17 62
18 void clearTypeInformation() => providedTypes = null; 63 void clearTypeInformation() => providedTypes = null;
19 bool get hasTypeInformation() => providedTypes != null; 64 bool get hasTypeInformation() => providedTypes != null;
20 65
21 } 66 }
22 67
23 class JavaScriptBackend extends Backend { 68 class JavaScriptBackend extends Backend {
24 SsaBuilderTask builder; 69 SsaBuilderTask builder;
25 SsaOptimizerTask optimizer; 70 SsaOptimizerTask optimizer;
26 SsaCodeGeneratorTask generator; 71 SsaCodeGeneratorTask generator;
27 CodeEmitterTask emitter; 72 CodeEmitterTask emitter;
28 final Map<Element, Map<Element, HType>> fieldInitializers; 73 final Map<Element, Map<Element, HType>> fieldInitializers;
29 final Map<Element, Map<Element, HType>> fieldConstructorSetters; 74 final Map<Element, Map<Element, HType>> fieldConstructorSetters;
30 final Map<Element, Map<Element, HType>> fieldSettersType; 75 final Map<Element, Map<Element, HType>> fieldSettersType;
31 76
77 final Map<Element, InvocationInfo> staticInvocationInfo;
32 final Map<SourceString, Map<Selector, InvocationInfo>> invocationInfo; 78 final Map<SourceString, Map<Selector, InvocationInfo>> invocationInfo;
33 79
34 final List<Element> invalidateAfterCodegen; 80 final List<Element> invalidateAfterCodegen;
35 81
36 List<CompilerTask> get tasks() { 82 List<CompilerTask> get tasks() {
37 return <CompilerTask>[builder, optimizer, generator, emitter]; 83 return <CompilerTask>[builder, optimizer, generator, emitter];
38 } 84 }
39 85
40 JavaScriptBackend(Compiler compiler, bool generateSourceMap) 86 JavaScriptBackend(Compiler compiler, bool generateSourceMap)
41 : emitter = new CodeEmitterTask(compiler, generateSourceMap), 87 : emitter = new CodeEmitterTask(compiler, generateSourceMap),
42 fieldInitializers = new Map<Element, Map<Element, HType>>(), 88 fieldInitializers = new Map<Element, Map<Element, HType>>(),
43 fieldConstructorSetters = new Map<Element, Map<Element, HType>>(), 89 fieldConstructorSetters = new Map<Element, Map<Element, HType>>(),
44 fieldSettersType = new Map<Element, Map<Element, HType>>(), 90 fieldSettersType = new Map<Element, Map<Element, HType>>(),
45 invocationInfo = new Map<SourceString, Map<Selector, InvocationInfo>>(), 91 invocationInfo = new Map<SourceString, Map<Selector, InvocationInfo>>(),
92 staticInvocationInfo = new Map<Element, InvocationInfo>(),
46 invalidateAfterCodegen = new List<Element>(), 93 invalidateAfterCodegen = new List<Element>(),
47 super(compiler) { 94 super(compiler) {
48 builder = new SsaBuilderTask(this); 95 builder = new SsaBuilderTask(this);
49 optimizer = new SsaOptimizerTask(this); 96 optimizer = new SsaOptimizerTask(this);
50 generator = new SsaCodeGeneratorTask(this); 97 generator = new SsaCodeGeneratorTask(this);
51 } 98 }
52 99
53 void enqueueHelpers(Enqueuer world) { 100 void enqueueHelpers(Enqueuer world) {
54 enqueueAllTopLevelFunctions(compiler.jsHelperLibrary, world); 101 enqueueAllTopLevelFunctions(compiler.jsHelperLibrary, world);
55 enqueueAllTopLevelFunctions(compiler.interceptorsLibrary, world); 102 enqueueAllTopLevelFunctions(compiler.interceptorsLibrary, world);
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 /** 237 /**
191 * Register a dynamic invocation and collect the provided types for the 238 * Register a dynamic invocation and collect the provided types for the
192 * named selector. 239 * named selector.
193 */ 240 */
194 void registerDynamicInvocation(HInvokeDynamicMethod node, Selector selector) { 241 void registerDynamicInvocation(HInvokeDynamicMethod node, Selector selector) {
195 Map<Selector, InvocationInfo> invocationInfos = 242 Map<Selector, InvocationInfo> invocationInfos =
196 invocationInfo.putIfAbsent(node.name, 243 invocationInfo.putIfAbsent(node.name,
197 () => new Map<Selector, InvocationInfo>()); 244 () => new Map<Selector, InvocationInfo>());
198 InvocationInfo info = invocationInfos[selector]; 245 InvocationInfo info = invocationInfos[selector];
199 if (info != null) { 246 if (info != null) {
200 // If we don't know anything useful about the types adding more 247 recompile(Element element) {
floitsch 2012/08/15 09:11:59 void recompile(Element element) {
Søren Gjesse 2012/08/15 12:17:10 Done.
201 // information will not help. 248 if (compiler.phase == Compiler.PHASE_COMPILING) {
202 if (!info.hasTypeInformation) return; 249 invalidateAfterCodegen.add(element);
250 }
251 }
floitsch 2012/08/15 09:11:59 new line after function declarations.
Søren Gjesse 2012/08/15 12:17:10 Done.
252 info.update(node, recompile);
253 } else {
254 invocationInfos[selector] = new InvocationInfo(node);
255 }
256 }
203 257
204 // Update the type information with the provided types. 258 /**
205 bool typesChanged = false; 259 * Register a static invocation and collect the provided types for the
206 List<HType> types = info.providedTypes; 260 * named selector.
207 bool allUnknown = true; 261 */
208 for (int i = 0; i < types.length; i++) { 262 void registerStaticInvocation(HInvokeStatic node) {
209 HType newType = types[i].union(node.inputs[i + 1].propagatedType); 263 InvocationInfo info = staticInvocationInfo[node.element];
210 if (newType != types[i]) { 264 if (info != null) {
211 typesChanged = true; 265 recompile(Element element) {
212 types[i] = newType; 266 if (compiler.phase == Compiler.PHASE_COMPILING) {
267 invalidateAfterCodegen.add(element);
213 } 268 }
214 if (types[i] != HType.UNKNOWN) allUnknown = false;
215 } 269 }
216 // If the provided types change we need to recompile all functions which 270 info.update(node, recompile);
217 // have been compiled under the now invalidated assumptions. 271 } else {
218 if (typesChanged && info.compiledFunctions.length != 0) { 272 staticInvocationInfo[node.element] = new InvocationInfo(node);
273 }
274 }
275
276 /**
277 * Register that a static is used for something else than a call target.
278 */
279 void registerNonCallStaticUse(HStatic node) {
floitsch 2012/08/15 09:11:59 where is the same functionality for dynamic calls?
Søren Gjesse 2012/08/15 12:17:10 We don't have it, and its a bug. I have filed http
280 // When a static is used for anything else than a call target we cannot
281 // infer anything about its parameter types.
282 InvocationInfo info = staticInvocationInfo[node.element];
283 if (info == null) {
284 staticInvocationInfo[node.element] = new InvocationInfo(null);
285 } else {
286 info.clearTypeInformation();
287 if (info.compiledFunctions.length != 0) {
219 if (compiler.phase == Compiler.PHASE_COMPILING) { 288 if (compiler.phase == Compiler.PHASE_COMPILING) {
220 info.compiledFunctions.forEach(invalidateAfterCodegen.add); 289 info.compiledFunctions.forEach(invalidateAfterCodegen.add);
221 info.compiledFunctions.clear(); 290 info.compiledFunctions.clear();
222 } 291 }
223 } 292 }
224 // If all information is lost no need to keep it around.
225 if (allUnknown) info.clearTypeInformation();
226 } else {
227 // Gather the type information provided. If the types contains no useful
228 // information there is no need to actually store them.
229 bool allUnknown = true;
230 for (int i = 1; i < node.inputs.length; i++) {
231 if (node.inputs[i].propagatedType != HType.UNKNOWN) {
232 allUnknown = false;
233 break;
234 }
235 }
236 List<HType> types = null;
237 if (!allUnknown) {
238 types = new List<HType>(node.inputs.length - 1);
239 for (int i = 0; i < types.length; i++) {
240 types[i] = node.inputs[i + 1].propagatedType;
241 }
242 }
243 InvocationInfo info = new InvocationInfo(types);
244 invocationInfos[selector] = info;
245 } 293 }
246 } 294 }
247 295
248 /** 296 /**
249 * Retreive the types of the parameters used for calling the [element] 297 * Retreive the types of the parameters used for calling the [element]
250 * function. The types are optimistic in the sense as they are based on the 298 * function. The types are optimistic in the sense as they are based on the
251 * possible invocations of the function seen so far. As compiling more 299 * possible invocations of the function seen so far. As compiling more
252 * code can invalidate this asumption the function is registered for being 300 * code can invalidate this asumption the function is registered for being
253 * re-compiled if new possible invocations of this function invalidate these 301 * re-compiled if new possible invocations of this function invalidate these
254 * asumptions. 302 * asumptions.
255 */ 303 */
256 List<HType> optimisticParameterTypesWithRecompilationOnTypeChange( 304 List<HType> optimisticParameterTypesWithRecompilationOnTypeChange(
257 FunctionElement element) { 305 FunctionElement element) {
258 Map<Selector, InvocationInfo> invocationInfos = 306 if (Elements.isStaticOrTopLevelFunction(element)) {
259 invocationInfo[element.name]; 307 InvocationInfo found = staticInvocationInfo[element];
260 if (invocationInfos == null) return null; 308 if (found != null && found.hasTypeInformation) {
309 FunctionSignature signature = element.computeSignature(compiler);
310 if (signature.parameterCount == found.parameterCount) {
311 found.addCompiledFunction(element);
312 return found.providedTypes;
313 }
314 }
315 return null;
316 } else {
317 Map<Selector, InvocationInfo> invocationInfos =
318 invocationInfo[element.name];
319 if (invocationInfos == null) return null;
261 320
262 int foundCount = 0; 321 int foundCount = 0;
263 InvocationInfo found = null; 322 InvocationInfo found = null;
264 invocationInfos.forEach((Selector selector, InvocationInfo info) { 323 invocationInfos.forEach((Selector selector, InvocationInfo info) {
265 if (selector.applies(element, compiler)) { 324 if (selector.applies(element, compiler)) {
266 found = info; 325 found = info;
267 foundCount++; 326 foundCount++;
327 }
328 });
329
330 if (foundCount == 1 && found.hasTypeInformation) {
331 FunctionSignature signature = element.computeSignature(compiler);
332 if (signature.parameterCount == found.parameterCount) {
333 found.addCompiledFunction(element);
334 return found.providedTypes;
335 }
268 } 336 }
269 }); 337 return null;
270
271 if (foundCount == 1 && found.hasTypeInformation) {
272 FunctionSignature signature = element.computeSignature(compiler);
273 if (signature.parameterCount == found.parameterCount) {
274 found.addCompiledFunction(element);
275 return found.providedTypes;
276 }
277 } 338 }
278 return null;
279 } 339 }
280 } 340 }
OLDNEW
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/codegen.dart » ('j') | lib/compiler/implementation/ssa/codegen.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698