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 class NativeEmitter { | 5 class NativeEmitter { |
6 | 6 |
7 Compiler compiler; | 7 Compiler compiler; |
8 StringBuffer buffer; | 8 StringBuffer buffer; |
9 | 9 |
10 // Classes that participate in dynamic dispatch. These are the | 10 // Classes that participate in dynamic dispatch. These are the |
11 // classes that contain used members. | 11 // classes that contain used members. |
12 Set<ClassElement> classesWithDynamicDispatch; | 12 Set<ClassElement> classesWithDynamicDispatch; |
13 | 13 |
14 // Native classes found in the application. | 14 // Native classes found in the application. |
15 Set<ClassElement> nativeClasses; | 15 Set<ClassElement> nativeClasses; |
16 | 16 |
17 // Caches the native subtypes of a native class. | 17 // Caches the native subtypes of a native class. |
18 Map<ClassElement, List<ClassElement>> subtypes; | 18 Map<ClassElement, List<ClassElement>> subtypes; |
19 | 19 |
20 // Caches the direct native subtypes of a native class. | 20 // Caches the direct native subtypes of a native class. |
21 Map<ClassElement, List<ClassElement>> directSubtypes; | 21 Map<ClassElement, List<ClassElement>> directSubtypes; |
22 | 22 |
23 // Caches the native methods that are overridden by a native class. | 23 // Caches the native methods that are overridden by a native class. |
24 // Note that the method that overrides does not have to be native: | 24 // Note that the method that overrides does not have to be native: |
25 // it's the overridden method that must make sure it will dispatch | 25 // it's the overridden method that must make sure it will dispatch |
26 // to its subclass if it sees an instance whose class is a subclass. | 26 // to its subclass if it sees an instance whose class is a subclass. |
27 Set<FunctionElement> overriddenMethods; | 27 Set<FunctionElement> overriddenMethods; |
28 | 28 |
| 29 // Caches the methods that should just call a native JS |
| 30 // implementation. |
| 31 Set<FunctionElement> nativeMethods; |
| 32 |
29 NativeEmitter(this.compiler) | 33 NativeEmitter(this.compiler) |
30 : classesWithDynamicDispatch = new Set<ClassElement>(), | 34 : classesWithDynamicDispatch = new Set<ClassElement>(), |
31 nativeClasses = new Set<ClassElement>(), | 35 nativeClasses = new Set<ClassElement>(), |
32 subtypes = new Map<ClassElement, List<ClassElement>>(), | 36 subtypes = new Map<ClassElement, List<ClassElement>>(), |
33 directSubtypes = new Map<ClassElement, List<ClassElement>>(), | 37 directSubtypes = new Map<ClassElement, List<ClassElement>>(), |
34 overriddenMethods = new Set<FunctionElement>(), | 38 overriddenMethods = new Set<FunctionElement>(), |
| 39 nativeMethods = new Set<FunctionElement>(), |
35 buffer = new StringBuffer(); | 40 buffer = new StringBuffer(); |
36 | 41 |
37 String get dynamicName() { | 42 String get dynamicName() { |
38 Element element = compiler.findHelper( | 43 Element element = compiler.findHelper( |
39 const SourceString('dynamicFunction')); | 44 const SourceString('dynamicFunction')); |
40 return compiler.namer.isolateAccess(element); | 45 return compiler.namer.isolateAccess(element); |
41 } | 46 } |
42 | 47 |
43 String get dynamicSetMetadataName() { | 48 String get dynamicSetMetadataName() { |
44 Element element = compiler.findHelper( | 49 Element element = compiler.findHelper( |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 List<String> nativeArgumentsBuffer = argumentsBuffer.getRange( | 177 List<String> nativeArgumentsBuffer = argumentsBuffer.getRange( |
173 0, indexOfLastOptionalArgumentInParameters + 1); | 178 0, indexOfLastOptionalArgumentInParameters + 1); |
174 | 179 |
175 ClassElement classElement = member.enclosingElement; | 180 ClassElement classElement = member.enclosingElement; |
176 String nativeName = classElement.nativeName.slowToString(); | 181 String nativeName = classElement.nativeName.slowToString(); |
177 String nativeArguments = Strings.join(nativeArgumentsBuffer, ","); | 182 String nativeArguments = Strings.join(nativeArgumentsBuffer, ","); |
178 | 183 |
179 StringBuffer code = new StringBuffer(); | 184 StringBuffer code = new StringBuffer(); |
180 potentiallyConvertDartClosuresToJs(code, member); | 185 potentiallyConvertDartClosuresToJs(code, member); |
181 | 186 |
182 String name = member.name.slowToString(); | 187 if (!nativeMethods.contains(member)) { |
183 code.add(' return this.$name($nativeArguments);'); | 188 // When calling a method that has a native body, we call it |
| 189 // with our calling conventions. |
| 190 String arguments = Strings.join(argumentsBuffer, ","); |
| 191 code.add(' return this.${compiler.namer.getName(member)}($arguments)'); |
| 192 } else { |
| 193 // When calling a JS method, we call it with the native name. |
| 194 String name = member.name.slowToString(); |
| 195 code.add(' return this.$name($nativeArguments);'); |
| 196 } |
184 | 197 |
185 if (isNativeLiteral(nativeName) || !overriddenMethods.contains(member)) { | 198 if (isNativeLiteral(nativeName) || !overriddenMethods.contains(member)) { |
186 // Call the method directly. | 199 // Call the method directly. |
187 buffer.add(code.toString()); | 200 buffer.add(code.toString()); |
188 } else { | 201 } else { |
189 native.generateMethodWithPrototypeCheck( | 202 native.generateMethodWithPrototypeCheck( |
190 compiler, buffer, invocationName, code.toString(), stubParameters); | 203 compiler, buffer, invocationName, code.toString(), stubParameters); |
191 } | 204 } |
192 } | 205 } |
193 | 206 |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 String toStringName = compiler.namer.instanceMethodName( | 367 String toStringName = compiler.namer.instanceMethodName( |
355 null, const SourceString('toString'), 0); | 368 null, const SourceString('toString'), 0); |
356 objectProperties.add("$defPropName(Object.prototype, '$toStringName', "); | 369 objectProperties.add("$defPropName(Object.prototype, '$toStringName', "); |
357 objectProperties.add( | 370 objectProperties.add( |
358 'function() { return $toStringHelperName(this); });\n'); | 371 'function() { return $toStringHelperName(this); });\n'); |
359 | 372 |
360 // Finally, emit the code in the main buffer. | 373 // Finally, emit the code in the main buffer. |
361 targetBuffer.add('(function() {\n$objectProperties$buffer\n})();\n'); | 374 targetBuffer.add('(function() {\n$objectProperties$buffer\n})();\n'); |
362 } | 375 } |
363 } | 376 } |
OLD | NEW |