Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library dart2js.new_js_emitter.model_emitter; | 5 library dart2js.new_js_emitter.model_emitter; |
| 6 | 6 |
| 7 import '../../dart2jslib.dart' show Compiler; | 7 import '../../dart2jslib.dart' show Compiler; |
| 8 import '../../js/js.dart' as js; | 8 import '../../js/js.dart' as js; |
| 9 import '../../js_backend/js_backend.dart' show | 9 import '../../js_backend/js_backend.dart' show |
| 10 JavaScriptBackend, | 10 JavaScriptBackend, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 68 var suffix = ''; | 68 var suffix = ''; |
| 69 if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}'; | 69 if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}'; |
| 70 return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n'; | 70 return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n'; |
| 71 } | 71 } |
| 72 | 72 |
| 73 js.Statement emitMainUnit(Program program) { | 73 js.Statement emitMainUnit(Program program) { |
| 74 MainOutput unit = program.outputs.first; | 74 MainOutput unit = program.outputs.first; |
| 75 List<js.Expression> elements = unit.libraries.map(emitLibrary).toList(); | 75 List<js.Expression> elements = unit.libraries.map(emitLibrary).toList(); |
| 76 elements.add( | 76 elements.add( |
| 77 emitLazilyInitializedStatics(unit.staticLazilyInitializedFields)); | 77 emitLazilyInitializedStatics(unit.staticLazilyInitializedFields)); |
| 78 js.Expression code = new js.ArrayInitializer.from(elements); | 78 js.Expression code = new js.ArrayInitializer(elements); |
| 79 return js.js.statement( | 79 return js.js.statement( |
| 80 boilerplate, | 80 boilerplate, |
| 81 {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap), | 81 {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap), |
| 82 'holders': emitHolders(unit.holders), | 82 'holders': emitHolders(unit.holders), |
| 83 'cyclicThrow': namer.elementAccess(backend.getCyclicThrowHelper()), | 83 'cyclicThrow': namer.elementAccess(backend.getCyclicThrowHelper()), |
| 84 'outputContainsConstantList': program.outputContainsConstantList, | 84 'outputContainsConstantList': program.outputContainsConstantList, |
| 85 'embeddedGlobals': emitEmbeddedGlobals(program.loadMap), | 85 'embeddedGlobals': emitEmbeddedGlobals(program.loadMap), |
| 86 'constants': emitConstants(unit.constants), | 86 'constants': emitConstants(unit.constants), |
| 87 'staticNonFinals': emitStaticNonFinalFields(unit.staticNonFinalFields), | 87 'staticNonFinals': emitStaticNonFinalFields(unit.staticNonFinalFields), |
| 88 'eagerClasses': emitEagerClassInitializations(unit.libraries), | 88 'eagerClasses': emitEagerClassInitializations(unit.libraries), |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 100 // | 100 // |
| 101 // and it is inserted at the top of the top-level function expression | 101 // and it is inserted at the top of the top-level function expression |
| 102 // that covers the entire program. | 102 // that covers the entire program. |
| 103 | 103 |
| 104 List<js.Statement> statements = [ | 104 List<js.Statement> statements = [ |
| 105 new js.ExpressionStatement( | 105 new js.ExpressionStatement( |
| 106 new js.VariableDeclarationList(holders.map((e) => | 106 new js.VariableDeclarationList(holders.map((e) => |
| 107 new js.VariableInitialization( | 107 new js.VariableInitialization( |
| 108 new js.VariableDeclaration(e.name, allowRename: false), | 108 new js.VariableDeclaration(e.name, allowRename: false), |
| 109 new js.ObjectInitializer(const []))).toList())), | 109 new js.ObjectInitializer(const []))).toList())), |
| 110 js.js.statement('var holders = #', new js.ArrayInitializer.from( | 110 js.js.statement('var holders = #', new js.ArrayInitializer( |
| 111 holders.map((e) => new js.VariableUse(e.name)))) | 111 holders.map((e) => new js.VariableUse(e.name)).toList())) |
|
floitsch
2014/11/28 12:42:50
growable: false ?
but probably not enough space...
sigurdm
2014/11/28 14:52:12
Done.
| |
| 112 ]; | 112 ]; |
| 113 return new js.Block(statements); | 113 return new js.Block(statements); |
| 114 } | 114 } |
| 115 | 115 |
| 116 static js.Template get makeConstantListTemplate { | 116 static js.Template get makeConstantListTemplate { |
| 117 // TODO(floitsch): remove hard-coded name. | 117 // TODO(floitsch): remove hard-coded name. |
| 118 // TODO(floitsch): there is no harm in caching the template. | 118 // TODO(floitsch): there is no harm in caching the template. |
| 119 return js.js.uncachedExpressionTemplate('makeConstList(#)'); | 119 return js.js.uncachedExpressionTemplate('makeConstList(#)'); |
| 120 } | 120 } |
| 121 | 121 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 191 } | 191 } |
| 192 | 192 |
| 193 js.Expression emitDeferredUnit(DeferredOutput unit, List<Holder> holders) { | 193 js.Expression emitDeferredUnit(DeferredOutput unit, List<Holder> holders) { |
| 194 // TODO(floitsch): initialize eager classes. | 194 // TODO(floitsch): initialize eager classes. |
| 195 // TODO(floitsch): the hash must depend on the output. | 195 // TODO(floitsch): the hash must depend on the output. |
| 196 int hash = this.hashCode; | 196 int hash = this.hashCode; |
| 197 if (unit.constants.isNotEmpty) { | 197 if (unit.constants.isNotEmpty) { |
| 198 throw new UnimplementedError("constants in deferred units"); | 198 throw new UnimplementedError("constants in deferred units"); |
| 199 } | 199 } |
| 200 js.ArrayInitializer content = | 200 js.ArrayInitializer content = |
| 201 new js.ArrayInitializer.from(unit.libraries.map(emitLibrary)); | 201 new js.ArrayInitializer(unit.libraries.map(emitLibrary).toList()); |
|
floitsch
2014/11/28 12:42:50
ditto.
May create a new local:
List<Expression> en
sigurdm
2014/11/28 14:52:12
Done.
| |
| 202 return js.js("$deferredInitializersGlobal[$hash] = #", content); | 202 return js.js("$deferredInitializersGlobal[$hash] = #", content); |
| 203 } | 203 } |
| 204 | 204 |
| 205 js.Block emitConstants(List<Constant> constants) { | 205 js.Block emitConstants(List<Constant> constants) { |
| 206 Iterable<js.Statement> statements = constants.map((Constant constant) { | 206 Iterable<js.Statement> statements = constants.map((Constant constant) { |
| 207 js.Expression code = | 207 js.Expression code = |
| 208 constantEmitter.initializationExpression(constant.value); | 208 constantEmitter.initializationExpression(constant.value); |
| 209 return js.js.statement("#.# = #;", | 209 return js.js.statement("#.# = #;", |
| 210 [constant.holder.name, constant.name, code]); | 210 [constant.holder.name, constant.name, code]); |
| 211 }); | 211 }); |
| 212 return new js.Block(statements.toList()); | 212 return new js.Block(statements.toList()); |
| 213 } | 213 } |
| 214 | 214 |
| 215 js.Block emitStaticNonFinalFields(List<StaticField> fields) { | 215 js.Block emitStaticNonFinalFields(List<StaticField> fields) { |
| 216 Iterable<js.Statement> statements = fields.map((StaticField field) { | 216 Iterable<js.Statement> statements = fields.map((StaticField field) { |
| 217 return js.js.statement("#.# = #;", | 217 return js.js.statement("#.# = #;", |
| 218 [field.holder.name, field.name, field.code]); | 218 [field.holder.name, field.name, field.code]); |
| 219 }); | 219 }); |
| 220 return new js.Block(statements.toList()); | 220 return new js.Block(statements.toList()); |
| 221 } | 221 } |
| 222 | 222 |
| 223 js.Expression emitLazilyInitializedStatics(List<StaticField> fields) { | 223 js.Expression emitLazilyInitializedStatics(List<StaticField> fields) { |
| 224 Iterable fieldDescriptors = fields.expand((field) => | 224 Iterable fieldDescriptors = fields.expand((field) => |
| 225 [ js.string(field.name), | 225 [ js.string(field.name), |
| 226 js.string("${namer.getterPrefix}${field.name}"), | 226 js.string("${namer.getterPrefix}${field.name}"), |
| 227 js.number(field.holder.index), | 227 js.number(field.holder.index), |
| 228 emitLazyInitializer(field) ]); | 228 emitLazyInitializer(field) ]); |
| 229 return new js.ArrayInitializer.from(fieldDescriptors); | 229 return new js.ArrayInitializer(fieldDescriptors.toList()); |
|
floitsch
2014/11/28 12:42:50
ditto.
sigurdm
2014/11/28 14:52:12
Done.
| |
| 230 } | 230 } |
| 231 | 231 |
| 232 js.Block emitEagerClassInitializations(List<Library> libraries) { | 232 js.Block emitEagerClassInitializations(List<Library> libraries) { |
| 233 js.Statement createInstantiation(Class cls) { | 233 js.Statement createInstantiation(Class cls) { |
| 234 return js.js.statement('new #.#()', [cls.holder.name, cls.name]); | 234 return js.js.statement('new #.#()', [cls.holder.name, cls.name]); |
| 235 } | 235 } |
| 236 | 236 |
| 237 List<js.Statement> instantiations = | 237 List<js.Statement> instantiations = |
| 238 libraries.expand((Library library) => library.classes) | 238 libraries.expand((Library library) => library.classes) |
| 239 .where((Class cls) => cls.isEager) | 239 .where((Class cls) => cls.isEager) |
| 240 .map(createInstantiation) | 240 .map(createInstantiation) |
| 241 .toList(growable: false); | 241 .toList(growable: false); |
| 242 return new js.Block(instantiations); | 242 return new js.Block(instantiations); |
| 243 } | 243 } |
| 244 | 244 |
| 245 js.Expression emitLibrary(Library library) { | 245 js.Expression emitLibrary(Library library) { |
| 246 Iterable staticDescriptors = library.statics.expand((e) => | 246 Iterable staticDescriptors = library.statics.expand((e) => |
| 247 [ js.string(e.name), js.number(e.holder.index), emitStaticMethod(e) ]); | 247 [ js.string(e.name), js.number(e.holder.index), emitStaticMethod(e) ]); |
| 248 Iterable classDescriptors = library.classes.expand((e) => | 248 Iterable classDescriptors = library.classes.expand((e) => |
| 249 [ js.string(e.name), js.number(e.holder.index), emitClass(e) ]); | 249 [ js.string(e.name), js.number(e.holder.index), emitClass(e) ]); |
| 250 | 250 |
| 251 js.Expression staticArray = new js.ArrayInitializer.from(staticDescriptors); | 251 js.Expression staticArray = |
| 252 js.Expression classArray = new js.ArrayInitializer.from(classDescriptors); | 252 new js.ArrayInitializer(staticDescriptors.toList()); |
|
floitsch
2014/11/28 12:42:50
ditto.
sigurdm
2014/11/28 14:52:12
Done.
| |
| 253 js.Expression classArray = | |
| 254 new js.ArrayInitializer(classDescriptors.toList()); | |
|
floitsch
2014/11/28 12:42:50
ditto.
sigurdm
2014/11/28 14:52:12
Done.
| |
| 253 | 255 |
| 254 return new js.ArrayInitializer.from([staticArray, classArray]); | 256 return new js.ArrayInitializer([staticArray, classArray]); |
| 255 } | 257 } |
| 256 | 258 |
| 257 js.Expression _generateConstructor(Class cls) { | 259 js.Expression _generateConstructor(Class cls) { |
| 258 List<String> allFieldNames = <String>[]; | 260 List<String> allFieldNames = <String>[]; |
| 259 | 261 |
| 260 // If the class is not directly instantiated we only need it for inheritance | 262 // If the class is not directly instantiated we only need it for inheritance |
| 261 // or RTI. In either case we don't need its fields. | 263 // or RTI. In either case we don't need its fields. |
| 262 if (cls.isDirectlyInstantiated) { | 264 if (cls.isDirectlyInstantiated) { |
| 263 Class currentClass = cls; | 265 Class currentClass = cls; |
| 264 while (currentClass != null) { | 266 while (currentClass != null) { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 327 js.Expression emitClass(Class cls) { | 329 js.Expression emitClass(Class cls) { |
| 328 if (cls.isMixinApplication) return emitMixinApplication(cls); | 330 if (cls.isMixinApplication) return emitMixinApplication(cls); |
| 329 | 331 |
| 330 List elements = [js.string(cls.superclassName), | 332 List elements = [js.string(cls.superclassName), |
| 331 js.number(cls.superclassHolderIndex), | 333 js.number(cls.superclassHolderIndex), |
| 332 _generateConstructor(cls)]; | 334 _generateConstructor(cls)]; |
| 333 Iterable<Method> methods = cls.methods; | 335 Iterable<Method> methods = cls.methods; |
| 334 Iterable<Method> gettersSetters = _generateGettersSetters(cls); | 336 Iterable<Method> gettersSetters = _generateGettersSetters(cls); |
| 335 Iterable<Method> allMethods = [methods, gettersSetters].expand((x) => x); | 337 Iterable<Method> allMethods = [methods, gettersSetters].expand((x) => x); |
| 336 elements.addAll(allMethods.expand((e) => [js.string(e.name), e.code])); | 338 elements.addAll(allMethods.expand((e) => [js.string(e.name), e.code])); |
| 337 return unparse(compiler, new js.ArrayInitializer.from(elements)); | 339 return unparse(compiler, new js.ArrayInitializer(elements)); |
| 338 } | 340 } |
| 339 | 341 |
| 340 // This string should be referenced wherever JavaScript code makes assumptions | 342 // This string should be referenced wherever JavaScript code makes assumptions |
| 341 // on the mixin format. | 343 // on the mixin format. |
| 342 static final String mixinFormatDescription = | 344 static final String mixinFormatDescription = |
| 343 "Mixins have no constructor, but a reference to their mixin class."; | 345 "Mixins have no constructor, but a reference to their mixin class."; |
| 344 | 346 |
| 345 js.Expression emitMixinApplication(MixinApplication cls) { | 347 js.Expression emitMixinApplication(MixinApplication cls) { |
| 346 List elements = [js.string(cls.superclassName), | 348 List elements = [js.string(cls.superclassName), |
| 347 js.number(cls.superclassHolderIndex), | 349 js.number(cls.superclassHolderIndex), |
| 348 js.string(cls.mixinClass.name), | 350 js.string(cls.mixinClass.name), |
| 349 js.number(cls.mixinClass.holder.index)]; | 351 js.number(cls.mixinClass.holder.index)]; |
| 350 return unparse(compiler, new js.ArrayInitializer.from(elements)); | 352 return unparse(compiler, new js.ArrayInitializer(elements)); |
| 351 } | 353 } |
| 352 | 354 |
| 353 js.Expression emitLazyInitializer(StaticField field) { | 355 js.Expression emitLazyInitializer(StaticField field) { |
| 354 assert(field.isLazy); | 356 assert(field.isLazy); |
| 355 return unparse(compiler, field.code); | 357 return unparse(compiler, field.code); |
| 356 } | 358 } |
| 357 | 359 |
| 358 js.Expression emitStaticMethod(StaticMethod method) { | 360 js.Expression emitStaticMethod(StaticMethod method) { |
| 359 return unparse(compiler, method.code); | 361 return unparse(compiler, method.code); |
| 360 } | 362 } |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 539 | 541 |
| 540 var end = Date.now(); | 542 var end = Date.now(); |
| 541 print('Setup: ' + (end - start) + ' ms.'); | 543 print('Setup: ' + (end - start) + ' ms.'); |
| 542 | 544 |
| 543 #main(); // Start main. | 545 #main(); // Start main. |
| 544 | 546 |
| 545 }(Date.now(), #code) | 547 }(Date.now(), #code) |
| 546 }"""; | 548 }"""; |
| 547 | 549 |
| 548 } | 550 } |
| OLD | NEW |