Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Side by Side Diff: pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart

Issue 752553004: dart2js: Support mixins in the new emitter. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix typo. Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 = new js.ArrayInitializer.from(staticDescriptors);
252 js.Expression classArray = new js.ArrayInitializer.from(classDescriptors); 252 js.Expression classArray = new js.ArrayInitializer.from(classDescriptors);
253 253
254 return new js.ArrayInitializer.from([staticArray, classArray]); 254 return new js.ArrayInitializer.from([staticArray, classArray]);
255 } 255 }
256 256
257 js.Expression _generateConstructor(Class cls) { 257 js.Expression _generateConstructor(Class cls) {
258 List<String> allFieldNames = <String>[]; 258 List<String> allFieldNames = <String>[];
259 Class currentClass = cls; 259
260 while (currentClass != null) { 260 // If the class is not directly instantiated we only need it for inheritance
261 allFieldNames.addAll( 261 // or RTI. In either case we don't need its fields.
262 currentClass.fields.map((InstanceField field) => field.name)); 262 if (cls.isDirectlyInstantiated) {
263 currentClass = currentClass.superclass; 263 Class currentClass = cls;
264 while (currentClass != null) {
265 assert(() {
kasperl 2014/11/27 09:05:14 Add a comment for the assert. What are you verifyi
floitsch 2014/11/27 12:35:16 Reduced the assert. It is now just testing that mi
266 if (currentClass.isMixinApplication) {
267 if (currentClass.fields.isNotEmpty) return false;
268 if (currentClass.methods.isNotEmpty) return false;
269 MixinApplication mixinApplication = currentClass;
270 if (mixinApplication.mixinClass.fields.isNotEmpty) return false;
271 }
272 return true;
273 });
274
275 allFieldNames.addAll(
276 currentClass.fields.map((InstanceField field) => field.name));
277 currentClass = currentClass.superclass;
278 }
264 } 279 }
265 String name = cls.name; 280 String name = cls.name;
266 String parameters = allFieldNames.join(', '); 281 String parameters = allFieldNames.join(', ');
267 String assignments = allFieldNames 282 String assignments = allFieldNames
268 .map((String field) => "this.$field = $field;\n") 283 .map((String field) => "this.$field = $field;\n")
269 .join(); 284 .join();
270 String code = 'function $name($parameters) { $assignments }'; 285 String code = 'function $name($parameters) { $assignments }';
271 js.Template template = js.js.uncachedExpressionTemplate(code); 286 js.Template template = js.js.uncachedExpressionTemplate(code);
272 return template.instantiate(const []); 287 return template.instantiate(const []);
273 } 288 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 .map(_generateGetter); 324 .map(_generateGetter);
310 325
311 Iterable<Method> setters = cls.fields 326 Iterable<Method> setters = cls.fields
312 .where((InstanceField field) => field.needsSetter) 327 .where((InstanceField field) => field.needsSetter)
313 .map(_generateSetter); 328 .map(_generateSetter);
314 329
315 return [getters, setters].expand((x) => x); 330 return [getters, setters].expand((x) => x);
316 } 331 }
317 332
318 js.Expression emitClass(Class cls) { 333 js.Expression emitClass(Class cls) {
334 if (cls.isMixinApplication) return emitMixinApplication(cls);
335
319 List elements = [ js.string(cls.superclassName), 336 List elements = [ js.string(cls.superclassName),
320 js.number(cls.superclassHolderIndex), 337 js.number(cls.superclassHolderIndex),
321 _generateConstructor(cls) ]; 338 _generateConstructor(cls) ];
322 Iterable<Method> methods = cls.methods; 339 Iterable<Method> methods = cls.methods;
323 Iterable<Method> gettersSetters = _generateGettersSetters(cls); 340 Iterable<Method> gettersSetters = _generateGettersSetters(cls);
324 Iterable<Method> allMethods = [methods, gettersSetters].expand((x) => x); 341 Iterable<Method> allMethods = [methods, gettersSetters].expand((x) => x);
325 elements.addAll(allMethods.expand((e) => [ js.string(e.name), e.code ])); 342 elements.addAll(allMethods.expand((e) => [ js.string(e.name), e.code ]));
sigurdm 2014/11/27 09:25:54 Space inside the '['
floitsch 2014/11/27 12:35:16 Done.
326 return unparse(compiler, new js.ArrayInitializer.from(elements)); 343 return unparse(compiler, new js.ArrayInitializer.from(elements));
327 } 344 }
328 345
346 static final String mixinFormatComment =
347 "Mixins have no constructor, but a reference to their mixin class.";
sigurdm 2014/11/27 09:25:54 Empty line between members.
floitsch 2014/11/27 12:35:16 Done.
348 js.Expression emitMixinApplication(MixinApplication cls) {
349 List elements = [ js.string(cls.superclassName),
sigurdm 2014/11/27 09:25:54 Space inside the '['
floitsch 2014/11/27 12:35:16 Done.
350 js.number(cls.superclassHolderIndex),
351 js.string(cls.mixinClass.name),
352 js.number(cls.mixinClass.holder.index) ];
353 return unparse(compiler, new js.ArrayInitializer.from(elements));
354 }
355
329 js.Expression emitLazyInitializer(StaticField field) { 356 js.Expression emitLazyInitializer(StaticField field) {
330 assert(field.isLazy); 357 assert(field.isLazy);
331 return unparse(compiler, field.code); 358 return unparse(compiler, field.code);
332 } 359 }
333 360
334 js.Expression emitStaticMethod(StaticMethod method) { 361 js.Expression emitStaticMethod(StaticMethod method) {
335 return unparse(compiler, method.code); 362 return unparse(compiler, method.code);
336 } 363 }
337 }
338 364
339 final String boilerplate = r""" 365 static final String boilerplate = """
340 { 366 {
341 // Declare deferred-initializer global. 367 // Declare deferred-initializer global.
342 #; 368 #;
343 369
344 !function(start, program) { 370 !function(start, program) {
345 371
346 // Initialize holder objects. 372 // Initialize holder objects.
347 #; 373 #;
348 374
349 function setupProgram() { 375 function setupProgram() {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 // to resolve superclass references without constructing instances. The 453 // to resolve superclass references without constructing instances. The
428 // resolve property also serves as a marker that indicates whether or not 454 // resolve property also serves as a marker that indicates whether or not
429 // a class has been resolved yet. 455 // a class has been resolved yet.
430 patch.resolve = resolve; 456 patch.resolve = resolve;
431 holder[name] = patch; 457 holder[name] = patch;
432 } 458 }
433 459
434 function compileConstructor(name, descriptor) { 460 function compileConstructor(name, descriptor) {
435 descriptor = compile(name, descriptor); 461 descriptor = compile(name, descriptor);
436 var prototype = determinePrototype(descriptor); 462 var prototype = determinePrototype(descriptor);
463 // $mixinFormatComment.
floitsch 2014/11/26 17:32:09 I'm using this "marker" as a way to easily find al
sigurdm 2014/11/27 09:25:54 Perhaps also explain that in a comment in the code
floitsch 2014/11/27 12:35:16 Done.
464 if (typeof descriptor[2] !== 'function') {
sigurdm 2014/11/27 09:25:54 Could there be a less fragile way of distinguishin
floitsch 2014/11/27 12:35:16 I don't see any, that wouldn't require bigger chan
465 return compileMixinConstructor(name, prototype, descriptor);
466 }
437 var constructor = descriptor[2]; 467 var constructor = descriptor[2];
438 for (var i = 3; i < descriptor.length; i += 2) { 468 for (var i = 3; i < descriptor.length; i += 2) {
439 prototype[descriptor[i]] = descriptor[i + 1]; 469 prototype[descriptor[i]] = descriptor[i + 1];
440 } 470 }
441 constructor.prototype = prototype; 471 constructor.prototype = prototype;
442 return constructor; 472 return constructor;
443 } 473 }
444 474
475 function compileMixinConstructor(name, prototype, descriptor) {
476 var mixinName = descriptor[2];
477 var mixinHolderIndex = descriptor[3];
478 var mixin = holders[mixinHolderIndex][mixinName];
479 if (mixin.resolve) mixin = mixin.resolve();
480 var mixinPrototype = mixin.prototype;
481
482 // Fill the prototype with the mixin's properties.
483 var mixinProperties = Object.keys(mixinPrototype);
484 for (var i = 0; i < mixinProperties.length; i++) {
485 var p = mixinProperties[i];
486 prototype[p] = mixinPrototype[p];
487 }
488 // Since this is a mixin application the constructor will actually never
489 // be invoked. We only use its prototype for the application's subclasses.
490 var constructor = function() {};
491 constructor.prototype = prototype;
492 return constructor;
493 }
494
445 function determinePrototype(descriptor) { 495 function determinePrototype(descriptor) {
446 var superclassName = descriptor[0]; 496 var superclassName = descriptor[0];
447 if (!superclassName) return { }; 497 if (!superclassName) return { };
448 498
449 // Look up the superclass constructor function in the right holder. 499 // Look up the superclass constructor function in the right holder.
450 var holderIndex = descriptor[1]; 500 var holderIndex = descriptor[1];
451 var superclass = holders[holderIndex][superclassName]; 501 var superclass = holders[holderIndex][superclassName];
452 if (superclass.resolve) superclass = superclass.resolve(); 502 if (superclass.resolve) superclass = superclass.resolve();
453 503
454 // Create a new prototype object chained to the superclass prototype. 504 // Create a new prototype object chained to the superclass prototype.
455 var intermediate = function() { }; 505 var intermediate = function() { };
456 intermediate.prototype = superclass.prototype; 506 intermediate.prototype = superclass.prototype;
457 return new intermediate(); 507 return new intermediate();
458 } 508 }
459 509
460 function compile(__name__, __s__) { 510 function compile(__name__, __s__) {
461 'use strict'; 511 'use strict';
462 // TODO(floitsch): evaluate the performance impact of the string 512 // TODO(floitsch): evaluate the performance impact of the string
463 // concatenations. 513 // concatenations.
464 return eval(__s__ + "\n//# sourceURL=" + __name__ + ".js"); 514 return eval(__s__ + "\\n//# sourceURL=" + __name__ + ".js");
465 } 515 }
466 516
467 if (#) { // outputContainsConstantList 517 if (#) { // outputContainsConstantList
468 function makeConstList(list) { 518 function makeConstList(list) {
469 // By assigning a function to the properties they become part of the 519 // By assigning a function to the properties they become part of the
470 // hidden class. The actual values of the fields don't matter, since we 520 // hidden class. The actual values of the fields don't matter, since we
471 // only check if they exist. 521 // only check if they exist.
472 list.immutable$list = Array; 522 list.immutable\$list = Array;
473 list.fixed$length = Array; 523 list.fixed\$length = Array;
474 return list; 524 return list;
475 } 525 }
476 } 526 }
477 527
478 setupProgram(); 528 setupProgram();
479 529
480 // Initialize globals. 530 // Initialize globals.
481 #; 531 #;
482 532
483 // Initialize constants. 533 // Initialize constants.
484 #; 534 #;
485 535
486 // Initialize static non-final fields. 536 // Initialize static non-final fields.
487 #; 537 #;
488 538
489 // Initialize eager classes. 539 // Initialize eager classes.
490 #; 540 #;
491 541
492 var end = Date.now(); 542 var end = Date.now();
493 print('Setup: ' + (end - start) + ' ms.'); 543 print('Setup: ' + (end - start) + ' ms.');
494 544
495 if (true) #(); // Start main. 545 if (true) #(); // Start main.
496 546
497 }(Date.now(), #) 547 }(Date.now(), #)
498 }"""; 548 }""";
549
550 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698