| 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 class InvocationInfo { | 5 class InvocationInfo { |
| 6 int parameterCount = -1; | 6 int parameterCount = -1; |
| 7 List<HType> providedTypes; | 7 List<HType> providedTypes; |
| 8 List<Element> compiledFunctions; | 8 List<Element> compiledFunctions; |
| 9 | 9 |
| 10 InvocationInfo(HInvoke node) | 10 InvocationInfo(HInvoke node, HTypeMap types) |
| 11 : compiledFunctions = new List<Element>() { | 11 : compiledFunctions = new List<Element>() { |
| 12 assert(node != null); | 12 assert(node != null); |
| 13 // Gather the type information provided. If the types contains no useful | 13 // Gather the type information provided. If the types contains no useful |
| 14 // information there is no need to actually store them. | 14 // information there is no need to actually store them. |
| 15 bool allUnknown = true; | 15 bool allUnknown = true; |
| 16 for (int i = 1; i < node.inputs.length; i++) { | 16 for (int i = 1; i < node.inputs.length; i++) { |
| 17 if (node.inputs[i].propagatedType != HType.UNKNOWN) { | 17 if (types[node.inputs[i]] != HType.UNKNOWN) { |
| 18 allUnknown = false; | 18 allUnknown = false; |
| 19 break; | 19 break; |
| 20 } | 20 } |
| 21 } | 21 } |
| 22 if (!allUnknown) { | 22 if (!allUnknown) { |
| 23 providedTypes = new List<HType>(node.inputs.length - 1); | 23 providedTypes = new List<HType>(node.inputs.length - 1); |
| 24 for (int i = 0; i < providedTypes.length; i++) { | 24 for (int i = 0; i < providedTypes.length; i++) { |
| 25 providedTypes[i] = node.inputs[i + 1].propagatedType; | 25 providedTypes[i] = types[node.inputs[i + 1]]; |
| 26 } | 26 } |
| 27 parameterCount = providedTypes.length; | 27 parameterCount = providedTypes.length; |
| 28 } | 28 } |
| 29 } | 29 } |
| 30 | 30 |
| 31 InvocationInfo.unknownTypes(); | 31 InvocationInfo.unknownTypes(); |
| 32 | 32 |
| 33 void update(HInvoke node, var recompile) { | 33 void update(HInvoke node, HTypeMap types, var recompile) { |
| 34 // If we don't know anything useful about the types adding more | 34 // If we don't know anything useful about the types adding more |
| 35 // information will not help. | 35 // information will not help. |
| 36 if (!hasTypeInformation) return; | 36 if (!hasTypeInformation) return; |
| 37 | 37 |
| 38 // Update the type information with the provided types. | 38 // Update the type information with the provided types. |
| 39 bool typesChanged = false; | 39 bool typesChanged = false; |
| 40 bool allUnknown = true; | 40 bool allUnknown = true; |
| 41 for (int i = 0; i < providedTypes.length; i++) { | 41 for (int i = 0; i < providedTypes.length; i++) { |
| 42 HType newType = providedTypes[i].union(node.inputs[i + 1].propagatedType); | 42 HType newType = providedTypes[i].union(types[node.inputs[i + 1]]); |
| 43 if (newType != providedTypes[i]) { | 43 if (newType != providedTypes[i]) { |
| 44 typesChanged = true; | 44 typesChanged = true; |
| 45 providedTypes[i] = newType; | 45 providedTypes[i] = newType; |
| 46 } | 46 } |
| 47 if (providedTypes[i] != HType.UNKNOWN) allUnknown = false; | 47 if (providedTypes[i] != HType.UNKNOWN) allUnknown = false; |
| 48 } | 48 } |
| 49 // If the provided types change we need to recompile all functions which | 49 // If the provided types change we need to recompile all functions which |
| 50 // have been compiled under the now invalidated assumptions. | 50 // have been compiled under the now invalidated assumptions. |
| 51 if (typesChanged && compiledFunctions.length != 0) { | 51 if (typesChanged && compiledFunctions.length != 0) { |
| 52 if (recompile != null) { | 52 if (recompile != null) { |
| 53 compiledFunctions.forEach(recompile); | 53 compiledFunctions.forEach(recompile); |
| 54 } | 54 } |
| 55 compiledFunctions.clear(); | 55 compiledFunctions.clear(); |
| 56 } | 56 } |
| 57 // If all information is lost no need to keep it around. | 57 // If all information is lost no need to keep it around. |
| 58 if (allUnknown) clearTypeInformation(); | 58 if (allUnknown) clearTypeInformation(); |
| 59 } | 59 } |
| 60 | 60 |
| 61 addCompiledFunction(FunctionElement function) => | 61 addCompiledFunction(FunctionElement function) => |
| 62 compiledFunctions.add(function); | 62 compiledFunctions.add(function); |
| 63 | 63 |
| 64 void clearTypeInformation() => providedTypes = null; | 64 void clearTypeInformation() => providedTypes = null; |
| 65 bool get hasTypeInformation() => providedTypes != null; | 65 bool get hasTypeInformation() => providedTypes != null; |
| 66 | 66 |
| 67 } | 67 } |
| 68 | 68 |
| 69 class JavaScriptItemCompilationContext extends ItemCompilationContext { |
| 70 final HTypeMap types; |
| 71 |
| 72 JavaScriptItemCompilationContext() : types = new HTypeMap(); |
| 73 } |
| 74 |
| 69 class JavaScriptBackend extends Backend { | 75 class JavaScriptBackend extends Backend { |
| 70 SsaBuilderTask builder; | 76 SsaBuilderTask builder; |
| 71 SsaOptimizerTask optimizer; | 77 SsaOptimizerTask optimizer; |
| 72 SsaCodeGeneratorTask generator; | 78 SsaCodeGeneratorTask generator; |
| 73 CodeEmitterTask emitter; | 79 CodeEmitterTask emitter; |
| 74 final Map<Element, Map<Element, HType>> fieldInitializers; | 80 final Map<Element, Map<Element, HType>> fieldInitializers; |
| 75 final Map<Element, Map<Element, HType>> fieldConstructorSetters; | 81 final Map<Element, Map<Element, HType>> fieldConstructorSetters; |
| 76 final Map<Element, Map<Element, HType>> fieldSettersType; | 82 final Map<Element, Map<Element, HType>> fieldSettersType; |
| 77 | 83 |
| 78 final Map<Element, InvocationInfo> staticInvocationInfo; | 84 final Map<Element, InvocationInfo> staticInvocationInfo; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 91 fieldSettersType = new Map<Element, Map<Element, HType>>(), | 97 fieldSettersType = new Map<Element, Map<Element, HType>>(), |
| 92 invocationInfo = new Map<SourceString, Map<Selector, InvocationInfo>>(), | 98 invocationInfo = new Map<SourceString, Map<Selector, InvocationInfo>>(), |
| 93 staticInvocationInfo = new Map<Element, InvocationInfo>(), | 99 staticInvocationInfo = new Map<Element, InvocationInfo>(), |
| 94 invalidateAfterCodegen = new List<Element>(), | 100 invalidateAfterCodegen = new List<Element>(), |
| 95 super(compiler) { | 101 super(compiler) { |
| 96 builder = new SsaBuilderTask(this); | 102 builder = new SsaBuilderTask(this); |
| 97 optimizer = new SsaOptimizerTask(this); | 103 optimizer = new SsaOptimizerTask(this); |
| 98 generator = new SsaCodeGeneratorTask(this); | 104 generator = new SsaCodeGeneratorTask(this); |
| 99 } | 105 } |
| 100 | 106 |
| 107 JavaScriptItemCompilationContext createItemCompilationContext() { |
| 108 return new JavaScriptItemCompilationContext(); |
| 109 } |
| 110 |
| 101 void enqueueHelpers(Enqueuer world) { | 111 void enqueueHelpers(Enqueuer world) { |
| 102 enqueueAllTopLevelFunctions(compiler.jsHelperLibrary, world); | 112 enqueueAllTopLevelFunctions(compiler.jsHelperLibrary, world); |
| 103 enqueueAllTopLevelFunctions(compiler.interceptorsLibrary, world); | 113 enqueueAllTopLevelFunctions(compiler.interceptorsLibrary, world); |
| 104 for (var helper in [const SourceString('Closure'), | 114 for (var helper in [const SourceString('Closure'), |
| 105 const SourceString('ConstantMap'), | 115 const SourceString('ConstantMap'), |
| 106 const SourceString('ConstantProtoMap')]) { | 116 const SourceString('ConstantProtoMap')]) { |
| 107 var e = compiler.findHelper(helper); | 117 var e = compiler.findHelper(helper); |
| 108 if (e !== null) world.registerInstantiatedClass(e); | 118 if (e !== null) world.registerInstantiatedClass(e); |
| 109 } | 119 } |
| 110 } | 120 } |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 } | 242 } |
| 233 Map<Element, HType> fields = fieldSettersType[enclosingClass]; | 243 Map<Element, HType> fields = fieldSettersType[enclosingClass]; |
| 234 if (!fields.containsKey(field)) return HType.CONFLICTING; | 244 if (!fields.containsKey(field)) return HType.CONFLICTING; |
| 235 return fields[field]; | 245 return fields[field]; |
| 236 } | 246 } |
| 237 | 247 |
| 238 /** | 248 /** |
| 239 * Register a dynamic invocation and collect the provided types for the | 249 * Register a dynamic invocation and collect the provided types for the |
| 240 * named selector. | 250 * named selector. |
| 241 */ | 251 */ |
| 242 void registerDynamicInvocation(HInvokeDynamicMethod node, Selector selector) { | 252 void registerDynamicInvocation(HInvokeDynamicMethod node, |
| 253 Selector selector, |
| 254 HTypeMap types) { |
| 243 Map<Selector, InvocationInfo> invocationInfos = | 255 Map<Selector, InvocationInfo> invocationInfos = |
| 244 invocationInfo.putIfAbsent(node.name, | 256 invocationInfo.putIfAbsent(node.name, |
| 245 () => new Map<Selector, InvocationInfo>()); | 257 () => new Map<Selector, InvocationInfo>()); |
| 246 InvocationInfo info = invocationInfos[selector]; | 258 InvocationInfo info = invocationInfos[selector]; |
| 247 if (info != null) { | 259 if (info != null) { |
| 248 void recompile(Element element) { | 260 void recompile(Element element) { |
| 249 if (compiler.phase == Compiler.PHASE_COMPILING) { | 261 if (compiler.phase == Compiler.PHASE_COMPILING) { |
| 250 invalidateAfterCodegen.add(element); | 262 invalidateAfterCodegen.add(element); |
| 251 } | 263 } |
| 252 } | 264 } |
| 253 | 265 |
| 254 info.update(node, recompile); | 266 info.update(node, types, recompile); |
| 255 } else { | 267 } else { |
| 256 invocationInfos[selector] = new InvocationInfo(node); | 268 invocationInfos[selector] = new InvocationInfo(node, types); |
| 257 } | 269 } |
| 258 } | 270 } |
| 259 | 271 |
| 260 /** | 272 /** |
| 261 * Register a static invocation and collect the provided types for the | 273 * Register a static invocation and collect the provided types for the |
| 262 * named selector. | 274 * named selector. |
| 263 */ | 275 */ |
| 264 void registerStaticInvocation(HInvokeStatic node) { | 276 void registerStaticInvocation(HInvokeStatic node, HTypeMap types) { |
| 265 InvocationInfo info = staticInvocationInfo[node.element]; | 277 InvocationInfo info = staticInvocationInfo[node.element]; |
| 266 if (info != null) { | 278 if (info != null) { |
| 267 recompile(Element element) { | 279 recompile(Element element) { |
| 268 if (compiler.phase == Compiler.PHASE_COMPILING) { | 280 if (compiler.phase == Compiler.PHASE_COMPILING) { |
| 269 invalidateAfterCodegen.add(element); | 281 invalidateAfterCodegen.add(element); |
| 270 } | 282 } |
| 271 } | 283 } |
| 272 info.update(node, recompile); | 284 info.update(node, types, recompile); |
| 273 } else { | 285 } else { |
| 274 staticInvocationInfo[node.element] = new InvocationInfo(node); | 286 staticInvocationInfo[node.element] = new InvocationInfo(node, types); |
| 275 } | 287 } |
| 276 } | 288 } |
| 277 | 289 |
| 278 /** | 290 /** |
| 279 * Register that a static is used for something else than a call target. | 291 * Register that a static is used for something else than a call target. |
| 280 */ | 292 */ |
| 281 void registerNonCallStaticUse(HStatic node) { | 293 void registerNonCallStaticUse(HStatic node) { |
| 282 // When a static is used for anything else than a call target we cannot | 294 // When a static is used for anything else than a call target we cannot |
| 283 // infer anything about its parameter types. | 295 // infer anything about its parameter types. |
| 284 InvocationInfo info = staticInvocationInfo[node.element]; | 296 InvocationInfo info = staticInvocationInfo[node.element]; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 FunctionSignature signature = element.computeSignature(compiler); | 346 FunctionSignature signature = element.computeSignature(compiler); |
| 335 if (signature.parameterCount == found.parameterCount) { | 347 if (signature.parameterCount == found.parameterCount) { |
| 336 found.addCompiledFunction(element); | 348 found.addCompiledFunction(element); |
| 337 return found.providedTypes; | 349 return found.providedTypes; |
| 338 } | 350 } |
| 339 } | 351 } |
| 340 return null; | 352 return null; |
| 341 } | 353 } |
| 342 } | 354 } |
| 343 } | 355 } |
| OLD | NEW |