| 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 30 matching lines...) Expand all Loading... |
| 41 const SourceString('dynamicSetMetadata')); | 41 const SourceString('dynamicSetMetadata')); |
| 42 return compiler.namer.isolateAccess(element); | 42 return compiler.namer.isolateAccess(element); |
| 43 } | 43 } |
| 44 | 44 |
| 45 String get typeNameOfName() { | 45 String get typeNameOfName() { |
| 46 Element element = compiler.findHelper( | 46 Element element = compiler.findHelper( |
| 47 const SourceString('getTypeNameOf')); | 47 const SourceString('getTypeNameOf')); |
| 48 return compiler.namer.isolateAccess(element); | 48 return compiler.namer.isolateAccess(element); |
| 49 } | 49 } |
| 50 | 50 |
| 51 String get dynamicIsCheckName() { | 51 String get defPropName() { |
| 52 Element element = compiler.findHelper( | 52 Element element = compiler.findHelper( |
| 53 const SourceString('dynamicIsCheck')); | 53 const SourceString('defineProperty')); |
| 54 return compiler.namer.isolateAccess(element); | |
| 55 } | |
| 56 | |
| 57 String get isChecksHelperName() { | |
| 58 Element element = compiler.findHelper( | |
| 59 const SourceString('isChecksHelper')); | |
| 60 if (element === null) return null; | |
| 61 return compiler.namer.isolateAccess(element); | 54 return compiler.namer.isolateAccess(element); |
| 62 } | 55 } |
| 63 | 56 |
| 64 void generateNativeLiteral(ClassElement classElement) { | 57 void generateNativeLiteral(ClassElement classElement) { |
| 65 String quotedNative = classElement.nativeName.slowToString(); | 58 String quotedNative = classElement.nativeName.slowToString(); |
| 66 String nativeCode = quotedNative.substring(2, quotedNative.length - 1); | 59 String nativeCode = quotedNative.substring(2, quotedNative.length - 1); |
| 67 String className = compiler.namer.getName(classElement); | 60 String className = compiler.namer.getName(classElement); |
| 68 buffer.add(className); | 61 buffer.add(className); |
| 69 buffer.add(' = '); | 62 buffer.add(' = '); |
| 70 buffer.add(nativeCode); | 63 buffer.add(nativeCode); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 return "$dynamicName('$name').$nativeName"; | 111 return "$dynamicName('$name').$nativeName"; |
| 119 } | 112 } |
| 120 | 113 |
| 121 for (Element member in classElement.members) { | 114 for (Element member in classElement.members) { |
| 122 if (member.isInstanceMember()) { | 115 if (member.isInstanceMember()) { |
| 123 compiler.emitter.addInstanceMember( | 116 compiler.emitter.addInstanceMember( |
| 124 member, attachTo, buffer, isNative: true); | 117 member, attachTo, buffer, isNative: true); |
| 125 } | 118 } |
| 126 } | 119 } |
| 127 | 120 |
| 128 // Create an object that contains the is checks properties. | 121 compiler.emitter.generateTypeTests(classElement, (Element other) { |
| 129 buffer.add('$isChecksHelperName.$nativeName = { '); | 122 assert(requiresNativeIsCheck(other)); |
| 130 List<String> tests = <String>[]; | 123 buffer.add('${attachTo(compiler.namer.operatorIs(other))} = '); |
| 131 | 124 buffer.add('function() { return true; };\n'); |
| 132 ClassElement objectClass = | 125 }); |
| 133 compiler.coreLibrary.find(const SourceString('Object')); | |
| 134 ClassElement element = classElement; | |
| 135 // We need to put the super class is checks too, since a check on | |
| 136 // the subclass can happen before a check on the super class | |
| 137 // (which does the patching on the prototype). | |
| 138 do { | |
| 139 compiler.emitter.generateTypeTests(element, (Element other) { | |
| 140 tests.add("${compiler.namer.operatorIs(other)}:true"); | |
| 141 }); | |
| 142 element = element.superclass; | |
| 143 } while (element !== objectClass); | |
| 144 | |
| 145 buffer.add('${Strings.join(tests, ",")}'); | |
| 146 buffer.add('};\n'); | |
| 147 | 126 |
| 148 if (hasUsedSelectors) classesWithDynamicDispatch.add(classElement); | 127 if (hasUsedSelectors) classesWithDynamicDispatch.add(classElement); |
| 149 } | 128 } |
| 150 | 129 |
| 151 List<ClassElement> getDirectSubclasses(ClassElement cls) { | 130 List<ClassElement> getDirectSubclasses(ClassElement cls) { |
| 152 List<ClassElement> result = subtypes[cls]; | 131 List<ClassElement> result = subtypes[cls]; |
| 153 if (result === null) result = const<ClassElement>[]; | 132 if (result === null) result = const<ClassElement>[]; |
| 154 return result; | 133 return result; |
| 155 } | 134 } |
| 156 | 135 |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 entries.add("\n ['$clsName', ${tagDefns[cls]}]"); | 287 entries.add("\n ['$clsName', ${tagDefns[cls]}]"); |
| 309 } | 288 } |
| 310 buffer.add(Strings.join(entries, ',')); | 289 buffer.add(Strings.join(entries, ',')); |
| 311 buffer.add('];\n'); | 290 buffer.add('];\n'); |
| 312 buffer.add('$dynamicSetMetadataName(table);\n'); | 291 buffer.add('$dynamicSetMetadataName(table);\n'); |
| 313 | 292 |
| 314 buffer.add('})();\n'); | 293 buffer.add('})();\n'); |
| 315 } | 294 } |
| 316 } | 295 } |
| 317 | 296 |
| 297 bool isSupertypeOfNativeClass(Element element) { |
| 298 if (element.isTypeVariable()) { |
| 299 compiler.cancel("Is check for type variable", element: work.element); |
| 300 return false; |
| 301 } |
| 302 if (element.computeType(compiler) is FunctionType) return false; |
| 303 |
| 304 if (!element.isClass()) { |
| 305 compiler.cancel("Is check does not handle element", element: element); |
| 306 return false; |
| 307 } |
| 308 |
| 309 return subtypes[element] !== null; |
| 310 } |
| 311 |
| 312 bool requiresNativeIsCheck(Element element) { |
| 313 if (!element.isClass()) return false; |
| 314 ClassElement cls = element; |
| 315 if (cls.isNative()) return true; |
| 316 return isSupertypeOfNativeClass(element); |
| 317 } |
| 318 |
| 319 void emitIsChecks(StringBuffer buffer) { |
| 320 for (Element type in compiler.universe.isChecks) { |
| 321 if (!requiresNativeIsCheck(type)) continue; |
| 322 String name = compiler.namer.operatorIs(type); |
| 323 buffer.add("$defPropName(Object.prototype, '$name', "); |
| 324 buffer.add('function() { return false; });\n'); |
| 325 } |
| 326 } |
| 327 |
| 318 void assembleCode(StringBuffer other) { | 328 void assembleCode(StringBuffer other) { |
| 319 if (isChecksHelperName === null) return; | 329 StringBuffer isChecks = new StringBuffer(); |
| 320 other.add('(function() { $isChecksHelperName = {};\n$buffer\n })();\n'); | 330 emitIsChecks(isChecks); |
| 331 other.add('(function() {\n$isChecks$buffer\n})();\n'); |
| 321 } | 332 } |
| 322 } | 333 } |
| OLD | NEW |