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 |