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 | |
3838 void handleForeignJsEmbeddedGlobal(ast.Send node) { | 3797 void handleForeignJsEmbeddedGlobal(ast.Send node) { |
3839 List<ast.Node> arguments = node.arguments.toList(); | 3798 List<ast.Node> arguments = node.arguments.toList(); |
3840 ast.Node globalNameNode; | 3799 ast.Node globalNameNode; |
3841 switch (arguments.length) { | 3800 switch (arguments.length) { |
3842 case 0: | 3801 case 0: |
3843 case 1: | 3802 case 1: |
3844 compiler.reportError( | 3803 compiler.reportError( |
3845 node, MessageKind.GENERIC, | 3804 node, MessageKind.GENERIC, |
3846 {'text': 'Error: Expected two arguments to JS_EMBEDDED_GLOBAL.'}); | 3805 {'text': 'Error: Expected two arguments to JS_EMBEDDED_GLOBAL.'}); |
3847 return; | 3806 return; |
3848 case 2: | 3807 case 2: |
3849 // The type has been extracted earlier. We are only interested in the | 3808 // The type has been extracted earlier. We are only interested in the |
3850 // name in this function. | 3809 // name in this function. |
3851 globalNameNode = arguments[1]; | 3810 globalNameNode = arguments[1]; |
3852 break; | 3811 break; |
3853 default: | 3812 default: |
3854 for (int i = 2; i < arguments.length; i++) { | 3813 for (int i = 2; i < arguments.length; i++) { |
3855 compiler.reportError( | 3814 compiler.reportError( |
3856 arguments[i], MessageKind.GENERIC, | 3815 arguments[i], MessageKind.GENERIC, |
3857 {'text': 'Error: Extra argument to JS_EMBEDDED_GLOBAL.'}); | 3816 {'text': 'Error: Extra argument to JS_EMBEDDED_GLOBAL.'}); |
3858 } | 3817 } |
3859 return; | 3818 return; |
3860 } | 3819 } |
3861 visit(globalNameNode); | 3820 visit(arguments[1]); |
3862 HInstruction globalNameHNode = pop(); | 3821 HInstruction globalNameHNode = pop(); |
3863 if (!globalNameHNode.isConstantString()) { | 3822 if (!globalNameHNode.isConstantString()) { |
3864 compiler.reportError( | 3823 compiler.reportError( |
3865 arguments[1], MessageKind.GENERIC, | 3824 arguments[1], MessageKind.GENERIC, |
3866 {'text': 'Error: Expected String as second argument ' | 3825 {'text': 'Error: Expected String as second argument ' |
3867 'to JS_EMBEDDED_GLOBAL.'}); | 3826 'to JS_EMBEDDED_GLOBAL.'}); |
3868 return; | 3827 return; |
3869 } | 3828 } |
3870 HConstant hConstant = globalNameHNode; | 3829 HConstant hConstant = globalNameHNode; |
3871 StringConstantValue constant = hConstant.constant; | 3830 StringConstantValue constant = hConstant.constant; |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3975 SideEffects sideEffects = new SideEffects.empty(); | 3934 SideEffects sideEffects = new SideEffects.empty(); |
3976 sideEffects.setAllSideEffects(); | 3935 sideEffects.setAllSideEffects(); |
3977 push(new HForeignCode( | 3936 push(new HForeignCode( |
3978 js.js.parseForeignJS("$isolateName = #"), | 3937 js.js.parseForeignJS("$isolateName = #"), |
3979 backend.dynamicType, | 3938 backend.dynamicType, |
3980 <HInstruction>[pop()], | 3939 <HInstruction>[pop()], |
3981 nativeBehavior: native.NativeBehavior.PURE, | 3940 nativeBehavior: native.NativeBehavior.PURE, |
3982 effects: sideEffects)); | 3941 effects: sideEffects)); |
3983 } | 3942 } |
3984 | 3943 |
| 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 |
3985 void handleForeignJsCurrentIsolate(ast.Send node) { | 3955 void handleForeignJsCurrentIsolate(ast.Send node) { |
3986 if (!node.arguments.isEmpty) { | 3956 if (!node.arguments.isEmpty) { |
3987 compiler.internalError(node.argumentsNode, 'Too many arguments.'); | 3957 compiler.internalError(node.argumentsNode, 'Too many arguments.'); |
3988 } | 3958 } |
3989 push(new HForeignCode(js.js.parseForeignJS(backend.namer.currentIsolate), | 3959 push(new HForeignCode(js.js.parseForeignJS(backend.namer.currentIsolate), |
3990 backend.dynamicType, | 3960 backend.dynamicType, |
3991 <HInstruction>[])); | 3961 <HInstruction>[])); |
3992 } | 3962 } |
3993 | 3963 |
3994 visitForeignSend(ast.Send node) { | 3964 visitForeignSend(ast.Send node) { |
(...skipping 15 matching lines...) Expand all Loading... |
4010 // TODO(floitsch): this should be a JS_NAME. | 3980 // TODO(floitsch): this should be a JS_NAME. |
4011 stack.add(addConstantString(backend.namer.operatorIsPrefix)); | 3981 stack.add(addConstantString(backend.namer.operatorIsPrefix)); |
4012 } else if (name == 'JS_OBJECT_CLASS_NAME') { | 3982 } else if (name == 'JS_OBJECT_CLASS_NAME') { |
4013 // TODO(floitsch): this should be a JS_NAME. | 3983 // TODO(floitsch): this should be a JS_NAME. |
4014 String name = backend.namer.runtimeTypeName(compiler.objectClass); | 3984 String name = backend.namer.runtimeTypeName(compiler.objectClass); |
4015 stack.add(addConstantString(name)); | 3985 stack.add(addConstantString(name)); |
4016 } else if (name == 'JS_NULL_CLASS_NAME') { | 3986 } else if (name == 'JS_NULL_CLASS_NAME') { |
4017 // TODO(floitsch): this should be a JS_NAME. | 3987 // TODO(floitsch): this should be a JS_NAME. |
4018 String name = backend.namer.runtimeTypeName(compiler.nullClass); | 3988 String name = backend.namer.runtimeTypeName(compiler.nullClass); |
4019 stack.add(addConstantString(name)); | 3989 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)); |
4020 } else if (name == 'JS_OPERATOR_AS_PREFIX') { | 3994 } else if (name == 'JS_OPERATOR_AS_PREFIX') { |
4021 // TODO(floitsch): this should be a JS_NAME. | 3995 // TODO(floitsch): this should be a JS_NAME. |
4022 stack.add(addConstantString(backend.namer.operatorAsPrefix)); | 3996 stack.add(addConstantString(backend.namer.operatorAsPrefix)); |
4023 } else if (name == 'JS_SIGNATURE_NAME') { | 3997 } else if (name == 'JS_SIGNATURE_NAME') { |
4024 // TODO(floitsch): this should be a JS_NAME. | 3998 // TODO(floitsch): this should be a JS_NAME. |
4025 stack.add(addConstantString(backend.namer.operatorSignature)); | 3999 stack.add(addConstantString(backend.namer.operatorSignature)); |
4026 } else if (name == 'JS_TYPEDEF_TAG') { | 4000 } else if (name == 'JS_TYPEDEF_TAG') { |
4027 // TODO(floitsch): this should be a JS_NAME. | 4001 // TODO(floitsch): this should be a JS_NAME. |
4028 stack.add(addConstantString(backend.namer.typedefTag)); | 4002 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)); |
4029 } else if (name == 'JS_FUNCTION_TYPE_VOID_RETURN_TAG') { | 4006 } else if (name == 'JS_FUNCTION_TYPE_VOID_RETURN_TAG') { |
4030 // TODO(floitsch): this should be a JS_NAME. | 4007 // TODO(floitsch): this should be a JS_NAME. |
4031 stack.add(addConstantString(backend.namer.functionTypeVoidReturnTag)); | 4008 stack.add(addConstantString(backend.namer.functionTypeVoidReturnTag)); |
4032 } else if (name == 'JS_FUNCTION_TYPE_RETURN_TYPE_TAG') { | 4009 } else if (name == 'JS_FUNCTION_TYPE_RETURN_TYPE_TAG') { |
4033 // TODO(floitsch): this should be a JS_NAME. | 4010 // TODO(floitsch): this should be a JS_NAME. |
4034 stack.add(addConstantString(backend.namer.functionTypeReturnTypeTag)); | 4011 stack.add(addConstantString(backend.namer.functionTypeReturnTypeTag)); |
4035 } else if (name == | 4012 } else if (name == |
4036 'JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG') { | 4013 'JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG') { |
4037 // TODO(floitsch): this should be a JS_NAME. | 4014 // TODO(floitsch): this should be a JS_NAME. |
4038 stack.add(addConstantString( | 4015 stack.add(addConstantString( |
4039 backend.namer.functionTypeRequiredParametersTag)); | 4016 backend.namer.functionTypeRequiredParametersTag)); |
4040 } else if (name == | 4017 } else if (name == |
4041 'JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG') { | 4018 'JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG') { |
4042 // TODO(floitsch): this should be a JS_NAME. | 4019 // TODO(floitsch): this should be a JS_NAME. |
4043 stack.add(addConstantString( | 4020 stack.add(addConstantString( |
4044 backend.namer.functionTypeOptionalParametersTag)); | 4021 backend.namer.functionTypeOptionalParametersTag)); |
4045 } else if (name == | 4022 } else if (name == |
4046 'JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG') { | 4023 'JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG') { |
4047 // TODO(floitsch): this should be a JS_NAME. | 4024 // TODO(floitsch): this should be a JS_NAME. |
4048 stack.add(addConstantString( | 4025 stack.add(addConstantString( |
4049 backend.namer.functionTypeNamedParametersTag)); | 4026 backend.namer.functionTypeNamedParametersTag)); |
| 4027 } else if (name == 'JS_DART_OBJECT_CONSTRUCTOR') { |
| 4028 handleForeignDartObjectJsConstructorFunction(node); |
4050 } else if (name == 'JS_IS_INDEXABLE_FIELD_NAME') { | 4029 } else if (name == 'JS_IS_INDEXABLE_FIELD_NAME') { |
4051 // TODO(floitsch): this should be a JS_NAME. | 4030 // TODO(floitsch): this should be a JS_NAME. |
4052 Element element = backend.findHelper('JavaScriptIndexingBehavior'); | 4031 Element element = backend.findHelper('JavaScriptIndexingBehavior'); |
4053 stack.add(addConstantString(backend.namer.operatorIs(element))); | 4032 stack.add(addConstantString(backend.namer.operatorIs(element))); |
4054 } else if (name == 'JS_CURRENT_ISOLATE') { | 4033 } else if (name == 'JS_CURRENT_ISOLATE') { |
4055 handleForeignJsCurrentIsolate(node); | 4034 handleForeignJsCurrentIsolate(node); |
4056 } else if (name == 'JS_GET_NAME') { | 4035 } else if (name == 'JS_GET_NAME') { |
4057 handleForeignJsGetName(node); | 4036 handleForeignJsGetName(node); |
4058 } else if (name == 'JS_EMBEDDED_GLOBAL') { | 4037 } else if (name == 'JS_EMBEDDED_GLOBAL') { |
4059 handleForeignJsEmbeddedGlobal(node); | 4038 handleForeignJsEmbeddedGlobal(node); |
4060 } else if (name == 'JS_BUILTIN') { | |
4061 handleForeignJsBuiltin(node); | |
4062 } else if (name == 'JS_GET_FLAG') { | 4039 } else if (name == 'JS_GET_FLAG') { |
4063 handleForeingJsGetFlag(node); | 4040 handleForeingJsGetFlag(node); |
4064 } else if (name == 'JS_EFFECT') { | 4041 } else if (name == 'JS_EFFECT') { |
4065 stack.add(graph.addConstantNull(compiler)); | 4042 stack.add(graph.addConstantNull(compiler)); |
4066 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { | 4043 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { |
4067 handleJsInterceptorConstant(node); | 4044 handleJsInterceptorConstant(node); |
4068 } else if (name == 'JS_STRING_CONCAT') { | 4045 } else if (name == 'JS_STRING_CONCAT') { |
4069 handleJsStringConcat(node); | 4046 handleJsStringConcat(node); |
4070 } else { | 4047 } else { |
4071 throw "Unknown foreign: ${selector}"; | 4048 throw "Unknown foreign: ${selector}"; |
(...skipping 2954 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7026 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 7003 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
7027 unaliased.accept(this, builder); | 7004 unaliased.accept(this, builder); |
7028 } | 7005 } |
7029 | 7006 |
7030 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 7007 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
7031 JavaScriptBackend backend = builder.compiler.backend; | 7008 JavaScriptBackend backend = builder.compiler.backend; |
7032 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 7009 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
7033 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 7010 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
7034 } | 7011 } |
7035 } | 7012 } |
OLD | NEW |