Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Side by Side Diff: pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart

Issue 1185633003: cps-ir: Support foreign code. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Status file updates. Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 dart2js.ir_builder_task; 5 library dart2js.ir_builder_task;
6 6
7 import '../closure.dart' as closurelib; 7 import '../closure.dart' as closurelib;
8 import '../closure.dart' hide ClosureScope; 8 import '../closure.dart' hide ClosureScope;
9 import '../constants/expressions.dart'; 9 import '../constants/expressions.dart';
10 import '../dart_types.dart'; 10 import '../dart_types.dart';
11 import '../dart2jslib.dart'; 11 import '../dart2jslib.dart';
12 import '../elements/elements.dart'; 12 import '../elements/elements.dart';
13 import '../elements/modelx.dart' show SynthesizedConstructorElementX, 13 import '../elements/modelx.dart' show SynthesizedConstructorElementX,
14 ConstructorBodyElementX, FunctionSignatureX; 14 ConstructorBodyElementX, FunctionSignatureX;
15 import '../io/source_information.dart'; 15 import '../io/source_information.dart';
16 import '../js_backend/js_backend.dart' show JavaScriptBackend; 16 import '../js_backend/js_backend.dart' show JavaScriptBackend;
17 import '../resolution/semantic_visitor.dart'; 17 import '../resolution/semantic_visitor.dart';
18 import '../resolution/operators.dart' as op; 18 import '../resolution/operators.dart' as op;
19 import '../scanner/scannerlib.dart' show Token, isUserDefinableOperator; 19 import '../scanner/scannerlib.dart' show Token, isUserDefinableOperator;
20 import '../tree/tree.dart' as ast; 20 import '../tree/tree.dart' as ast;
21 import '../universe/universe.dart' show SelectorKind, CallStructure; 21 import '../universe/universe.dart' show SelectorKind, CallStructure;
22 import 'cps_ir_nodes.dart' as ir; 22 import 'cps_ir_nodes.dart' as ir;
23 import 'cps_ir_builder.dart'; 23 import 'cps_ir_builder.dart';
24 import '../native/native.dart' show NativeBehavior;
25
26 // TODO(karlklose): remove.
27 import '../js/js.dart' as js show js, Template, Expression;
28 import '../ssa/ssa.dart' show TypeMaskFactory;
29 import '../types/types.dart' show TypeMask;
30 import '../util/util.dart';
31
32 import 'package:_internal/compiler/js_lib/shared/embedded_names.dart'
33 show JsBuiltin, JsGetName;
34 import '../constants/values.dart';
24 35
25 typedef void IrBuilderCallback(Element element, ir.FunctionDefinition irNode); 36 typedef void IrBuilderCallback(Element element, ir.FunctionDefinition irNode);
26 37
27 /// This task provides the interface to build IR nodes from [ast.Node]s, which 38 /// This task provides the interface to build IR nodes from [ast.Node]s, which
28 /// is used from the [CpsFunctionCompiler] to generate code. 39 /// is used from the [CpsFunctionCompiler] to generate code.
29 /// 40 ///
30 /// This class is mainly there to correctly measure how long building the IR 41 /// This class is mainly there to correctly measure how long building the IR
31 /// takes. 42 /// takes.
32 class IrBuilderTask extends CompilerTask { 43 class IrBuilderTask extends CompilerTask {
33 final SourceInformationFactory sourceInformationFactory; 44 final SourceInformationFactory sourceInformationFactory;
(...skipping 953 matching lines...) Expand 10 before | Expand all | Expand 10 after
987 callStructure, 998 callStructure,
988 translateDynamicArguments(arguments, callStructure)); 999 translateDynamicArguments(arguments, callStructure));
989 } 1000 }
990 1001
991 @override 1002 @override
992 ir.Primitive handleStaticFunctionInvoke( 1003 ir.Primitive handleStaticFunctionInvoke(
993 ast.Send node, 1004 ast.Send node,
994 MethodElement function, 1005 MethodElement function,
995 ast.NodeList arguments, 1006 ast.NodeList arguments,
996 CallStructure callStructure, 1007 CallStructure callStructure,
997 _) { 1008 _);
998 // TODO(karlklose): support foreign functions.
999 if (compiler.backend.isForeign(function)) {
1000 return giveup(node, 'handleStaticFunctionInvoke: foreign: $function');
1001 }
1002 return irBuilder.buildStaticFunctionInvocation(function, callStructure,
1003 translateStaticArguments(arguments, function, callStructure),
1004 sourceInformation: sourceInformationBuilder.buildCall(node));
1005 }
1006 1009
1007 @override 1010 @override
1008 ir.Primitive handleStaticFunctionIncompatibleInvoke( 1011 ir.Primitive handleStaticFunctionIncompatibleInvoke(
1009 ast.Send node, 1012 ast.Send node,
1010 MethodElement function, 1013 MethodElement function,
1011 ast.NodeList arguments, 1014 ast.NodeList arguments,
1012 CallStructure callStructure, _) { 1015 CallStructure callStructure, _) {
1013 return buildStaticNoSuchMethod( 1016 return buildStaticNoSuchMethod(
1014 elements.getSelector(node), 1017 elements.getSelector(node),
1015 arguments.nodes.mapToList(visit)); 1018 arguments.nodes.mapToList(visit));
(...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after
1854 try { 1857 try {
1855 return action(); 1858 return action();
1856 } catch(e) { 1859 } catch(e) {
1857 if (e == ABORT_IRNODE_BUILDER) { 1860 if (e == ABORT_IRNODE_BUILDER) {
1858 return null; 1861 return null;
1859 } 1862 }
1860 rethrow; 1863 rethrow;
1861 } 1864 }
1862 } 1865 }
1863 1866
1864 void internalError(ast.Node node, String message) { 1867 internalError(ast.Node node, String message) {
1865 giveup(node, message); 1868 giveup(node, message);
1866 } 1869 }
1867 1870
1868 @override 1871 @override
1869 visitNode(ast.Node node) { 1872 visitNode(ast.Node node) {
1870 internalError(node, "Unhandled node"); 1873 internalError(node, "Unhandled node");
1871 } 1874 }
1872 1875
1873 dynamic giveup(ast.Node node, [String reason]) { 1876 dynamic giveup(ast.Node node, [String reason]) {
1874 bailoutMessage = '($node): $reason'; 1877 bailoutMessage = '($node): $reason';
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
2047 2050
2048 /// Returns [true], if the analysis could not determine that the type 2051 /// Returns [true], if the analysis could not determine that the type
2049 /// arguments for the class [cls] are never used in the program. 2052 /// arguments for the class [cls] are never used in the program.
2050 bool requiresRuntimeTypesFor(ClassElement cls) { 2053 bool requiresRuntimeTypesFor(ClassElement cls) {
2051 return cls.typeVariables.isNotEmpty && _backend.classNeedsRti(cls); 2054 return cls.typeVariables.isNotEmpty && _backend.classNeedsRti(cls);
2052 } 2055 }
2053 2056
2054 FunctionElement get throwTypeErrorHelper => _backend.getThrowTypeError(); 2057 FunctionElement get throwTypeErrorHelper => _backend.getThrowTypeError();
2055 2058
2056 ClassElement get nullClass => _compiler.nullClass; 2059 ClassElement get nullClass => _compiler.nullClass;
2060
2061 TypeMask getTypeMaskForForeign(NativeBehavior behavior) {
2062 return TypeMaskFactory.fromNativeBehavior(behavior, _compiler);
2063 }
2057 } 2064 }
2058 2065
2059 /// IR builder specific to the JavaScript backend, coupled to the [JsIrBuilder]. 2066 /// IR builder specific to the JavaScript backend, coupled to the [JsIrBuilder].
2060 class JsIrBuilderVisitor extends IrBuilderVisitor { 2067 class JsIrBuilderVisitor extends IrBuilderVisitor {
2061 /// Promote the type of [irBuilder] to [JsIrBuilder]. 2068 /// Promote the type of [irBuilder] to [JsIrBuilder].
2062 JsIrBuilder get irBuilder => super.irBuilder; 2069 JsIrBuilder get irBuilder => super.irBuilder;
2063 2070
2064 JavaScriptBackend get backend => compiler.backend; 2071 JavaScriptBackend get backend => compiler.backend;
2065 2072
2066 /// Result of closure conversion for the current body of code. 2073 /// Result of closure conversion for the current body of code.
(...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after
2798 ConstantExpression constant = 2805 ConstantExpression constant =
2799 backend.constants.getConstantForVariable(field); 2806 backend.constants.getConstantForVariable(field);
2800 if (constant != null && !field.isAssignable) { 2807 if (constant != null && !field.isAssignable) {
2801 return buildConstant(constant); 2808 return buildConstant(constant);
2802 } else if (backend.constants.lazyStatics.contains(field)) { 2809 } else if (backend.constants.lazyStatics.contains(field)) {
2803 return irBuilder.buildStaticFieldLazyGet(field, src); 2810 return irBuilder.buildStaticFieldLazyGet(field, src);
2804 } else { 2811 } else {
2805 return irBuilder.buildStaticFieldGet(field, src); 2812 return irBuilder.buildStaticFieldGet(field, src);
2806 } 2813 }
2807 } 2814 }
2815
2816 /// Build code to handle foreign code, that is, native JavaScript code, or
2817 /// builtin values and operations of the backend.
2818 ir.Primitive handleForeignSend(ast.Send node,
2819 MethodElement function,
2820 Link<ast.Node> argumentNodes,
2821 CallStructure callStructure) {
2822
2823 void validateArgumentCount({int minimum, int exactly}) {
2824 assert((minimum == null) != (exactly == null));
2825 int count = 0;
2826 if (exactly != null) {
2827 minimum = exactly;
2828 }
2829 for (Link<ast.Node> arguments = argumentNodes;
Kevin Millikin (Google) 2015/06/16 11:23:10 I'd make argumentNodes a NodeList (to avoid exposi
karlklose 2015/06/18 09:38:14 Done.
2830 !arguments.isEmpty;
2831 arguments = arguments.tail) {
2832 count++;
2833 if (exactly != null && count > exactly) {
2834 internalError(arguments.head, 'Additional argument.');
2835 }
2836 }
2837 if (minimum != null && count < minimum) {
Kevin Millikin (Google) 2015/06/16 11:23:10 minimum should always be non-null.
karlklose 2015/06/18 09:38:14 Done.
2838 internalError(node, 'Expected at least $minimum arguments.');
2839 }
2840 }
2841
2842 /// Call a helper method from the isolate library. The isolate library uses
2843 /// its own isolate structure, that encapsulates dart2js's isolate.
2844 ir.Primitive buildIsolateHelperInvocation(String helperName,
2845 CallStructure callStructure,
2846 Link<ast.Node> argumentNodes) {
Kevin Millikin (Google) 2015/06/16 11:23:10 argumentNodes is unused in this function.
karlklose 2015/06/18 09:38:14 Done.
2847 Element element = backend.isolateHelperLibrary.find(helperName);
2848 if (element == null) {
2849 compiler.internalError(node,
2850 'Isolate library and compiler mismatch.');
2851 }
2852 List<ir.Primitive> arguments = translateStaticArguments(
2853 node.argumentsNode, element, CallStructure.TWO_ARGS);
Kevin Millikin (Google) 2015/06/16 11:23:10 This uses the arguments NodeList off the Send. It
karlklose 2015/06/18 09:38:14 Done.
2854 return irBuilder.buildStaticFunctionInvocation(element,
2855 CallStructure.TWO_ARGS, arguments,
2856 sourceInformation: sourceInformationBuilder.buildCall(node));
2857 }
2858
2859 /// Lookup the value of the enum described by [node].
2860 getEnumValue(ast.Node node, EnumClassElement enumClass, List values) {
2861 Element element = elements[node];
2862 if (element is! FieldElement || element.enclosingClass != enumClass) {
2863 internalError(node, 'expected a JsBuiltin enum value');
2864 }
2865
2866 int index = enumClass.enumValues.indexOf(element);
2867 return values[index];
2868 }
2869
2870 /// Returns the String the node evaluates to, or throws an error if the
2871 /// result is not a string constant.
2872 String expectStringConstant(ast.Node node) {
2873 ir.Primitive nameValue = visit(node);
2874 if (nameValue is ir.Constant && nameValue.value.isString) {
2875 StringConstantValue constantValue = nameValue.value;
2876 return constantValue.primitiveValue.slowToString();
2877 } else {
2878 return internalError(node, 'expected a literal string');
2879 }
2880 }
2881
2882 NativeBehavior behavior =
2883 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node);
2884 switch (function.name) {
2885 case 'JS':
2886 validateArgumentCount(minimum: 2);
2887 // The first two arguments are the type and the foreign code template,
2888 // which already have been analyzed by the resolver and can be retrieved
2889 // using [NativeBehavior]. We can ignore these arguments in the backend.
2890 List<ir.Primitive> arguments =
2891 argumentNodes.skip(2).mapToList(visit, growable: false);
2892 return irBuilder.buildForeignCode(behavior.codeTemplate, arguments,
2893 behavior);
2894
2895 case 'DART_CLOSURE_TO_JS':
2896 // TODO(ahe): This should probably take care to wrap the closure in
2897 // another closure that saves the current isolate.
2898 case 'RAW_DART_FUNCTION_REF':
2899 validateArgumentCount(exactly: 1);
2900
2901 ast.Node argument = node.arguments.single;
2902 FunctionElement closure = elements[argument].implementation;
2903 if (!Elements.isStaticOrTopLevelFunction(closure)) {
2904 internalError(argument,
2905 'only static or toplevel function supported');
2906 }
2907 if (closure.functionSignature.hasOptionalParameters) {
2908 internalError(argument,
2909 'closures with optional parameters not supported');
2910 }
2911 return irBuilder.buildForeignCode(
2912 js.js.expressionTemplateYielding(
2913 backend.emitter.staticFunctionAccess(function)),
2914 <ir.Primitive>[],
2915 NativeBehavior.PURE,
2916 dependency: closure);
2917
2918 case 'JS_BUILTIN':
2919 // The first argument is a description of the type and effect of the
2920 // builtin, which has already been analyzed in the frontend. The second
2921 // argument must be a [JsBuiltin] value. All other arguments are
2922 // values used by the JavaScript template that is associated with the
2923 // builtin.
2924 validateArgumentCount(minimum: 2);
2925
2926 ast.Node builtin = argumentNodes.tail.head;
2927 JsBuiltin value = getEnumValue(argumentNodes.tail.head,
2928 backend.jsBuiltinEnum, JsBuiltin.values);
2929 js.Template template = backend.emitter.builtinTemplateFor(value);
2930 List<ir.Primitive> arguments =
2931 argumentNodes.skip(2).mapToList(visit, growable: false);
2932 return irBuilder.buildForeignCode(template, arguments, behavior);
2933
2934 case 'JS_EMBEDDED_GLOBAL':
2935 validateArgumentCount(exactly: 2);
2936
2937 String name = expectStringConstant(argumentNodes.tail.head);
2938 js.Expression access =
2939 backend.emitter.generateEmbeddedGlobalAccess(name);
2940 js.Template template = js.js.expressionTemplateYielding(access);
2941 return irBuilder.buildForeignCode(template, <ir.Primitive>[], behavior);
2942
2943 case 'JS_INTERCEPTOR_CONSTANT':
2944 validateArgumentCount(exactly: 1);
2945
2946 ast.Node argument = argumentNodes.head;
2947 ir.Primitive argumentValue = visit(argument);
2948 if (argumentValue is ir.Constant && argumentValue.value.isType) {
2949 TypeConstantValue constant = argumentValue.value;
2950 ConstantValue interceptorValue =
2951 new InterceptorConstantValue(constant.representedType);
2952 return irBuilder.buildConstant(argumentValue.expression,
2953 interceptorValue);
2954 } else {
2955 internalError(argument, 'expected Type as argument');
2956 }
2957 break;
2958
2959 case 'JS_EFFECT':
2960 return irBuilder.buildNullConstant();
2961
2962 case 'JS_GET_NAME':
2963 validateArgumentCount(exactly: 1);
2964
2965 ast.Node argument = argumentNodes.head;
2966 JsGetName id = getEnumValue(argument, backend.jsGetNameEnum,
2967 JsGetName.values);
2968 String name = backend.namer.getNameForJsGetName(argument, id);
2969 return irBuilder.buildStringConstant(name);
2970
2971 case 'JS_GET_FLAG':
2972 validateArgumentCount(exactly: 1);
2973
2974 String name = expectStringConstant(argumentNodes.first);
2975 bool value = false;
2976 switch (name) {
2977 case 'MUST_RETAIN_METADATA':
2978 value = backend.mustRetainMetadata;
2979 break;
2980 case 'USE_CONTENT_SECURITY_POLICY':
2981 value = compiler.useContentSecurityPolicy;
2982 break;
2983 default:
2984 internalError(node, 'Unknown internal flag "$name".');
2985 }
2986 return irBuilder.buildBooleanConstant(value);
2987
2988 case 'JS_STRING_CONCAT':
2989 validateArgumentCount(exactly: 2);
2990 List<ir.Primitive> arguments = argumentNodes.mapToList(visit);
2991 return irBuilder.buildStringConcatenation(arguments);
2992
2993 case 'JS_CURRENT_ISOLATE_CONTEXT':
2994 validateArgumentCount(exactly: 0);
2995
2996 if (!compiler.hasIsolateSupport) {
2997 // If the isolate library is not used, we just generate code
2998 // to fetch the current isolate.
2999 String name = backend.namer.currentIsolate;
3000 return irBuilder.buildForeignCode(js.js.parseForeignJS(name),
3001 const <ir.Primitive>[], NativeBehavior.PURE);
3002 } else {
3003 return buildIsolateHelperInvocation('_currentIsolate',
3004 CallStructure.NO_ARGS, argumentNodes);
3005 }
3006 break;
3007
3008 case 'JS_CALL_IN_ISOLATE':
3009 validateArgumentCount(exactly: 2);
3010
3011 if (!compiler.hasIsolateSupport) {
3012 ir.Primitive closure = visit(argumentNodes.tail.head);
3013 return irBuilder.buildCallInvocation(closure, CallStructure.NO_ARGS,
3014 const <ir.Primitive>[]);
3015 } else {
3016 return buildIsolateHelperInvocation('_callInIsolate',
3017 CallStructure.TWO_ARGS, argumentNodes);
3018 }
3019 break;
3020
3021 default:
3022 giveup(node, 'unplemented native construct: ${function.name}');
3023 break;
3024 }
3025 }
3026
3027 @override
3028 ir.Primitive handleStaticFunctionInvoke(ast.Send node,
3029 MethodElement function,
3030 ast.NodeList argumentList,
3031 CallStructure callStructure,
3032 _) {
3033 if (compiler.backend.isForeign(function)) {
3034 return handleForeignSend(node, function, argumentList.nodes,
Kevin Millikin (Google) 2015/06/16 11:23:10 "Send" seems weird here. handleForeignCode?
karlklose 2015/06/18 09:38:14 Done.
3035 callStructure);
3036 } else {
3037 return irBuilder.buildStaticFunctionInvocation(function, callStructure,
3038 translateStaticArguments(argumentList, function, callStructure),
3039 sourceInformation: sourceInformationBuilder.buildCall(node));
3040 }
3041 }
2808 } 3042 }
2809 3043
2810 /// Perform simple post-processing on the initial CPS-translated root term. 3044 /// Perform simple post-processing on the initial CPS-translated root term.
2811 /// 3045 ///
2812 /// This pass performs backend-independent post-processing on the translated 3046 /// This pass performs backend-independent post-processing on the translated
2813 /// term. It is implemented separately from the optimization passes because 3047 /// term. It is implemented separately from the optimization passes because
2814 /// it is required for correctness of the implementation. 3048 /// it is required for correctness of the implementation.
2815 /// 3049 ///
2816 /// It performs the following translations: 3050 /// It performs the following translations:
2817 /// - Replace [ir.LetPrim] binding a [ir.NonTailThrow] with a [ir.Throw] 3051 /// - Replace [ir.LetPrim] binding a [ir.NonTailThrow] with a [ir.Throw]
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2857 } 3091 }
2858 3092
2859 processSetStatic(ir.SetStatic node) { 3093 processSetStatic(ir.SetStatic node) {
2860 node.body = replacementFor(node.body); 3094 node.body = replacementFor(node.body);
2861 } 3095 }
2862 3096
2863 processContinuation(ir.Continuation node) { 3097 processContinuation(ir.Continuation node) {
2864 node.body = replacementFor(node.body); 3098 node.body = replacementFor(node.body);
2865 } 3099 }
2866 } 3100 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698