Chromium Code Reviews| 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 '../elements/resolution_types.dart'; | 13 import '../elements/resolution_types.dart'; |
| 14 import '../elements/elements.dart'; | 14 import '../elements/elements.dart'; |
| 15 import '../elements/entities.dart' show MemberEntity; | 15 import '../elements/entities.dart'; |
| 16 import '../elements/modelx.dart'; | 16 import '../elements/modelx.dart'; |
| 17 import '../elements/types.dart'; | |
| 17 import '../js/js.dart' as js; | 18 import '../js/js.dart' as js; |
| 18 import '../js_backend/backend_helpers.dart'; | 19 import '../js_backend/backend_helpers.dart'; |
| 19 import '../js_backend/js_backend.dart'; | 20 import '../js_backend/js_backend.dart'; |
| 20 import '../kernel/kernel.dart'; | 21 import '../kernel/kernel.dart'; |
| 21 import '../kernel/kernel_debug.dart'; | 22 import '../kernel/kernel_debug.dart'; |
| 22 import '../native/native.dart' as native; | 23 import '../native/native.dart' as native; |
| 23 import '../resolution/tree_elements.dart'; | 24 import '../resolution/tree_elements.dart'; |
| 24 import '../tree/tree.dart' as ast; | 25 import '../tree/tree.dart' as ast; |
| 25 import '../types/masks.dart'; | 26 import '../types/masks.dart'; |
| 26 import '../types/types.dart'; | 27 import '../types/types.dart'; |
| 27 import '../universe/call_structure.dart'; | 28 import '../universe/call_structure.dart'; |
| 28 import '../universe/selector.dart'; | 29 import '../universe/selector.dart'; |
| 29 import '../universe/side_effects.dart'; | 30 import '../universe/side_effects.dart'; |
| 30 import '../world.dart'; | 31 import '../world.dart'; |
| 31 import 'graph_builder.dart'; | 32 import 'graph_builder.dart'; |
| 32 import 'jump_handler.dart' show SwitchCaseJumpHandler; | 33 import 'jump_handler.dart' show SwitchCaseJumpHandler; |
| 33 import 'locals_handler.dart'; | 34 import 'locals_handler.dart'; |
| 34 import 'types.dart'; | 35 import 'types.dart'; |
| 35 | 36 |
| 37 /// Interface that translates between Kernel IR nodes and entities. | |
|
Siggi Cherem (dart-lang)
2017/01/24 21:16:21
is the idea that this will be used to actually bui
Johnni Winther
2017/01/25 09:08:56
In time the implementation of this interface will
| |
| 38 abstract class KernelWorldBuilder { | |
| 39 /// Returns the [DartType] corresponding to [type]. | |
| 40 DartType getDartType(ir.DartType type); | |
| 41 | |
| 42 /// Returns the list of [DartType]s corresponding to [types]. | |
| 43 List<DartType> getDartTypes(List<ir.DartType> types); | |
| 44 | |
| 45 /// Returns the [InterfaceType] corresponding to [type]. | |
| 46 InterfaceType getInterfaceType(ir.InterfaceType type); | |
| 47 | |
| 48 /// Return the [InterfaceType] corresponding to the [cls] with the given | |
| 49 /// [typeArguments]. | |
| 50 InterfaceType createInterfaceType( | |
| 51 ir.Class cls, List<ir.DartType> typeArguments); | |
| 52 | |
| 53 /// Returns the [CallStructure] corresponding to the [arguments]. | |
| 54 CallStructure getCallStructure(ir.Arguments arguments); | |
| 55 | |
| 56 /// Returns the [Selector] corresponding to the invocation or getter/setter | |
| 57 /// access of [node]. | |
| 58 Selector getSelector(ir.Expression node); | |
| 59 | |
| 60 /// Returns the [FunctionEntity] corresponding to the generative or factory | |
| 61 /// constructor [node]. | |
| 62 FunctionEntity getConstructor(ir.Member node); | |
| 63 | |
| 64 /// Returns the [MemberEntity] corresponding to the member [node]. | |
| 65 MemberEntity getMember(ir.Member node); | |
| 66 | |
| 67 /// Returns the [FunctionEntity] corresponding to the procedure [node]. | |
| 68 FunctionEntity getMethod(ir.Procedure node); | |
| 69 | |
| 70 /// Returns the [FieldEntity] corresponding to the field [node]. | |
| 71 FieldEntity getField(ir.Field node); | |
| 72 | |
| 73 /// Returns the [ClassEntity] corresponding to the class [node]. | |
| 74 ClassEntity getClass(ir.Class node); | |
| 75 | |
| 76 /// Returns the [Local] corresponding to the [node]. The node must be either | |
| 77 /// a [ir.FunctionDeclaration] or [ir.FunctionExpression]. | |
| 78 Local getLocalFunction(ir.Node node); | |
| 79 | |
| 80 /// Returns the [Name] corresponding to [name]. | |
| 81 Name getName(ir.Name name); | |
| 82 | |
| 83 /// Returns `true` is [node] has a `@Native(...)` annotation. | |
| 84 bool isNativeClass(ir.Class node); | |
| 85 | |
| 86 /// Return `true` if [node] is the `dart:_foreign_helper` library. | |
| 87 bool isForeignLibrary(ir.Library node); | |
| 88 | |
| 89 /// Computes the native behavior for reading the native [field]. | |
| 90 native.NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field); | |
| 91 | |
| 92 /// Computes the native behavior for writing to the native [field]. | |
| 93 native.NativeBehavior getNativeBehaviorForFieldStore(ir.Field field); | |
| 94 | |
| 95 /// Computes the native behavior for calling [procedure]. | |
| 96 native.NativeBehavior getNativeBehaviorForMethod(ir.Procedure procedure); | |
| 97 | |
| 98 /// Computes the [native.NativeBehavior] for a call to the [JS] function. | |
| 99 native.NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node); | |
| 100 | |
| 101 /// Computes the [native.NativeBehavior] for a call to the [JS_BUILTIN] | |
| 102 /// function. | |
| 103 native.NativeBehavior getNativeBehaviorForJsBuiltinCall( | |
| 104 ir.StaticInvocation node); | |
| 105 | |
| 106 /// Computes the [native.NativeBehavior] for a call to the | |
| 107 /// [JS_EMBEDDED_GLOBAL] function. | |
| 108 native.NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall( | |
| 109 ir.StaticInvocation node); | |
| 110 | |
| 111 /// Compute the kind of foreign helper function called by [node], if any. | |
| 112 ForeignKind getForeignKind(ir.StaticInvocation node); | |
| 113 | |
| 114 /// Computes the [InterfaceType] referenced by a call to the | |
| 115 /// [JS_INTERCEPTOR_CONSTANT] function, if any. | |
| 116 InterfaceType getInterfaceTypeForJsInterceptorCall(ir.StaticInvocation node); | |
| 117 } | |
| 118 | |
| 36 /// A helper class that abstracts all accesses of the AST from Kernel nodes. | 119 /// A helper class that abstracts all accesses of the AST from Kernel nodes. |
| 37 /// | 120 /// |
| 38 /// The goal is to remove all need for the AST from the Kernel SSA builder. | 121 /// The goal is to remove all need for the AST from the Kernel SSA builder. |
| 39 class KernelAstAdapter { | 122 class KernelAstAdapter implements KernelWorldBuilder { |
| 40 final Kernel kernel; | 123 final Kernel kernel; |
| 41 final JavaScriptBackend _backend; | 124 final JavaScriptBackend _backend; |
| 42 final Map<ir.Node, ast.Node> _nodeToAst; | 125 final Map<ir.Node, ast.Node> _nodeToAst; |
| 43 final Map<ir.Node, Element> _nodeToElement; | 126 final Map<ir.Node, Element> _nodeToElement; |
| 44 final Map<ir.VariableDeclaration, SyntheticLocal> _syntheticLocals = | 127 final Map<ir.VariableDeclaration, SyntheticLocal> _syntheticLocals = |
| 45 <ir.VariableDeclaration, SyntheticLocal>{}; | 128 <ir.VariableDeclaration, SyntheticLocal>{}; |
| 46 // TODO(efortuna): In an ideal world the TreeNodes should be some common | 129 // TODO(efortuna): In an ideal world the TreeNodes should be some common |
| 47 // interface we create for both ir.Statements and ir.SwitchCase (the | 130 // interface we create for both ir.Statements and ir.SwitchCase (the |
| 48 // ContinueSwitchStatement's target is a SwitchCase) rather than general | 131 // ContinueSwitchStatement's target is a SwitchCase) rather than general |
| 49 // TreeNode. Talking to Asger about this. | 132 // TreeNode. Talking to Asger about this. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 120 } | 203 } |
| 121 | 204 |
| 122 // TODO(johnniwinther): Use the more precise functions below. | 205 // TODO(johnniwinther): Use the more precise functions below. |
| 123 Element getElement(ir.Node node) { | 206 Element getElement(ir.Node node) { |
| 124 Element result = _nodeToElement[node]; | 207 Element result = _nodeToElement[node]; |
| 125 assert(invariant(CURRENT_ELEMENT_SPANNABLE, result != null, | 208 assert(invariant(CURRENT_ELEMENT_SPANNABLE, result != null, |
| 126 message: "No element found for $node.")); | 209 message: "No element found for $node.")); |
| 127 return result; | 210 return result; |
| 128 } | 211 } |
| 129 | 212 |
| 130 ConstructorElement getConstructor(ir.Node node) => | 213 ConstructorElement getConstructor(ir.Member node) => |
| 131 getElement(node).declaration; | 214 getElement(node).declaration; |
| 132 | 215 |
| 133 MemberElement getMember(ir.Node node) => getElement(node).declaration; | 216 MemberElement getMember(ir.Member node) => getElement(node).declaration; |
| 134 | 217 |
| 135 MethodElement getMethod(ir.Node node) => getElement(node).declaration; | 218 MethodElement getMethod(ir.Procedure node) => getElement(node).declaration; |
| 136 | 219 |
| 137 FieldElement getField(ir.Node node) => getElement(node).declaration; | 220 FieldElement getField(ir.Field node) => getElement(node).declaration; |
| 138 | 221 |
| 139 ClassElement getClass(ir.Node node) => getElement(node).declaration; | 222 ClassElement getClass(ir.Class node) => getElement(node).declaration; |
| 223 | |
| 224 LocalFunctionElement getLocalFunction(ir.Node node) => getElement(node); | |
| 140 | 225 |
| 141 ast.Node getNode(ir.Node node) { | 226 ast.Node getNode(ir.Node node) { |
| 142 ast.Node result = _nodeToAst[node]; | 227 ast.Node result = _nodeToAst[node]; |
| 143 assert(invariant(CURRENT_ELEMENT_SPANNABLE, result != null, | 228 assert(invariant(CURRENT_ELEMENT_SPANNABLE, result != null, |
| 144 message: "No node found for $node")); | 229 message: "No node found for $node")); |
| 145 return result; | 230 return result; |
| 146 } | 231 } |
| 147 | 232 |
| 148 ast.Node getNodeOrNull(ir.Node node) { | 233 ast.Node getNodeOrNull(ir.Node node) { |
| 149 return _nodeToAst[node]; | 234 return _nodeToAst[node]; |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 590 List<ir.VariableDeclaration> sortedNamedParameters = | 675 List<ir.VariableDeclaration> sortedNamedParameters = |
| 591 node.namedParameters.toList()..sort((a, b) => a.name.compareTo(b.name)); | 676 node.namedParameters.toList()..sort((a, b) => a.name.compareTo(b.name)); |
| 592 for (ir.VariableDeclaration variable in sortedNamedParameters) { | 677 for (ir.VariableDeclaration variable in sortedNamedParameters) { |
| 593 namedParameters.add(variable.name); | 678 namedParameters.add(variable.name); |
| 594 namedParameterTypes.add(getDartType(variable.type)); | 679 namedParameterTypes.add(getDartType(variable.type)); |
| 595 } | 680 } |
| 596 return new ResolutionFunctionType.synthesized(returnType, parameterTypes, | 681 return new ResolutionFunctionType.synthesized(returnType, parameterTypes, |
| 597 optionalParameterTypes, namedParameters, namedParameterTypes); | 682 optionalParameterTypes, namedParameters, namedParameterTypes); |
| 598 } | 683 } |
| 599 | 684 |
| 600 ResolutionInterfaceType getInterfaceType(ir.DartType type) => | 685 ResolutionInterfaceType getInterfaceType(ir.InterfaceType type) => |
| 601 getDartType(type); | 686 getDartType(type); |
| 602 | 687 |
| 603 ResolutionInterfaceType createInterfaceType( | 688 ResolutionInterfaceType createInterfaceType( |
| 604 ClassElement cls, List<ResolutionDartType> typeArguments) { | 689 ir.Class cls, List<ir.DartType> typeArguments) { |
| 605 return new ResolutionInterfaceType(cls, typeArguments); | 690 return new ResolutionInterfaceType( |
| 691 getClass(cls), getDartTypes(typeArguments)); | |
| 606 } | 692 } |
| 607 | 693 |
| 608 /// Converts [annotations] into a list of [ConstantExpression]s. | 694 /// Converts [annotations] into a list of [ConstantExpression]s. |
| 609 List<ConstantExpression> getMetadata(List<ir.Expression> annotations) { | 695 List<ConstantExpression> getMetadata(List<ir.Expression> annotations) { |
| 610 List<ConstantExpression> metadata = <ConstantExpression>[]; | 696 List<ConstantExpression> metadata = <ConstantExpression>[]; |
| 611 annotations.forEach((ir.Expression node) { | 697 annotations.forEach((ir.Expression node) { |
| 612 ConstantExpression constant = node.accept(new Constantifier(this)); | 698 ConstantExpression constant = node.accept(new Constantifier(this)); |
| 613 if (constant == null) { | 699 if (constant == null) { |
| 614 throw new UnsupportedError( | 700 throw new UnsupportedError( |
| 615 'No constant for ${DebugPrinter.prettyPrint(node)}'); | 701 'No constant for ${DebugPrinter.prettyPrint(node)}'); |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 766 return new native.NativeBehavior(); | 852 return new native.NativeBehavior(); |
| 767 } | 853 } |
| 768 return native.NativeBehavior.ofJsEmbeddedGlobalCall( | 854 return native.NativeBehavior.ofJsEmbeddedGlobalCall( |
| 769 specString, | 855 specString, |
| 770 _typeLookup(resolveAsRaw: true), | 856 _typeLookup(resolveAsRaw: true), |
| 771 CURRENT_ELEMENT_SPANNABLE, | 857 CURRENT_ELEMENT_SPANNABLE, |
| 772 reporter, | 858 reporter, |
| 773 _compiler.commonElements); | 859 _compiler.commonElements); |
| 774 } | 860 } |
| 775 | 861 |
| 862 /// Computes the [InterfaceType] referenced by a call to the | |
| 863 /// [JS_INTERCEPTOR_CONSTANT] function, if any. | |
| 864 InterfaceType getInterfaceTypeForJsInterceptorCall(ir.StaticInvocation node) { | |
| 865 if (node.arguments.positional.length != 1 || | |
| 866 node.arguments.named.isNotEmpty) { | |
| 867 reporter.reportErrorMessage(CURRENT_ELEMENT_SPANNABLE, | |
| 868 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); | |
| 869 } | |
| 870 ir.Node argument = node.arguments.positional.first; | |
| 871 if (argument is ir.TypeLiteral && argument.type is ir.InterfaceType) { | |
| 872 return getInterfaceType(argument.type); | |
| 873 } | |
| 874 return null; | |
| 875 } | |
| 876 | |
| 776 /// Returns `true` is [node] has a `@Native(...)` annotation. | 877 /// Returns `true` is [node] has a `@Native(...)` annotation. |
| 777 // TODO(johnniwinther): Cache this for later use. | 878 // TODO(johnniwinther): Cache this for later use. |
| 778 bool isNative(ir.Class node) { | 879 bool isNativeClass(ir.Class node) { |
| 779 for (ir.Expression annotation in node.annotations) { | 880 for (ir.Expression annotation in node.annotations) { |
| 780 if (annotation is ir.ConstructorInvocation) { | 881 if (annotation is ir.ConstructorInvocation) { |
| 781 ConstructorElement target = getElement(annotation.target).declaration; | 882 ConstructorElement target = getElement(annotation.target).declaration; |
| 782 if (target.enclosingClass == | 883 if (target.enclosingClass == |
| 783 _compiler.commonElements.nativeAnnotationClass) { | 884 _compiler.commonElements.nativeAnnotationClass) { |
| 784 return true; | 885 return true; |
| 785 } | 886 } |
| 786 } | 887 } |
| 787 } | 888 } |
| 788 return false; | 889 return false; |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1098 JumpTarget continueTarget = | 1199 JumpTarget continueTarget = |
| 1099 astAdapter.getJumpTarget(switchCase, isContinueTarget: true); | 1200 astAdapter.getJumpTarget(switchCase, isContinueTarget: true); |
| 1100 assert(continueTarget is KernelJumpTarget); | 1201 assert(continueTarget is KernelJumpTarget); |
| 1101 targetIndexMap[continueTarget] = switchIndex; | 1202 targetIndexMap[continueTarget] = switchIndex; |
| 1102 assert(builder.jumpTargets[continueTarget] == null); | 1203 assert(builder.jumpTargets[continueTarget] == null); |
| 1103 builder.jumpTargets[continueTarget] = this; | 1204 builder.jumpTargets[continueTarget] = this; |
| 1104 switchIndex++; | 1205 switchIndex++; |
| 1105 } | 1206 } |
| 1106 } | 1207 } |
| 1107 } | 1208 } |
| OLD | NEW |