| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 /** | 5 /** |
| 6 * Generates the code for all used classes in the program. Static fields (even | 6 * Generates the code for all used classes in the program. Static fields (even |
| 7 * in classes) are ignored, since they can be treated as non-class elements. | 7 * in classes) are ignored, since they can be treated as non-class elements. |
| 8 * | 8 * |
| 9 * The code for the containing (used) methods must exist in the [:universe:]. | 9 * The code for the containing (used) methods must exist in the [:universe:]. |
| 10 */ | 10 */ |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 } | 49 } |
| 50 codeBlock = compiler.universe.generatedBailoutCode[member]; | 50 codeBlock = compiler.universe.generatedBailoutCode[member]; |
| 51 if (codeBlock !== null) { | 51 if (codeBlock !== null) { |
| 52 String name = namer.getBailoutName(member); | 52 String name = namer.getBailoutName(member); |
| 53 buffer.add('$prototype.$name = $codeBlock;\n'); | 53 buffer.add('$prototype.$name = $codeBlock;\n'); |
| 54 } | 54 } |
| 55 } else { | 55 } else { |
| 56 // TODO(ngeoffray): Have another class generate the code for the | 56 // TODO(ngeoffray): Have another class generate the code for the |
| 57 // fields. | 57 // fields. |
| 58 assert(member.kind === ElementKind.FIELD); | 58 assert(member.kind === ElementKind.FIELD); |
| 59 if (compiler.universe.invokedSetters.contains(member.name.stringValue)) { | 59 if (compiler.universe.invokedSetters.contains(member.name)) { |
| 60 String setterName = namer.setterName(member.name); | 60 String setterName = namer.setterName(member.name); |
| 61 buffer.add('$prototype.$setterName = function(v){\n' + | 61 buffer.add('$prototype.$setterName = function(v){\n' + |
| 62 ' this.${namer.getName(member)} = v;\n}\n'); | 62 ' this.${namer.getName(member)} = v;\n}\n'); |
| 63 } | 63 } |
| 64 if (compiler.universe.invokedGetters.contains(member.name.stringValue)) { | 64 if (compiler.universe.invokedGetters.contains(member.name)) { |
| 65 String getterName = namer.getterName(member.name); | 65 String getterName = namer.getterName(member.name); |
| 66 buffer.add('$prototype.$getterName = function(){\n' + | 66 buffer.add('$prototype.$getterName = function(){\n' + |
| 67 ' return this.${namer.getName(member)};\n}\n'); | 67 ' return this.${namer.getName(member)};\n}\n'); |
| 68 } | 68 } |
| 69 } | 69 } |
| 70 } | 70 } |
| 71 | 71 |
| 72 bool generateFieldInits(ClassElement classElement, | 72 bool generateFieldInits(ClassElement classElement, |
| 73 StringBuffer argumentsBuffer, | 73 StringBuffer argumentsBuffer, |
| 74 StringBuffer bodyBuffer) { | 74 StringBuffer bodyBuffer) { |
| 75 bool isFirst = true; | 75 bool isFirst = true; |
| 76 do { | 76 do { |
| 77 // TODO(floitsch): make sure there are no name clashes. | 77 // TODO(floitsch): make sure there are no name clashes. |
| 78 String className = namer.getName(classElement); | 78 String className = namer.getName(classElement); |
| 79 for (Element member in classElement.members) { | 79 for (Element member in classElement.members) { |
| 80 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { | 80 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { |
| 81 if (!isFirst) argumentsBuffer.add(', '); | 81 if (!isFirst) argumentsBuffer.add(', '); |
| 82 isFirst = false; | 82 isFirst = false; |
| 83 String memberName = namer.instanceName(member.name); | 83 String memberName = namer.instanceFieldName(member.name); |
| 84 argumentsBuffer.add('${className}_$memberName'); | 84 argumentsBuffer.add('${className}_$memberName'); |
| 85 bodyBuffer.add(' this.$memberName = ${className}_$memberName;\n'); | 85 bodyBuffer.add(' this.$memberName = ${className}_$memberName;\n'); |
| 86 } | 86 } |
| 87 } | 87 } |
| 88 classElement = classElement.superClass; | 88 classElement = classElement.superClass; |
| 89 } while(classElement !== null); | 89 } while(classElement !== null); |
| 90 } | 90 } |
| 91 | 91 |
| 92 void generateClass(ClassElement classElement, | 92 void generateClass(ClassElement classElement, |
| 93 StringBuffer buffer, | 93 StringBuffer buffer, |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 CompileTimeConstantHandler constants = compiler.compileTimeConstantHandler; | 176 CompileTimeConstantHandler constants = compiler.compileTimeConstantHandler; |
| 177 List<VariableElement> staticFinalFields = | 177 List<VariableElement> staticFinalFields = |
| 178 constants.getStaticFinalFieldsForEmission(); | 178 constants.getStaticFinalFieldsForEmission(); |
| 179 for (VariableElement element in staticFinalFields) { | 179 for (VariableElement element in staticFinalFields) { |
| 180 buffer.add('${namer.isolatePropertyAccess(element)} = '); | 180 buffer.add('${namer.isolatePropertyAccess(element)} = '); |
| 181 constants.emitJsCodeForField(element, buffer); | 181 constants.emitJsCodeForField(element, buffer); |
| 182 buffer.add(';\n'); | 182 buffer.add(';\n'); |
| 183 } | 183 } |
| 184 } | 184 } |
| 185 | 185 |
| 186 void emitNoSuchMethodCalls(StringBuffer buffer) { |
| 187 // Do not generate no such method calls if there is no class. |
| 188 if (compiler.universe.instantiatedClasses.isEmpty()) return; |
| 189 |
| 190 // TODO(ngeoffray): We don't need to generate these methods if |
| 191 // nobody overwrites noSuchMethod. |
| 192 |
| 193 ClassElement objectClass = |
| 194 compiler.universe.find(const SourceString('Object')); |
| 195 String className = namer.isolatePropertyAccess(objectClass); |
| 196 String prototype = '$className.prototype'; |
| 197 String noSuchMethodName = |
| 198 namer.instanceMethodName(Compiler.NO_SUCH_METHOD, 2); |
| 199 |
| 200 void generateMethod(String methodName, String jsName, int arity) { |
| 201 buffer.add('$prototype.$jsName = function'); |
| 202 StringBuffer args = new StringBuffer(); |
| 203 for (int i = 0; i < arity; i++) { |
| 204 if (i != 0) args.add(', '); |
| 205 args.add('arg$i'); |
| 206 } |
| 207 buffer.add(' ($args) {\n'); |
| 208 buffer.add(" return this.$noSuchMethodName('$methodName', [$args]);\n"); |
| 209 buffer.add('}\n'); |
| 210 } |
| 211 |
| 212 compiler.universe.invokedNames.forEach((SourceString methodName, |
| 213 Set<int> arities) { |
| 214 if (objectClass.lookupLocalMember(methodName) === null) { |
| 215 for (int arity in arities) { |
| 216 String jsName = namer.instanceMethodName(methodName, arity); |
| 217 generateMethod(methodName.stringValue, jsName, arity); |
| 218 } |
| 219 } |
| 220 }); |
| 221 |
| 222 compiler.universe.invokedGetters.forEach((SourceString getterName) { |
| 223 String jsName = namer.getterName(getterName); |
| 224 generateMethod('get $getterName', jsName, 0); |
| 225 }); |
| 226 |
| 227 compiler.universe.invokedSetters.forEach((SourceString setterName) { |
| 228 String jsName = namer.setterName(setterName); |
| 229 generateMethod('set $setterName', jsName, 1); |
| 230 }); |
| 231 } |
| 232 |
| 186 String assembleProgram() { | 233 String assembleProgram() { |
| 187 measure(() { | 234 measure(() { |
| 188 StringBuffer buffer = new StringBuffer(); | 235 StringBuffer buffer = new StringBuffer(); |
| 189 buffer.add('function ${namer.ISOLATE}() {'); | 236 buffer.add('function ${namer.ISOLATE}() {'); |
| 190 emitStaticNonFinalFieldInitializations(buffer); | 237 emitStaticNonFinalFieldInitializations(buffer); |
| 191 buffer.add('}\n\n'); | 238 buffer.add('}\n\n'); |
| 192 emitClasses(buffer); | 239 emitClasses(buffer); |
| 240 emitNoSuchMethodCalls(buffer); |
| 193 emitStaticFunctions(buffer); | 241 emitStaticFunctions(buffer); |
| 194 emitStaticFinalFieldInitializations(buffer); | 242 emitStaticFinalFieldInitializations(buffer); |
| 195 buffer.add('var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); | 243 buffer.add('var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); |
| 196 buffer.add('${namer.CURRENT_ISOLATE}.main();\n'); | 244 Element main = compiler.universe.find(Compiler.MAIN); |
| 245 buffer.add('${namer.isolateAccess(main)}();\n'); |
| 197 compiler.assembledCode = buffer.toString(); | 246 compiler.assembledCode = buffer.toString(); |
| 198 }); | 247 }); |
| 199 return compiler.assembledCode; | 248 return compiler.assembledCode; |
| 200 } | 249 } |
| 201 } | 250 } |
| OLD | NEW |