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