| 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 |