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

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

Powered by Google App Engine
This is Rietveld 408576698