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

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: Address comments. 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 // Mixins are not allowed to inject fields.
266 assert(!currentClass.isMixinApplication ||
267 (currentClass as MixinApplication).mixinClass.fields.isEmpty);
268
269 allFieldNames.addAll(
270 currentClass.fields.map((InstanceField field) => field.name));
271 currentClass = currentClass.superclass;
272 }
264 } 273 }
265 String name = cls.name; 274 String name = cls.name;
266 String parameters = allFieldNames.join(', '); 275 String parameters = allFieldNames.join(', ');
267 String assignments = allFieldNames 276 String assignments = allFieldNames
268 .map((String field) => "this.$field = $field;\n") 277 .map((String field) => "this.$field = $field;\n")
269 .join(); 278 .join();
270 String code = 'function $name($parameters) { $assignments }'; 279 String code = 'function $name($parameters) { $assignments }';
271 js.Template template = js.js.uncachedExpressionTemplate(code); 280 js.Template template = js.js.uncachedExpressionTemplate(code);
272 return template.instantiate(const []); 281 return template.instantiate(const []);
273 } 282 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 .map(_generateGetter); 318 .map(_generateGetter);
310 319
311 Iterable<Method> setters = cls.fields 320 Iterable<Method> setters = cls.fields
312 .where((InstanceField field) => field.needsSetter) 321 .where((InstanceField field) => field.needsSetter)
313 .map(_generateSetter); 322 .map(_generateSetter);
314 323
315 return [getters, setters].expand((x) => x); 324 return [getters, setters].expand((x) => x);
316 } 325 }
317 326
318 js.Expression emitClass(Class cls) { 327 js.Expression emitClass(Class cls) {
319 List elements = [ js.string(cls.superclassName), 328 if (cls.isMixinApplication) return emitMixinApplication(cls);
320 js.number(cls.superclassHolderIndex), 329
321 _generateConstructor(cls) ]; 330 List elements = [js.string(cls.superclassName),
331 js.number(cls.superclassHolderIndex),
332 _generateConstructor(cls)];
322 Iterable<Method> methods = cls.methods; 333 Iterable<Method> methods = cls.methods;
323 Iterable<Method> gettersSetters = _generateGettersSetters(cls); 334 Iterable<Method> gettersSetters = _generateGettersSetters(cls);
324 Iterable<Method> allMethods = [methods, gettersSetters].expand((x) => x); 335 Iterable<Method> allMethods = [methods, gettersSetters].expand((x) => x);
325 elements.addAll(allMethods.expand((e) => [ js.string(e.name), e.code ])); 336 elements.addAll(allMethods.expand((e) => [js.string(e.name), e.code]));
326 return unparse(compiler, new js.ArrayInitializer.from(elements)); 337 return unparse(compiler, new js.ArrayInitializer.from(elements));
327 } 338 }
328 339
340 // This string should be referenced wherever JavaScript code makes assumptions
341 // on the mixin format.
342 static final String mixinFormatDescription =
343 "Mixins have no constructor, but a reference to their mixin class.";
344
345 js.Expression emitMixinApplication(MixinApplication cls) {
346 List elements = [js.string(cls.superclassName),
347 js.number(cls.superclassHolderIndex),
348 js.string(cls.mixinClass.name),
349 js.number(cls.mixinClass.holder.index)];
350 return unparse(compiler, new js.ArrayInitializer.from(elements));
351 }
352
329 js.Expression emitLazyInitializer(StaticField field) { 353 js.Expression emitLazyInitializer(StaticField field) {
330 assert(field.isLazy); 354 assert(field.isLazy);
331 return unparse(compiler, field.code); 355 return unparse(compiler, field.code);
332 } 356 }
333 357
334 js.Expression emitStaticMethod(StaticMethod method) { 358 js.Expression emitStaticMethod(StaticMethod method) {
335 return unparse(compiler, method.code); 359 return unparse(compiler, method.code);
336 } 360 }
337 }
338 361
339 final String boilerplate = r""" 362 static final String boilerplate = """
340 { 363 {
341 // Declare deferred-initializer global. 364 // Declare deferred-initializer global.
342 #; 365 #;
343 366
344 !function(start, program) { 367 !function(start, program) {
345 368
346 // Initialize holder objects. 369 // Initialize holder objects.
347 #; 370 #;
348 371
349 function setupProgram() { 372 function setupProgram() {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 // to resolve superclass references without constructing instances. The 450 // to resolve superclass references without constructing instances. The
428 // resolve property also serves as a marker that indicates whether or not 451 // resolve property also serves as a marker that indicates whether or not
429 // a class has been resolved yet. 452 // a class has been resolved yet.
430 patch.resolve = resolve; 453 patch.resolve = resolve;
431 holder[name] = patch; 454 holder[name] = patch;
432 } 455 }
433 456
434 function compileConstructor(name, descriptor) { 457 function compileConstructor(name, descriptor) {
435 descriptor = compile(name, descriptor); 458 descriptor = compile(name, descriptor);
436 var prototype = determinePrototype(descriptor); 459 var prototype = determinePrototype(descriptor);
460 // $mixinFormatDescription.
461 if (typeof descriptor[2] !== 'function') {
462 return compileMixinConstructor(name, prototype, descriptor);
463 }
437 var constructor = descriptor[2]; 464 var constructor = descriptor[2];
438 for (var i = 3; i < descriptor.length; i += 2) { 465 for (var i = 3; i < descriptor.length; i += 2) {
439 prototype[descriptor[i]] = descriptor[i + 1]; 466 prototype[descriptor[i]] = descriptor[i + 1];
440 } 467 }
441 constructor.prototype = prototype; 468 constructor.prototype = prototype;
442 return constructor; 469 return constructor;
443 } 470 }
444 471
472 function compileMixinConstructor(name, prototype, descriptor) {
473 // $mixinFormatDescription.
474 var mixinName = descriptor[2];
475 var mixinHolderIndex = descriptor[3];
476 var mixin = holders[mixinHolderIndex][mixinName];
477 if (mixin.resolve) mixin = mixin.resolve();
478 var mixinPrototype = mixin.prototype;
479
480 // Fill the prototype with the mixin's properties.
481 var mixinProperties = Object.keys(mixinPrototype);
482 for (var i = 0; i < mixinProperties.length; i++) {
483 var p = mixinProperties[i];
484 prototype[p] = mixinPrototype[p];
485 }
486 // Since this is a mixin application the constructor will actually never
487 // be invoked. We only use its prototype for the application's subclasses.
488 var constructor = function() {};
489 constructor.prototype = prototype;
490 return constructor;
491 }
492
445 function determinePrototype(descriptor) { 493 function determinePrototype(descriptor) {
446 var superclassName = descriptor[0]; 494 var superclassName = descriptor[0];
447 if (!superclassName) return { }; 495 if (!superclassName) return { };
448 496
449 // Look up the superclass constructor function in the right holder. 497 // Look up the superclass constructor function in the right holder.
450 var holderIndex = descriptor[1]; 498 var holderIndex = descriptor[1];
451 var superclass = holders[holderIndex][superclassName]; 499 var superclass = holders[holderIndex][superclassName];
452 if (superclass.resolve) superclass = superclass.resolve(); 500 if (superclass.resolve) superclass = superclass.resolve();
453 501
454 // Create a new prototype object chained to the superclass prototype. 502 // Create a new prototype object chained to the superclass prototype.
455 var intermediate = function() { }; 503 var intermediate = function() { };
456 intermediate.prototype = superclass.prototype; 504 intermediate.prototype = superclass.prototype;
457 return new intermediate(); 505 return new intermediate();
458 } 506 }
459 507
460 function compile(__name__, __s__) { 508 function compile(__name__, __s__) {
461 'use strict'; 509 'use strict';
462 // TODO(floitsch): evaluate the performance impact of the string 510 // TODO(floitsch): evaluate the performance impact of the string
463 // concatenations. 511 // concatenations.
464 return eval(__s__ + "\n//# sourceURL=" + __name__ + ".js"); 512 return eval(__s__ + "\\n//# sourceURL=" + __name__ + ".js");
465 } 513 }
466 514
467 if (#) { // outputContainsConstantList 515 if (#) { // outputContainsConstantList
468 function makeConstList(list) { 516 function makeConstList(list) {
469 // By assigning a function to the properties they become part of the 517 // 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 518 // hidden class. The actual values of the fields don't matter, since we
471 // only check if they exist. 519 // only check if they exist.
472 list.immutable$list = Array; 520 list.immutable\$list = Array;
473 list.fixed$length = Array; 521 list.fixed\$length = Array;
474 return list; 522 return list;
475 } 523 }
476 } 524 }
477 525
478 setupProgram(); 526 setupProgram();
479 527
480 // Initialize globals. 528 // Initialize globals.
481 #; 529 #;
482 530
483 // Initialize constants. 531 // Initialize constants.
484 #; 532 #;
485 533
486 // Initialize static non-final fields. 534 // Initialize static non-final fields.
487 #; 535 #;
488 536
489 // Initialize eager classes. 537 // Initialize eager classes.
490 #; 538 #;
491 539
492 var end = Date.now(); 540 var end = Date.now();
493 print('Setup: ' + (end - start) + ' ms.'); 541 print('Setup: ' + (end - start) + ' ms.');
494 542
495 if (true) #(); // Start main. 543 if (true) #(); // Start main.
496 544
497 }(Date.now(), #) 545 }(Date.now(), #)
498 }"""; 546 }""";
547
548 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/model.dart ('k') | pkg/compiler/lib/src/js_emitter/program_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698