| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 native; | 5 part of native; |
| 6 | 6 |
| 7 final RegExp nativeRedirectionRegExp = new RegExp(r'^[a-zA-Z][a-zA-Z_$0-9]*$'); | 7 final RegExp nativeRedirectionRegExp = new RegExp(r'^[a-zA-Z][a-zA-Z_$0-9]*$'); |
| 8 | 8 |
| 9 void handleSsaNative(SsaBuilder builder, Expression nativeBody) { | 9 void handleSsaNative(SsaBuilder builder, Expression nativeBody) { |
| 10 Compiler compiler = builder.compiler; | 10 Compiler compiler = builder.compiler; |
| 11 FunctionElement element = builder.work.element; | 11 FunctionElement element = builder.work.element; |
| 12 NativeEmitter nativeEmitter = builder.nativeEmitter; | 12 NativeEmitter nativeEmitter = builder.nativeEmitter; |
| 13 JavaScriptBackend backend = builder.backend; | 13 JavaScriptBackend backend = builder.backend; |
| 14 DiagnosticReporter reporter = compiler.reporter; |
| 14 | 15 |
| 15 HInstruction convertDartClosure(ParameterElement parameter, | 16 HInstruction convertDartClosure(ParameterElement parameter, |
| 16 FunctionType type) { | 17 FunctionType type) { |
| 17 HInstruction local = builder.localsHandler.readLocal(parameter); | 18 HInstruction local = builder.localsHandler.readLocal(parameter); |
| 18 ConstantValue arityConstant = | 19 ConstantValue arityConstant = |
| 19 builder.constantSystem.createInt(type.computeArity()); | 20 builder.constantSystem.createInt(type.computeArity()); |
| 20 HInstruction arity = builder.graph.addConstant(arityConstant, compiler); | 21 HInstruction arity = builder.graph.addConstant(arityConstant, compiler); |
| 21 // TODO(ngeoffray): For static methods, we could pass a method with a | 22 // TODO(ngeoffray): For static methods, we could pass a method with a |
| 22 // defined arity. | 23 // defined arity. |
| 23 Element helper = backend.getClosureConverter(); | 24 Element helper = backend.getClosureConverter(); |
| 24 builder.pushInvokeStatic(nativeBody, helper, [local, arity]); | 25 builder.pushInvokeStatic(nativeBody, helper, [local, arity]); |
| 25 HInstruction closure = builder.pop(); | 26 HInstruction closure = builder.pop(); |
| 26 return closure; | 27 return closure; |
| 27 } | 28 } |
| 28 | 29 |
| 29 // Check which pattern this native method follows: | 30 // Check which pattern this native method follows: |
| 30 // 1) foo() native; | 31 // 1) foo() native; |
| 31 // hasBody = false | 32 // hasBody = false |
| 32 // 2) foo() native "bar"; | 33 // 2) foo() native "bar"; |
| 33 // No longer supported, this is now done with @JSName('foo') and case 1. | 34 // No longer supported, this is now done with @JSName('foo') and case 1. |
| 34 // 3) foo() native "return 42"; | 35 // 3) foo() native "return 42"; |
| 35 // hasBody = true | 36 // hasBody = true |
| 36 bool hasBody = false; | 37 bool hasBody = false; |
| 37 assert(element.isNative); | 38 assert(element.isNative); |
| 38 String nativeMethodName = element.fixedBackendName; | 39 String nativeMethodName = element.fixedBackendName; |
| 39 if (nativeBody != null) { | 40 if (nativeBody != null) { |
| 40 LiteralString jsCode = nativeBody.asLiteralString(); | 41 LiteralString jsCode = nativeBody.asLiteralString(); |
| 41 String str = jsCode.dartString.slowToString(); | 42 String str = jsCode.dartString.slowToString(); |
| 42 if (nativeRedirectionRegExp.hasMatch(str)) { | 43 if (nativeRedirectionRegExp.hasMatch(str)) { |
| 43 compiler.internalError( | 44 reporter.internalError( |
| 44 nativeBody, "Deprecated syntax, use @JSName('name') instead."); | 45 nativeBody, "Deprecated syntax, use @JSName('name') instead."); |
| 45 } | 46 } |
| 46 hasBody = true; | 47 hasBody = true; |
| 47 } | 48 } |
| 48 | 49 |
| 49 if (!hasBody) { | 50 if (!hasBody) { |
| 50 nativeEmitter.nativeMethods.add(element); | 51 nativeEmitter.nativeMethods.add(element); |
| 51 } | 52 } |
| 52 | 53 |
| 53 FunctionSignature parameters = element.functionSignature; | 54 FunctionSignature parameters = element.functionSignature; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 73 | 74 |
| 74 String foreignParameters = arguments.join(','); | 75 String foreignParameters = arguments.join(','); |
| 75 String nativeMethodCall; | 76 String nativeMethodCall; |
| 76 if (element.kind == ElementKind.FUNCTION) { | 77 if (element.kind == ElementKind.FUNCTION) { |
| 77 nativeMethodCall = '$receiver$nativeMethodName($foreignParameters)'; | 78 nativeMethodCall = '$receiver$nativeMethodName($foreignParameters)'; |
| 78 } else if (element.kind == ElementKind.GETTER) { | 79 } else if (element.kind == ElementKind.GETTER) { |
| 79 nativeMethodCall = '$receiver$nativeMethodName'; | 80 nativeMethodCall = '$receiver$nativeMethodName'; |
| 80 } else if (element.kind == ElementKind.SETTER) { | 81 } else if (element.kind == ElementKind.SETTER) { |
| 81 nativeMethodCall = '$receiver$nativeMethodName = $foreignParameters'; | 82 nativeMethodCall = '$receiver$nativeMethodName = $foreignParameters'; |
| 82 } else { | 83 } else { |
| 83 builder.compiler.internalError(element, | 84 builder.reporter.internalError(element, |
| 84 'Unexpected kind: "${element.kind}".'); | 85 'Unexpected kind: "${element.kind}".'); |
| 85 } | 86 } |
| 86 | 87 |
| 87 builder.push( | 88 builder.push( |
| 88 new HForeignCode( | 89 new HForeignCode( |
| 89 // TODO(sra): This could be cached. The number of templates should | 90 // TODO(sra): This could be cached. The number of templates should |
| 90 // be proportional to the number of native methods, which is bounded | 91 // be proportional to the number of native methods, which is bounded |
| 91 // by the dart: libraries. | 92 // by the dart: libraries. |
| 92 js.js.uncachedExpressionTemplate(nativeMethodCall), | 93 js.js.uncachedExpressionTemplate(nativeMethodCall), |
| 93 backend.dynamicType, | 94 backend.dynamicType, |
| 94 inputs, effects: new SideEffects())); | 95 inputs, effects: new SideEffects())); |
| 95 // TODO(johnniwinther): Provide source information. | 96 // TODO(johnniwinther): Provide source information. |
| 96 builder | 97 builder |
| 97 .close(new HReturn(builder.pop(), null)) | 98 .close(new HReturn(builder.pop(), null)) |
| 98 .addSuccessor(builder.graph.exit); | 99 .addSuccessor(builder.graph.exit); |
| 99 } else { | 100 } else { |
| 100 if (parameters.parameterCount != 0) { | 101 if (parameters.parameterCount != 0) { |
| 101 compiler.internalError(nativeBody, | 102 reporter.internalError(nativeBody, |
| 102 'native "..." syntax is restricted to ' | 103 'native "..." syntax is restricted to ' |
| 103 'functions with zero parameters.'); | 104 'functions with zero parameters.'); |
| 104 } | 105 } |
| 105 LiteralString jsCode = nativeBody.asLiteralString(); | 106 LiteralString jsCode = nativeBody.asLiteralString(); |
| 106 builder.push(new HForeignCode.statement( | 107 builder.push(new HForeignCode.statement( |
| 107 js.js.statementTemplateYielding( | 108 js.js.statementTemplateYielding( |
| 108 new js.LiteralStatement(jsCode.dartString.slowToString())), | 109 new js.LiteralStatement(jsCode.dartString.slowToString())), |
| 109 <HInstruction>[], | 110 <HInstruction>[], |
| 110 new SideEffects(), | 111 new SideEffects(), |
| 111 null, | 112 null, |
| 112 backend.dynamicType)); | 113 backend.dynamicType)); |
| 113 } | 114 } |
| 114 } | 115 } |
| OLD | NEW |