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 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 } | 216 } |
217 index++; | 217 index++; |
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 FieldTypesRegistry { |
| 227 final JavaScriptBackend backend; |
| 228 |
| 229 /** |
| 230 * For each class, [constructors] holds the set of constructors. If there is |
| 231 * more than one constructor for a class it is currently not possible to |
| 232 * infer the field types from construction, as the information collected does |
| 233 * not correlate the generative constructors and generative constructor |
| 234 * body/bodies. |
| 235 */ |
| 236 final Map<Element, Set<ClassElement>> constructors; |
| 237 |
| 238 /** |
| 239 * The collected type information is stored in three maps. One for types |
| 240 * assigned in the initializer list(s) [fieldInitializerTypeMap], one for |
| 241 * types assigned in the constructor(s) [fieldConstructorTypeMap], and one |
| 242 * for types assigned in the rest of the code, where the field can be |
| 243 * resolved [fieldTypeMap]. |
| 244 * |
| 245 * If a field has a type both from constructors and from the initializer |
| 246 * list(s), then the type from the constructor(s) will owerride the one from |
| 247 * the initializer list(s). |
| 248 * |
| 249 * Because the order in which generative constructors, generative constructor |
| 250 * bodies and normal method/function bodies are compiled is undefined, and |
| 251 * because they can all be recompiled, it is not possible to combine this |
| 252 * information into one map at the moment. |
| 253 */ |
| 254 final Map<Element, HType> fieldInitializerTypeMap; |
| 255 final Map<Element, HType> fieldConstructorTypeMap; |
| 256 final Map<Element, HType> fieldTypeMap; |
| 257 |
| 258 /** |
| 259 * The set of current names setter selectors used. If a named selector is |
| 260 * used it is currently not possible to infer the type of the field. |
| 261 */ |
| 262 final Set<SourceString> setterSelectorsUsed; |
| 263 |
| 264 final Map<Element, Set<Element>> optimizedStaticFunctions; |
| 265 final Map<Element, FunctionSet> optimizedFunctions; |
| 266 |
| 267 FieldTypesRegistry(JavaScriptBackend backend) |
| 268 : constructors = new Map<Element, Set<Element>>(), |
| 269 fieldInitializerTypeMap = new Map<Element, HType>(), |
| 270 fieldConstructorTypeMap = new Map<Element, HType>(), |
| 271 fieldTypeMap = new Map<Element, HType>(), |
| 272 setterSelectorsUsed = new Set<SourceString>(), |
| 273 optimizedStaticFunctions = new Map<Element, Set<Element>>(), |
| 274 optimizedFunctions = new Map<Element, FunctionSet>(), |
| 275 this.backend = backend; |
| 276 |
| 277 Compiler get compiler => backend.compiler; |
| 278 |
| 279 void scheduleRecompilation(Element field) { |
| 280 Set optimizedStatics = optimizedStaticFunctions[field]; |
| 281 if (optimizedStatics != null) { |
| 282 optimizedStatics.forEach(backend.scheduleForRecompilation); |
| 283 optimizedStaticFunctions.remove(field); |
| 284 } |
| 285 FunctionSet optimized = optimizedFunctions[field]; |
| 286 if (optimized != null) { |
| 287 optimized.forEach(backend.scheduleForRecompilation); |
| 288 optimizedFunctions.remove(field); |
| 289 } |
| 290 } |
| 291 |
| 292 int constructorCount(Element element) { |
| 293 assert(element.isClass()); |
| 294 Set<Element> ctors = constructors[element]; |
| 295 return ctors === null ? 0 : ctors.length; |
| 296 } |
| 297 |
| 298 void registerFieldType(Map<Element, HType> typeMap, |
| 299 Element field, |
| 300 HType type) { |
| 301 assert(field.isField()); |
| 302 HType before = optimisticFieldType(field); |
| 303 |
| 304 HType oldType = typeMap[field]; |
| 305 HType newType; |
| 306 |
| 307 if (oldType != null) { |
| 308 newType = oldType.union(type); |
| 309 } else { |
| 310 newType = type; |
| 311 } |
| 312 typeMap[field] = newType; |
| 313 if (oldType != newType) { |
| 314 scheduleRecompilation(field); |
| 315 } |
| 316 } |
| 317 |
| 318 void registerConstructor(Element element) { |
| 319 assert(element.isGenerativeConstructor()); |
| 320 Element cls = element.enclosingElement; |
| 321 constructors.putIfAbsent(cls, () => new Set<Element>()); |
| 322 Set<Element> ctors = constructors[cls]; |
| 323 if (ctors.contains(element)) return; |
| 324 ctors.add(element); |
| 325 // We cannot infer field types for classes with more than one constructor. |
| 326 // When the second constructor is seen, recompile all functions relying on |
| 327 // optimistic field types for that class. |
| 328 // TODO(sgjesse): Handle field types for classes with more than one |
| 329 // constructor. |
| 330 if (ctors.length == 2) { |
| 331 optimizedFunctions.forEach((Element field, _) { |
| 332 if (field.enclosingElement === cls) { |
| 333 scheduleRecompilation(field); |
| 334 } |
| 335 }); |
| 336 } |
| 337 } |
| 338 |
| 339 void registerFieldInitializer(Element field, HType type) { |
| 340 registerFieldType(fieldInitializerTypeMap, field, type); |
| 341 } |
| 342 |
| 343 void registerFieldConstructor(Element field, HType type) { |
| 344 registerFieldType(fieldConstructorTypeMap, field, type); |
| 345 } |
| 346 |
| 347 void registerFieldSetter(FunctionElement element, Element field, HType type) { |
| 348 HType initializerType = fieldInitializerTypeMap[field]; |
| 349 HType constructorType = fieldConstructorTypeMap[field]; |
| 350 HType setterType = fieldTypeMap[field]; |
| 351 if (type == HType.UNKNOWN |
| 352 && initializerType == null |
| 353 && constructorType == null |
| 354 && setterType == null) { |
| 355 // Don't register UNKONWN if there is currently no type information |
| 356 // present for the field. Instead register the function holding the |
| 357 // setter for recompilation if better type information for the field |
| 358 // becomes available. |
| 359 registerOptimizedFunction(element, field, type); |
| 360 return; |
| 361 } |
| 362 registerFieldType(fieldTypeMap, field, type); |
| 363 } |
| 364 |
| 365 void addedDynamicSetter(Selector setter, HType type) { |
| 366 // Field type optimizations are disabled for all fields matching a |
| 367 // setter selector. |
| 368 assert(setter.isSetter()); |
| 369 // TODO(sgjesse): Take the type of the setter into account. |
| 370 if (setterSelectorsUsed.contains(setter.name)) return; |
| 371 setterSelectorsUsed.add(setter.name); |
| 372 optimizedStaticFunctions.forEach((Element field, _) { |
| 373 if (field.name == setter.name) { |
| 374 scheduleRecompilation(field); |
| 375 } |
| 376 }); |
| 377 optimizedFunctions.forEach((Element field, _) { |
| 378 if (field.name == setter.name) { |
| 379 scheduleRecompilation(field); |
| 380 } |
| 381 }); |
| 382 } |
| 383 |
| 384 HType optimisticFieldType(Element field) { |
| 385 assert(field.isField()); |
| 386 if (constructorCount(field.enclosingElement) > 1) { |
| 387 return HType.UNKNOWN; |
| 388 } |
| 389 if (setterSelectorsUsed.contains(field.name)) { |
| 390 return HType.UNKNOWN; |
| 391 } |
| 392 HType initializerType = fieldInitializerTypeMap[field]; |
| 393 HType constructorType = fieldConstructorTypeMap[field]; |
| 394 if (initializerType === null && constructorType === null) { |
| 395 // If there are no constructor type information return UNKNOWN. This |
| 396 // ensures that the function will be recompiled if useful constructor |
| 397 // type information becomes available. |
| 398 return HType.UNKNOWN; |
| 399 } |
| 400 // A type set through the constructor overrides the type from the |
| 401 // initializer list. |
| 402 HType result = constructorType != null ? constructorType : initializerType; |
| 403 HType type = fieldTypeMap[field]; |
| 404 if (type !== null) result = result.union(type); |
| 405 return result; |
| 406 } |
| 407 |
| 408 void registerOptimizedFunction(FunctionElement element, |
| 409 Element field, |
| 410 HType type) { |
| 411 assert(field.isField()); |
| 412 if (Elements.isStaticOrTopLevel(element)) { |
| 413 optimizedStaticFunctions.putIfAbsent( |
| 414 field, () => new Set<Element>()); |
| 415 optimizedStaticFunctions[field].add(element); |
| 416 } else { |
| 417 optimizedFunctions.putIfAbsent( |
| 418 field, () => new FunctionSet(backend.compiler)); |
| 419 optimizedFunctions[field].add(element); |
| 420 } |
| 421 } |
| 422 |
| 423 void dump() { |
| 424 Set<Element> allFields = new Set<Element>(); |
| 425 fieldInitializerTypeMap.getKeys().forEach(allFields.add); |
| 426 fieldConstructorTypeMap.getKeys().forEach(allFields.add); |
| 427 fieldTypeMap.getKeys().forEach(allFields.add); |
| 428 allFields.forEach((Element field) { |
| 429 print("Inferred $field has type ${optimisticFieldType(field)}"); |
| 430 }); |
| 431 } |
| 432 } |
| 433 |
226 class ArgumentTypesRegistry { | 434 class ArgumentTypesRegistry { |
227 final JavaScriptBackend backend; | 435 final JavaScriptBackend backend; |
228 | 436 |
229 /** | 437 /** |
230 * Documentation wanted -- johnniwinther | 438 * Documentation wanted -- johnniwinther |
231 * | 439 * |
232 * Invariant: Keys must be declaration elements. | 440 * Invariant: Keys must be declaration elements. |
233 */ | 441 */ |
234 final Map<Element, HTypeList> staticTypeMap; | 442 final Map<Element, HTypeList> staticTypeMap; |
235 | 443 |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 signature, | 586 signature, |
379 defaultValueTypes); | 587 defaultValueTypes); |
380 } | 588 } |
381 assert(types.allUnknown || types.length == signature.parameterCount); | 589 assert(types.allUnknown || types.length == signature.parameterCount); |
382 found = (found === null) ? types : found.union(types); | 590 found = (found === null) ? types : found.union(types); |
383 return !found.allUnknown; | 591 return !found.allUnknown; |
384 }); | 592 }); |
385 return found !== null ? found : HTypeList.ALL_UNKNOWN; | 593 return found !== null ? found : HTypeList.ALL_UNKNOWN; |
386 } | 594 } |
387 | 595 |
388 void registerOptimization(Element element, | 596 void registerOptimizedFunction(Element element, |
389 HTypeList parameterTypes, | 597 HTypeList parameterTypes, |
390 OptionalParameterTypes defaultValueTypes) { | 598 OptionalParameterTypes defaultValueTypes) { |
391 assert(invariant(element, element.isDeclaration)); | |
392 if (Elements.isStaticOrTopLevelFunction(element)) { | 599 if (Elements.isStaticOrTopLevelFunction(element)) { |
393 if (parameterTypes.allUnknown) { | 600 if (parameterTypes.allUnknown) { |
394 optimizedStaticFunctions.remove(element); | 601 optimizedStaticFunctions.remove(element); |
395 } else { | 602 } else { |
396 optimizedStaticFunctions.add(element); | 603 optimizedStaticFunctions.add(element); |
397 } | 604 } |
398 } | 605 } |
399 | 606 |
400 // TODO(kasperl): What kind of non-members do we get here? | 607 // TODO(kasperl): What kind of non-members do we get here? |
401 if (!element.isMember()) return; | 608 if (!element.isMember()) return; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 | 643 |
437 final Namer namer; | 644 final Namer namer; |
438 | 645 |
439 /** | 646 /** |
440 * Interface used to determine if an object has the JavaScript | 647 * Interface used to determine if an object has the JavaScript |
441 * indexing behavior. The interface is only visible to specific | 648 * indexing behavior. The interface is only visible to specific |
442 * libraries. | 649 * libraries. |
443 */ | 650 */ |
444 ClassElement jsIndexingBehaviorInterface; | 651 ClassElement jsIndexingBehaviorInterface; |
445 | 652 |
446 final Map<Element, Map<Element, HType>> fieldInitializers; | |
447 final Map<Element, Map<Element, HType>> fieldConstructorSetters; | |
448 final Map<Element, Map<Element, HType>> fieldSettersType; | |
449 | |
450 final Map<Element, ReturnInfo> returnInfo; | 653 final Map<Element, ReturnInfo> returnInfo; |
451 | 654 |
452 /** | 655 /** |
453 * Documentation wanted -- johnniwinther | 656 * Documentation wanted -- johnniwinther |
454 * | 657 * |
455 * Invariant: Elements must be declaration elements. | 658 * Invariant: Elements must be declaration elements. |
456 */ | 659 */ |
457 final List<Element> invalidateAfterCodegen; | 660 final List<Element> invalidateAfterCodegen; |
458 ArgumentTypesRegistry argumentTypes; | 661 ArgumentTypesRegistry argumentTypes; |
| 662 FieldTypesRegistry fieldTypes; |
459 | 663 |
460 List<CompilerTask> get tasks { | 664 List<CompilerTask> get tasks { |
461 return <CompilerTask>[builder, optimizer, generator, emitter]; | 665 return <CompilerTask>[builder, optimizer, generator, emitter]; |
462 } | 666 } |
463 | 667 |
464 JavaScriptBackend(Compiler compiler, bool generateSourceMap) | 668 JavaScriptBackend(Compiler compiler, bool generateSourceMap) |
465 : fieldInitializers = new Map<Element, Map<Element, HType>>(), | 669 : namer = new Namer(compiler), |
466 fieldConstructorSetters = new Map<Element, Map<Element, HType>>(), | |
467 fieldSettersType = new Map<Element, Map<Element, HType>>(), | |
468 namer = new Namer(compiler), | |
469 returnInfo = new Map<Element, ReturnInfo>(), | 670 returnInfo = new Map<Element, ReturnInfo>(), |
470 invalidateAfterCodegen = new List<Element>(), | 671 invalidateAfterCodegen = new List<Element>(), |
471 super(compiler, constantSystem: JAVA_SCRIPT_CONSTANT_SYSTEM) { | 672 super(compiler, constantSystem: JAVA_SCRIPT_CONSTANT_SYSTEM) { |
472 emitter = new CodeEmitterTask(compiler, namer, generateSourceMap); | 673 emitter = new CodeEmitterTask(compiler, namer, generateSourceMap); |
473 builder = new SsaBuilderTask(this); | 674 builder = new SsaBuilderTask(this); |
474 optimizer = new SsaOptimizerTask(this); | 675 optimizer = new SsaOptimizerTask(this); |
475 generator = new SsaCodeGeneratorTask(this); | 676 generator = new SsaCodeGeneratorTask(this); |
476 argumentTypes = new ArgumentTypesRegistry(this); | 677 argumentTypes = new ArgumentTypesRegistry(this); |
| 678 fieldTypes = new FieldTypesRegistry(this); |
477 } | 679 } |
478 | 680 |
479 Element get cyclicThrowHelper { | 681 Element get cyclicThrowHelper { |
480 return compiler.findHelper(const SourceString("throwCyclicInit")); | 682 return compiler.findHelper(const SourceString("throwCyclicInit")); |
481 } | 683 } |
482 | 684 |
483 JavaScriptItemCompilationContext createItemCompilationContext() { | 685 JavaScriptItemCompilationContext createItemCompilationContext() { |
484 return new JavaScriptItemCompilationContext(); | 686 return new JavaScriptItemCompilationContext(); |
485 } | 687 } |
486 | 688 |
(...skipping 22 matching lines...) Expand all Loading... |
509 } else { | 711 } else { |
510 // If the constant-handler was not able to produce a result we have to | 712 // If the constant-handler was not able to produce a result we have to |
511 // go through the builder (below) to generate the lazy initializer for | 713 // go through the builder (below) to generate the lazy initializer for |
512 // the static variable. | 714 // the static variable. |
513 // We also need to register the use of the cyclic-error helper. | 715 // We also need to register the use of the cyclic-error helper. |
514 compiler.enqueuer.codegen.registerStaticUse(cyclicThrowHelper); | 716 compiler.enqueuer.codegen.registerStaticUse(cyclicThrowHelper); |
515 } | 717 } |
516 } | 718 } |
517 | 719 |
518 HGraph graph = builder.build(work); | 720 HGraph graph = builder.build(work); |
519 optimizer.optimize(work, graph); | 721 optimizer.optimize(work, graph, false); |
520 if (work.allowSpeculativeOptimization | 722 if (work.allowSpeculativeOptimization |
521 && optimizer.trySpeculativeOptimizations(work, graph)) { | 723 && optimizer.trySpeculativeOptimizations(work, graph)) { |
522 CodeBuffer codeBuffer = generator.generateBailoutMethod(work, graph); | 724 CodeBuffer codeBuffer = generator.generateBailoutMethod(work, graph); |
523 compiler.codegenWorld.addBailoutCode(work, codeBuffer); | 725 compiler.codegenWorld.addBailoutCode(work, codeBuffer); |
524 optimizer.prepareForSpeculativeOptimizations(work, graph); | 726 optimizer.prepareForSpeculativeOptimizations(work, graph); |
525 optimizer.optimize(work, graph); | 727 optimizer.optimize(work, graph, true); |
526 } | 728 } |
527 CodeBuffer codeBuffer = generator.generateCode(work, graph); | 729 CodeBuffer codeBuffer = generator.generateCode(work, graph); |
528 compiler.codegenWorld.addGeneratedCode(work, codeBuffer); | 730 compiler.codegenWorld.addGeneratedCode(work, codeBuffer); |
529 invalidateAfterCodegen.forEach(compiler.enqueuer.codegen.eagerRecompile); | 731 invalidateAfterCodegen.forEach(compiler.enqueuer.codegen.eagerRecompile); |
530 invalidateAfterCodegen.clear(); | 732 invalidateAfterCodegen.clear(); |
531 } | 733 } |
532 | 734 |
533 void processNativeClasses(Enqueuer world, | 735 void processNativeClasses(Enqueuer world, |
534 Collection<LibraryElement> libraries) { | 736 Collection<LibraryElement> libraries) { |
535 native.processNativeClasses(world, emitter, libraries); | 737 native.processNativeClasses(world, emitter, libraries); |
536 } | 738 } |
537 | 739 |
538 void assembleProgram() { | 740 void assembleProgram() { |
539 emitter.assembleProgram(); | 741 emitter.assembleProgram(); |
540 } | 742 } |
541 | 743 |
542 void updateFieldInitializers(Element field, HType propagatedType) { | |
543 assert(field.isField()); | |
544 assert(field.isMember()); | |
545 Map<Element, HType> fields = | |
546 fieldInitializers.putIfAbsent( | |
547 field.getEnclosingClass(), () => new Map<Element, HType>()); | |
548 if (!fields.containsKey(field)) { | |
549 fields[field] = propagatedType; | |
550 } else { | |
551 fields[field] = fields[field].union(propagatedType); | |
552 } | |
553 } | |
554 | |
555 HType typeFromInitializersSoFar(Element field) { | |
556 assert(field.isField()); | |
557 assert(field.isMember()); | |
558 if (!fieldInitializers.containsKey(field.getEnclosingClass())) { | |
559 return HType.CONFLICTING; | |
560 } | |
561 Map<Element, HType> fields = fieldInitializers[field.getEnclosingClass()]; | |
562 return fields[field]; | |
563 } | |
564 | |
565 void updateFieldConstructorSetters(Element field, HType type) { | |
566 assert(field.isField()); | |
567 assert(field.isMember()); | |
568 Map<Element, HType> fields = | |
569 fieldConstructorSetters.putIfAbsent( | |
570 field.getEnclosingClass(), () => new Map<Element, HType>()); | |
571 if (!fields.containsKey(field)) { | |
572 fields[field] = type; | |
573 } else { | |
574 fields[field] = fields[field].union(type); | |
575 } | |
576 } | |
577 | |
578 // Check if this field is set in the constructor body. | |
579 bool hasConstructorBodyFieldSetter(Element field) { | |
580 ClassElement enclosingClass = field.getEnclosingClass(); | |
581 if (!fieldConstructorSetters.containsKey(enclosingClass)) { | |
582 return false; | |
583 } | |
584 return fieldConstructorSetters[enclosingClass][field] != null; | |
585 } | |
586 | |
587 // Provide an optimistic estimate of the type of a field after construction. | |
588 // If the constructor body has setters for fields returns HType.UNKNOWN. | |
589 // This only takes the initializer lists and field assignments in the | |
590 // constructor body into account. The constructor body might have method calls | |
591 // that could alter the field. | |
592 HType optimisticFieldTypeAfterConstruction(Element field) { | |
593 assert(field.isField()); | |
594 assert(field.isMember()); | |
595 | |
596 ClassElement classElement = field.getEnclosingClass(); | |
597 if (hasConstructorBodyFieldSetter(field)) { | |
598 // If there are field setters but there is only constructor then the type | |
599 // of the field is determined by the assignments in the constructor | |
600 // body. | |
601 var constructors = classElement.constructors; | |
602 if (constructors.head !== null && constructors.tail.isEmpty()) { | |
603 return fieldConstructorSetters[classElement][field]; | |
604 } else { | |
605 return HType.UNKNOWN; | |
606 } | |
607 } else if (fieldInitializers.containsKey(classElement)) { | |
608 HType type = fieldInitializers[classElement][field]; | |
609 return type == null ? HType.CONFLICTING : type; | |
610 } else { | |
611 return HType.CONFLICTING; | |
612 } | |
613 } | |
614 | |
615 void updateFieldSetters(Element field, HType type) { | |
616 assert(field.isField()); | |
617 assert(field.isMember()); | |
618 Map<Element, HType> fields = | |
619 fieldSettersType.putIfAbsent( | |
620 field.getEnclosingClass(), () => new Map<Element, HType>()); | |
621 if (!fields.containsKey(field)) { | |
622 fields[field] = type; | |
623 } else { | |
624 fields[field] = fields[field].union(type); | |
625 } | |
626 } | |
627 | |
628 // Returns the type that field setters are setting the field to based on what | |
629 // have been seen during compilation so far. | |
630 HType fieldSettersTypeSoFar(Element field) { | |
631 assert(field.isField()); | |
632 assert(field.isMember()); | |
633 ClassElement enclosingClass = field.getEnclosingClass(); | |
634 if (!fieldSettersType.containsKey(enclosingClass)) { | |
635 return HType.CONFLICTING; | |
636 } | |
637 Map<Element, HType> fields = fieldSettersType[enclosingClass]; | |
638 if (!fields.containsKey(field)) return HType.CONFLICTING; | |
639 return fields[field]; | |
640 } | |
641 | |
642 /** | 744 /** |
643 * Documentation wanted -- johnniwinther | 745 * Documentation wanted -- johnniwinther |
644 * | 746 * |
645 * Invariant: [element] must be a declaration element. | 747 * Invariant: [element] must be a declaration element. |
646 */ | 748 */ |
647 void scheduleForRecompilation(Element element) { | 749 void scheduleForRecompilation(Element element) { |
648 assert(invariant(element, element.isDeclaration)); | 750 assert(invariant(element, element.isDeclaration)); |
649 if (compiler.phase == Compiler.PHASE_COMPILING) { | 751 if (compiler.phase == Compiler.PHASE_COMPILING) { |
650 invalidateAfterCodegen.add(element); | 752 invalidateAfterCodegen.add(element); |
651 } | 753 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 * scheduled for recompilation. | 802 * scheduled for recompilation. |
701 * | 803 * |
702 * Invariant: [element] must be a declaration element. | 804 * Invariant: [element] must be a declaration element. |
703 */ | 805 */ |
704 registerParameterTypesOptimization( | 806 registerParameterTypesOptimization( |
705 FunctionElement element, | 807 FunctionElement element, |
706 HTypeList parameterTypes, | 808 HTypeList parameterTypes, |
707 OptionalParameterTypes defaultValueTypes) { | 809 OptionalParameterTypes defaultValueTypes) { |
708 assert(invariant(element, element.isDeclaration)); | 810 assert(invariant(element, element.isDeclaration)); |
709 if (element.parameterCount(compiler) == 0) return; | 811 if (element.parameterCount(compiler) == 0) return; |
710 argumentTypes.registerOptimization( | 812 argumentTypes.registerOptimizedFunction( |
711 element, parameterTypes, defaultValueTypes); | 813 element, parameterTypes, defaultValueTypes); |
712 } | 814 } |
713 | 815 |
| 816 registerFieldTypesOptimization(FunctionElement element, |
| 817 Element field, |
| 818 HType type) { |
| 819 fieldTypes.registerOptimizedFunction(element, field, type); |
| 820 } |
| 821 |
714 /** | 822 /** |
715 * Documentation wanted -- johnniwinther | 823 * Documentation wanted -- johnniwinther |
716 * | 824 * |
717 * Invariant: [element] must be a declaration element. | 825 * Invariant: [element] must be a declaration element. |
718 */ | 826 */ |
719 void registerReturnType(FunctionElement element, HType returnType) { | 827 void registerReturnType(FunctionElement element, HType returnType) { |
720 assert(invariant(element, element.isDeclaration)); | 828 assert(invariant(element, element.isDeclaration)); |
721 ReturnInfo info = returnInfo[element]; | 829 ReturnInfo info = returnInfo[element]; |
722 if (info != null) { | 830 if (info != null) { |
723 info.update(returnType, scheduleForRecompilation); | 831 info.update(returnType, scheduleForRecompilation); |
(...skipping 24 matching lines...) Expand all Loading... |
748 } | 856 } |
749 | 857 |
750 void dumpReturnTypes() { | 858 void dumpReturnTypes() { |
751 returnInfo.forEach((Element element, ReturnInfo info) { | 859 returnInfo.forEach((Element element, ReturnInfo info) { |
752 if (info.returnType != HType.UNKNOWN) { | 860 if (info.returnType != HType.UNKNOWN) { |
753 print("Inferred $element has return type ${info.returnType}"); | 861 print("Inferred $element has return type ${info.returnType}"); |
754 } | 862 } |
755 }); | 863 }); |
756 } | 864 } |
757 | 865 |
| 866 void registerConstructor(Element element) { |
| 867 fieldTypes.registerConstructor(element); |
| 868 } |
| 869 |
| 870 void registerFieldInitializer(Element field, HType type) { |
| 871 fieldTypes.registerFieldInitializer(field, type); |
| 872 } |
| 873 |
| 874 void registerFieldConstructor(Element field, HType type) { |
| 875 fieldTypes.registerFieldConstructor(field, type); |
| 876 } |
| 877 |
| 878 void registerFieldSetter(FunctionElement element, Element field, HType type) { |
| 879 fieldTypes.registerFieldSetter(element, field, type); |
| 880 } |
| 881 |
| 882 void addedDynamicSetter(Selector setter, HType type) { |
| 883 fieldTypes.addedDynamicSetter(setter, type); |
| 884 } |
| 885 |
| 886 HType optimisticFieldType(Element element) { |
| 887 return fieldTypes.optimisticFieldType(element); |
| 888 } |
| 889 |
758 SourceString getCheckedModeHelper(DartType type) { | 890 SourceString getCheckedModeHelper(DartType type) { |
759 Element element = type.element; | 891 Element element = type.element; |
760 bool nativeCheck = | 892 bool nativeCheck = |
761 emitter.nativeEmitter.requiresNativeIsCheck(element); | 893 emitter.nativeEmitter.requiresNativeIsCheck(element); |
762 if (element == compiler.stringClass) { | 894 if (element == compiler.stringClass) { |
763 return const SourceString('stringTypeCheck'); | 895 return const SourceString('stringTypeCheck'); |
764 } else if (element == compiler.doubleClass) { | 896 } else if (element == compiler.doubleClass) { |
765 return const SourceString('doubleTypeCheck'); | 897 return const SourceString('doubleTypeCheck'); |
766 } else if (element == compiler.numClass) { | 898 } else if (element == compiler.numClass) { |
767 return const SourceString('numTypeCheck'); | 899 return const SourceString('numTypeCheck'); |
(...skipping 19 matching lines...) Expand all Loading... |
787 ? const SourceString('listSuperNativeTypeCheck') | 919 ? const SourceString('listSuperNativeTypeCheck') |
788 : const SourceString('listSuperTypeCheck'); | 920 : const SourceString('listSuperTypeCheck'); |
789 } else { | 921 } else { |
790 return nativeCheck | 922 return nativeCheck |
791 ? const SourceString('callTypeCheck') | 923 ? const SourceString('callTypeCheck') |
792 : const SourceString('propertyTypeCheck'); | 924 : const SourceString('propertyTypeCheck'); |
793 } | 925 } |
794 } | 926 } |
795 } | 927 } |
796 } | 928 } |
OLD | NEW |