| 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 library js_backend.backend; | 5 library js_backend.backend; |
| 6 | 6 |
| 7 import '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../common/backend_api.dart' | 8 import '../common/backend_api.dart' |
| 9 show ForeignResolver, NativeRegistry, ImpactTransformer; | 9 show ForeignResolver, NativeRegistry, ImpactTransformer; |
| 10 import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem; | 10 import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem; |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 /// called. When TRACE_METHOD is 'console' this will be logged | 347 /// called. When TRACE_METHOD is 'console' this will be logged |
| 348 /// directly in the JavaScript console. When TRACE_METHOD is 'post' the | 348 /// directly in the JavaScript console. When TRACE_METHOD is 'post' the |
| 349 /// information will be sent to a server via a POST request. | 349 /// information will be sent to a server via a POST request. |
| 350 static const String TRACE_METHOD = const String.fromEnvironment('traceCalls'); | 350 static const String TRACE_METHOD = const String.fromEnvironment('traceCalls'); |
| 351 static const bool TRACE_CALLS = | 351 static const bool TRACE_CALLS = |
| 352 TRACE_METHOD == 'post' || TRACE_METHOD == 'console'; | 352 TRACE_METHOD == 'post' || TRACE_METHOD == 'console'; |
| 353 | 353 |
| 354 Namer _namer; | 354 Namer _namer; |
| 355 | 355 |
| 356 Namer get namer { | 356 Namer get namer { |
| 357 assert(invariant(NO_LOCATION_SPANNABLE, _namer != null, | 357 assert(_namer != null, |
| 358 message: "Namer has not been created yet.")); | 358 failedAt(NO_LOCATION_SPANNABLE, "Namer has not been created yet.")); |
| 359 return _namer; | 359 return _namer; |
| 360 } | 360 } |
| 361 | 361 |
| 362 /** | 362 /** |
| 363 * Set of classes whose `operator ==` methods handle `null` themselves. | 363 * Set of classes whose `operator ==` methods handle `null` themselves. |
| 364 */ | 364 */ |
| 365 final Set<ClassEntity> specialOperatorEqClasses = new Set<ClassEntity>(); | 365 final Set<ClassEntity> specialOperatorEqClasses = new Set<ClassEntity>(); |
| 366 | 366 |
| 367 List<CompilerTask> get tasks { | 367 List<CompilerTask> get tasks { |
| 368 List<CompilerTask> result = functionCompiler.tasks; | 368 List<CompilerTask> result = functionCompiler.tasks; |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 | 530 |
| 531 CommonElements get commonElements => compiler.commonElements; | 531 CommonElements get commonElements => compiler.commonElements; |
| 532 | 532 |
| 533 Resolution get resolution => compiler.resolution; | 533 Resolution get resolution => compiler.resolution; |
| 534 | 534 |
| 535 Target get target => _target; | 535 Target get target => _target; |
| 536 | 536 |
| 537 /// Resolution support for generating table of interceptors and | 537 /// Resolution support for generating table of interceptors and |
| 538 /// constructors for custom elements. | 538 /// constructors for custom elements. |
| 539 CustomElementsResolutionAnalysis get customElementsResolutionAnalysis { | 539 CustomElementsResolutionAnalysis get customElementsResolutionAnalysis { |
| 540 assert(invariant( | 540 assert( |
| 541 NO_LOCATION_SPANNABLE, _customElementsResolutionAnalysis != null, | 541 _customElementsResolutionAnalysis != null, |
| 542 message: "CustomElementsResolutionAnalysis has not been created yet.")); | 542 failedAt(NO_LOCATION_SPANNABLE, |
| 543 "CustomElementsResolutionAnalysis has not been created yet.")); |
| 543 return _customElementsResolutionAnalysis; | 544 return _customElementsResolutionAnalysis; |
| 544 } | 545 } |
| 545 | 546 |
| 546 /// Codegen support for generating table of interceptors and | 547 /// Codegen support for generating table of interceptors and |
| 547 /// constructors for custom elements. | 548 /// constructors for custom elements. |
| 548 CustomElementsCodegenAnalysis get customElementsCodegenAnalysis { | 549 CustomElementsCodegenAnalysis get customElementsCodegenAnalysis { |
| 549 assert(invariant( | 550 assert( |
| 550 NO_LOCATION_SPANNABLE, _customElementsCodegenAnalysis != null, | 551 _customElementsCodegenAnalysis != null, |
| 551 message: "CustomElementsCodegenAnalysis has not been created yet.")); | 552 failedAt(NO_LOCATION_SPANNABLE, |
| 553 "CustomElementsCodegenAnalysis has not been created yet.")); |
| 552 return _customElementsCodegenAnalysis; | 554 return _customElementsCodegenAnalysis; |
| 553 } | 555 } |
| 554 | 556 |
| 555 NativeBasicData get nativeBasicData { | 557 NativeBasicData get nativeBasicData { |
| 556 assert(invariant(NO_LOCATION_SPANNABLE, _nativeBasicData != null, | 558 assert( |
| 557 message: "NativeBasicData has not been computed yet.")); | 559 _nativeBasicData != null, |
| 560 failedAt(NO_LOCATION_SPANNABLE, |
| 561 "NativeBasicData has not been computed yet.")); |
| 558 return _nativeBasicData; | 562 return _nativeBasicData; |
| 559 } | 563 } |
| 560 | 564 |
| 561 NativeBasicDataBuilder get nativeBasicDataBuilder => _nativeBasicDataBuilder; | 565 NativeBasicDataBuilder get nativeBasicDataBuilder => _nativeBasicDataBuilder; |
| 562 | 566 |
| 563 /// Resolution analysis for tracking reflective access to type variables. | 567 /// Resolution analysis for tracking reflective access to type variables. |
| 564 TypeVariableResolutionAnalysis get typeVariableResolutionAnalysis { | 568 TypeVariableResolutionAnalysis get typeVariableResolutionAnalysis { |
| 565 assert(invariant( | 569 assert( |
| 566 NO_LOCATION_SPANNABLE, _typeVariableCodegenAnalysis == null, | 570 _typeVariableCodegenAnalysis == null, |
| 567 message: "TypeVariableHandler has already been created.")); | 571 failedAt(NO_LOCATION_SPANNABLE, |
| 572 "TypeVariableHandler has already been created.")); |
| 568 return _typeVariableResolutionAnalysis; | 573 return _typeVariableResolutionAnalysis; |
| 569 } | 574 } |
| 570 | 575 |
| 571 /// Codegen handler for reflective access to type variables. | 576 /// Codegen handler for reflective access to type variables. |
| 572 TypeVariableCodegenAnalysis get typeVariableCodegenAnalysis { | 577 TypeVariableCodegenAnalysis get typeVariableCodegenAnalysis { |
| 573 assert(invariant( | 578 assert( |
| 574 NO_LOCATION_SPANNABLE, _typeVariableCodegenAnalysis != null, | 579 _typeVariableCodegenAnalysis != null, |
| 575 message: "TypeVariableHandler has not been created yet.")); | 580 failedAt(NO_LOCATION_SPANNABLE, |
| 581 "TypeVariableHandler has not been created yet.")); |
| 576 return _typeVariableCodegenAnalysis; | 582 return _typeVariableCodegenAnalysis; |
| 577 } | 583 } |
| 578 | 584 |
| 579 MirrorsData get mirrorsData => _mirrorsData; | 585 MirrorsData get mirrorsData => _mirrorsData; |
| 580 | 586 |
| 581 MirrorsDataBuilder get mirrorsDataBuilder => _mirrorsData; | 587 MirrorsDataBuilder get mirrorsDataBuilder => _mirrorsData; |
| 582 | 588 |
| 583 /// Resolution support for computing reflectable elements. | 589 /// Resolution support for computing reflectable elements. |
| 584 MirrorsResolutionAnalysis get mirrorsResolutionAnalysis => | 590 MirrorsResolutionAnalysis get mirrorsResolutionAnalysis => |
| 585 _mirrorsResolutionAnalysis; | 591 _mirrorsResolutionAnalysis; |
| 586 | 592 |
| 587 /// Codegen support for computing reflectable elements. | 593 /// Codegen support for computing reflectable elements. |
| 588 MirrorsCodegenAnalysis get mirrorsCodegenAnalysis { | 594 MirrorsCodegenAnalysis get mirrorsCodegenAnalysis { |
| 589 assert(invariant(NO_LOCATION_SPANNABLE, _mirrorsCodegenAnalysis != null, | 595 assert( |
| 590 message: "MirrorsCodegenAnalysis has not been created yet.")); | 596 _mirrorsCodegenAnalysis != null, |
| 597 failedAt(NO_LOCATION_SPANNABLE, |
| 598 "MirrorsCodegenAnalysis has not been created yet.")); |
| 591 return _mirrorsCodegenAnalysis; | 599 return _mirrorsCodegenAnalysis; |
| 592 } | 600 } |
| 593 | 601 |
| 594 /// Codegen support for tree-shaking entries of `LookupMap`. | 602 /// Codegen support for tree-shaking entries of `LookupMap`. |
| 595 LookupMapAnalysis get lookupMapAnalysis { | 603 LookupMapAnalysis get lookupMapAnalysis { |
| 596 assert(invariant(NO_LOCATION_SPANNABLE, _lookupMapAnalysis != null, | 604 assert( |
| 597 message: "LookupMapAnalysis has not been created yet.")); | 605 _lookupMapAnalysis != null, |
| 606 failedAt(NO_LOCATION_SPANNABLE, |
| 607 "LookupMapAnalysis has not been created yet.")); |
| 598 return _lookupMapAnalysis; | 608 return _lookupMapAnalysis; |
| 599 } | 609 } |
| 600 | 610 |
| 601 OneShotInterceptorData get oneShotInterceptorData { | 611 OneShotInterceptorData get oneShotInterceptorData { |
| 602 assert(invariant(NO_LOCATION_SPANNABLE, _oneShotInterceptorData != null, | 612 assert( |
| 603 message: "OneShotInterceptorData has not been prepared yet.")); | 613 _oneShotInterceptorData != null, |
| 614 failedAt(NO_LOCATION_SPANNABLE, |
| 615 "OneShotInterceptorData has not been prepared yet.")); |
| 604 return _oneShotInterceptorData; | 616 return _oneShotInterceptorData; |
| 605 } | 617 } |
| 606 | 618 |
| 607 RuntimeTypesNeed get rtiNeed { | 619 RuntimeTypesNeed get rtiNeed { |
| 608 assert(invariant(NO_LOCATION_SPANNABLE, _rtiNeed != null, | 620 assert( |
| 609 message: "RuntimeTypesNeed has not been computed yet.")); | 621 _rtiNeed != null, |
| 622 failedAt(NO_LOCATION_SPANNABLE, |
| 623 "RuntimeTypesNeed has not been computed yet.")); |
| 610 return _rtiNeed; | 624 return _rtiNeed; |
| 611 } | 625 } |
| 612 | 626 |
| 613 RuntimeTypesNeedBuilder get rtiNeedBuilder { | 627 RuntimeTypesNeedBuilder get rtiNeedBuilder { |
| 614 assert(invariant(NO_LOCATION_SPANNABLE, _rtiNeed == null, | 628 assert( |
| 615 message: "RuntimeTypesNeed has already been computed.")); | 629 _rtiNeed == null, |
| 630 failedAt(NO_LOCATION_SPANNABLE, |
| 631 "RuntimeTypesNeed has already been computed.")); |
| 616 return _rtiNeedBuilder; | 632 return _rtiNeedBuilder; |
| 617 } | 633 } |
| 618 | 634 |
| 619 RuntimeTypesChecksBuilder get rtiChecksBuilder { | 635 RuntimeTypesChecksBuilder get rtiChecksBuilder { |
| 620 assert(invariant(NO_LOCATION_SPANNABLE, !_rti.rtiChecksBuilderClosed, | 636 assert( |
| 621 message: "RuntimeTypesChecks has already been computed.")); | 637 !_rti.rtiChecksBuilderClosed, |
| 638 failedAt(NO_LOCATION_SPANNABLE, |
| 639 "RuntimeTypesChecks has already been computed.")); |
| 622 return _rti; | 640 return _rti; |
| 623 } | 641 } |
| 624 | 642 |
| 625 RuntimeTypesSubstitutions get rtiSubstitutions => _rti; | 643 RuntimeTypesSubstitutions get rtiSubstitutions => _rti; |
| 626 | 644 |
| 627 RuntimeTypesEncoder get rtiEncoder { | 645 RuntimeTypesEncoder get rtiEncoder { |
| 628 assert(invariant(NO_LOCATION_SPANNABLE, _rtiEncoder != null, | 646 assert( |
| 629 message: "RuntimeTypesEncoder has not been created.")); | 647 _rtiEncoder != null, |
| 648 failedAt(NO_LOCATION_SPANNABLE, |
| 649 "RuntimeTypesEncoder has not been created.")); |
| 630 return _rtiEncoder; | 650 return _rtiEncoder; |
| 631 } | 651 } |
| 632 | 652 |
| 633 CheckedModeHelpers get checkedModeHelpers => _checkedModeHelpers; | 653 CheckedModeHelpers get checkedModeHelpers => _checkedModeHelpers; |
| 634 | 654 |
| 635 /// Returns constant environment for the JavaScript interpretation of the | 655 /// Returns constant environment for the JavaScript interpretation of the |
| 636 /// constants. | 656 /// constants. |
| 637 JavaScriptConstantCompiler get constants { | 657 JavaScriptConstantCompiler get constants { |
| 638 return constantCompilerTask.jsConstantCompiler; | 658 return constantCompilerTask.jsConstantCompiler; |
| 639 } | 659 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 714 ClassEntity interceptorClass) { | 734 ClassEntity interceptorClass) { |
| 715 if (interceptorClass == null) return; | 735 if (interceptorClass == null) return; |
| 716 ClassEntity objectClass = commonElements.objectClass; | 736 ClassEntity objectClass = commonElements.objectClass; |
| 717 compiler.elementEnvironment.forEachClassMember(objectClass, | 737 compiler.elementEnvironment.forEachClassMember(objectClass, |
| 718 (_, MemberEntity member) { | 738 (_, MemberEntity member) { |
| 719 if (member.isConstructor) return; | 739 if (member.isConstructor) return; |
| 720 MemberEntity interceptorMember = compiler.elementEnvironment | 740 MemberEntity interceptorMember = compiler.elementEnvironment |
| 721 .lookupClassMember(interceptorClass, member.name); | 741 .lookupClassMember(interceptorClass, member.name); |
| 722 // Interceptors must override all Object methods due to calling convention | 742 // Interceptors must override all Object methods due to calling convention |
| 723 // differences. | 743 // differences. |
| 724 assert(invariant(interceptorMember, | 744 assert( |
| 725 interceptorMember.enclosingClass == interceptorClass, | 745 interceptorMember.enclosingClass == interceptorClass, |
| 726 message: | 746 failedAt( |
| 747 interceptorMember, |
| 727 "Member ${member.name} not overridden in ${interceptorClass}. " | 748 "Member ${member.name} not overridden in ${interceptorClass}. " |
| 728 "Found $interceptorMember from " | 749 "Found $interceptorMember from " |
| 729 "${interceptorMember.enclosingClass}.")); | 750 "${interceptorMember.enclosingClass}.")); |
| 730 }); | 751 }); |
| 731 } | 752 } |
| 732 | 753 |
| 733 /// Called before processing of the resolution queue is started. | 754 /// Called before processing of the resolution queue is started. |
| 734 void onResolutionStart(ResolutionEnqueuer enqueuer) { | 755 void onResolutionStart(ResolutionEnqueuer enqueuer) { |
| 735 // TODO(johnniwinther): Avoid the compiler.elementEnvironment.getThisType | 756 // TODO(johnniwinther): Avoid the compiler.elementEnvironment.getThisType |
| 736 // calls. Currently needed to ensure resolution of the classes for various | 757 // calls. Currently needed to ensure resolution of the classes for various |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 942 work.registry.worldImpact | 963 work.registry.worldImpact |
| 943 .registerConstantUse(new ConstantUse.init(initialValue)); | 964 .registerConstantUse(new ConstantUse.init(initialValue)); |
| 944 // We don't need to generate code for static or top-level | 965 // We don't need to generate code for static or top-level |
| 945 // variables. For instance variables, we may need to generate | 966 // variables. For instance variables, we may need to generate |
| 946 // the checked setter. | 967 // the checked setter. |
| 947 if (Elements.isStaticOrTopLevel(element)) { | 968 if (Elements.isStaticOrTopLevel(element)) { |
| 948 return _codegenImpactTransformer | 969 return _codegenImpactTransformer |
| 949 .transformCodegenImpact(work.registry.worldImpact); | 970 .transformCodegenImpact(work.registry.worldImpact); |
| 950 } | 971 } |
| 951 } else { | 972 } else { |
| 952 assert(invariant( | 973 assert( |
| 953 variableElement, | |
| 954 variableElement.isInstanceMember || | 974 variableElement.isInstanceMember || |
| 955 constant.isImplicit || | 975 constant.isImplicit || |
| 956 constant.isPotential, | 976 constant.isPotential, |
| 957 message: "Constant expression without value: " | 977 failedAt( |
| 978 variableElement, |
| 979 "Constant expression without value: " |
| 958 "${constant.toStructuredText()}.")); | 980 "${constant.toStructuredText()}.")); |
| 959 } | 981 } |
| 960 } else { | 982 } else { |
| 961 // If the constant-handler was not able to produce a result we have to | 983 // If the constant-handler was not able to produce a result we have to |
| 962 // go through the builder (below) to generate the lazy initializer for | 984 // go through the builder (below) to generate the lazy initializer for |
| 963 // the static variable. | 985 // the static variable. |
| 964 // We also need to register the use of the cyclic-error helper. | 986 // We also need to register the use of the cyclic-error helper. |
| 965 work.registry.worldImpact.registerStaticUse(new StaticUse.staticInvoke( | 987 work.registry.worldImpact.registerStaticUse(new StaticUse.staticInvoke( |
| 966 commonElements.cyclicThrowHelper, CallStructure.ONE_ARG)); | 988 commonElements.cyclicThrowHelper, CallStructure.ONE_ARG)); |
| 967 } | 989 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 993 ? commonElements.jsInterceptorClass | 1015 ? commonElements.jsInterceptorClass |
| 994 : commonElements.objectClass; | 1016 : commonElements.objectClass; |
| 995 } | 1017 } |
| 996 | 1018 |
| 997 /** | 1019 /** |
| 998 * Unit test hook that returns code of an element as a String. | 1020 * Unit test hook that returns code of an element as a String. |
| 999 * | 1021 * |
| 1000 * Invariant: [element] must be a declaration element. | 1022 * Invariant: [element] must be a declaration element. |
| 1001 */ | 1023 */ |
| 1002 String getGeneratedCode(Element element) { | 1024 String getGeneratedCode(Element element) { |
| 1003 assert(invariant(element, element.isDeclaration)); | 1025 assert(element.isDeclaration, failedAt(element)); |
| 1004 return jsAst.prettyPrint(generatedCode[element], compiler.options); | 1026 return jsAst.prettyPrint(generatedCode[element], compiler.options); |
| 1005 } | 1027 } |
| 1006 | 1028 |
| 1007 /// Generates the output and returns the total size of the generated code. | 1029 /// Generates the output and returns the total size of the generated code. |
| 1008 int assembleProgram(ClosedWorld closedWorld) { | 1030 int assembleProgram(ClosedWorld closedWorld) { |
| 1009 int programSize = emitter.assembleProgram(namer, closedWorld); | 1031 int programSize = emitter.assembleProgram(namer, closedWorld); |
| 1010 noSuchMethodRegistry.emitDiagnostic(reporter); | 1032 noSuchMethodRegistry.emitDiagnostic(reporter); |
| 1011 int totalMethodCount = generatedCode.length; | 1033 int totalMethodCount = generatedCode.length; |
| 1012 if (totalMethodCount != mirrorsCodegenAnalysis.preMirrorsMethodCount) { | 1034 if (totalMethodCount != mirrorsCodegenAnalysis.preMirrorsMethodCount) { |
| 1013 int mirrorCount = | 1035 int mirrorCount = |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1432 | 1454 |
| 1433 bool canUseAliasedSuperMember(MemberEntity member, Selector selector) { | 1455 bool canUseAliasedSuperMember(MemberEntity member, Selector selector) { |
| 1434 return !selector.isGetter; | 1456 return !selector.isGetter; |
| 1435 } | 1457 } |
| 1436 | 1458 |
| 1437 /// Returns `true` if [member] is called from a subclass via `super`. | 1459 /// Returns `true` if [member] is called from a subclass via `super`. |
| 1438 bool isAliasedSuperMember(MemberEntity member) { | 1460 bool isAliasedSuperMember(MemberEntity member) { |
| 1439 return _aliasedSuperMembers.contains(member); | 1461 return _aliasedSuperMembers.contains(member); |
| 1440 } | 1462 } |
| 1441 } | 1463 } |
| OLD | NEW |