| 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 CodeEmitterTask emitter; | 7 Compiler compiler; |
| 8 StringBuffer nativeBuffer; | 8 StringBuffer nativeBuffer; |
| 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 | 29 // Caches the methods that should just call a native JS |
| 30 // implementation. | 30 // implementation. |
| 31 Set<FunctionElement> nativeMethods; | 31 Set<FunctionElement> nativeMethods; |
| 32 | 32 |
| 33 NativeEmitter(this.emitter) | 33 NativeEmitter(this.compiler) |
| 34 : classesWithDynamicDispatch = new Set<ClassElement>(), | 34 : classesWithDynamicDispatch = new Set<ClassElement>(), |
| 35 nativeClasses = new Set<ClassElement>(), | 35 nativeClasses = new Set<ClassElement>(), |
| 36 subtypes = new Map<ClassElement, List<ClassElement>>(), | 36 subtypes = new Map<ClassElement, List<ClassElement>>(), |
| 37 directSubtypes = new Map<ClassElement, List<ClassElement>>(), | 37 directSubtypes = new Map<ClassElement, List<ClassElement>>(), |
| 38 overriddenMethods = new Set<FunctionElement>(), | 38 overriddenMethods = new Set<FunctionElement>(), |
| 39 nativeMethods = new Set<FunctionElement>(), | 39 nativeMethods = new Set<FunctionElement>(), |
| 40 nativeBuffer = new StringBuffer(); | 40 nativeBuffer = new StringBuffer(); |
| 41 | 41 |
| 42 Compiler get compiler() => emitter.compiler; | |
| 43 | |
| 44 String get dynamicName() { | 42 String get dynamicName() { |
| 45 Element element = compiler.findHelper( | 43 Element element = compiler.findHelper( |
| 46 const SourceString('dynamicFunction')); | 44 const SourceString('dynamicFunction')); |
| 47 return compiler.namer.isolateAccess(element); | 45 return compiler.namer.isolateAccess(element); |
| 48 } | 46 } |
| 49 | 47 |
| 50 String get dynamicSetMetadataName() { | 48 String get dynamicSetMetadataName() { |
| 51 Element element = compiler.findHelper( | 49 Element element = compiler.findHelper( |
| 52 const SourceString('dynamicSetMetadata')); | 50 const SourceString('dynamicSetMetadata')); |
| 53 return compiler.namer.isolateAccess(element); | 51 return compiler.namer.isolateAccess(element); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 70 const SourceString('toStringForNativeObject')); | 68 const SourceString('toStringForNativeObject')); |
| 71 return compiler.namer.isolateAccess(element); | 69 return compiler.namer.isolateAccess(element); |
| 72 } | 70 } |
| 73 | 71 |
| 74 String get defineNativeClassName() | 72 String get defineNativeClassName() |
| 75 => '${compiler.namer.CURRENT_ISOLATE}.\$defineNativeClass'; | 73 => '${compiler.namer.CURRENT_ISOLATE}.\$defineNativeClass'; |
| 76 | 74 |
| 77 String get defineNativeClassFunction() { | 75 String get defineNativeClassFunction() { |
| 78 return """ | 76 return """ |
| 79 function(cls, fields, methods) { | 77 function(cls, fields, methods) { |
| 80 var generateGetterSetter = ${emitter.generateGetterSetterFunction}; | 78 var generateGetterSetter = ${compiler.emitter.generateGetterSetterFunction}; |
| 81 for (var i = 0; i < fields.length; i++) { | 79 for (var i = 0; i < fields.length; i++) { |
| 82 generateGetterSetter(fields[i], methods); | 80 generateGetterSetter(fields[i], methods); |
| 83 } | 81 } |
| 84 for (var method in methods) { | 82 for (var method in methods) { |
| 85 $dynamicName(method)[cls] = methods[method]; | 83 $dynamicName(method)[cls] = methods[method]; |
| 86 } | 84 } |
| 87 }"""; | 85 }"""; |
| 88 } | 86 } |
| 89 | 87 |
| 90 void generateNativeLiteral(ClassElement classElement) { | 88 void generateNativeLiteral(ClassElement classElement) { |
| 91 String quotedNative = classElement.nativeName.slowToString(); | 89 String quotedNative = classElement.nativeName.slowToString(); |
| 92 String nativeCode = quotedNative.substring(2, quotedNative.length - 1); | 90 String nativeCode = quotedNative.substring(2, quotedNative.length - 1); |
| 93 String className = compiler.namer.getName(classElement); | 91 String className = compiler.namer.getName(classElement); |
| 94 nativeBuffer.add(className); | 92 nativeBuffer.add(className); |
| 95 nativeBuffer.add(' = '); | 93 nativeBuffer.add(' = '); |
| 96 nativeBuffer.add(nativeCode); | 94 nativeBuffer.add(nativeCode); |
| 97 nativeBuffer.add(';\n'); | 95 nativeBuffer.add(';\n'); |
| 98 | 96 |
| 99 void defineInstanceMember(String name, String value) { | 97 void defineInstanceMember(String name, String value) { |
| 100 nativeBuffer.add("$className.$name = $value;\n"); | 98 nativeBuffer.add("$className.$name = $value;\n"); |
| 101 } | 99 } |
| 102 | 100 |
| 103 for (Element member in classElement.members) { | 101 for (Element member in classElement.members) { |
| 104 if (member.isInstanceMember()) { | 102 if (member.isInstanceMember()) { |
| 105 emitter.addInstanceMember(member, defineInstanceMember); | 103 compiler.emitter.addInstanceMember(member, defineInstanceMember); |
| 106 } | 104 } |
| 107 } | 105 } |
| 108 } | 106 } |
| 109 | 107 |
| 110 bool isNativeLiteral(String quotedName) { | 108 bool isNativeLiteral(String quotedName) { |
| 111 return quotedName[1] === '='; | 109 return quotedName[1] === '='; |
| 112 } | 110 } |
| 113 | 111 |
| 114 bool isNativeGlobal(String quotedName) { | 112 bool isNativeGlobal(String quotedName) { |
| 115 return quotedName[1] === '@'; | 113 return quotedName[1] === '@'; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 131 assert(classElement.backendMembers.isEmpty()); | 129 assert(classElement.backendMembers.isEmpty()); |
| 132 String quotedName = classElement.nativeName.slowToString(); | 130 String quotedName = classElement.nativeName.slowToString(); |
| 133 if (isNativeLiteral(quotedName)) { | 131 if (isNativeLiteral(quotedName)) { |
| 134 generateNativeLiteral(classElement); | 132 generateNativeLiteral(classElement); |
| 135 // The native literal kind needs to be dealt with specially when | 133 // The native literal kind needs to be dealt with specially when |
| 136 // generating code for it. | 134 // generating code for it. |
| 137 return; | 135 return; |
| 138 } | 136 } |
| 139 | 137 |
| 140 StringBuffer fieldBuffer = new StringBuffer(); | 138 StringBuffer fieldBuffer = new StringBuffer(); |
| 141 emitter.emitClassFields(classElement, fieldBuffer); | 139 compiler.emitter.emitClassFields(classElement, fieldBuffer); |
| 142 | 140 |
| 143 StringBuffer methodBuffer = new StringBuffer(); | 141 StringBuffer methodBuffer = new StringBuffer(); |
| 144 emitter.emitInstanceMembers(classElement, methodBuffer); | 142 compiler.emitter.emitInstanceMembers(classElement, methodBuffer); |
| 145 | 143 |
| 146 if (methodBuffer.isEmpty() && fieldBuffer.isEmpty()) return; | 144 if (methodBuffer.isEmpty() && fieldBuffer.isEmpty()) return; |
| 147 | 145 |
| 148 String nativeName = toNativeName(classElement); | 146 String nativeName = toNativeName(classElement); |
| 149 nativeBuffer.add("$defineNativeClassName('$nativeName', ["); | 147 nativeBuffer.add("$defineNativeClassName('$nativeName', ["); |
| 150 nativeBuffer.add(fieldBuffer); | 148 nativeBuffer.add(fieldBuffer); |
| 151 nativeBuffer.add('], {'); | 149 nativeBuffer.add('], {'); |
| 152 nativeBuffer.add(methodBuffer); | 150 nativeBuffer.add(methodBuffer); |
| 153 nativeBuffer.add('\n});\n\n'); | 151 nativeBuffer.add('\n});\n\n'); |
| 154 | 152 |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 String toStringName = compiler.namer.instanceMethodName( | 383 String toStringName = compiler.namer.instanceMethodName( |
| 386 null, const SourceString('toString'), 0); | 384 null, const SourceString('toString'), 0); |
| 387 objectProperties.add("$defPropName(Object.prototype, '$toStringName', "); | 385 objectProperties.add("$defPropName(Object.prototype, '$toStringName', "); |
| 388 objectProperties.add( | 386 objectProperties.add( |
| 389 'function() { return $toStringHelperName(this); });\n'); | 387 'function() { return $toStringHelperName(this); });\n'); |
| 390 | 388 |
| 391 targetBuffer.add('$defineNativeClassName = $defineNativeClassFunction;\n'); | 389 targetBuffer.add('$defineNativeClassName = $defineNativeClassFunction;\n'); |
| 392 targetBuffer.add('$objectProperties$nativeBuffer\n'); | 390 targetBuffer.add('$objectProperties$nativeBuffer\n'); |
| 393 } | 391 } |
| 394 } | 392 } |
| OLD | NEW |