| 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) { |
| 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
); |
| 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 | |
| 445 // Initialize holder objects. | 501 // Initialize holder objects. |
| 446 #holders; | 502 #holders; |
| 447 | 503 |
| 448 function setupProgram() { | 504 function setupProgram() { |
| 449 for (var i = 0; i < program.length - 1; i++) { | 505 for (var i = 0; i < program.length - 1; i++) { |
| 450 setupLibrary(program[i]); | 506 setupLibrary(program[i]); |
| 451 } | 507 } |
| 452 setupLazyStatics(program[i]); | 508 setupLazyStatics(program[i]); |
| 453 } | 509 } |
| 454 | 510 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 constructor.apply(object, arguments); | 579 constructor.apply(object, arguments); |
| 524 return object; | 580 return object; |
| 525 }; | 581 }; |
| 526 | 582 |
| 527 // We store the ensureResolved function on the patch function to make it | 583 // We store the ensureResolved function on the patch function to make it |
| 528 // possible to resolve superclass references without constructing instances. | 584 // possible to resolve superclass references without constructing instances. |
| 529 patch.ensureResolved = ensureResolved; | 585 patch.ensureResolved = ensureResolved; |
| 530 holder[name] = patch; | 586 holder[name] = patch; |
| 531 } | 587 } |
| 532 | 588 |
| 589 #tearOff; |
| 590 |
| 591 #parseFunctionDescriptor; |
| 592 |
| 533 function compileConstructor(name, descriptor) { | 593 function compileConstructor(name, descriptor) { |
| 534 descriptor = compile(name, descriptor); | 594 descriptor = compile(name, descriptor); |
| 535 var prototype = determinePrototype(descriptor); | 595 var prototype = determinePrototype(descriptor); |
| 536 var constructor; | 596 var constructor; |
| 537 // $mixinFormatDescription. | 597 // $mixinFormatDescription. |
| 538 if (typeof descriptor[2] !== 'function') { | 598 if (typeof descriptor[2] !== 'function') { |
| 539 constructor = compileMixinConstructor(name, prototype, descriptor); | 599 constructor = compileMixinConstructor(name, prototype, descriptor); |
| 540 for (var i = 4; i < descriptor.length; i += 2) { | 600 for (var i = 4; i < descriptor.length; i += 2) { |
| 541 prototype[descriptor[i]] = descriptor[i + 1]; | 601 parseFunctionDescriptor(prototype, descriptor, descriptor[i + 1]); |
| 542 } | 602 } |
| 543 } else { | 603 } else { |
| 544 constructor = descriptor[2]; | 604 constructor = descriptor[2]; |
| 545 for (var i = 3; i < descriptor.length; i += 2) { | 605 for (var i = 3; i < descriptor.length; i += 2) { |
| 546 prototype[descriptor[i]] = descriptor[i + 1]; | 606 parseFunctionDescriptor(prototype, descriptor[i], descriptor[i + 1]); |
| 547 } | 607 } |
| 548 } | 608 } |
| 549 constructor.builtin\$cls = name; // Needed for RTI. | 609 constructor.builtin\$cls = name; // Needed for RTI. |
| 550 constructor.prototype = prototype; | 610 constructor.prototype = prototype; |
| 551 prototype[#operatorIsPrefix + name] = constructor; | 611 prototype[#operatorIsPrefix + name] = constructor; |
| 552 prototype.constructor = constructor; | 612 prototype.constructor = constructor; |
| 553 return constructor; | 613 return constructor; |
| 554 } | 614 } |
| 555 | 615 |
| 556 function compileMixinConstructor(name, prototype, descriptor) { | 616 function compileMixinConstructor(name, prototype, descriptor) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 623 | 683 |
| 624 var end = Date.now(); | 684 var end = Date.now(); |
| 625 print('Setup: ' + (end - start) + ' ms.'); | 685 print('Setup: ' + (end - start) + ' ms.'); |
| 626 | 686 |
| 627 #main(); // Start main. | 687 #main(); // Start main. |
| 628 | 688 |
| 629 }(Date.now(), #code) | 689 }(Date.now(), #code) |
| 630 }"""; | 690 }"""; |
| 631 | 691 |
| 632 } | 692 } |
| OLD | NEW |