Chromium Code Reviews| 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 typedef void Recompile(Element element); | 5 typedef void Recompile(Element element); |
| 6 | 6 |
| 7 class ReturnInfo { | 7 class ReturnInfo { |
| 8 HType returnType; | 8 HType returnType; |
| 9 List<Element> compiledFunctions; | 9 List<Element> compiledFunctions; |
| 10 | 10 |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 218 }); | 218 }); |
| 219 return result; | 219 return result; |
| 220 } | 220 } |
| 221 | 221 |
| 222 String toString() => | 222 String toString() => |
| 223 allUnknown ? "HTypeList.ALL_UNKNOWN" : "HTypeList $types"; | 223 allUnknown ? "HTypeList.ALL_UNKNOWN" : "HTypeList $types"; |
| 224 } | 224 } |
| 225 | 225 |
| 226 class ArgumentTypesRegistry { | 226 class ArgumentTypesRegistry { |
| 227 final JavaScriptBackend backend; | 227 final JavaScriptBackend backend; |
| 228 /// Invariant: Keys must be declaration elements. | |
| 228 final Map<Element, HTypeList> staticTypeMap; | 229 final Map<Element, HTypeList> staticTypeMap; |
| 230 /// Invariant: Elements must be declaration elements. | |
| 229 final Set<Element> optimizedStaticFunctions; | 231 final Set<Element> optimizedStaticFunctions; |
| 230 final SelectorMap<HTypeList> selectorTypeMap; | 232 final SelectorMap<HTypeList> selectorTypeMap; |
| 231 final FunctionSet optimizedFunctions; | 233 final FunctionSet optimizedFunctions; |
| 234 /// Invariant: Keys must be declaration elements. | |
| 232 final Map<Element, HTypeList> optimizedTypes; | 235 final Map<Element, HTypeList> optimizedTypes; |
| 233 final Map<Element, OptionalParameterTypes> optimizedDefaultValueTypes; | 236 final Map<Element, OptionalParameterTypes> optimizedDefaultValueTypes; |
| 234 | 237 |
| 235 ArgumentTypesRegistry(JavaScriptBackend backend) | 238 ArgumentTypesRegistry(JavaScriptBackend backend) |
| 236 : staticTypeMap = new Map<Element, HTypeList>(), | 239 : staticTypeMap = new Map<Element, HTypeList>(), |
| 237 optimizedStaticFunctions = new Set<Element>(), | 240 optimizedStaticFunctions = new Set<Element>(), |
| 238 selectorTypeMap = new SelectorMap<HTypeList>(backend.compiler), | 241 selectorTypeMap = new SelectorMap<HTypeList>(backend.compiler), |
| 239 optimizedFunctions = new FunctionSet(backend.compiler), | 242 optimizedFunctions = new FunctionSet(backend.compiler), |
| 240 optimizedTypes = new Map<Element, HTypeList>(), | 243 optimizedTypes = new Map<Element, HTypeList>(), |
| 241 optimizedDefaultValueTypes = | 244 optimizedDefaultValueTypes = |
| 242 new Map<Element, OptionalParameterTypes>(), | 245 new Map<Element, OptionalParameterTypes>(), |
| 243 this.backend = backend; | 246 this.backend = backend; |
| 244 | 247 |
| 245 Compiler get compiler => backend.compiler; | 248 Compiler get compiler => backend.compiler; |
| 246 | 249 |
| 247 void registerStaticInvocation(HInvokeStatic node, HTypeMap types) { | 250 void registerStaticInvocation(HInvokeStatic node, HTypeMap types) { |
| 248 Element element = node.element; | 251 Element element = node.element; |
| 252 assert(element.isDeclaration); | |
| 249 HTypeList oldTypes = staticTypeMap[element]; | 253 HTypeList oldTypes = staticTypeMap[element]; |
| 250 if (oldTypes == null) { | 254 if (oldTypes == null) { |
| 251 staticTypeMap[element] = new HTypeList.fromStaticInvocation(node, types); | 255 staticTypeMap[element] = new HTypeList.fromStaticInvocation(node, types); |
| 252 } else { | 256 } else { |
| 253 if (oldTypes.allUnknown) return; | 257 if (oldTypes.allUnknown) return; |
| 254 HTypeList newTypes = oldTypes.unionWithInvoke(node, types); | 258 HTypeList newTypes = oldTypes.unionWithInvoke(node, types); |
| 255 if (newTypes === oldTypes) return; | 259 if (newTypes === oldTypes) return; |
| 256 staticTypeMap[element] = newTypes; | 260 staticTypeMap[element] = newTypes; |
| 257 if (optimizedStaticFunctions.contains(element)) { | 261 if (optimizedStaticFunctions.contains(element)) { |
| 258 backend.scheduleForRecompilation(element); | 262 backend.scheduleForRecompilation(element); |
| 259 } | 263 } |
| 260 } | 264 } |
| 261 } | 265 } |
| 262 | 266 |
| 263 void registerNonCallStaticUse(HStatic node) { | 267 void registerNonCallStaticUse(HStatic node) { |
| 264 // When a static is used for anything else than a call target we cannot | 268 // When a static is used for anything else than a call target we cannot |
| 265 // infer anything about its parameter types. | 269 // infer anything about its parameter types. |
| 266 Element element = node.element; | 270 Element element = node.element; |
| 271 assert(element.isDeclaration); | |
| 267 if (optimizedStaticFunctions.contains(element)) { | 272 if (optimizedStaticFunctions.contains(element)) { |
| 268 backend.scheduleForRecompilation(element); | 273 backend.scheduleForRecompilation(element); |
| 269 } | 274 } |
| 270 staticTypeMap[element] = HTypeList.ALL_UNKNOWN; | 275 staticTypeMap[element] = HTypeList.ALL_UNKNOWN; |
| 271 } | 276 } |
| 272 | 277 |
| 273 void registerDynamicInvocation(HInvokeDynamicMethod node, | 278 void registerDynamicInvocation(HInvokeDynamicMethod node, |
| 274 Selector selector, | 279 Selector selector, |
| 275 HTypeMap types) { | 280 HTypeMap types) { |
| 276 // If there are any getters for this method we cannot know anything about | 281 // If there are any getters for this method we cannot know anything about |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 320 break; | 325 break; |
| 321 } | 326 } |
| 322 } | 327 } |
| 323 } | 328 } |
| 324 if (recompile) backend.scheduleForRecompilation(element); | 329 if (recompile) backend.scheduleForRecompilation(element); |
| 325 }); | 330 }); |
| 326 } | 331 } |
| 327 | 332 |
| 328 HTypeList parameterTypes(FunctionElement element, | 333 HTypeList parameterTypes(FunctionElement element, |
| 329 OptionalParameterTypes defaultValueTypes) { | 334 OptionalParameterTypes defaultValueTypes) { |
| 335 assert(element.isDeclaration); | |
| 330 // Handle static functions separately. | 336 // Handle static functions separately. |
| 331 if (Elements.isStaticOrTopLevelFunction(element) || | 337 if (Elements.isStaticOrTopLevelFunction(element) || |
| 332 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { | 338 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { |
| 333 HTypeList types = staticTypeMap[element]; | 339 HTypeList types = staticTypeMap[element]; |
| 334 if (types !== null) { | 340 if (types !== null) { |
| 335 if (!optimizedStaticFunctions.contains(element)) { | 341 if (!optimizedStaticFunctions.contains(element)) { |
| 336 optimizedStaticFunctions.add(element); | 342 optimizedStaticFunctions.add(element); |
| 337 } | 343 } |
| 338 return types; | 344 return types; |
| 339 } else { | 345 } else { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 360 assert(types.allUnknown || types.length == signature.parameterCount); | 366 assert(types.allUnknown || types.length == signature.parameterCount); |
| 361 found = (found === null) ? types : found.union(types); | 367 found = (found === null) ? types : found.union(types); |
| 362 return !found.allUnknown; | 368 return !found.allUnknown; |
| 363 }); | 369 }); |
| 364 return found !== null ? found : HTypeList.ALL_UNKNOWN; | 370 return found !== null ? found : HTypeList.ALL_UNKNOWN; |
| 365 } | 371 } |
| 366 | 372 |
| 367 void registerOptimization(Element element, | 373 void registerOptimization(Element element, |
| 368 HTypeList parameterTypes, | 374 HTypeList parameterTypes, |
| 369 OptionalParameterTypes defaultValueTypes) { | 375 OptionalParameterTypes defaultValueTypes) { |
| 376 assert(element.isDeclaration); | |
| 370 if (Elements.isStaticOrTopLevelFunction(element)) { | 377 if (Elements.isStaticOrTopLevelFunction(element)) { |
| 371 if (parameterTypes.allUnknown) { | 378 if (parameterTypes.allUnknown) { |
| 372 optimizedStaticFunctions.remove(element); | 379 optimizedStaticFunctions.remove(element); |
| 373 } else { | 380 } else { |
| 374 optimizedStaticFunctions.add(element); | 381 optimizedStaticFunctions.add(element); |
| 375 } | 382 } |
| 376 } | 383 } |
| 377 | 384 |
| 378 // TODO(kasperl): What kind of non-members do we get here? | 385 // TODO(kasperl): What kind of non-members do we get here? |
| 379 if (!element.isMember()) return; | 386 if (!element.isMember()) return; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 420 * libraries. | 427 * libraries. |
| 421 */ | 428 */ |
| 422 ClassElement jsIndexingBehaviorInterface; | 429 ClassElement jsIndexingBehaviorInterface; |
| 423 | 430 |
| 424 final Map<Element, Map<Element, HType>> fieldInitializers; | 431 final Map<Element, Map<Element, HType>> fieldInitializers; |
| 425 final Map<Element, Map<Element, HType>> fieldConstructorSetters; | 432 final Map<Element, Map<Element, HType>> fieldConstructorSetters; |
| 426 final Map<Element, Map<Element, HType>> fieldSettersType; | 433 final Map<Element, Map<Element, HType>> fieldSettersType; |
| 427 | 434 |
| 428 final Map<Element, ReturnInfo> returnInfo; | 435 final Map<Element, ReturnInfo> returnInfo; |
| 429 | 436 |
| 437 /// Invariant: Elements must be declaration elements. | |
| 430 final List<Element> invalidateAfterCodegen; | 438 final List<Element> invalidateAfterCodegen; |
| 431 ArgumentTypesRegistry argumentTypes; | 439 ArgumentTypesRegistry argumentTypes; |
| 432 | 440 |
| 433 List<CompilerTask> get tasks { | 441 List<CompilerTask> get tasks { |
| 434 return <CompilerTask>[builder, optimizer, generator, emitter]; | 442 return <CompilerTask>[builder, optimizer, generator, emitter]; |
| 435 } | 443 } |
| 436 | 444 |
| 437 JavaScriptBackend(Compiler compiler, bool generateSourceMap) | 445 JavaScriptBackend(Compiler compiler, bool generateSourceMap) |
| 438 : fieldInitializers = new Map<Element, Map<Element, HType>>(), | 446 : fieldInitializers = new Map<Element, Map<Element, HType>>(), |
| 439 fieldConstructorSetters = new Map<Element, Map<Element, HType>>(), | 447 fieldConstructorSetters = new Map<Element, Map<Element, HType>>(), |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 606 assert(field.isMember()); | 614 assert(field.isMember()); |
| 607 ClassElement enclosingClass = field.getEnclosingClass(); | 615 ClassElement enclosingClass = field.getEnclosingClass(); |
| 608 if (!fieldSettersType.containsKey(enclosingClass)) { | 616 if (!fieldSettersType.containsKey(enclosingClass)) { |
| 609 return HType.CONFLICTING; | 617 return HType.CONFLICTING; |
| 610 } | 618 } |
| 611 Map<Element, HType> fields = fieldSettersType[enclosingClass]; | 619 Map<Element, HType> fields = fieldSettersType[enclosingClass]; |
| 612 if (!fields.containsKey(field)) return HType.CONFLICTING; | 620 if (!fields.containsKey(field)) return HType.CONFLICTING; |
| 613 return fields[field]; | 621 return fields[field]; |
| 614 } | 622 } |
| 615 | 623 |
| 624 /** | |
| 625 * Invariant: [element] must be the declaration element. | |
|
ahe
2012/09/18 11:25:54
Not documentation.
Johnni Winther
2012/09/20 08:12:23
Done.
| |
| 626 */ | |
| 616 void scheduleForRecompilation(Element element) { | 627 void scheduleForRecompilation(Element element) { |
| 628 assert(element.isDeclaration); | |
| 617 if (compiler.phase == Compiler.PHASE_COMPILING) { | 629 if (compiler.phase == Compiler.PHASE_COMPILING) { |
| 618 invalidateAfterCodegen.add(element); | 630 invalidateAfterCodegen.add(element); |
| 619 } | 631 } |
| 620 } | 632 } |
| 621 | 633 |
| 622 /** | 634 /** |
| 623 * Register a dynamic invocation and collect the provided types for the | 635 * Register a dynamic invocation and collect the provided types for the |
| 624 * named selector. | 636 * named selector. |
| 625 */ | 637 */ |
| 626 void registerDynamicInvocation(HInvokeDynamicMethod node, | 638 void registerDynamicInvocation(HInvokeDynamicMethod node, |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 642 * target. | 654 * target. |
| 643 */ | 655 */ |
| 644 void registerNonCallStaticUse(HStatic node) { | 656 void registerNonCallStaticUse(HStatic node) { |
| 645 argumentTypes.registerNonCallStaticUse(node); | 657 argumentTypes.registerNonCallStaticUse(node); |
| 646 } | 658 } |
| 647 | 659 |
| 648 /** | 660 /** |
| 649 * Retrieve the types of the parameters used for calling the [element] | 661 * Retrieve the types of the parameters used for calling the [element] |
| 650 * function. The types are optimistic in the sense as they are based on the | 662 * function. The types are optimistic in the sense as they are based on the |
| 651 * possible invocations of the function seen so far. | 663 * possible invocations of the function seen so far. |
| 664 * | |
| 665 * Invariant: [element] must be the declaration element. | |
| 652 */ | 666 */ |
| 653 HTypeList optimisticParameterTypes( | 667 HTypeList optimisticParameterTypes( |
| 654 FunctionElement element, | 668 FunctionElement element, |
| 655 OptionalParameterTypes defaultValueTypes) { | 669 OptionalParameterTypes defaultValueTypes) { |
| 670 assert(element.isDeclaration); | |
| 656 if (element.parameterCount(compiler) == 0) return HTypeList.ALL_UNKNOWN; | 671 if (element.parameterCount(compiler) == 0) return HTypeList.ALL_UNKNOWN; |
| 657 return argumentTypes.parameterTypes(element, defaultValueTypes); | 672 return argumentTypes.parameterTypes(element, defaultValueTypes); |
| 658 } | 673 } |
| 659 | 674 |
| 660 /** | 675 /** |
| 661 * Register that the function [element] has been optimized under the | 676 * Register that the function [element] has been optimized under the |
| 662 * assumptions that the types [parameterType] will be used for calling it. | 677 * assumptions that the types [parameterType] will be used for calling it. |
| 663 * The passed [defaultValueTypes] holds the types of default values for | 678 * The passed [defaultValueTypes] holds the types of default values for |
| 664 * the optional parameters. If this assumption fail the function will be | 679 * the optional parameters. If this assumption fail the function will be |
| 665 * scheduled for recompilation. | 680 * scheduled for recompilation. |
| 681 * | |
| 682 * Invariant: [element] must be the declaration element. | |
| 666 */ | 683 */ |
| 667 registerParameterTypesOptimization( | 684 registerParameterTypesOptimization( |
| 668 FunctionElement element, | 685 FunctionElement element, |
| 669 HTypeList parameterTypes, | 686 HTypeList parameterTypes, |
| 670 OptionalParameterTypes defaultValueTypes) { | 687 OptionalParameterTypes defaultValueTypes) { |
| 671 if (element.parameterCount(compiler) == 0) return; | 688 if (element.parameterCount(compiler) == 0) return; |
| 672 argumentTypes.registerOptimization( | 689 argumentTypes.registerOptimization( |
| 673 element, parameterTypes, defaultValueTypes); | 690 element, parameterTypes, defaultValueTypes); |
| 674 } | 691 } |
| 675 | 692 |
| 693 /** | |
| 694 * Invariant: [element] must be the declaration element. | |
| 695 */ | |
| 676 void registerReturnType(FunctionElement element, HType returnType) { | 696 void registerReturnType(FunctionElement element, HType returnType) { |
| 697 assert(element.isDeclaration); | |
| 677 ReturnInfo info = returnInfo[element]; | 698 ReturnInfo info = returnInfo[element]; |
| 678 if (info != null) { | 699 if (info != null) { |
| 679 info.update(returnType, scheduleForRecompilation); | 700 info.update(returnType, scheduleForRecompilation); |
| 680 } else { | 701 } else { |
| 681 returnInfo[element] = new ReturnInfo(returnType); | 702 returnInfo[element] = new ReturnInfo(returnType); |
| 682 } | 703 } |
| 683 } | 704 } |
| 684 | 705 |
| 685 /** | 706 /** |
| 686 * Retrieve the return type of the function [callee]. The type is optimistic | 707 * Retrieve the return type of the function [callee]. The type is optimistic |
| 687 * in the sense that is is based on the compilation of [callee]. If [callee] | 708 * in the sense that is is based on the compilation of [callee]. If [callee] |
| 688 * is recompiled the return type might change to someting broader. For that | 709 * is recompiled the return type might change to someting broader. For that |
| 689 * reason [caller] is registered for recompilation if this happens. If the | 710 * reason [caller] is registered for recompilation if this happens. If the |
| 690 * function [callee] has not yet been compiled the returned type is [null]. | 711 * function [callee] has not yet been compiled the returned type is [null]. |
| 712 * | |
| 713 * Invariant: Both [caller] and [callee] must be the declaration elements. | |
| 691 */ | 714 */ |
| 692 HType optimisticReturnTypesWithRecompilationOnTypeChange( | 715 HType optimisticReturnTypesWithRecompilationOnTypeChange( |
| 693 Element caller, FunctionElement callee) { | 716 Element caller, FunctionElement callee) { |
| 694 returnInfo.putIfAbsent(callee, () => new ReturnInfo.unknownType()); | 717 returnInfo.putIfAbsent(callee, () => new ReturnInfo.unknownType()); |
| 695 ReturnInfo info = returnInfo[callee]; | 718 ReturnInfo info = returnInfo[callee]; |
| 696 if (info.returnType != HType.UNKNOWN && caller != null) { | 719 if (info.returnType != HType.UNKNOWN && caller != null) { |
| 697 info.addCompiledFunction(caller); | 720 info.addCompiledFunction(caller); |
| 698 } | 721 } |
| 699 return info.returnType; | 722 return info.returnType; |
| 700 } | 723 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 739 ? const SourceString('listSuperNativeTypeCheck') | 762 ? const SourceString('listSuperNativeTypeCheck') |
| 740 : const SourceString('listSuperTypeCheck'); | 763 : const SourceString('listSuperTypeCheck'); |
| 741 } else { | 764 } else { |
| 742 return nativeCheck | 765 return nativeCheck |
| 743 ? const SourceString('callTypeCheck') | 766 ? const SourceString('callTypeCheck') |
| 744 : const SourceString('propertyTypeCheck'); | 767 : const SourceString('propertyTypeCheck'); |
| 745 } | 768 } |
| 746 } | 769 } |
| 747 } | 770 } |
| 748 } | 771 } |
| OLD | NEW |