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 |