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 |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 // must be turned into a JS call to: | 153 // must be turned into a JS call to: |
154 // foo(null, y). | 154 // foo(null, y). |
155 | 155 |
156 List<String> nativeArgumentsBuffer = argumentsBuffer.getRange( | 156 List<String> nativeArgumentsBuffer = argumentsBuffer.getRange( |
157 0, indexOfLastOptionalArgumentInParameters + 1); | 157 0, indexOfLastOptionalArgumentInParameters + 1); |
158 | 158 |
159 ClassElement classElement = member.enclosingElement; | 159 ClassElement classElement = member.enclosingElement; |
160 String nativeName = classElement.nativeName.slowToString(); | 160 String nativeName = classElement.nativeName.slowToString(); |
161 String nativeArguments = Strings.join(nativeArgumentsBuffer, ","); | 161 String nativeArguments = Strings.join(nativeArgumentsBuffer, ","); |
162 | 162 |
| 163 String name = member.name.slowToString(); |
| 164 String code = ' return this.$name($nativeArguments);\n'; |
163 if (isNativeLiteral(nativeName) || !overriddenMethods.contains(member)) { | 165 if (isNativeLiteral(nativeName) || !overriddenMethods.contains(member)) { |
164 // Call the method directly. | 166 // Call the method directly. |
165 buffer.add(' return this.${member.name.slowToString()}'); | 167 buffer.add(code); |
166 buffer.add('($nativeArguments)'); | 168 } else { |
167 return; | 169 native.generateMethodWithPrototypeCheck( |
| 170 compiler, buffer, invocationName, code, stubParameters); |
168 } | 171 } |
169 | |
170 // If the method is overridden, we must check if the prototype of | |
171 // 'this' has the method available. Otherwise, we may end up | |
172 // calling the method from the super class. If the method is not | |
173 // available, we make a direct call to | |
174 // Object.prototype.$invocationName. This method will patch the | |
175 // prototype of 'this' to the real method. | |
176 | |
177 buffer.add(' if (Object.getPrototypeOf(this).hasOwnProperty('); | |
178 buffer.add("'$invocationName')) {\n"); | |
179 buffer.add(' return this.${member.name.slowToString()}'); | |
180 buffer.add('($nativeArguments)'); | |
181 buffer.add('\n }\n'); | |
182 buffer.add(' return Object.prototype.$invocationName.call(this'); | |
183 buffer.add(stubParameters == '' ? '' : ', $stubParameters'); | |
184 buffer.add(');'); | |
185 } | 172 } |
186 | 173 |
187 void emitDynamicDispatchMetadata() { | 174 void emitDynamicDispatchMetadata() { |
188 if (classesWithDynamicDispatch.isEmpty()) return; | 175 if (classesWithDynamicDispatch.isEmpty()) return; |
189 buffer.add('// ${classesWithDynamicDispatch.length} dynamic classes.\n'); | 176 buffer.add('// ${classesWithDynamicDispatch.length} dynamic classes.\n'); |
190 | 177 |
191 // Build a pre-order traversal over all the classes and their subclasses. | 178 // Build a pre-order traversal over all the classes and their subclasses. |
192 Set<ClassElement> seen = new Set<ClassElement>(); | 179 Set<ClassElement> seen = new Set<ClassElement>(); |
193 List<ClassElement> classes = <ClassElement>[]; | 180 List<ClassElement> classes = <ClassElement>[]; |
194 void visit(ClassElement cls) { | 181 void visit(ClassElement cls) { |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 String toStringName = compiler.namer.instanceMethodName( | 334 String toStringName = compiler.namer.instanceMethodName( |
348 null, const SourceString('toString'), 0); | 335 null, const SourceString('toString'), 0); |
349 objectProperties.add("$defPropName(Object.prototype, '$toStringName', "); | 336 objectProperties.add("$defPropName(Object.prototype, '$toStringName', "); |
350 objectProperties.add( | 337 objectProperties.add( |
351 'function() { return $toStringHelperName(this); });\n'); | 338 'function() { return $toStringHelperName(this); });\n'); |
352 | 339 |
353 // Finally, emit the code in the main buffer. | 340 // Finally, emit the code in the main buffer. |
354 targetBuffer.add('(function() {\n$objectProperties$buffer\n})();\n'); | 341 targetBuffer.add('(function() {\n$objectProperties$buffer\n})();\n'); |
355 } | 342 } |
356 } | 343 } |
OLD | NEW |