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 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 388 List elements = [js.string(cls.superclassName), | 391 List elements = [js.string(cls.superclassName), |
| 389 js.number(cls.superclassHolderIndex)]; | 392 js.number(cls.superclassHolderIndex)]; |
| 390 | 393 |
| 391 if (cls.isMixinApplication) { | 394 if (cls.isMixinApplication) { |
| 392 MixinApplication mixin = cls; | 395 MixinApplication mixin = cls; |
| 393 elements.add(js.string(mixin.mixinClass.name)); | 396 elements.add(js.string(mixin.mixinClass.name)); |
| 394 elements.add(js.number(mixin.mixinClass.holder.index)); | 397 elements.add(js.number(mixin.mixinClass.holder.index)); |
| 395 } else { | 398 } else { |
| 396 elements.add(_generateConstructor(cls)); | 399 elements.add(_generateConstructor(cls)); |
| 397 } | 400 } |
| 398 Iterable<Method> methods = cls.methods.expand((Method method) { | 401 Iterable<Method> methods = cls.methods; |
| 399 // TODO(floitsch): can there be anything else than a DartMethod? | |
| 400 if (method is DartMethod) { | |
| 401 return [method]..addAll(method.parameterStubs); | |
| 402 } else { | |
| 403 return [method]; | |
| 404 } | |
| 405 }); | |
| 406 Iterable<Method> isChecks = cls.isChecks; | 402 Iterable<Method> isChecks = cls.isChecks; |
| 407 Iterable<Method> gettersSetters = _generateGettersSetters(cls); | 403 Iterable<Method> gettersSetters = _generateGettersSetters(cls); |
| 408 Iterable<Method> allMethods = | 404 Iterable<Method> allMethods = |
| 409 [methods, isChecks, gettersSetters].expand((x) => x); | 405 [methods, isChecks, gettersSetters].expand((x) => x); |
| 410 elements.addAll(allMethods.expand((e) => [js.string(e.name), e.code])); | 406 elements.addAll(allMethods.expand(emitInstanceMethod)); |
| 411 return unparse(compiler, new js.ArrayInitializer(elements)); | 407 return unparse(compiler, new js.ArrayInitializer(elements)); |
| 412 } | 408 } |
| 413 | 409 |
| 414 js.Expression emitLazyInitializer(StaticField field) { | 410 js.Expression emitLazyInitializer(StaticField field) { |
| 415 assert(field.isLazy); | 411 assert(field.isLazy); |
| 416 return unparse(compiler, field.code); | 412 return unparse(compiler, field.code); |
| 417 } | 413 } |
| 418 | 414 |
| 415 static final String parseFunctionDescriptorBoilerplate = r""" | |
| 416 function parseFunctionDescriptor(proto, name, desc) { | |
| 417 if (desc instanceof Array) { | |
|
zarah
2015/02/02 08:20:10
It would be nice with a comment here describing th
| |
| 418 proto[name] = desc[0]; | |
| 419 var funs = [desc[0]]; | |
| 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 // TODO(floitsch): desc[3] should be the reflectionInfo, not | |
| 429 // isIntercepted. | |
| 430 var isIntercepted = desc[3]; | |
| 431 var reflectionInfo = null; | |
| 432 proto[desc[2]] = tearOff(funs, reflectionInfo, false, name, isIntercepted) ; | |
| 433 } | |
| 434 } else { | |
| 435 proto[name] = desc; | |
| 436 } | |
| 437 } | |
| 438 """; | |
| 439 | |
| 440 Iterable<js.Expression> emitInstanceMethod(Method method) { | |
| 441 | |
| 442 List<js.Expression> makeNameCodePair(Method method) { | |
| 443 return [js.string(method.name), method.code]; | |
| 444 } | |
| 445 | |
| 446 List<js.Expression> makeNameCallNameCodeTriplet(ParameterStubMethod stub) { | |
| 447 js.Expression callName = stub.callName == null | |
| 448 ? new js.LiteralNull() | |
| 449 : js.string(stub.callName); | |
| 450 return [js.string(stub.name), callName, stub.code]; | |
| 451 } | |
| 452 | |
| 453 if (method is DartMethod) { | |
| 454 if (method.needsTearOff) { | |
| 455 bool isIntercepted = backend.isInterceptedMethod(method.element); | |
| 456 // [name, [function, callName, tearOffName, functionType, | |
| 457 // stub1_name, stub1_callName, stub1_code, ...] | |
| 458 var data = [method.code]; | |
| 459 data.add(js.string(method.callName)); | |
| 460 data.add(js.string(method.tearOffName)); | |
| 461 // TODO(floitsch): this field should be the type, not the bool if the | |
| 462 // method is intercepted. | |
| 463 // data.add(new js.LiteralNull()); | |
| 464 data.add(new js.LiteralBool(isIntercepted)); | |
| 465 data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet)); | |
| 466 return [js.string(method.name), new js.ArrayInitializer(data)]; | |
| 467 } else { | |
| 468 // TODO(floitsch): not the most efficient way... | |
| 469 return ([method]..addAll(method.parameterStubs)).expand(makeNameCodePair ); | |
|
zarah
2015/02/02 08:20:11
long line.
| |
| 470 } | |
| 471 } else { | |
| 472 return makeNameCodePair(method); | |
| 473 } | |
| 474 } | |
| 475 | |
| 419 Iterable<js.Expression> emitStaticMethod(StaticMethod method) { | 476 Iterable<js.Expression> emitStaticMethod(StaticMethod method) { |
| 420 js.Expression holderIndex = js.number(method.holder.index); | 477 js.Expression holderIndex = js.number(method.holder.index); |
| 421 List<js.Expression> output = <js.Expression>[]; | 478 List<js.Expression> output = <js.Expression>[]; |
| 422 | 479 |
| 423 void _addMethod(Method method) { | 480 void _addMethod(Method method) { |
| 424 js.Expression unparsed = unparse(compiler, method.code); | 481 js.Expression unparsed = unparse(compiler, method.code); |
| 425 output.add(js.string(method.name)); | 482 output.add(js.string(method.name)); |
| 426 output.add(holderIndex); | 483 output.add(holderIndex); |
| 427 output.add(unparsed); | 484 output.add(unparsed); |
| 428 } | 485 } |
| 429 | 486 |
| 430 _addMethod(method); | 487 _addMethod(method); |
| 431 // TODO(floitsch): can there be anything else than a StaticDartMethod? | 488 // TODO(floitsch): can there be anything else than a StaticDartMethod? |
| 432 if (method is StaticDartMethod) { | 489 if (method is StaticDartMethod) { |
| 433 method.parameterStubs.forEach(_addMethod); | 490 method.parameterStubs.forEach(_addMethod); |
| 434 } | 491 } |
| 435 return output; | 492 return output; |
| 436 } | 493 } |
| 437 | 494 |
| 438 static final String boilerplate = """ | 495 static final String boilerplate = """ |
| 439 { | 496 { |
| 440 // Declare deferred-initializer global. | 497 // Declare deferred-initializer global. |
| 441 #deferredInitializer; | 498 #deferredInitializer; |
| 442 | 499 |
| 443 !function(start, program) { | 500 !function(start, program) { |
| 444 | 501 var functionCounter = 0; |
| 445 // Initialize holder objects. | 502 // Initialize holder objects. |
| 446 #holders; | 503 #holders; |
| 447 | 504 |
| 448 function setupProgram() { | 505 function setupProgram() { |
| 449 for (var i = 0; i < program.length - 1; i++) { | 506 for (var i = 0; i < program.length - 1; i++) { |
| 450 setupLibrary(program[i]); | 507 setupLibrary(program[i]); |
| 451 } | 508 } |
| 452 setupLazyStatics(program[i]); | 509 setupLazyStatics(program[i]); |
| 453 } | 510 } |
| 454 | 511 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 523 constructor.apply(object, arguments); | 580 constructor.apply(object, arguments); |
| 524 return object; | 581 return object; |
| 525 }; | 582 }; |
| 526 | 583 |
| 527 // We store the ensureResolved function on the patch function to make it | 584 // We store the ensureResolved function on the patch function to make it |
| 528 // possible to resolve superclass references without constructing instances. | 585 // possible to resolve superclass references without constructing instances. |
| 529 patch.ensureResolved = ensureResolved; | 586 patch.ensureResolved = ensureResolved; |
| 530 holder[name] = patch; | 587 holder[name] = patch; |
| 531 } | 588 } |
| 532 | 589 |
| 590 #tearOff; | |
| 591 | |
| 592 #parseFunctionDescriptor; | |
| 593 | |
| 533 function compileConstructor(name, descriptor) { | 594 function compileConstructor(name, descriptor) { |
| 534 descriptor = compile(name, descriptor); | 595 descriptor = compile(name, descriptor); |
| 535 var prototype = determinePrototype(descriptor); | 596 var prototype = determinePrototype(descriptor); |
| 536 var constructor; | 597 var constructor; |
| 537 // $mixinFormatDescription. | 598 // $mixinFormatDescription. |
| 538 if (typeof descriptor[2] !== 'function') { | 599 if (typeof descriptor[2] !== 'function') { |
| 539 constructor = compileMixinConstructor(name, prototype, descriptor); | 600 constructor = compileMixinConstructor(name, prototype, descriptor); |
| 540 for (var i = 4; i < descriptor.length; i += 2) { | 601 for (var i = 4; i < descriptor.length; i += 2) { |
| 541 prototype[descriptor[i]] = descriptor[i + 1]; | 602 parseFunctionDescriptor(prototype, descriptor); |
| 542 } | 603 } |
| 543 } else { | 604 } else { |
| 544 constructor = descriptor[2]; | 605 constructor = descriptor[2]; |
| 545 for (var i = 3; i < descriptor.length; i += 2) { | 606 for (var i = 3; i < descriptor.length; i += 2) { |
| 546 prototype[descriptor[i]] = descriptor[i + 1]; | 607 parseFunctionDescriptor(prototype, descriptor[i], descriptor[i+1]); |
| 547 } | 608 } |
| 548 } | 609 } |
| 549 constructor.builtin\$cls = name; // Needed for RTI. | 610 constructor.builtin\$cls = name; // Needed for RTI. |
| 550 constructor.prototype = prototype; | 611 constructor.prototype = prototype; |
| 551 prototype[#operatorIsPrefix + name] = constructor; | 612 prototype[#operatorIsPrefix + name] = constructor; |
| 552 prototype.constructor = constructor; | 613 prototype.constructor = constructor; |
| 553 return constructor; | 614 return constructor; |
| 554 } | 615 } |
| 555 | 616 |
| 556 function compileMixinConstructor(name, prototype, descriptor) { | 617 function compileMixinConstructor(name, prototype, descriptor) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 623 | 684 |
| 624 var end = Date.now(); | 685 var end = Date.now(); |
| 625 print('Setup: ' + (end - start) + ' ms.'); | 686 print('Setup: ' + (end - start) + ' ms.'); |
| 626 | 687 |
| 627 #main(); // Start main. | 688 #main(); // Start main. |
| 628 | 689 |
| 629 }(Date.now(), #code) | 690 }(Date.now(), #code) |
| 630 }"""; | 691 }"""; |
| 631 | 692 |
| 632 } | 693 } |
| OLD | NEW |