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, |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |