Chromium Code Reviews| 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 * Top level generator object for writing code and keeping track of | 6 * Top level generator object for writing code and keeping track of |
| 7 * dependencies. | 7 * dependencies. |
| 8 * | 8 * |
| 9 * Should have two compilation models, but only one implemented so far. | 9 * Should have two compilation models, but only one implemented so far. |
| 10 * | 10 * |
| 11 * 1. Do a top-level resolution of all types and their members. | 11 * 1. Do a top-level resolution of all types and their members. |
| 12 * 2. Start from main and walk the call-graph compiling members as needed. | 12 * 2. Start from main and walk the call-graph compiling members as needed. |
| 13 * 2a. That includes compiling overriding methods and calling methods by | 13 * 2a. That includes compiling overriding methods and calling methods by |
| 14 * selector when invoked on var. | 14 * selector when invoked on var. |
| 15 * 3. Spit out all required code. | 15 * 3. Spit out all required code. |
| 16 */ | 16 */ |
| 17 class WorldGenerator { | 17 class WorldGenerator { |
| 18 MethodMember main; | 18 MethodMember main; |
| 19 CodeWriter writer; | 19 CodeWriter writer; |
| 20 | |
| 21 /** | |
| 22 * Whether the app has any static fields used. Note this could still be true | |
| 23 * and [globals] be empty if no static field has a default initialization. | |
| 24 */ | |
| 25 bool hasStatics = false; | |
|
jimhug
2011/11/18 17:49:17
FYI - Nice comment - this could also be very relev
| |
| 26 | |
| 27 /** Global const and static field initializations. */ | |
| 20 Map<String, GlobalValue> globals; | 28 Map<String, GlobalValue> globals; |
| 21 CoreJs corejs; | 29 CoreJs corejs; |
| 22 bool _inheritsGenerated = false; | 30 bool _inheritsGenerated = false; |
| 23 | 31 |
| 24 WorldGenerator(this.main, this.writer): globals = {}, corejs = new CoreJs(); | 32 WorldGenerator(this.main, this.writer): globals = {}, corejs = new CoreJs(); |
| 25 | 33 |
| 26 run() { | 34 run() { |
| 27 var metaGen = new MethodGenerator(main, null); | 35 var metaGen = new MethodGenerator(main, null); |
| 28 var mainCall = main.invoke(metaGen, null, null, Arguments.EMPTY); | 36 var mainCall = main.invoke(metaGen, null, null, Arguments.EMPTY); |
| 29 main.declaringType.markUsed(); | 37 main.declaringType.markUsed(); |
| 30 | 38 |
| 31 // TODO(jimhug): Better way to capture hidden control flow. | 39 // TODO(jimhug): Better way to capture hidden control flow. |
| 32 world.corelib.types['BadNumberFormatException'].markUsed(); | 40 world.corelib.types['BadNumberFormatException'].markUsed(); |
| 33 world.coreimpl.types['NumImplementation'].markUsed(); | 41 world.coreimpl.types['NumImplementation'].markUsed(); |
| 34 world.coreimpl.types['StringImplementation'].markUsed(); | 42 world.coreimpl.types['StringImplementation'].markUsed(); |
| 35 genMethod( | 43 genMethod( |
| 36 world.coreimpl.types['StringImplementation'].getMember('contains')); | 44 world.coreimpl.types['StringImplementation'].getMember('contains')); |
| 37 | 45 |
| 38 // Only include isolate-specific code if isolates are used. | 46 // Only include isolate-specific code if isolates are used. |
| 39 if (world.corelib.types['Isolate'].isUsed | 47 if (world.corelib.types['Isolate'].isUsed |
| 40 || world.coreimpl.types['ReceivePortImpl'].isUsed) { | 48 || world.coreimpl.types['ReceivePortImpl'].isUsed) { |
| 41 corejs.useIsolates = true; | 49 corejs.useIsolates = true; |
| 42 MethodMember isolateMain = | 50 MethodMember isolateMain = |
| 43 world.coreimpl.topType.resolveMember('startAsIsolate').members[0]; | 51 world.coreimpl.topType.resolveMember('startRootIsolate').members[0]; |
| 44 mainCall = isolateMain.invoke(metaGen, null, null, | 52 mainCall = isolateMain.invoke(metaGen, null, null, |
| 45 new Arguments(null, [main._get(metaGen, main.definition, null)])); | 53 new Arguments(null, [main._get(metaGen, main.definition, null)])); |
| 46 } | 54 } |
| 47 | 55 |
| 48 writeTypes(world.coreimpl); | 56 writeTypes(world.coreimpl); |
| 49 writeTypes(world.corelib); | 57 writeTypes(world.corelib); |
| 50 | 58 |
| 51 // Write the main library. This will cause all libraries to be written in | 59 // Write the main library. This will cause all libraries to be written in |
| 52 // the topographic sort order. | 60 // the topographic sort order. |
| 53 writeTypes(main.declaringType.library); | 61 writeTypes(main.declaringType.library); |
| 54 | 62 |
| 55 _writeGlobals(); | 63 writeGlobals(); |
| 56 writer.writeln('${mainCall.code};'); | 64 writer.writeln('${mainCall.code};'); |
| 57 } | 65 } |
| 58 | 66 |
| 59 GlobalValue globalForStaticField(FieldMember field, Value fieldValue, | 67 GlobalValue globalForStaticField(FieldMember field, Value fieldValue, |
| 60 List<Value> dependencies) { | 68 List<Value> dependencies) { |
| 69 hasStatics = true; | |
| 61 var fullname = "${field.declaringType.jsname}.${field.jsname}"; | 70 var fullname = "${field.declaringType.jsname}.${field.jsname}"; |
| 62 if (!globals.containsKey(fullname)) { | 71 if (!globals.containsKey(fullname)) { |
| 63 globals[fullname] = new GlobalValue.fromStatic( | 72 globals[fullname] = new GlobalValue.fromStatic( |
| 64 field, fieldValue, dependencies); | 73 field, fieldValue, dependencies); |
| 65 } | 74 } |
| 66 return globals[fullname]; | 75 return globals[fullname]; |
| 67 } | 76 } |
| 68 | 77 |
| 69 GlobalValue globalForConst(EvaluatedValue exp, List<Value> dependencies) { | 78 GlobalValue globalForConst(EvaluatedValue exp, List<Value> dependencies) { |
| 70 var code = exp.canonicalCode; | 79 var code = exp.canonicalCode; |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 287 } | 296 } |
| 288 | 297 |
| 289 _writeStaticField(FieldMember field) { | 298 _writeStaticField(FieldMember field) { |
| 290 // Final static fields must be constants which will be folded and inlined. | 299 // Final static fields must be constants which will be folded and inlined. |
| 291 if (field.isFinal) return; | 300 if (field.isFinal) return; |
| 292 | 301 |
| 293 var fullname = "${field.declaringType.jsname}.${field.jsname}"; | 302 var fullname = "${field.declaringType.jsname}.${field.jsname}"; |
| 294 if (globals.containsKey(fullname)) { | 303 if (globals.containsKey(fullname)) { |
| 295 var value = globals[fullname]; | 304 var value = globals[fullname]; |
| 296 if (field.declaringType.isTop && !field.isNative) { | 305 if (field.declaringType.isTop && !field.isNative) { |
| 297 writer.writeln('var ${field.jsname} = ${value.exp.code};'); | 306 writer.writeln('\$globals.${field.jsname} = ${value.exp.code};'); |
| 298 } else { | 307 } else { |
| 299 writer.writeln( | 308 writer.writeln('\$globals.${field.declaringType.jsname}_${field.jsname}' |
| 300 '${field.declaringType.jsname}.${field.jsname} = ${value.exp.code};'); | 309 + ' = ${value.exp.code};'); |
| 301 } | 310 } |
| 302 } | 311 } |
| 303 // No need to write code for a static class field with no initial value. | 312 // No need to write code for a static class field with no initial value. |
| 304 } | 313 } |
| 305 | 314 |
| 306 _writeField(FieldMember field) { | 315 _writeField(FieldMember field) { |
| 307 // Generate declarations for static top-level fields with no value. | 316 // Generate declarations for static top-level fields with no value. |
| 308 if (field.declaringType.isTop && !field.isNative && field.value == null) { | 317 if (field.declaringType.isTop && !field.isNative && field.value == null) { |
| 309 writer.writeln('var ${field.jsname};'); | 318 writer.writeln('var ${field.jsname};'); |
| 310 } | 319 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 347 writer.exitBlock('});'); | 356 writer.exitBlock('});'); |
| 348 } | 357 } |
| 349 } | 358 } |
| 350 | 359 |
| 351 _writeMethod(Member method) { | 360 _writeMethod(Member method) { |
| 352 if (method.generator != null) { | 361 if (method.generator != null) { |
| 353 method.generator.writeDefinition(writer, null); | 362 method.generator.writeDefinition(writer, null); |
| 354 } | 363 } |
| 355 } | 364 } |
| 356 | 365 |
| 357 _writeGlobals() { | 366 writeGlobals() { |
| 358 if (globals.length > 0) { | 367 if (globals.length > 0) { |
| 359 writer.comment('// ********** Globals **************'); | 368 writer.comment('// ********** Globals **************'); |
| 369 var list = globals.getValues(); | |
| 370 list.sort((a, b) => a.compareTo(b)); | |
| 371 | |
| 372 // put all static field initializations in a method | |
| 373 writer.enterBlock('function \$static_init(){'); | |
|
Jennifer Messerly
2011/11/18 01:46:39
presumably library top-level variables need to go
Jennifer Messerly
2011/11/18 01:47:03
Ignore this comment. I forgot to delete it :)
| |
| 374 for (var global in list) { | |
| 375 if (global.field != null) { | |
| 376 _writeStaticField(global.field); | |
| 377 } | |
| 378 } | |
| 379 writer.exitBlock('}'); | |
| 380 | |
| 381 // Keep const expressions shared across isolates. Note that the frog | |
| 382 // isolate library needs this because we wrote it's bootstrap and | |
| 383 // book-keeping directly in Dart. Specifically, that code uses | |
| 384 // [HashMapImplementation] which internally uses a constant expression. | |
| 385 for (var global in list) { | |
| 386 if (global.field == null) { | |
| 387 writer.writeln('${global.name} = ${global.exp.code};'); | |
| 388 } | |
| 389 } | |
| 360 } | 390 } |
| 361 var list = globals.getValues(); | 391 |
| 362 list.sort((a, b) => a.compareTo(b)); | 392 if (!corejs.useIsolates) { |
| 363 for (var global in list) { | 393 if (hasStatics) { |
| 364 if (global.field != null) { | 394 writer.writeln('var \$globals = {};'); |
| 365 _writeStaticField(global.field); | 395 } |
| 366 } else { | 396 if (globals.length > 0) { |
| 367 writer.writeln('var ${global.name} = ${global.exp.code};'); | 397 writer.writeln('\$static_init();'); |
| 368 } | 398 } |
| 369 } | 399 } |
| 370 } | 400 } |
| 371 | 401 |
| 372 /** Order a list of values in a Map by SourceSpan, then by name. */ | 402 /** Order a list of values in a Map by SourceSpan, then by name. */ |
| 373 List _orderValues(Map map) { | 403 List _orderValues(Map map) { |
| 374 // TODO(jmesserly): should we copy the list? | 404 // TODO(jmesserly): should we copy the list? |
| 375 // Right now, the Maps are returning a copy already. | 405 // Right now, the Maps are returning a copy already. |
| 376 List values = map.getValues(); | 406 List values = map.getValues(); |
| 377 values.sort(_compareMembers); | 407 values.sort(_compareMembers); |
| (...skipping 1894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2272 result.add(new Value(world.varType, '\$$i', null, /*needsTemp:*/false)); | 2302 result.add(new Value(world.varType, '\$$i', null, /*needsTemp:*/false)); |
| 2273 } | 2303 } |
| 2274 for (int i = bareCount; i < length; i++) { | 2304 for (int i = bareCount; i < length; i++) { |
| 2275 var name = getName(i); | 2305 var name = getName(i); |
| 2276 if (name == null) name = '\$$i'; | 2306 if (name == null) name = '\$$i'; |
| 2277 result.add(new Value(world.varType, name, null, /*needsTemp:*/false)); | 2307 result.add(new Value(world.varType, name, null, /*needsTemp:*/false)); |
| 2278 } | 2308 } |
| 2279 return new Arguments(nodes, result); | 2309 return new Arguments(nodes, result); |
| 2280 } | 2310 } |
| 2281 } | 2311 } |
| OLD | NEW |