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 part of ssa; | 5 part of ssa; |
6 | 6 |
7 class SsaFunctionCompiler implements FunctionCompiler { | 7 class SsaFunctionCompiler implements FunctionCompiler { |
8 SsaCodeGeneratorTask generator; | 8 SsaCodeGeneratorTask generator; |
9 SsaBuilderTask builder; | 9 SsaBuilderTask builder; |
10 SsaOptimizerTask optimizer; | 10 SsaOptimizerTask optimizer; |
(...skipping 3755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3766 compiler.reportError( | 3766 compiler.reportError( |
3767 node, MessageKind.GENERIC, | 3767 node, MessageKind.GENERIC, |
3768 {'text': 'Error: Expected one argument to JS_GET_NAME.'}); | 3768 {'text': 'Error: Expected one argument to JS_GET_NAME.'}); |
3769 return; | 3769 return; |
3770 case 1: | 3770 case 1: |
3771 argument = arguments[0]; | 3771 argument = arguments[0]; |
3772 break; | 3772 break; |
3773 default: | 3773 default: |
3774 for (int i = 1; i < arguments.length; i++) { | 3774 for (int i = 1; i < arguments.length; i++) { |
3775 compiler.reportError( | 3775 compiler.reportError( |
3776 arguments[i], MessageKind.GENERIC, | 3776 arguments[i], MessageKind.GENERIC, |
3777 {'text': 'Error: Extra argument to JS_GET_NAME.'}); | 3777 {'text': 'Error: Extra argument to JS_GET_NAME.'}); |
3778 } | 3778 } |
3779 return; | 3779 return; |
3780 } | 3780 } |
3781 Element element = elements[argument]; | 3781 Element element = elements[argument]; |
3782 if (element == null || | 3782 if (element == null || |
3783 element is! FieldElement || | 3783 element is! FieldElement || |
3784 element.enclosingClass != backend.jsGetNameEnum) { | 3784 element.enclosingClass != backend.jsGetNameEnum) { |
3785 compiler.reportError( | 3785 compiler.reportError( |
3786 argument, MessageKind.GENERIC, | 3786 argument, MessageKind.GENERIC, |
3787 {'text': 'Error: Expected a JsGetName enum value.'}); | 3787 {'text': 'Error: Expected a JsGetName enum value.'}); |
3788 } | 3788 } |
3789 EnumClassElement enumClass = element.enclosingClass; | 3789 EnumClassElement enumClass = element.enclosingClass; |
3790 int index = enumClass.enumValues.indexOf(element); | 3790 int index = enumClass.enumValues.indexOf(element); |
3791 stack.add( | 3791 stack.add( |
3792 addConstantString( | 3792 addConstantString( |
3793 backend.namer.getNameForJsGetName( | 3793 backend.namer.getNameForJsGetName( |
3794 argument, JsGetName.values[index]))); | 3794 argument, JsGetName.values[index]))); |
3795 } | 3795 } |
3796 | 3796 |
| 3797 void handleForeignJsBuiltin(ast.Send node) { |
| 3798 List<ast.Node> arguments = node.arguments.toList(); |
| 3799 ast.Node argument; |
| 3800 if (arguments.length < 2) { |
| 3801 compiler.reportError( |
| 3802 node, MessageKind.GENERIC, |
| 3803 {'text': 'Error: Expected at least two arguments to JS_BUILTIN.'}); |
| 3804 } |
| 3805 |
| 3806 Element builtinElement = elements[arguments[1]]; |
| 3807 if (builtinElement == null || |
| 3808 (builtinElement is! FieldElement) || |
| 3809 builtinElement.enclosingClass != backend.jsBuiltinEnum) { |
| 3810 compiler.reportError( |
| 3811 argument, MessageKind.GENERIC, |
| 3812 {'text': 'Error: Expected a JsBuiltin enum value.'}); |
| 3813 } |
| 3814 EnumClassElement enumClass = builtinElement.enclosingClass; |
| 3815 int index = enumClass.enumValues.indexOf(builtinElement); |
| 3816 |
| 3817 js.Template template = |
| 3818 backend.emitter.builtinTemplateFor(JsBuiltin.values[index]); |
| 3819 |
| 3820 List<HInstruction> compiledArguments = <HInstruction>[]; |
| 3821 for (int i = 2; i < arguments.length; i++) { |
| 3822 visit(arguments[i]); |
| 3823 compiledArguments.add(pop()); |
| 3824 } |
| 3825 |
| 3826 native.NativeBehavior nativeBehavior = |
| 3827 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); |
| 3828 |
| 3829 TypeMask ssaType = |
| 3830 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); |
| 3831 |
| 3832 push(new HForeignCode(template, |
| 3833 ssaType, |
| 3834 compiledArguments, |
| 3835 nativeBehavior: nativeBehavior)); |
| 3836 } |
| 3837 |
3797 void handleForeignJsEmbeddedGlobal(ast.Send node) { | 3838 void handleForeignJsEmbeddedGlobal(ast.Send node) { |
3798 List<ast.Node> arguments = node.arguments.toList(); | 3839 List<ast.Node> arguments = node.arguments.toList(); |
3799 ast.Node globalNameNode; | 3840 ast.Node globalNameNode; |
3800 switch (arguments.length) { | 3841 switch (arguments.length) { |
3801 case 0: | 3842 case 0: |
3802 case 1: | 3843 case 1: |
3803 compiler.reportError( | 3844 compiler.reportError( |
3804 node, MessageKind.GENERIC, | 3845 node, MessageKind.GENERIC, |
3805 {'text': 'Error: Expected two arguments to JS_EMBEDDED_GLOBAL.'}); | 3846 {'text': 'Error: Expected two arguments to JS_EMBEDDED_GLOBAL.'}); |
3806 return; | 3847 return; |
3807 case 2: | 3848 case 2: |
3808 // The type has been extracted earlier. We are only interested in the | 3849 // The type has been extracted earlier. We are only interested in the |
3809 // name in this function. | 3850 // name in this function. |
3810 globalNameNode = arguments[1]; | 3851 globalNameNode = arguments[1]; |
3811 break; | 3852 break; |
3812 default: | 3853 default: |
3813 for (int i = 2; i < arguments.length; i++) { | 3854 for (int i = 2; i < arguments.length; i++) { |
3814 compiler.reportError( | 3855 compiler.reportError( |
3815 arguments[i], MessageKind.GENERIC, | 3856 arguments[i], MessageKind.GENERIC, |
3816 {'text': 'Error: Extra argument to JS_EMBEDDED_GLOBAL.'}); | 3857 {'text': 'Error: Extra argument to JS_EMBEDDED_GLOBAL.'}); |
3817 } | 3858 } |
3818 return; | 3859 return; |
3819 } | 3860 } |
3820 visit(arguments[1]); | 3861 visit(globalNameNode); |
3821 HInstruction globalNameHNode = pop(); | 3862 HInstruction globalNameHNode = pop(); |
3822 if (!globalNameHNode.isConstantString()) { | 3863 if (!globalNameHNode.isConstantString()) { |
3823 compiler.reportError( | 3864 compiler.reportError( |
3824 arguments[1], MessageKind.GENERIC, | 3865 arguments[1], MessageKind.GENERIC, |
3825 {'text': 'Error: Expected String as second argument ' | 3866 {'text': 'Error: Expected String as second argument ' |
3826 'to JS_EMBEDDED_GLOBAL.'}); | 3867 'to JS_EMBEDDED_GLOBAL.'}); |
3827 return; | 3868 return; |
3828 } | 3869 } |
3829 HConstant hConstant = globalNameHNode; | 3870 HConstant hConstant = globalNameHNode; |
3830 StringConstantValue constant = hConstant.constant; | 3871 StringConstantValue constant = hConstant.constant; |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3934 SideEffects sideEffects = new SideEffects.empty(); | 3975 SideEffects sideEffects = new SideEffects.empty(); |
3935 sideEffects.setAllSideEffects(); | 3976 sideEffects.setAllSideEffects(); |
3936 push(new HForeignCode( | 3977 push(new HForeignCode( |
3937 js.js.parseForeignJS("$isolateName = #"), | 3978 js.js.parseForeignJS("$isolateName = #"), |
3938 backend.dynamicType, | 3979 backend.dynamicType, |
3939 <HInstruction>[pop()], | 3980 <HInstruction>[pop()], |
3940 nativeBehavior: native.NativeBehavior.PURE, | 3981 nativeBehavior: native.NativeBehavior.PURE, |
3941 effects: sideEffects)); | 3982 effects: sideEffects)); |
3942 } | 3983 } |
3943 | 3984 |
3944 void handleForeignDartObjectJsConstructorFunction(ast.Send node) { | |
3945 if (!node.arguments.isEmpty) { | |
3946 compiler.internalError(node.argumentsNode, 'Too many arguments.'); | |
3947 } | |
3948 push(new HForeignCode( | |
3949 js.js.expressionTemplateYielding( | |
3950 backend.emitter.typeAccess(compiler.objectClass)), | |
3951 backend.dynamicType, | |
3952 <HInstruction>[])); | |
3953 } | |
3954 | |
3955 void handleForeignJsCurrentIsolate(ast.Send node) { | 3985 void handleForeignJsCurrentIsolate(ast.Send node) { |
3956 if (!node.arguments.isEmpty) { | 3986 if (!node.arguments.isEmpty) { |
3957 compiler.internalError(node.argumentsNode, 'Too many arguments.'); | 3987 compiler.internalError(node.argumentsNode, 'Too many arguments.'); |
3958 } | 3988 } |
3959 push(new HForeignCode(js.js.parseForeignJS(backend.namer.currentIsolate), | 3989 push(new HForeignCode(js.js.parseForeignJS(backend.namer.currentIsolate), |
3960 backend.dynamicType, | 3990 backend.dynamicType, |
3961 <HInstruction>[])); | 3991 <HInstruction>[])); |
3962 } | 3992 } |
3963 | 3993 |
3964 visitForeignSend(ast.Send node) { | 3994 visitForeignSend(ast.Send node) { |
(...skipping 15 matching lines...) Expand all Loading... |
3980 // TODO(floitsch): this should be a JS_NAME. | 4010 // TODO(floitsch): this should be a JS_NAME. |
3981 stack.add(addConstantString(backend.namer.operatorIsPrefix)); | 4011 stack.add(addConstantString(backend.namer.operatorIsPrefix)); |
3982 } else if (name == 'JS_OBJECT_CLASS_NAME') { | 4012 } else if (name == 'JS_OBJECT_CLASS_NAME') { |
3983 // TODO(floitsch): this should be a JS_NAME. | 4013 // TODO(floitsch): this should be a JS_NAME. |
3984 String name = backend.namer.runtimeTypeName(compiler.objectClass); | 4014 String name = backend.namer.runtimeTypeName(compiler.objectClass); |
3985 stack.add(addConstantString(name)); | 4015 stack.add(addConstantString(name)); |
3986 } else if (name == 'JS_NULL_CLASS_NAME') { | 4016 } else if (name == 'JS_NULL_CLASS_NAME') { |
3987 // TODO(floitsch): this should be a JS_NAME. | 4017 // TODO(floitsch): this should be a JS_NAME. |
3988 String name = backend.namer.runtimeTypeName(compiler.nullClass); | 4018 String name = backend.namer.runtimeTypeName(compiler.nullClass); |
3989 stack.add(addConstantString(name)); | 4019 stack.add(addConstantString(name)); |
3990 } else if (name == 'JS_FUNCTION_CLASS_NAME') { | |
3991 // TODO(floitsch): this should be a JS_NAME. | |
3992 String name = backend.namer.runtimeTypeName(compiler.functionClass); | |
3993 stack.add(addConstantString(name)); | |
3994 } else if (name == 'JS_OPERATOR_AS_PREFIX') { | 4020 } else if (name == 'JS_OPERATOR_AS_PREFIX') { |
3995 // TODO(floitsch): this should be a JS_NAME. | 4021 // TODO(floitsch): this should be a JS_NAME. |
3996 stack.add(addConstantString(backend.namer.operatorAsPrefix)); | 4022 stack.add(addConstantString(backend.namer.operatorAsPrefix)); |
3997 } else if (name == 'JS_SIGNATURE_NAME') { | 4023 } else if (name == 'JS_SIGNATURE_NAME') { |
3998 // TODO(floitsch): this should be a JS_NAME. | 4024 // TODO(floitsch): this should be a JS_NAME. |
3999 stack.add(addConstantString(backend.namer.operatorSignature)); | 4025 stack.add(addConstantString(backend.namer.operatorSignature)); |
4000 } else if (name == 'JS_TYPEDEF_TAG') { | 4026 } else if (name == 'JS_TYPEDEF_TAG') { |
4001 // TODO(floitsch): this should be a JS_NAME. | 4027 // TODO(floitsch): this should be a JS_NAME. |
4002 stack.add(addConstantString(backend.namer.typedefTag)); | 4028 stack.add(addConstantString(backend.namer.typedefTag)); |
4003 } else if (name == 'JS_FUNCTION_TYPE_TAG') { | |
4004 // TODO(floitsch): this should be a JS_NAME. | |
4005 stack.add(addConstantString(backend.namer.functionTypeTag)); | |
4006 } else if (name == 'JS_FUNCTION_TYPE_VOID_RETURN_TAG') { | 4029 } else if (name == 'JS_FUNCTION_TYPE_VOID_RETURN_TAG') { |
4007 // TODO(floitsch): this should be a JS_NAME. | 4030 // TODO(floitsch): this should be a JS_NAME. |
4008 stack.add(addConstantString(backend.namer.functionTypeVoidReturnTag)); | 4031 stack.add(addConstantString(backend.namer.functionTypeVoidReturnTag)); |
4009 } else if (name == 'JS_FUNCTION_TYPE_RETURN_TYPE_TAG') { | 4032 } else if (name == 'JS_FUNCTION_TYPE_RETURN_TYPE_TAG') { |
4010 // TODO(floitsch): this should be a JS_NAME. | 4033 // TODO(floitsch): this should be a JS_NAME. |
4011 stack.add(addConstantString(backend.namer.functionTypeReturnTypeTag)); | 4034 stack.add(addConstantString(backend.namer.functionTypeReturnTypeTag)); |
4012 } else if (name == | 4035 } else if (name == |
4013 'JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG') { | 4036 'JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG') { |
4014 // TODO(floitsch): this should be a JS_NAME. | 4037 // TODO(floitsch): this should be a JS_NAME. |
4015 stack.add(addConstantString( | 4038 stack.add(addConstantString( |
4016 backend.namer.functionTypeRequiredParametersTag)); | 4039 backend.namer.functionTypeRequiredParametersTag)); |
4017 } else if (name == | 4040 } else if (name == |
4018 'JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG') { | 4041 'JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG') { |
4019 // TODO(floitsch): this should be a JS_NAME. | 4042 // TODO(floitsch): this should be a JS_NAME. |
4020 stack.add(addConstantString( | 4043 stack.add(addConstantString( |
4021 backend.namer.functionTypeOptionalParametersTag)); | 4044 backend.namer.functionTypeOptionalParametersTag)); |
4022 } else if (name == | 4045 } else if (name == |
4023 'JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG') { | 4046 'JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG') { |
4024 // TODO(floitsch): this should be a JS_NAME. | 4047 // TODO(floitsch): this should be a JS_NAME. |
4025 stack.add(addConstantString( | 4048 stack.add(addConstantString( |
4026 backend.namer.functionTypeNamedParametersTag)); | 4049 backend.namer.functionTypeNamedParametersTag)); |
4027 } else if (name == 'JS_DART_OBJECT_CONSTRUCTOR') { | |
4028 handleForeignDartObjectJsConstructorFunction(node); | |
4029 } else if (name == 'JS_IS_INDEXABLE_FIELD_NAME') { | 4050 } else if (name == 'JS_IS_INDEXABLE_FIELD_NAME') { |
4030 // TODO(floitsch): this should be a JS_NAME. | 4051 // TODO(floitsch): this should be a JS_NAME. |
4031 Element element = backend.findHelper('JavaScriptIndexingBehavior'); | 4052 Element element = backend.findHelper('JavaScriptIndexingBehavior'); |
4032 stack.add(addConstantString(backend.namer.operatorIs(element))); | 4053 stack.add(addConstantString(backend.namer.operatorIs(element))); |
4033 } else if (name == 'JS_CURRENT_ISOLATE') { | 4054 } else if (name == 'JS_CURRENT_ISOLATE') { |
4034 handleForeignJsCurrentIsolate(node); | 4055 handleForeignJsCurrentIsolate(node); |
4035 } else if (name == 'JS_GET_NAME') { | 4056 } else if (name == 'JS_GET_NAME') { |
4036 handleForeignJsGetName(node); | 4057 handleForeignJsGetName(node); |
4037 } else if (name == 'JS_EMBEDDED_GLOBAL') { | 4058 } else if (name == 'JS_EMBEDDED_GLOBAL') { |
4038 handleForeignJsEmbeddedGlobal(node); | 4059 handleForeignJsEmbeddedGlobal(node); |
| 4060 } else if (name == 'JS_BUILTIN') { |
| 4061 handleForeignJsBuiltin(node); |
4039 } else if (name == 'JS_GET_FLAG') { | 4062 } else if (name == 'JS_GET_FLAG') { |
4040 handleForeingJsGetFlag(node); | 4063 handleForeingJsGetFlag(node); |
4041 } else if (name == 'JS_EFFECT') { | 4064 } else if (name == 'JS_EFFECT') { |
4042 stack.add(graph.addConstantNull(compiler)); | 4065 stack.add(graph.addConstantNull(compiler)); |
4043 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { | 4066 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { |
4044 handleJsInterceptorConstant(node); | 4067 handleJsInterceptorConstant(node); |
4045 } else if (name == 'JS_STRING_CONCAT') { | 4068 } else if (name == 'JS_STRING_CONCAT') { |
4046 handleJsStringConcat(node); | 4069 handleJsStringConcat(node); |
4047 } else { | 4070 } else { |
4048 throw "Unknown foreign: ${selector}"; | 4071 throw "Unknown foreign: ${selector}"; |
(...skipping 2932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6981 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 7004 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
6982 unaliased.accept(this, builder); | 7005 unaliased.accept(this, builder); |
6983 } | 7006 } |
6984 | 7007 |
6985 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 7008 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
6986 JavaScriptBackend backend = builder.compiler.backend; | 7009 JavaScriptBackend backend = builder.compiler.backend; |
6987 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 7010 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
6988 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 7011 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
6989 } | 7012 } |
6990 } | 7013 } |
OLD | NEW |