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 '../../constants/values.dart' show ConstantValue, FunctionConstantValue; | 7 import '../../constants/values.dart' show ConstantValue, FunctionConstantValue; |
| 8 import '../../dart2jslib.dart' show Compiler; | 8 import '../../dart2jslib.dart' show Compiler; |
| 9 import '../../dart_types.dart' show DartType; | 9 import '../../dart_types.dart' show DartType; |
| 10 import '../../elements/elements.dart' show ClassElement, FunctionElement; | 10 import '../../elements/elements.dart' show ClassElement, FunctionElement; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 61 this.constantEmitter = new ConstantEmitter( | 61 this.constantEmitter = new ConstantEmitter( |
| 62 compiler, namer, this.generateConstantReference, | 62 compiler, namer, this.generateConstantReference, |
| 63 makeConstantListTemplate); | 63 makeConstantListTemplate); |
| 64 } | 64 } |
| 65 | 65 |
| 66 js.Expression generateEmbeddedGlobalAccess(String global) { | 66 js.Expression generateEmbeddedGlobalAccess(String global) { |
| 67 // TODO(floitsch): We should not use "init" for globals. | 67 // TODO(floitsch): We should not use "init" for globals. |
| 68 return js.js("init.$global"); | 68 return js.js("init.$global"); |
| 69 } | 69 } |
| 70 | 70 |
| 71 String generateEmbeddedGlobalAccessString(String global) { | |
| 72 // TODO(floitsch): We should not use "init" for globals. | |
| 73 return "init.$global"; | |
| 74 } | |
| 75 | |
| 71 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) { | 76 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) { |
| 72 if (constant.isFunction) return true; // Already emitted. | 77 if (constant.isFunction) return true; // Already emitted. |
| 73 if (constant.isPrimitive) return true; // Inlined. | 78 if (constant.isPrimitive) return true; // Inlined. |
| 74 if (constant.isDummy) return true; // Inlined. | 79 if (constant.isDummy) return true; // Inlined. |
| 75 // The name is null when the constant is already a JS constant. | 80 // The name is null when the constant is already a JS constant. |
| 76 // TODO(floitsch): every constant should be registered, so that we can | 81 // TODO(floitsch): every constant should be registered, so that we can |
| 77 // share the ones that take up too much space (like some strings). | 82 // share the ones that take up too much space (like some strings). |
| 78 if (namer.constantName(constant) == null) return true; | 83 if (namer.constantName(constant) == null) return true; |
| 79 return false; | 84 return false; |
| 80 } | 85 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 125 int emitProgram(Program program) { | 130 int emitProgram(Program program) { |
| 126 List<Fragment> fragments = program.fragments; | 131 List<Fragment> fragments = program.fragments; |
| 127 MainFragment mainFragment = fragments.first; | 132 MainFragment mainFragment = fragments.first; |
| 128 | 133 |
| 129 int totalSize = 0; | 134 int totalSize = 0; |
| 130 | 135 |
| 131 // We have to emit the deferred fragments first, since we need their | 136 // We have to emit the deferred fragments first, since we need their |
| 132 // deferred hash (which depends on the output) when emitting the main | 137 // deferred hash (which depends on the output) when emitting the main |
| 133 // fragment. | 138 // fragment. |
| 134 fragments.skip(1).forEach((DeferredFragment deferredUnit) { | 139 fragments.skip(1).forEach((DeferredFragment deferredUnit) { |
| 135 js.Expression ast = emitDeferredFragment(deferredUnit, program.holders); | 140 List<String> types = program.metadataTypes[deferredUnit.outputUnit]; |
| 141 js.Expression ast = emitDeferredFragment(types, deferredUnit, | |
| 142 program.holders); | |
| 136 String code = js.prettyPrint(ast, compiler).getText(); | 143 String code = js.prettyPrint(ast, compiler).getText(); |
| 137 totalSize += code.length; | 144 totalSize += code.length; |
| 138 compiler.outputProvider(deferredUnit.outputFileName, deferredExtension) | 145 compiler.outputProvider(deferredUnit.outputFileName, deferredExtension) |
| 139 ..add(code) | 146 ..add(code) |
| 140 ..close(); | 147 ..close(); |
| 141 }); | 148 }); |
| 142 | 149 |
| 143 js.Statement mainAst = emitMainFragment(program); | 150 js.Statement mainAst = emitMainFragment(program); |
| 144 String mainCode = js.prettyPrint(mainAst, compiler).getText(); | 151 String mainCode = js.prettyPrint(mainAst, compiler).getText(); |
| 145 compiler.outputProvider(mainFragment.outputFileName, 'js') | 152 compiler.outputProvider(mainFragment.outputFileName, 'js') |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 377 js.Expression isHunkLoadedFunction = | 384 js.Expression isHunkLoadedFunction = |
| 378 js.js("function(hash) { return !!$deferredInitializersGlobal[hash]; }"); | 385 js.js("function(hash) { return !!$deferredInitializersGlobal[hash]; }"); |
| 379 globals.add(new js.Property(js.string(IS_HUNK_LOADED), | 386 globals.add(new js.Property(js.string(IS_HUNK_LOADED), |
| 380 isHunkLoadedFunction)); | 387 isHunkLoadedFunction)); |
| 381 | 388 |
| 382 js.Expression isHunkInitializedFunction = | 389 js.Expression isHunkInitializedFunction = |
| 383 js.js("function(hash) { return false; }"); | 390 js.js("function(hash) { return false; }"); |
| 384 globals.add(new js.Property(js.string(IS_HUNK_INITIALIZED), | 391 globals.add(new js.Property(js.string(IS_HUNK_INITIALIZED), |
| 385 isHunkInitializedFunction)); | 392 isHunkInitializedFunction)); |
| 386 | 393 |
| 394 String typesAccess = generateEmbeddedGlobalAccessString(TYPES); | |
| 395 | |
| 387 /// See [emitEmbeddedGlobalsForDeferredLoading] for the format of the | 396 /// See [emitEmbeddedGlobalsForDeferredLoading] for the format of the |
| 388 /// deferred hunk. | 397 /// deferred hunk. |
| 389 js.Expression initializeLoadedHunkFunction = | 398 js.Expression initializeLoadedHunkFunction = |
| 390 js.js(""" | 399 js.js(""" |
| 391 function(hash) { | 400 function(hash) { |
| 392 var hunk = $deferredInitializersGlobal[hash]; | 401 var hunk = $deferredInitializersGlobal[hash]; |
| 393 $setupProgramName(hunk[0]); | 402 $setupProgramName(hunk[0], ${typesAccess}.length); |
|
sigurdm
2015/04/09 13:00:15
Why not
$setupProgramName(hunk[0], #typesAcces
zarah
2015/04/10 10:56:03
Done.
| |
| 394 eval(hunk[1]); | 403 eval(hunk[1]); |
| 404 var deferredTypes = eval(hunk[2]); | |
| 405 ${typesAccess}.push.apply(${typesAccess}, deferredTypes); | |
| 395 }"""); | 406 }"""); |
| 396 | 407 |
| 397 globals.add(new js.Property(js.string(INITIALIZE_LOADED_HUNK), | 408 globals.add(new js.Property(js.string(INITIALIZE_LOADED_HUNK), |
| 398 initializeLoadedHunkFunction)); | 409 initializeLoadedHunkFunction)); |
| 399 | 410 |
| 400 return globals; | 411 return globals; |
| 401 } | 412 } |
| 402 | 413 |
| 403 js.Property emitGetTypeFromName() { | 414 js.Property emitGetTypeFromName() { |
| 404 js.Expression function = | 415 js.Expression function = |
| 405 js.js( """function(name) { | 416 js.js( """function(name) { |
| 406 return holdersMap[name][name].ensureResolved(); | 417 return holdersMap[name][name].ensureResolved(); |
| 407 }"""); | 418 }"""); |
| 408 return new js.Property(js.string(GET_TYPE_FROM_NAME), function); | 419 return new js.Property(js.string(GET_TYPE_FROM_NAME), function); |
| 409 } | 420 } |
| 410 | 421 |
| 411 List<js.Property> emitMetadata(Program program) { | 422 List<js.Property> emitMetadata(Program program) { |
| 412 | 423 |
| 413 List<js.Property> metadataGlobals = <js.Property>[]; | 424 List<js.Property> metadataGlobals = <js.Property>[]; |
| 414 | 425 |
| 415 js.Property createGlobal(List<String> list, String global) { | 426 js.Property createGlobal(List<String> list, String global) { |
| 416 String listAsString = "[${list.join(",")}]"; | 427 String listAsString = "[${list.join(",")}]"; |
| 417 js.Expression metadata = | 428 js.Expression metadata = |
| 418 js.js.uncachedExpressionTemplate(listAsString).instantiate([]); | 429 js.js.uncachedExpressionTemplate(listAsString).instantiate([]); |
| 419 return new js.Property(js.string(global), metadata); | 430 return new js.Property(js.string(global), metadata); |
| 420 } | 431 } |
| 421 | 432 |
| 422 metadataGlobals.add(createGlobal(program.metadata, METADATA)); | 433 metadataGlobals.add(createGlobal(program.metadata, METADATA)); |
| 423 metadataGlobals.add(createGlobal(program.metadataTypes, TYPES)); | 434 List<String> types = |
| 435 program.metadataTypes[program.fragments.first.outputUnit]; | |
| 436 if (types == null) types = <String>[]; | |
| 437 metadataGlobals.add(createGlobal(types, TYPES)); | |
| 424 | 438 |
| 425 return metadataGlobals; | 439 return metadataGlobals; |
| 426 } | 440 } |
| 427 | 441 |
| 428 js.Expression emitDeferredFragment(DeferredFragment fragment, | 442 js.Expression emitDeferredFragment(List<String> types, |
| 443 DeferredFragment fragment, | |
| 429 List<Holder> holders) { | 444 List<Holder> holders) { |
| 430 // TODO(floitsch): initialize eager classes. | 445 // TODO(floitsch): initialize eager classes. |
| 431 // TODO(floitsch): the hash must depend on the output. | 446 // TODO(floitsch): the hash must depend on the output. |
| 432 int hash = fragment.hashCode; | 447 int hash = fragment.hashCode; |
| 433 | 448 |
| 434 List<js.Expression> deferredCode = | 449 List<js.Expression> deferredCode = |
| 435 fragment.libraries.map(emitLibrary).toList(); | 450 fragment.libraries.map(emitLibrary).toList(); |
| 436 | 451 |
| 437 deferredCode.add( | 452 deferredCode.add( |
| 438 emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields)); | 453 emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields)); |
| 439 | 454 |
| 440 deferredCode.add(emitConstants(fragment.constants)); | 455 deferredCode.add(emitConstants(fragment.constants)); |
| 441 | 456 |
| 442 js.ArrayInitializer deferredArray = new js.ArrayInitializer(deferredCode); | 457 js.ArrayInitializer deferredArray = new js.ArrayInitializer(deferredCode); |
| 443 | 458 |
| 444 // This is the code that must be evaluated after all deferred classes have | 459 // This is the code that must be evaluated after all deferred classes have |
| 445 // been setup. | 460 // been setup. |
| 446 js.Statement immediateCode = | 461 js.Statement immediateCode = |
| 447 emitEagerClassInitializations(fragment.libraries); | 462 emitEagerClassInitializations(fragment.libraries); |
| 448 | 463 |
| 449 js.LiteralString immediateString = unparse(compiler, immediateCode); | 464 js.LiteralString immediateString = unparse(compiler, immediateCode); |
| 465 | |
| 466 js.Expression deferredTypes = types == null | |
| 467 ? js.string("[]") | |
| 468 : js.string("[${types.join(",")}]"); | |
| 469 | |
| 450 js.ArrayInitializer hunk = | 470 js.ArrayInitializer hunk = |
| 451 new js.ArrayInitializer([deferredArray, immediateString]); | 471 new js.ArrayInitializer([deferredArray, immediateString, |
| 472 deferredTypes]); | |
| 452 | 473 |
| 453 return js.js("$deferredInitializersGlobal[$hash] = #", hunk); | 474 return js.js("$deferredInitializersGlobal[$hash] = #", hunk); |
| 454 } | 475 } |
| 455 | 476 |
| 456 // This string should be referenced wherever JavaScript code makes assumptions | 477 // This string should be referenced wherever JavaScript code makes assumptions |
| 457 // on the constants format. | 478 // on the constants format. |
| 458 static final String constantsDescription = | 479 static final String constantsDescription = |
| 459 "The constants are encoded as a follows:" | 480 "The constants are encoded as a follows:" |
| 460 " [constantsHolderIndex, name, code, name2, code2, ...]." | 481 " [constantsHolderIndex, name, code, name2, code2, ...]." |
| 461 "The array is completely empty if there is no constant at all."; | 482 "The array is completely empty if there is no constant at all."; |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 656 /// | 677 /// |
| 657 /// for each stub in [DartMethod.parameterStubs]. | 678 /// for each stub in [DartMethod.parameterStubs]. |
| 658 /// | 679 /// |
| 659 /// If the closure could be used in `Function.apply` (i.e. | 680 /// If the closure could be used in `Function.apply` (i.e. |
| 660 /// [DartMethod.canBeApplied] is true) then the following fields are appended: | 681 /// [DartMethod.canBeApplied] is true) then the following fields are appended: |
| 661 /// | 682 /// |
| 662 /// * [DartMethod.requiredParameterCount] | 683 /// * [DartMethod.requiredParameterCount] |
| 663 /// * [DartMethod.optionalParameterDefaultValues] | 684 /// * [DartMethod.optionalParameterDefaultValues] |
| 664 | 685 |
| 665 static final String parseFunctionDescriptorBoilerplate = r""" | 686 static final String parseFunctionDescriptorBoilerplate = r""" |
| 666 function parseFunctionDescriptor(proto, name, descriptor) { | 687 function parseFunctionDescriptor(proto, name, descriptor, typesOffset) { |
| 667 if (descriptor instanceof Array) { | 688 if (descriptor instanceof Array) { |
| 668 // 'pos' points to the last read entry. | 689 // 'pos' points to the last read entry. |
| 669 var f, pos = -1; | 690 var f, pos = -1; |
| 670 var aliasOrFunction = descriptor[++pos]; | 691 var aliasOrFunction = descriptor[++pos]; |
| 671 if (typeof aliasOrFunction == "string") { | 692 if (typeof aliasOrFunction == "string") { |
| 672 // Install the alias for super calls on the prototype chain. | 693 // Install the alias for super calls on the prototype chain. |
| 673 proto[aliasOrFunction] = f = descriptor[++pos]; | 694 proto[aliasOrFunction] = f = descriptor[++pos]; |
| 674 } else { | 695 } else { |
| 675 f = aliasOrFunction; | 696 f = aliasOrFunction; |
| 676 } | 697 } |
| 677 | 698 |
| 678 proto[name] = f; | 699 proto[name] = f; |
| 679 var funs = [f]; | 700 var funs = [f]; |
| 680 f[#callName] = descriptor[++pos]; | 701 f[#callName] = descriptor[++pos]; |
| 681 | 702 |
| 682 var isInterceptedOrParameterStubName = descriptor[pos + 1]; | 703 var isInterceptedOrParameterStubName = descriptor[pos + 1]; |
| 683 var isIntercepted, tearOffName, reflectionInfo; | 704 var isIntercepted, tearOffName, reflectionInfo; |
| 684 if (typeof isInterceptedOrParameterStubName == "boolean") { | 705 if (typeof isInterceptedOrParameterStubName == "boolean") { |
| 685 isIntercepted = descriptor[++pos]; | 706 isIntercepted = descriptor[++pos]; |
| 686 tearOffName = descriptor[++pos]; | 707 tearOffName = descriptor[++pos]; |
| 687 reflectionInfo = descriptor[++pos]; | 708 reflectionInfo = descriptor[++pos]; |
| 709 if (typeof reflectionInfo == "number") { | |
| 710 reflectionInfo = reflectionInfo + typesOffset; | |
| 711 } | |
| 688 } | 712 } |
| 689 | 713 |
| 690 // We iterate in blocks of 3 but have to stop before we reach the (optional) | 714 // We iterate in blocks of 3 but have to stop before we reach the (optional) |
| 691 // two trailing items. To accomplish this, we only iterate until we reach | 715 // two trailing items. To accomplish this, we only iterate until we reach |
| 692 // length - 2. | 716 // length - 2. |
| 693 for (++pos; pos < descriptor.length - 2; pos += 3) { | 717 for (++pos; pos < descriptor.length - 2; pos += 3) { |
| 694 var stub = descriptor[pos + 2]; | 718 var stub = descriptor[pos + 2]; |
| 695 stub[#callName] = descriptor[pos + 1]; | 719 stub[#callName] = descriptor[pos + 1]; |
| 696 proto[descriptor[pos]] = stub; | 720 proto[descriptor[pos]] = stub; |
| 697 funs.push(stub); | 721 funs.push(stub); |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 832 #deferredInitializer; | 856 #deferredInitializer; |
| 833 | 857 |
| 834 !function(start, program) { | 858 !function(start, program) { |
| 835 // Initialize holder objects. | 859 // Initialize holder objects. |
| 836 #holders; | 860 #holders; |
| 837 var nativeInfos = Object.create(null); | 861 var nativeInfos = Object.create(null); |
| 838 | 862 |
| 839 // Counter to generate unique names for tear offs. | 863 // Counter to generate unique names for tear offs. |
| 840 var functionCounter = 0; | 864 var functionCounter = 0; |
| 841 | 865 |
| 842 function $setupProgramName(program) { | 866 function $setupProgramName(program, typesOffset) { |
| 843 for (var i = 0; i < program.length - 2; i++) { | 867 for (var i = 0; i < program.length - 2; i++) { |
| 844 setupLibrary(program[i]); | 868 setupLibrary(program[i], typesOffset); |
| 845 } | 869 } |
| 846 setupLazyStatics(program[i]); | 870 setupLazyStatics(program[i]); |
| 847 setupConstants(program[i + 1]); | 871 setupConstants(program[i + 1]); |
| 848 } | 872 } |
| 849 | 873 |
| 850 function setupLibrary(library) { | 874 function setupLibrary(library, typesOffset) { |
| 851 var statics = library[0]; | 875 var statics = library[0]; |
| 852 for (var i = 0; i < statics.length; i += 3) { | 876 for (var i = 0; i < statics.length; i += 3) { |
| 853 var holderIndex = statics[i + 1]; | 877 var holderIndex = statics[i + 1]; |
| 854 setupStatic(statics[i], holders[holderIndex], statics[i + 2]); | 878 setupStatic(statics[i], holders[holderIndex], statics[i + 2], |
| 879 typesOffset); | |
| 855 } | 880 } |
| 856 | 881 |
| 857 var classes = library[1]; | 882 var classes = library[1]; |
| 858 for (var i = 0; i < classes.length; i += 3) { | 883 for (var i = 0; i < classes.length; i += 3) { |
| 859 var name = classes[i]; | 884 var name = classes[i]; |
| 860 var cls = classes[i + 1]; | 885 var cls = classes[i + 1]; |
| 861 | 886 |
| 862 if (#needsNativeSupport) { | 887 if (#needsNativeSupport) { |
| 863 // $nativeInfoDescription. | 888 // $nativeInfoDescription. |
| 864 var indexOrNativeInfo = classes[i + 2]; | 889 var indexOrNativeInfo = classes[i + 2]; |
| 865 if (typeof indexOrNativeInfo == "number") { | 890 if (typeof indexOrNativeInfo == "number") { |
| 866 var holderIndex = classes[i + 2]; | 891 var holderIndex = classes[i + 2]; |
| 867 } else { | 892 } else { |
| 868 nativeInfos[name] = indexOrNativeInfo; | 893 nativeInfos[name] = indexOrNativeInfo; |
| 869 holderIndex = classes[i + 3]; | 894 holderIndex = classes[i + 3]; |
| 870 i++; | 895 i++; |
| 871 } | 896 } |
| 872 } | 897 } |
| 873 | 898 |
| 874 if (#needsNoNativeSupport) { | 899 if (#needsNoNativeSupport) { |
| 875 var holderIndex = classes[i + 2]; | 900 var holderIndex = classes[i + 2]; |
| 876 } | 901 } |
| 877 | 902 |
| 878 holdersMap[name] = holders[holderIndex]; | 903 holdersMap[name] = holders[holderIndex]; |
| 879 setupClass(name, holders[holderIndex], cls); | 904 setupClass(name, holders[holderIndex], cls, typesOffset); |
| 880 } | 905 } |
| 881 } | 906 } |
| 882 | 907 |
| 883 function setupLazyStatics(statics) { | 908 function setupLazyStatics(statics) { |
| 884 for (var i = 0; i < statics.length; i += 4) { | 909 for (var i = 0; i < statics.length; i += 4) { |
| 885 var name = statics[i]; | 910 var name = statics[i]; |
| 886 var getterName = statics[i + 1]; | 911 var getterName = statics[i + 1]; |
| 887 var holderIndex = statics[i + 2]; | 912 var holderIndex = statics[i + 2]; |
| 888 var initializer = statics[i + 3]; | 913 var initializer = statics[i + 3]; |
| 889 setupLazyStatic(name, getterName, holders[holderIndex], initializer); | 914 setupLazyStatic(name, getterName, holders[holderIndex], initializer); |
| 890 } | 915 } |
| 891 } | 916 } |
| 892 | 917 |
| 893 function setupConstants(constants) { | 918 function setupConstants(constants) { |
| 894 // $constantsDescription. | 919 // $constantsDescription. |
| 895 if (constants.length == 0) return; | 920 if (constants.length == 0) return; |
| 896 // We assume that all constants are in the same holder. | 921 // We assume that all constants are in the same holder. |
| 897 var holder = holders[constants[0]]; | 922 var holder = holders[constants[0]]; |
| 898 for (var i = 1; i < constants.length; i += 2) { | 923 for (var i = 1; i < constants.length; i += 2) { |
| 899 var name = constants[i]; | 924 var name = constants[i]; |
| 900 var initializer = constants[i + 1]; | 925 var initializer = constants[i + 1]; |
| 901 setupConstant(name, holder, initializer); | 926 setupConstant(name, holder, initializer); |
| 902 } | 927 } |
| 903 } | 928 } |
| 904 | 929 |
| 905 function setupStatic(name, holder, descriptor) { | 930 function setupStatic(name, holder, descriptor, typesOffset) { |
| 906 if (typeof descriptor == 'string') { | 931 if (typeof descriptor == 'string') { |
| 907 holder[name] = function() { | 932 holder[name] = function() { |
| 908 if (descriptor == null) { | 933 if (descriptor == null) { |
| 909 // Already compiled. This happens when we have calls to the static as | 934 // Already compiled. This happens when we have calls to the static as |
| 910 // arguments to the static: `foo(foo(499))`; | 935 // arguments to the static: `foo(foo(499))`; |
| 911 return holder[name].apply(this, arguments); | 936 return holder[name].apply(this, arguments); |
| 912 } | 937 } |
| 913 var method = compile(name, descriptor); | 938 var method = compile(name, descriptor); |
| 914 holder[name] = method; | 939 holder[name] = method; |
| 915 descriptor = null; // GC the descriptor. | 940 descriptor = null; // GC the descriptor. |
| 916 return method.apply(this, arguments); | 941 return method.apply(this, arguments); |
| 917 }; | 942 }; |
| 918 } else { | 943 } else { |
| 919 // Parse the tear off information and generate compile handlers. | 944 // Parse the tear off information and generate compile handlers. |
| 920 // TODO(herhut): Share parser with instance methods. | 945 // TODO(herhut): Share parser with instance methods. |
| 921 function compileAllStubs() { | 946 function compileAllStubs(typesOffset) { |
| 922 var funs; | 947 var funs; |
| 923 var fun = compile(name, descriptor[0]); | 948 var fun = compile(name, descriptor[0]); |
| 924 fun[#callName] = descriptor[1]; | 949 fun[#callName] = descriptor[1]; |
| 925 holder[name] = fun; | 950 holder[name] = fun; |
| 926 funs = [fun]; | 951 funs = [fun]; |
| 927 // We iterate in blocks of 3 but have to stop before we reach the | 952 // We iterate in blocks of 3 but have to stop before we reach the |
| 928 // (optional) two trailing items. To accomplish this, we only iterate | 953 // (optional) two trailing items. To accomplish this, we only iterate |
| 929 // until we reach length - 2. | 954 // until we reach length - 2. |
| 930 for (var pos = 4; pos < descriptor.length - 2; pos += 3) { | 955 for (var pos = 4; pos < descriptor.length - 2; pos += 3) { |
| 931 var stubName = descriptor[pos]; | 956 var stubName = descriptor[pos]; |
| 932 fun = compile(stubName, descriptor[pos + 2]); | 957 fun = compile(stubName, descriptor[pos + 2]); |
| 933 fun[#callName] = descriptor[pos + 1]; | 958 fun[#callName] = descriptor[pos + 1]; |
| 934 holder[stubName] = fun; | 959 holder[stubName] = fun; |
| 935 funs.push(fun); | 960 funs.push(fun); |
| 936 } | 961 } |
| 937 if (descriptor[2] != null) { // tear-off name. | 962 if (descriptor[2] != null) { // tear-off name. |
| 938 // functions, reflectionInfo, isStatic, name, isIntercepted. | 963 // functions, reflectionInfo, isStatic, name, isIntercepted. |
| 964 var reflectionInfo = descriptor[3]; | |
| 965 if (typeof reflectionInfo == "number") { | |
| 966 reflectionInfo = reflectionInfo + typesOffset; | |
| 967 } | |
| 939 holder[descriptor[2]] = | 968 holder[descriptor[2]] = |
| 940 tearOff(funs, descriptor[3], true, name, false); | 969 tearOff(funs, reflectionInfo, true, name, false); |
| 941 } | 970 } |
| 942 if (pos < descriptor.length) { | 971 if (pos < descriptor.length) { |
| 943 fun[#argumentCount] = descriptor[pos]; | 972 fun[#argumentCount] = descriptor[pos]; |
| 944 fun[#defaultArgumentValues] = descriptor[pos + 1]; | 973 fun[#defaultArgumentValues] = descriptor[pos + 1]; |
| 945 } | 974 } |
| 946 } | 975 } |
| 947 | 976 |
| 948 function setupCompileAllAndDelegateStub(name) { | 977 function setupCompileAllAndDelegateStub(name, typesOffset) { |
| 949 holder[name] = function() { | 978 holder[name] = function() { |
| 950 // The descriptor is null if we already compiled this function. This | 979 // The descriptor is null if we already compiled this function. This |
| 951 // happens when we have calls to the static as arguments to the | 980 // happens when we have calls to the static as arguments to the |
| 952 // static: `foo(foo(499))`; | 981 // static: `foo(foo(499))`; |
| 953 if (descriptor != null) { | 982 if (descriptor != null) { |
| 954 compileAllStubs(); | 983 compileAllStubs(typesOffset); |
| 955 descriptor = null; // GC the descriptor. | 984 descriptor = null; // GC the descriptor. |
| 956 } | 985 } |
| 957 return holder[name].apply(this, arguments); | 986 return holder[name].apply(this, arguments); |
| 958 }; | 987 }; |
| 959 } | 988 } |
| 960 | 989 |
| 961 setupCompileAllAndDelegateStub(name); | 990 setupCompileAllAndDelegateStub(name, typesOffset); |
| 962 for (var pos = 4; pos < descriptor.length; pos += 3) { | 991 for (var pos = 4; pos < descriptor.length; pos += 3) { |
| 963 setupCompileAllAndDelegateStub(descriptor[pos]); | 992 setupCompileAllAndDelegateStub(descriptor[pos], typesOffset); |
| 964 } | 993 } |
| 965 if (descriptor[2] != null) { // tear-off name. | 994 if (descriptor[2] != null) { // tear-off name. |
| 966 setupCompileAllAndDelegateStub(descriptor[2]) | 995 setupCompileAllAndDelegateStub(descriptor[2], typesOffset) |
| 967 } | 996 } |
| 968 } | 997 } |
| 969 } | 998 } |
| 970 | 999 |
| 971 function setupLazyStatic(name, getterName, holder, descriptor) { | 1000 function setupLazyStatic(name, getterName, holder, descriptor) { |
| 972 holder[name] = null; | 1001 holder[name] = null; |
| 973 holder[getterName] = function() { | 1002 holder[getterName] = function() { |
| 974 var initializer = compile(name, descriptor); | 1003 var initializer = compile(name, descriptor); |
| 975 holder[getterName] = function() { #cyclicThrow(name) }; | 1004 holder[getterName] = function() { #cyclicThrow(name) }; |
| 976 var result; | 1005 var result; |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 999 holder[name] = function() { | 1028 holder[name] = function() { |
| 1000 if (descriptor !== null) { | 1029 if (descriptor !== null) { |
| 1001 c = compile(name, descriptor); | 1030 c = compile(name, descriptor); |
| 1002 name = null; | 1031 name = null; |
| 1003 descriptor = null; | 1032 descriptor = null; |
| 1004 } | 1033 } |
| 1005 return c; | 1034 return c; |
| 1006 }; | 1035 }; |
| 1007 } | 1036 } |
| 1008 | 1037 |
| 1009 function setupClass(name, holder, descriptor) { | 1038 function setupClass(name, holder, descriptor, typesOffset) { |
| 1010 var patch = function() { | 1039 var patch = function() { |
| 1011 if (patch.ensureResolved == patch) { | 1040 if (patch.ensureResolved == patch) { |
| 1012 // We have not yet been compiled. | 1041 // We have not yet been compiled. |
| 1013 var constructor = compileConstructor(name, descriptor); | 1042 var constructor = compileConstructor(name, descriptor, typesOffset); |
| 1014 holder[name] = constructor; | 1043 holder[name] = constructor; |
| 1015 name = holder = descriptor = null; // GC the captured arguments. | 1044 name = holder = descriptor = null; // GC the captured arguments. |
| 1016 // Make sure we can invoke 'ensureResolved' multiple times on the patch | 1045 // Make sure we can invoke 'ensureResolved' multiple times on the patch |
| 1017 // function. | 1046 // function. |
| 1018 patch.ensureResolved = function() { return constructor; }; | 1047 patch.ensureResolved = function() { return constructor; }; |
| 1019 constructor.ensureResolved = function() { return this; }; | 1048 constructor.ensureResolved = function() { return this; }; |
| 1020 } else { | 1049 } else { |
| 1021 // This can happen when arguments to the constructor are of the same | 1050 // This can happen when arguments to the constructor are of the same |
| 1022 // class, like in `new A(new A(null))`. | 1051 // class, like in `new A(new A(null))`. |
| 1023 constructor = patch.ensureResolved(); | 1052 constructor = patch.ensureResolved(); |
| 1024 } | 1053 } |
| 1025 // If the patch has been called as "ensureResolved" return. | 1054 // If the patch has been called as "ensureResolved" return. |
| 1026 if (this === patch) return constructor; | 1055 if (this === patch) return constructor; |
| 1027 var object = new constructor(); | 1056 var object = new constructor(); |
| 1028 constructor.apply(object, arguments); | 1057 constructor.apply(object, arguments); |
| 1029 return object; | 1058 return object; |
| 1030 }; | 1059 }; |
| 1031 | 1060 |
| 1032 // We store the patch function on itself to make it | 1061 // We store the patch function on itself to make it |
| 1033 // possible to resolve superclass references without constructing instances. | 1062 // possible to resolve superclass references without constructing instances. |
| 1034 patch.ensureResolved = patch; | 1063 patch.ensureResolved = patch; |
| 1035 holder[name] = patch; | 1064 holder[name] = patch; |
| 1036 } | 1065 } |
| 1037 | 1066 |
| 1038 #tearOff; | 1067 #tearOff; |
| 1039 | 1068 |
| 1040 #parseFunctionDescriptor; | 1069 #parseFunctionDescriptor; |
| 1041 | 1070 |
| 1042 function compileConstructor(name, descriptor) { | 1071 function compileConstructor(name, descriptor, typesOffset) { |
| 1043 descriptor = compile(name, descriptor); | 1072 descriptor = compile(name, descriptor); |
| 1044 var prototype = determinePrototype(descriptor); | 1073 var prototype = determinePrototype(descriptor); |
| 1045 var constructor; | 1074 var constructor; |
| 1046 var functionsIndex; | 1075 var functionsIndex; |
| 1047 // $mixinFormatDescription. | 1076 // $mixinFormatDescription. |
| 1048 if (typeof descriptor[2] !== 'function') { | 1077 if (typeof descriptor[2] !== 'function') { |
| 1049 fillPrototypeWithMixedIn(descriptor[2], descriptor[3], prototype); | 1078 fillPrototypeWithMixedIn(descriptor[2], descriptor[3], prototype); |
| 1050 // descriptor[4] contains the constructor if the mixin application is | 1079 // descriptor[4] contains the constructor if the mixin application is |
| 1051 // directly instantiated. | 1080 // directly instantiated. |
| 1052 if (typeof descriptor[4] === 'function') { | 1081 if (typeof descriptor[4] === 'function') { |
| 1053 constructor = descriptor[4]; | 1082 constructor = descriptor[4]; |
| 1054 functionsIndex = 5; | 1083 functionsIndex = 5; |
| 1055 } else { | 1084 } else { |
| 1056 constructor = function() {}; | 1085 constructor = function() {}; |
| 1057 functionsIndex = 4; | 1086 functionsIndex = 4; |
| 1058 } | 1087 } |
| 1059 } else { | 1088 } else { |
| 1060 constructor = descriptor[2]; | 1089 constructor = descriptor[2]; |
| 1061 functionsIndex = 3; | 1090 functionsIndex = 3; |
| 1062 } | 1091 } |
| 1063 | 1092 |
| 1064 for (var i = functionsIndex; i < descriptor.length; i += 2) { | 1093 for (var i = functionsIndex; i < descriptor.length; i += 2) { |
| 1065 parseFunctionDescriptor(prototype, descriptor[i], descriptor[i + 1]); | 1094 parseFunctionDescriptor(prototype, descriptor[i], descriptor[i + 1], |
| 1095 typesOffset); | |
| 1066 } | 1096 } |
| 1067 | 1097 |
| 1068 constructor.builtin\$cls = name; // Needed for RTI. | 1098 constructor.builtin\$cls = name; // Needed for RTI. |
| 1069 constructor.prototype = prototype; | 1099 constructor.prototype = prototype; |
| 1070 prototype[#operatorIsPrefix + name] = constructor; | 1100 prototype[#operatorIsPrefix + name] = constructor; |
| 1071 prototype.constructor = constructor; | 1101 prototype.constructor = constructor; |
| 1072 return constructor; | 1102 return constructor; |
| 1073 } | 1103 } |
| 1074 | 1104 |
| 1075 function fillPrototypeWithMixedIn(mixinName, mixinHolderIndex, prototype) { | 1105 function fillPrototypeWithMixedIn(mixinName, mixinHolderIndex, prototype) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1119 if (#needsNativeSupport) { | 1149 if (#needsNativeSupport) { |
| 1120 function handleNativeClassInfos() { | 1150 function handleNativeClassInfos() { |
| 1121 for (var nativeClass in nativeInfos) { | 1151 for (var nativeClass in nativeInfos) { |
| 1122 var constructor = holdersMap[nativeClass][nativeClass].ensureResolved(); | 1152 var constructor = holdersMap[nativeClass][nativeClass].ensureResolved(); |
| 1123 var nativeInfo = nativeInfos[nativeClass]; | 1153 var nativeInfo = nativeInfos[nativeClass]; |
| 1124 #nativeInfoHandler; | 1154 #nativeInfoHandler; |
| 1125 } | 1155 } |
| 1126 } | 1156 } |
| 1127 } | 1157 } |
| 1128 | 1158 |
| 1129 $setupProgramName(program); | 1159 $setupProgramName(program, 0); |
| 1130 | 1160 |
| 1131 // Initialize globals. | 1161 // Initialize globals. |
| 1132 #embeddedGlobals; | 1162 #embeddedGlobals; |
| 1133 | 1163 |
| 1134 // TODO(floitsch): this order means that native classes may not be | 1164 // TODO(floitsch): this order means that native classes may not be |
| 1135 // referenced from constants. I'm mostly afraid of things like using them as | 1165 // referenced from constants. I'm mostly afraid of things like using them as |
| 1136 // generic arguments (which should be fine, but maybe there are other | 1166 // generic arguments (which should be fine, but maybe there are other |
| 1137 // similar things). | 1167 // similar things). |
| 1138 // Initialize natives. | 1168 // Initialize natives. |
| 1139 if (#needsNativeSupport) handleNativeClassInfos(); | 1169 if (#needsNativeSupport) handleNativeClassInfos(); |
| 1140 | 1170 |
| 1141 // Initialize static non-final fields. | 1171 // Initialize static non-final fields. |
| 1142 #staticNonFinals; | 1172 #staticNonFinals; |
| 1143 | 1173 |
| 1144 // Add native boilerplate code. | 1174 // Add native boilerplate code. |
| 1145 #nativeIsolateAffinityTagInitialization; | 1175 #nativeIsolateAffinityTagInitialization; |
| 1146 | 1176 |
| 1147 // Initialize eager classes. | 1177 // Initialize eager classes. |
| 1148 #eagerClasses; | 1178 #eagerClasses; |
| 1149 | 1179 |
| 1150 var end = Date.now(); | 1180 var end = Date.now(); |
| 1151 // print('Setup: ' + (end - start) + ' ms.'); | 1181 // print('Setup: ' + (end - start) + ' ms.'); |
| 1152 | 1182 |
| 1153 #invokeMain; // Start main. | 1183 #invokeMain; // Start main. |
| 1154 | 1184 |
| 1155 }(Date.now(), #code) | 1185 }(Date.now(), #code) |
| 1156 }"""; | 1186 }"""; |
| 1157 | 1187 |
| 1158 } | 1188 } |
| OLD | NEW |