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

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

Issue 890893002: Support generation of tearoffs for instance methods. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: unbreak old backend Created 5 years, 10 months 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
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/js_lib/js_helper.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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,
11 Namer, 11 Namer,
12 ConstantEmitter; 12 ConstantEmitter;
13 13
14 import 'package:_internal/compiler/js_lib/shared/embedded_names.dart' show 14 import 'package:_internal/compiler/js_lib/shared/embedded_names.dart' show
15 DEFERRED_LIBRARY_URIS, 15 DEFERRED_LIBRARY_URIS,
16 DEFERRED_LIBRARY_HASHES, 16 DEFERRED_LIBRARY_HASHES,
17 GET_TYPE_FROM_NAME, 17 GET_TYPE_FROM_NAME,
18 INITIALIZE_LOADED_HUNK, 18 INITIALIZE_LOADED_HUNK,
19 IS_HUNK_INITIALIZED, 19 IS_HUNK_INITIALIZED,
20 IS_HUNK_LOADED, 20 IS_HUNK_LOADED,
21 MANGLED_GLOBAL_NAMES, 21 MANGLED_GLOBAL_NAMES,
22 METADATA, 22 METADATA,
23 TYPE_TO_INTERCEPTOR_MAP; 23 TYPE_TO_INTERCEPTOR_MAP;
24 24
25 import '../js_emitter.dart' show NativeGenerator; 25 import '../js_emitter.dart' show NativeGenerator, buildTearOffCode;
26 import '../model.dart'; 26 import '../model.dart';
27 27
28 class ModelEmitter { 28 class ModelEmitter {
29 final Compiler compiler; 29 final Compiler compiler;
30 final Namer namer; 30 final Namer namer;
31 final ConstantEmitter constantEmitter; 31 final ConstantEmitter constantEmitter;
32 32
33 JavaScriptBackend get backend => compiler.backend; 33 JavaScriptBackend get backend => compiler.backend;
34 34
35 /// For deferred loading we communicate the initializers via this global var. 35 /// For deferred loading we communicate the initializers via this global var.
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 } else { 101 } else {
102 nativeBoilerplate = js.js.statement(";"); 102 nativeBoilerplate = js.js.statement(";");
103 } 103 }
104 104
105 js.Expression code = new js.ArrayInitializer(elements); 105 js.Expression code = new js.ArrayInitializer(elements);
106 106
107 return js.js.statement( 107 return js.js.statement(
108 boilerplate, 108 boilerplate,
109 {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap), 109 {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap),
110 'holders': emitHolders(fragment.holders), 110 'holders': emitHolders(fragment.holders),
111 'tearOff': buildTearOffCode(backend),
112 'parseFunctionDescriptor':
113 js.js.statement(parseFunctionDescriptorBoilerplate),
111 'cyclicThrow': 114 'cyclicThrow':
112 backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()), 115 backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()),
113 'outputContainsConstantList': program.outputContainsConstantList, 116 'outputContainsConstantList': program.outputContainsConstantList,
114 'embeddedGlobals': emitEmbeddedGlobals(program), 117 'embeddedGlobals': emitEmbeddedGlobals(program),
115 'constants': emitConstants(fragment.constants), 118 'constants': emitConstants(fragment.constants),
116 'staticNonFinals': 119 'staticNonFinals':
117 emitStaticNonFinalFields(fragment.staticNonFinalFields), 120 emitStaticNonFinalFields(fragment.staticNonFinalFields),
118 'nativeBoilerplate': nativeBoilerplate, 121 'nativeBoilerplate': nativeBoilerplate,
119 'operatorIsPrefix': js.string(namer.operatorIsPrefix), 122 'operatorIsPrefix': js.string(namer.operatorIsPrefix),
120 'eagerClasses': emitEagerClassInitializations(fragment.libraries), 123 'eagerClasses': emitEagerClassInitializations(fragment.libraries),
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 [methods, isChecks, gettersSetters].expand((x) => x); 405 [methods, isChecks, gettersSetters].expand((x) => x);
403 elements.addAll(allMethods.expand(emitInstanceMethod)); 406 elements.addAll(allMethods.expand(emitInstanceMethod));
404 return unparse(compiler, new js.ArrayInitializer(elements)); 407 return unparse(compiler, new js.ArrayInitializer(elements));
405 } 408 }
406 409
407 js.Expression emitLazyInitializer(StaticField field) { 410 js.Expression emitLazyInitializer(StaticField field) {
408 assert(field.isLazy); 411 assert(field.isLazy);
409 return unparse(compiler, field.code); 412 return unparse(compiler, field.code);
410 } 413 }
411 414
412 static final String tearOffBoilerplate = """ 415 static final String parseFunctionDescriptorBoilerplate = r"""
413 function(prototype, tearOffDescriptor) { 416 function parseFunctionDescriptor(proto, name, desc) {
414 prototype[tearOffDescriptor[0]] = tearOffDescriptor[1]; 417 if (desc instanceof Array) {
415 for (var i = 3; i < tearOffDescriptor.length; i += 3) { 418 proto[name] = desc[0];
416 // Copy over the adapter stubs. 419 var funs = [desc[0]];
417 prototype[tearOffDescriptor[i]] = tearOffDescriptor[i + 2]; 420 funs[0].$callName = desc[1];
421 for (var pos = 4; pos < desc.length; pos += 3) {
422 var stub = desc[pos+2];
423 stub.$callName = desc[pos+1];
424 proto[desc[pos]] = stub;
425 funs.push(stub);
426 }
427 if (desc[2] != null) {
428 proto[desc[2]] = tearOff(funs, desc[3], false, name, false);
429 }
430 } else {
431 proto[name] = desc;
418 } 432 }
419 // Build the functions map.
420 var funcs = Object.create(null);
421 for (var i = 3; i < tearOffDescriptor.length; i += 3) {
422 // Copy over the adapter stubs.
423 prototype[tearOffDescriptor[i]] = tearOffDescriptor[i + 2];
424 }
425
426 } 433 }
427 """; 434 """;
428 435
429 Iterable<js.Expression> emitInstanceMethod(Method method) { 436 Iterable<js.Expression> emitInstanceMethod(Method method) {
430 437
431 List<js.Expression> makeNameCodePair(Method method) { 438 List<js.Expression> makeNameCodePair(Method method) {
432 return [js.string(method.name), method.code]; 439 return [js.string(method.name), method.code];
433 } 440 }
434 441
435 List<js.Expression> makeNameCallNameCodeTriplet(AdapterStubMethod stub) { 442 List<js.Expression> makeNameCallNameCodeTriplet(AdapterStubMethod stub) {
436 js.Expression callName = stub.callName == null 443 js.Expression callName = stub.callName == null
437 ? new js.LiteralNull() 444 ? new js.LiteralNull()
438 : js.string(stub.callName); 445 : js.string(stub.callName);
439 return [js.string(stub.name), callName, method.code]; 446 return [js.string(stub.name), callName, method.code];
floitsch 2015/01/30 22:08:39 This should be `stub.code`.
440 } 447 }
441 448
442 if (method is DartMethod) { 449 if (method is DartMethod) {
443 if (method.needsTearOff) { 450 if (method.needsTearOff) {
444 var data = makeNameCodePair(method); 451 // [name, [function, callName, tearOffName, functionType,
452 // stub1_name, stub1_callName, stub1_code, ...]
453 var data = [method.code];
454 data.add(js.string(method.callName));
445 data.add(js.string(method.tearOffName)); 455 data.add(js.string(method.tearOffName));
456 data.add(new js.LiteralNull());
446 data.addAll(method.adapterStubs.expand(makeNameCallNameCodeTriplet)); 457 data.addAll(method.adapterStubs.expand(makeNameCallNameCodeTriplet));
447 return [new js.ArrayInitializer(data)]; 458 return [js.string(method.name), new js.ArrayInitializer(data)];
448 } else { 459 } else {
449 // TODO(floitsch): not the most efficient way... 460 // TODO(floitsch): not the most efficient way...
450 return ([method]..addAll(method.adapterStubs)).expand(makeNameCodePair); 461 return ([method]..addAll(method.adapterStubs)).expand(makeNameCodePair);
451 } 462 }
452 } else { 463 } else {
453 return makeNameCodePair(method); 464 return makeNameCodePair(method);
454 } 465 }
455 } 466 }
456 467
457 Iterable<js.Expression> emitStaticMethod(StaticMethod method) { 468 Iterable<js.Expression> emitStaticMethod(StaticMethod method) {
(...skipping 14 matching lines...) Expand all
472 } 483 }
473 return output; 484 return output;
474 } 485 }
475 486
476 static final String boilerplate = """ 487 static final String boilerplate = """
477 { 488 {
478 // Declare deferred-initializer global. 489 // Declare deferred-initializer global.
479 #deferredInitializer; 490 #deferredInitializer;
480 491
481 !function(start, program) { 492 !function(start, program) {
482 493 var functionCounter = 0;
483 // Initialize holder objects. 494 // Initialize holder objects.
484 #holders; 495 #holders;
485 496
486 function setupProgram() { 497 function setupProgram() {
487 for (var i = 0; i < program.length - 1; i++) { 498 for (var i = 0; i < program.length - 1; i++) {
488 setupLibrary(program[i]); 499 setupLibrary(program[i]);
489 } 500 }
490 setupLazyStatics(program[i]); 501 setupLazyStatics(program[i]);
491 } 502 }
492 503
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 constructor.apply(object, arguments); 572 constructor.apply(object, arguments);
562 return object; 573 return object;
563 }; 574 };
564 575
565 // We store the ensureResolved function on the patch function to make it 576 // We store the ensureResolved function on the patch function to make it
566 // possible to resolve superclass references without constructing instances. 577 // possible to resolve superclass references without constructing instances.
567 patch.ensureResolved = ensureResolved; 578 patch.ensureResolved = ensureResolved;
568 holder[name] = patch; 579 holder[name] = patch;
569 } 580 }
570 581
582 #tearOff;
583
584 #parseFunctionDescriptor;
585
571 function compileConstructor(name, descriptor) { 586 function compileConstructor(name, descriptor) {
572 descriptor = compile(name, descriptor); 587 descriptor = compile(name, descriptor);
573 var prototype = determinePrototype(descriptor); 588 var prototype = determinePrototype(descriptor);
574 var constructor; 589 var constructor;
575 // $mixinFormatDescription. 590 // $mixinFormatDescription.
576 if (typeof descriptor[2] !== 'function') { 591 if (typeof descriptor[2] !== 'function') {
577 constructor = compileMixinConstructor(name, prototype, descriptor); 592 constructor = compileMixinConstructor(name, prototype, descriptor);
578 for (var i = 4; i < descriptor.length; i += 2) { 593 for (var i = 4; i < descriptor.length; i += 2) {
579 prototype[descriptor[i]] = descriptor[i + 1]; 594 parseFunctionDescriptor(prototype, descriptor);
580 } 595 }
581 } else { 596 } else {
582 constructor = descriptor[2]; 597 constructor = descriptor[2];
583 for (var i = 3; i < descriptor.length; i += 2) { 598 for (var i = 3; i < descriptor.length; i += 2) {
584 prototype[descriptor[i]] = descriptor[i + 1]; 599 parseFunctionDescriptor(prototype, descriptor[i], descriptor[i+1]);
floitsch 2015/01/30 22:08:39 Don't remove the spaces of "i + 1".
585 } 600 }
586 } 601 }
587 constructor.builtin\$cls = name; // Needed for RTI. 602 constructor.builtin\$cls = name; // Needed for RTI.
588 constructor.prototype = prototype; 603 constructor.prototype = prototype;
589 prototype[#operatorIsPrefix + name] = constructor; 604 prototype[#operatorIsPrefix + name] = constructor;
590 prototype.constructor = constructor; 605 prototype.constructor = constructor;
591 return constructor; 606 return constructor;
592 } 607 }
593 608
594 function compileMixinConstructor(name, prototype, descriptor) { 609 function compileMixinConstructor(name, prototype, descriptor) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 676
662 var end = Date.now(); 677 var end = Date.now();
663 print('Setup: ' + (end - start) + ' ms.'); 678 print('Setup: ' + (end - start) + ' ms.');
664 679
665 #main(); // Start main. 680 #main(); // Start main.
666 681
667 }(Date.now(), #code) 682 }(Date.now(), #code)
668 }"""; 683 }""";
669 684
670 } 685 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/js_lib/js_helper.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698