| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'package:js_runtime/shared/embedded_names.dart'; | 5 import 'package:js_runtime/shared/embedded_names.dart'; |
| 6 import 'package:kernel/ast.dart' as ir; | 6 import 'package:kernel/ast.dart' as ir; |
| 7 | 7 |
| 8 import '../common.dart'; | 8 import '../common.dart'; |
| 9 import '../common/names.dart'; | 9 import '../common/names.dart'; |
| 10 import '../compiler.dart'; | 10 import '../compiler.dart'; |
| 11 import '../constants/expressions.dart'; | 11 import '../constants/expressions.dart'; |
| 12 import '../constants/values.dart'; | 12 import '../constants/values.dart'; |
| 13 import '../core_types.dart'; |
| 13 import '../elements/resolution_types.dart'; | 14 import '../elements/resolution_types.dart'; |
| 14 import '../elements/elements.dart'; | 15 import '../elements/elements.dart'; |
| 15 import '../elements/entities.dart'; | 16 import '../elements/entities.dart'; |
| 16 import '../elements/modelx.dart'; | 17 import '../elements/modelx.dart'; |
| 17 import '../elements/types.dart'; | 18 import '../elements/types.dart'; |
| 18 import '../js/js.dart' as js; | 19 import '../js/js.dart' as js; |
| 19 import '../js_backend/backend_helpers.dart'; | 20 import '../js_backend/backend_helpers.dart'; |
| 20 import '../js_backend/js_backend.dart'; | 21 import '../js_backend/js_backend.dart'; |
| 21 import '../kernel/element_adapter.dart'; | 22 import '../kernel/element_adapter.dart'; |
| 22 import '../kernel/kernel.dart'; | 23 import '../kernel/kernel.dart'; |
| 23 import '../kernel/kernel_debug.dart'; | 24 import '../kernel/kernel_debug.dart'; |
| 24 import '../native/native.dart' as native; | 25 import '../native/native.dart' as native; |
| 25 import '../resolution/tree_elements.dart'; | 26 import '../resolution/tree_elements.dart'; |
| 26 import '../tree/tree.dart' as ast; | 27 import '../tree/tree.dart' as ast; |
| 27 import '../types/masks.dart'; | 28 import '../types/masks.dart'; |
| 28 import '../types/types.dart'; | 29 import '../types/types.dart'; |
| 29 import '../universe/call_structure.dart'; | 30 import '../universe/call_structure.dart'; |
| 30 import '../universe/selector.dart'; | 31 import '../universe/selector.dart'; |
| 31 import '../universe/side_effects.dart'; | 32 import '../universe/side_effects.dart'; |
| 32 import '../world.dart'; | 33 import '../world.dart'; |
| 33 import 'graph_builder.dart'; | 34 import 'graph_builder.dart'; |
| 34 import 'jump_handler.dart' show SwitchCaseJumpHandler; | 35 import 'jump_handler.dart' show SwitchCaseJumpHandler; |
| 35 import 'locals_handler.dart'; | 36 import 'locals_handler.dart'; |
| 36 import 'types.dart'; | 37 import 'types.dart'; |
| 37 | 38 |
| 38 /// A helper class that abstracts all accesses of the AST from Kernel nodes. | 39 /// A helper class that abstracts all accesses of the AST from Kernel nodes. |
| 39 /// | 40 /// |
| 40 /// The goal is to remove all need for the AST from the Kernel SSA builder. | 41 /// The goal is to remove all need for the AST from the Kernel SSA builder. |
| 41 class KernelAstAdapter implements KernelElementAdapter { | 42 class KernelAstAdapter extends KernelElementAdapterMixin { |
| 42 final Kernel kernel; | 43 final Kernel kernel; |
| 43 final JavaScriptBackend _backend; | 44 final JavaScriptBackend _backend; |
| 44 final Map<ir.Node, ast.Node> _nodeToAst; | 45 final Map<ir.Node, ast.Node> _nodeToAst; |
| 45 final Map<ir.Node, Element> _nodeToElement; | 46 final Map<ir.Node, Element> _nodeToElement; |
| 46 final Map<ir.VariableDeclaration, SyntheticLocal> _syntheticLocals = | 47 final Map<ir.VariableDeclaration, SyntheticLocal> _syntheticLocals = |
| 47 <ir.VariableDeclaration, SyntheticLocal>{}; | 48 <ir.VariableDeclaration, SyntheticLocal>{}; |
| 48 // TODO(efortuna): In an ideal world the TreeNodes should be some common | 49 // TODO(efortuna): In an ideal world the TreeNodes should be some common |
| 49 // interface we create for both ir.Statements and ir.SwitchCase (the | 50 // interface we create for both ir.Statements and ir.SwitchCase (the |
| 50 // ContinueSwitchStatement's target is a SwitchCase) rather than general | 51 // ContinueSwitchStatement's target is a SwitchCase) rather than general |
| 51 // TreeNode. Talking to Asger about this. | 52 // TreeNode. Talking to Asger about this. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 77 } | 78 } |
| 78 for (LocalFunctionElement localFunction in kernel.localFunctions.keys) { | 79 for (LocalFunctionElement localFunction in kernel.localFunctions.keys) { |
| 79 _nodeToElement[kernel.localFunctions[localFunction]] = localFunction; | 80 _nodeToElement[kernel.localFunctions[localFunction]] = localFunction; |
| 80 } | 81 } |
| 81 for (TypeVariableElement typeVariable in kernel.typeParameters.keys) { | 82 for (TypeVariableElement typeVariable in kernel.typeParameters.keys) { |
| 82 _nodeToElement[kernel.typeParameters[typeVariable]] = typeVariable; | 83 _nodeToElement[kernel.typeParameters[typeVariable]] = typeVariable; |
| 83 } | 84 } |
| 84 _typeConverter = new DartTypeConverter(this); | 85 _typeConverter = new DartTypeConverter(this); |
| 85 } | 86 } |
| 86 | 87 |
| 88 CommonElements get commonElements => _compiler.commonElements; |
| 89 |
| 87 /// Push the existing resolved AST on the stack and shift the current resolved | 90 /// Push the existing resolved AST on the stack and shift the current resolved |
| 88 /// AST to the AST that this kernel node points to. | 91 /// AST to the AST that this kernel node points to. |
| 89 void pushResolvedAst(ir.Node node) { | 92 void pushResolvedAst(ir.Node node) { |
| 90 _resolvedAstStack.add(_resolvedAst); | 93 _resolvedAstStack.add(_resolvedAst); |
| 91 _resolvedAst = (getElement(node) as AstElement).resolvedAst; | 94 _resolvedAst = (getElement(node) as AstElement).resolvedAst; |
| 92 } | 95 } |
| 93 | 96 |
| 94 /// Pop the resolved AST stack to reset it to the previous resolved AST node. | 97 /// Pop the resolved AST stack to reset it to the previous resolved AST node. |
| 95 void popResolvedAstStack() { | 98 void popResolvedAstStack() { |
| 96 assert(_resolvedAstStack.isNotEmpty); | 99 assert(_resolvedAstStack.isNotEmpty); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 MemberElement getMember(ir.Member node) => getElement(node).declaration; | 138 MemberElement getMember(ir.Member node) => getElement(node).declaration; |
| 136 | 139 |
| 137 MethodElement getMethod(ir.Procedure node) => getElement(node).declaration; | 140 MethodElement getMethod(ir.Procedure node) => getElement(node).declaration; |
| 138 | 141 |
| 139 FieldElement getField(ir.Field node) => getElement(node).declaration; | 142 FieldElement getField(ir.Field node) => getElement(node).declaration; |
| 140 | 143 |
| 141 ClassElement getClass(ir.Class node) => getElement(node).declaration; | 144 ClassElement getClass(ir.Class node) => getElement(node).declaration; |
| 142 | 145 |
| 143 LibraryElement getLibrary(ir.Library node) => getElement(node).declaration; | 146 LibraryElement getLibrary(ir.Library node) => getElement(node).declaration; |
| 144 | 147 |
| 145 LocalFunctionElement getLocalFunction(ir.Node node) => getElement(node); | 148 LocalFunctionElement getLocalFunction(ir.TreeNode node) => getElement(node); |
| 146 | 149 |
| 147 ast.Node getNode(ir.Node node) { | 150 ast.Node getNode(ir.Node node) { |
| 148 ast.Node result = _nodeToAst[node]; | 151 ast.Node result = _nodeToAst[node]; |
| 149 assert(invariant(CURRENT_ELEMENT_SPANNABLE, result != null, | 152 assert(invariant(CURRENT_ELEMENT_SPANNABLE, result != null, |
| 150 message: "No node found for $node")); | 153 message: "No node found for $node")); |
| 151 return result; | 154 return result; |
| 152 } | 155 } |
| 153 | 156 |
| 154 ast.Node getNodeOrNull(ir.Node node) { | 157 ast.Node getNodeOrNull(ir.Node node) { |
| 155 return _nodeToAst[node]; | 158 return _nodeToAst[node]; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 177 | 180 |
| 178 TypeMask returnTypeOf(ir.Member node) { | 181 TypeMask returnTypeOf(ir.Member node) { |
| 179 return TypeMaskFactory.inferredReturnTypeForElement( | 182 return TypeMaskFactory.inferredReturnTypeForElement( |
| 180 getElement(node), _globalInferenceResults); | 183 getElement(node), _globalInferenceResults); |
| 181 } | 184 } |
| 182 | 185 |
| 183 SideEffects getSideEffects(ir.Node node, ClosedWorld closedWorld) { | 186 SideEffects getSideEffects(ir.Node node, ClosedWorld closedWorld) { |
| 184 return closedWorld.getSideEffectsOfElement(getElement(node)); | 187 return closedWorld.getSideEffectsOfElement(getElement(node)); |
| 185 } | 188 } |
| 186 | 189 |
| 187 CallStructure getCallStructure(ir.Arguments arguments) { | |
| 188 int argumentCount = arguments.positional.length + arguments.named.length; | |
| 189 List<String> namedArguments = arguments.named.map((e) => e.name).toList(); | |
| 190 return new CallStructure(argumentCount, namedArguments); | |
| 191 } | |
| 192 | |
| 193 FunctionSignature getFunctionSignature(ir.FunctionNode function) { | 190 FunctionSignature getFunctionSignature(ir.FunctionNode function) { |
| 194 return getElement(function).asFunctionElement().functionSignature; | 191 return getElement(function).asFunctionElement().functionSignature; |
| 195 } | 192 } |
| 196 | 193 |
| 197 Name getName(ir.Name name) { | |
| 198 return new Name( | |
| 199 name.name, name.isPrivate ? getLibrary(name.library) : null); | |
| 200 } | |
| 201 | |
| 202 ir.Field getFieldFromElement(FieldElement field) { | 194 ir.Field getFieldFromElement(FieldElement field) { |
| 203 return kernel.fields[field]; | 195 return kernel.fields[field]; |
| 204 } | 196 } |
| 205 | 197 |
| 206 Selector getSelector(ir.Expression node) { | |
| 207 if (node is ir.PropertyGet) return getGetterSelector(node); | |
| 208 if (node is ir.PropertySet) return getSetterSelector(node); | |
| 209 if (node is ir.InvocationExpression) return getInvocationSelector(node); | |
| 210 _compiler.reporter.internalError(getNode(node), | |
| 211 "Can only get the selector for a property get or an invocation."); | |
| 212 return null; | |
| 213 } | |
| 214 | |
| 215 Selector getInvocationSelector(ir.InvocationExpression invocation) { | |
| 216 Name name = getName(invocation.name); | |
| 217 SelectorKind kind; | |
| 218 if (Elements.isOperatorName(invocation.name.name)) { | |
| 219 if (name == Names.INDEX_NAME || name == Names.INDEX_SET_NAME) { | |
| 220 kind = SelectorKind.INDEX; | |
| 221 } else { | |
| 222 kind = SelectorKind.OPERATOR; | |
| 223 } | |
| 224 } else { | |
| 225 kind = SelectorKind.CALL; | |
| 226 } | |
| 227 | |
| 228 CallStructure callStructure = getCallStructure(invocation.arguments); | |
| 229 return new Selector(kind, name, callStructure); | |
| 230 } | |
| 231 | |
| 232 Selector getGetterSelector(ir.PropertyGet getter) { | |
| 233 ir.Name irName = getter.name; | |
| 234 Name name = new Name( | |
| 235 irName.name, irName.isPrivate ? getLibrary(irName.library) : null); | |
| 236 return new Selector.getter(name); | |
| 237 } | |
| 238 | |
| 239 Selector getSetterSelector(ir.PropertySet setter) { | |
| 240 ir.Name irName = setter.name; | |
| 241 Name name = new Name( | |
| 242 irName.name, irName.isPrivate ? getLibrary(irName.library) : null); | |
| 243 return new Selector.setter(name); | |
| 244 } | |
| 245 | |
| 246 TypeMask typeOfInvocation(ir.MethodInvocation send, ClosedWorld closedWorld) { | 198 TypeMask typeOfInvocation(ir.MethodInvocation send, ClosedWorld closedWorld) { |
| 247 ast.Node operatorNode = kernel.nodeToAstOperator[send]; | 199 ast.Node operatorNode = kernel.nodeToAstOperator[send]; |
| 248 if (operatorNode != null) { | 200 if (operatorNode != null) { |
| 249 return _resultOf(_target).typeOfOperator(operatorNode); | 201 return _resultOf(_target).typeOfOperator(operatorNode); |
| 250 } | 202 } |
| 251 if (send.name.name == '[]=') { | 203 if (send.name.name == '[]=') { |
| 252 return closedWorld.commonMasks.dynamicType; | 204 return closedWorld.commonMasks.dynamicType; |
| 253 } | 205 } |
| 254 return _resultOf(_target).typeOfSend(getNode(send)); | 206 return _resultOf(_target).typeOfSend(getNode(send)); |
| 255 } | 207 } |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 619 ConstantExpression constant = node.accept(new Constantifier(this)); | 571 ConstantExpression constant = node.accept(new Constantifier(this)); |
| 620 if (constant == null) { | 572 if (constant == null) { |
| 621 throw new UnsupportedError( | 573 throw new UnsupportedError( |
| 622 'No constant for ${DebugPrinter.prettyPrint(node)}'); | 574 'No constant for ${DebugPrinter.prettyPrint(node)}'); |
| 623 } | 575 } |
| 624 metadata.add(constant); | 576 metadata.add(constant); |
| 625 }); | 577 }); |
| 626 return metadata; | 578 return metadata; |
| 627 } | 579 } |
| 628 | 580 |
| 629 /// Compute the kind of foreign helper function called by [node], if any. | 581 @override |
| 630 ForeignKind getForeignKind(ir.StaticInvocation node) { | 582 LibraryEntity lookupLibrary(Uri uri) { |
| 631 if (isForeignLibrary(node.target.enclosingLibrary)) { | 583 return _compiler.libraryLoader.lookupLibrary(uri); |
| 632 switch (node.target.name.name) { | |
| 633 case BackendHelpers.JS: | |
| 634 return ForeignKind.JS; | |
| 635 case BackendHelpers.JS_BUILTIN: | |
| 636 return ForeignKind.JS_BUILTIN; | |
| 637 case BackendHelpers.JS_EMBEDDED_GLOBAL: | |
| 638 return ForeignKind.JS_EMBEDDED_GLOBAL; | |
| 639 case BackendHelpers.JS_INTERCEPTOR_CONSTANT: | |
| 640 return ForeignKind.JS_INTERCEPTOR_CONSTANT; | |
| 641 } | |
| 642 } | |
| 643 return ForeignKind.NONE; | |
| 644 } | 584 } |
| 645 | 585 |
| 646 /// Return `true` if [node] is the `dart:_foreign_helper` library. | 586 @override |
| 647 bool isForeignLibrary(ir.Library node) { | 587 ClassElement lookupClass(LibraryElement library, String name) { |
| 648 return node.importUri == BackendHelpers.DART_FOREIGN_HELPER; | 588 Element element = library.find(name); |
| 649 } | 589 if (element != null && element.isClass) { |
| 650 | 590 return element; |
| 651 /// Looks up [typeName] for use in the spec-string of a `JS` called. | |
| 652 // TODO(johnniwinther): Use this in [native.NativeBehavior] instead of calling | |
| 653 // the `ForeignResolver`. | |
| 654 // TODO(johnniwinther): Cache the result to avoid redundant lookups? | |
| 655 native.TypeLookup _typeLookup({bool resolveAsRaw: true}) { | |
| 656 return (String typeName) { | |
| 657 ResolutionDartType findIn(Uri uri) { | |
| 658 LibraryElement library = _compiler.libraryLoader.lookupLibrary(uri); | |
| 659 if (library != null) { | |
| 660 Element element = library.find(typeName); | |
| 661 if (element != null && element.isClass) { | |
| 662 ClassElement cls = element; | |
| 663 // TODO(johnniwinther): Align semantics. | |
| 664 return resolveAsRaw ? cls.rawType : cls.thisType; | |
| 665 } | |
| 666 } | |
| 667 return null; | |
| 668 } | |
| 669 | |
| 670 ResolutionDartType type = findIn(Uris.dart_core); | |
| 671 type ??= findIn(BackendHelpers.DART_JS_HELPER); | |
| 672 type ??= findIn(BackendHelpers.DART_INTERCEPTORS); | |
| 673 type ??= findIn(BackendHelpers.DART_ISOLATE_HELPER); | |
| 674 type ??= findIn(Uris.dart_collection); | |
| 675 type ??= findIn(Uris.dart_html); | |
| 676 type ??= findIn(Uris.dart_svg); | |
| 677 type ??= findIn(Uris.dart_web_audio); | |
| 678 type ??= findIn(Uris.dart_web_gl); | |
| 679 return type; | |
| 680 }; | |
| 681 } | |
| 682 | |
| 683 String _getStringArgument(ir.StaticInvocation node, int index) { | |
| 684 return node.arguments.positional[index].accept(new Stringifier()); | |
| 685 } | |
| 686 | |
| 687 /// Computes the [native.NativeBehavior] for a call to the [JS] function. | |
| 688 // TODO(johnniwinther): Cache this for later use. | |
| 689 native.NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) { | |
| 690 if (node.arguments.positional.length < 2 || | |
| 691 node.arguments.named.isNotEmpty) { | |
| 692 reporter.reportErrorMessage( | |
| 693 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS); | |
| 694 return new native.NativeBehavior(); | |
| 695 } | |
| 696 String specString = _getStringArgument(node, 0); | |
| 697 if (specString == null) { | |
| 698 reporter.reportErrorMessage( | |
| 699 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_FIRST); | |
| 700 return new native.NativeBehavior(); | |
| 701 } | |
| 702 | |
| 703 String codeString = _getStringArgument(node, 1); | |
| 704 if (codeString == null) { | |
| 705 reporter.reportErrorMessage( | |
| 706 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND); | |
| 707 return new native.NativeBehavior(); | |
| 708 } | |
| 709 | |
| 710 return native.NativeBehavior.ofJsCall( | |
| 711 specString, | |
| 712 codeString, | |
| 713 _typeLookup(resolveAsRaw: true), | |
| 714 CURRENT_ELEMENT_SPANNABLE, | |
| 715 reporter, | |
| 716 _compiler.commonElements); | |
| 717 } | |
| 718 | |
| 719 /// Computes the [native.NativeBehavior] for a call to the [JS_BUILTIN] | |
| 720 /// function. | |
| 721 // TODO(johnniwinther): Cache this for later use. | |
| 722 native.NativeBehavior getNativeBehaviorForJsBuiltinCall( | |
| 723 ir.StaticInvocation node) { | |
| 724 if (node.arguments.positional.length < 1) { | |
| 725 reporter.internalError( | |
| 726 CURRENT_ELEMENT_SPANNABLE, "JS builtin expression has no type."); | |
| 727 return new native.NativeBehavior(); | |
| 728 } | |
| 729 if (node.arguments.positional.length < 2) { | |
| 730 reporter.internalError( | |
| 731 CURRENT_ELEMENT_SPANNABLE, "JS builtin is missing name."); | |
| 732 return new native.NativeBehavior(); | |
| 733 } | |
| 734 String specString = _getStringArgument(node, 0); | |
| 735 if (specString == null) { | |
| 736 reporter.internalError( | |
| 737 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument."); | |
| 738 return new native.NativeBehavior(); | |
| 739 } | |
| 740 return native.NativeBehavior.ofJsBuiltinCall( | |
| 741 specString, | |
| 742 _typeLookup(resolveAsRaw: true), | |
| 743 CURRENT_ELEMENT_SPANNABLE, | |
| 744 reporter, | |
| 745 _compiler.commonElements); | |
| 746 } | |
| 747 | |
| 748 /// Computes the [native.NativeBehavior] for a call to the | |
| 749 /// [JS_EMBEDDED_GLOBAL] function. | |
| 750 // TODO(johnniwinther): Cache this for later use. | |
| 751 native.NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall( | |
| 752 ir.StaticInvocation node) { | |
| 753 if (node.arguments.positional.length < 1) { | |
| 754 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, | |
| 755 "JS embedded global expression has no type."); | |
| 756 return new native.NativeBehavior(); | |
| 757 } | |
| 758 if (node.arguments.positional.length < 2) { | |
| 759 reporter.internalError( | |
| 760 CURRENT_ELEMENT_SPANNABLE, "JS embedded global is missing name."); | |
| 761 return new native.NativeBehavior(); | |
| 762 } | |
| 763 if (node.arguments.positional.length > 2 || | |
| 764 node.arguments.named.isNotEmpty) { | |
| 765 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, | |
| 766 "JS embedded global has more than 2 arguments."); | |
| 767 return new native.NativeBehavior(); | |
| 768 } | |
| 769 String specString = _getStringArgument(node, 0); | |
| 770 if (specString == null) { | |
| 771 reporter.internalError( | |
| 772 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument."); | |
| 773 return new native.NativeBehavior(); | |
| 774 } | |
| 775 return native.NativeBehavior.ofJsEmbeddedGlobalCall( | |
| 776 specString, | |
| 777 _typeLookup(resolveAsRaw: true), | |
| 778 CURRENT_ELEMENT_SPANNABLE, | |
| 779 reporter, | |
| 780 _compiler.commonElements); | |
| 781 } | |
| 782 | |
| 783 /// Computes the [InterfaceType] referenced by a call to the | |
| 784 /// [JS_INTERCEPTOR_CONSTANT] function, if any. | |
| 785 InterfaceType getInterfaceTypeForJsInterceptorCall(ir.StaticInvocation node) { | |
| 786 if (node.arguments.positional.length != 1 || | |
| 787 node.arguments.named.isNotEmpty) { | |
| 788 reporter.reportErrorMessage(CURRENT_ELEMENT_SPANNABLE, | |
| 789 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); | |
| 790 } | |
| 791 ir.Node argument = node.arguments.positional.first; | |
| 792 if (argument is ir.TypeLiteral && argument.type is ir.InterfaceType) { | |
| 793 return getInterfaceType(argument.type); | |
| 794 } | 591 } |
| 795 return null; | 592 return null; |
| 796 } | 593 } |
| 797 | 594 |
| 798 /// Returns `true` is [node] has a `@Native(...)` annotation. | 595 @override |
| 799 // TODO(johnniwinther): Cache this for later use. | 596 InterfaceType getRawType(ClassElement cls) { |
| 800 bool isNativeClass(ir.Class node) { | 597 return cls.rawType; |
| 801 for (ir.Expression annotation in node.annotations) { | 598 } |
| 802 if (annotation is ir.ConstructorInvocation) { | 599 |
| 803 ConstructorElement target = getElement(annotation.target).declaration; | 600 @override |
| 804 if (target.enclosingClass == | 601 InterfaceType getThisType(ClassElement cls) { |
| 805 _compiler.commonElements.nativeAnnotationClass) { | 602 return cls.thisType; |
| 806 return true; | |
| 807 } | |
| 808 } | |
| 809 } | |
| 810 return false; | |
| 811 } | 603 } |
| 812 | 604 |
| 813 /// Computes the native behavior for reading the native [field]. | 605 /// Computes the native behavior for reading the native [field]. |
| 814 // TODO(johnniwinther): Cache this for later use. | 606 // TODO(johnniwinther): Cache this for later use. |
| 815 native.NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field) { | 607 native.NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field) { |
| 816 ResolutionDartType type = getDartType(field.type); | 608 ResolutionDartType type = getDartType(field.type); |
| 817 List<ConstantExpression> metadata = getMetadata(field.annotations); | 609 List<ConstantExpression> metadata = getMetadata(field.annotations); |
| 818 return native.NativeBehavior.ofFieldLoad(CURRENT_ELEMENT_SPANNABLE, type, | 610 return native.NativeBehavior.ofFieldLoad(CURRENT_ELEMENT_SPANNABLE, type, |
| 819 metadata, _typeLookup(resolveAsRaw: false), _compiler, | 611 metadata, typeLookup(resolveAsRaw: false), _compiler, |
| 820 isJsInterop: false); | 612 isJsInterop: false); |
| 821 } | 613 } |
| 822 | 614 |
| 823 /// Computes the native behavior for writing to the native [field]. | 615 /// Computes the native behavior for writing to the native [field]. |
| 824 // TODO(johnniwinther): Cache this for later use. | 616 // TODO(johnniwinther): Cache this for later use. |
| 825 native.NativeBehavior getNativeBehaviorForFieldStore(ir.Field field) { | 617 native.NativeBehavior getNativeBehaviorForFieldStore(ir.Field field) { |
| 826 ResolutionDartType type = getDartType(field.type); | 618 ResolutionDartType type = getDartType(field.type); |
| 827 return native.NativeBehavior.ofFieldStore(type, _compiler.resolution); | 619 return native.NativeBehavior.ofFieldStore(type, _compiler.resolution); |
| 828 } | 620 } |
| 829 | 621 |
| 830 /// Computes the native behavior for calling [procedure]. | 622 /// Computes the native behavior for calling [procedure]. |
| 831 // TODO(johnniwinther): Cache this for later use. | 623 // TODO(johnniwinther): Cache this for later use. |
| 832 native.NativeBehavior getNativeBehaviorForMethod(ir.Procedure procedure) { | 624 native.NativeBehavior getNativeBehaviorForMethod(ir.Procedure procedure) { |
| 833 ResolutionDartType type = getFunctionType(procedure.function); | 625 ResolutionDartType type = getFunctionType(procedure.function); |
| 834 List<ConstantExpression> metadata = getMetadata(procedure.annotations); | 626 List<ConstantExpression> metadata = getMetadata(procedure.annotations); |
| 835 return native.NativeBehavior.ofMethod(CURRENT_ELEMENT_SPANNABLE, type, | 627 return native.NativeBehavior.ofMethod(CURRENT_ELEMENT_SPANNABLE, type, |
| 836 metadata, _typeLookup(resolveAsRaw: false), _compiler, | 628 metadata, typeLookup(resolveAsRaw: false), _compiler, |
| 837 isJsInterop: false); | 629 isJsInterop: false); |
| 838 } | 630 } |
| 839 | 631 |
| 840 MemberEntity getConstructorBodyEntity(ir.Constructor constructor) { | 632 MemberEntity getConstructorBodyEntity(ir.Constructor constructor) { |
| 841 AstElement element = getElement(constructor); | 633 AstElement element = getElement(constructor); |
| 842 MemberEntity constructorBody = | 634 MemberEntity constructorBody = |
| 843 ConstructorBodyElementX.createFromResolvedAst(element.resolvedAst); | 635 ConstructorBodyElementX.createFromResolvedAst(element.resolvedAst); |
| 844 assert(constructorBody != null); | 636 assert(constructorBody != null); |
| 845 return constructorBody; | 637 return constructorBody; |
| 846 } | 638 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 901 .toList()), | 693 .toList()), |
| 902 visitTypes(node.positionalParameters | 694 visitTypes(node.positionalParameters |
| 903 .skip(node.requiredParameterCount) | 695 .skip(node.requiredParameterCount) |
| 904 .toList()), | 696 .toList()), |
| 905 node.namedParameters.map((n) => n.name).toList(), | 697 node.namedParameters.map((n) => n.name).toList(), |
| 906 node.namedParameters.map((n) => visitType(n.type)).toList()); | 698 node.namedParameters.map((n) => visitType(n.type)).toList()); |
| 907 } | 699 } |
| 908 | 700 |
| 909 @override | 701 @override |
| 910 ResolutionDartType visitInterfaceType(ir.InterfaceType node) { | 702 ResolutionDartType visitInterfaceType(ir.InterfaceType node) { |
| 911 ClassElement cls = astAdapter.getElement(node.classNode); | 703 ClassElement cls = astAdapter.getClass(node.classNode); |
| 912 return new ResolutionInterfaceType(cls, visitTypes(node.typeArguments)); | 704 return new ResolutionInterfaceType(cls, visitTypes(node.typeArguments)); |
| 913 } | 705 } |
| 914 | 706 |
| 915 @override | 707 @override |
| 916 ResolutionDartType visitVoidType(ir.VoidType node) { | 708 ResolutionDartType visitVoidType(ir.VoidType node) { |
| 917 return const ResolutionVoidType(); | 709 return const ResolutionVoidType(); |
| 918 } | 710 } |
| 919 | 711 |
| 920 @override | 712 @override |
| 921 ResolutionDartType visitDynamicType(ir.DynamicType node) { | 713 ResolutionDartType visitDynamicType(ir.DynamicType node) { |
| 922 return const ResolutionDynamicType(); | 714 return const ResolutionDynamicType(); |
| 923 } | 715 } |
| 924 | 716 |
| 925 @override | 717 @override |
| 926 ResolutionDartType visitInvalidType(ir.InvalidType node) { | 718 ResolutionDartType visitInvalidType(ir.InvalidType node) { |
| 927 if (topLevel) { | 719 if (topLevel) { |
| 928 throw new UnimplementedError( | 720 throw new UnimplementedError( |
| 929 "Outermost invalid types not currently supported"); | 721 "Outermost invalid types not currently supported"); |
| 930 } | 722 } |
| 931 // Nested invalid types are treated as `dynamic`. | 723 // Nested invalid types are treated as `dynamic`. |
| 932 return const ResolutionDynamicType(); | 724 return const ResolutionDynamicType(); |
| 933 } | 725 } |
| 934 } | 726 } |
| 935 | 727 |
| 936 /// Visitor that converts string literals and concatenations of string literals | |
| 937 /// into the string value. | |
| 938 class Stringifier extends ir.ExpressionVisitor<String> { | |
| 939 @override | |
| 940 String visitStringLiteral(ir.StringLiteral node) => node.value; | |
| 941 | |
| 942 @override | |
| 943 String visitStringConcatenation(ir.StringConcatenation node) { | |
| 944 StringBuffer sb = new StringBuffer(); | |
| 945 for (ir.Expression expression in node.expressions) { | |
| 946 String value = expression.accept(this); | |
| 947 if (value == null) return null; | |
| 948 sb.write(value); | |
| 949 } | |
| 950 return sb.toString(); | |
| 951 } | |
| 952 } | |
| 953 | |
| 954 /// Visitor that converts a kernel constant expression into a | 728 /// Visitor that converts a kernel constant expression into a |
| 955 /// [ConstantExpression]. | 729 /// [ConstantExpression]. |
| 956 class Constantifier extends ir.ExpressionVisitor<ConstantExpression> { | 730 class Constantifier extends ir.ExpressionVisitor<ConstantExpression> { |
| 957 final KernelAstAdapter astAdapter; | 731 final KernelAstAdapter astAdapter; |
| 958 | 732 |
| 959 Constantifier(this.astAdapter); | 733 Constantifier(this.astAdapter); |
| 960 | 734 |
| 961 @override | 735 @override |
| 962 ConstantExpression visitConstructorInvocation(ir.ConstructorInvocation node) { | 736 ConstantExpression visitConstructorInvocation(ir.ConstructorInvocation node) { |
| 963 ConstructorElement constructor = | 737 ConstructorElement constructor = |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1114 JumpTarget continueTarget = | 888 JumpTarget continueTarget = |
| 1115 astAdapter.getJumpTarget(switchCase, isContinueTarget: true); | 889 astAdapter.getJumpTarget(switchCase, isContinueTarget: true); |
| 1116 assert(continueTarget is KernelJumpTarget); | 890 assert(continueTarget is KernelJumpTarget); |
| 1117 targetIndexMap[continueTarget] = switchIndex; | 891 targetIndexMap[continueTarget] = switchIndex; |
| 1118 assert(builder.jumpTargets[continueTarget] == null); | 892 assert(builder.jumpTargets[continueTarget] == null); |
| 1119 builder.jumpTargets[continueTarget] = this; | 893 builder.jumpTargets[continueTarget] = this; |
| 1120 switchIndex++; | 894 switchIndex++; |
| 1121 } | 895 } |
| 1122 } | 896 } |
| 1123 } | 897 } |
| OLD | NEW |