@@ -40,7 +40,7 @@ const mkdirp = require("./util/mkdirp");
4040const find = require ( "./util/find" ) ;
4141const EOL = process . platform === "win32" ? "\r\n" : "\n" ;
4242const SEP = process . platform === "win32" ? "\\" : "/" ;
43- const binaryen = global . Binaryen || ( global . Binaryen = require ( "binaryen" ) ) ;
43+ const binaryen = global . binaryen || ( global . binaryen = require ( "binaryen" ) ) ;
4444
4545// Proxy Binaryen's ready event
4646Object . defineProperty ( exports , "ready" , {
@@ -51,28 +51,38 @@ Object.defineProperty(exports, "ready", {
5151// useless code fragment on top of an actual error. suppress this:
5252if ( process . removeAllListeners ) process . removeAllListeners ( "uncaughtException" ) ;
5353
54- // Use distribution files if present, otherwise run the sources directly
55- var assemblyscript , isDev = false ;
56- try { // `asc` on the command line
57- assemblyscript = require ( "../dist/assemblyscript.js" ) ;
58- } catch ( e ) {
59- try { // `asc` on the command line without dist files
60- require ( "ts-node" ) . register ( {
61- project : path . join ( __dirname , ".." , "src" , "tsconfig.json" ) ,
62- skipIgnore : true ,
63- compilerOptions : { target : "ES2016" }
64- } ) ;
65- require ( "../src/glue/js" ) ;
66- assemblyscript = require ( "../src" ) ;
67- isDev = true ;
68- } catch ( e_ts ) {
69- try { // `require("dist/asc.js")` in explicit browser tests
70- assemblyscript = eval ( "require('./assemblyscript')" ) ;
54+ // Use distribution files if present, otherwise run the sources directly.
55+ var assemblyscript ;
56+ var isDev = false ;
57+ ( function loadAssemblyScript ( ) {
58+ try {
59+ assemblyscript = require ( "assemblyscript" ) ;
60+ } catch ( e ) {
61+ function dynRequire ( ...args ) {
62+ return eval ( "require" ) ( ...args ) ;
63+ }
64+ try { // `asc` on the command line
65+ assemblyscript = dynRequire ( "../dist/assemblyscript.js" ) ;
7166 } catch ( e ) {
72- throw Error ( e_ts . stack + "\n---\n" + e . stack ) ;
67+ try { // `asc` on the command line without dist files
68+ dynRequire ( "ts-node" ) . register ( {
69+ project : path . join ( __dirname , ".." , "src" , "tsconfig.json" ) ,
70+ skipIgnore : true ,
71+ compilerOptions : { target : "ES2016" }
72+ } ) ;
73+ dynRequire ( "../src/glue/js" ) ;
74+ assemblyscript = dynRequire ( "../src" ) ;
75+ isDev = true ;
76+ } catch ( e_ts ) {
77+ try { // `require("dist/asc.js")` in explicit browser tests
78+ assemblyscript = dynRequire ( "./assemblyscript" ) ;
79+ } catch ( e ) {
80+ throw Error ( e_ts . stack + "\n---\n" + e . stack ) ;
81+ }
82+ }
7383 }
7484 }
75- }
85+ } ) ( ) ;
7686
7787/** Whether this is a webpack bundle or not. */
7888exports . isBundle = typeof BUNDLE_VERSION === "string" ;
@@ -635,26 +645,22 @@ exports.main = function main(argv, options, callback) {
635645 if ( args . trapMode === "clamp" ) {
636646 stats . optimizeCount ++ ;
637647 stats . optimizeTime += measure ( ( ) => {
638- module . runPasses ( [ "trap-mode-clamp" ] ) ;
648+ module . runPass ( "trap-mode-clamp" ) ;
639649 } ) ;
640650 } else if ( args . trapMode === "js" ) {
641651 stats . optimizeCount ++ ;
642652 stats . optimizeTime += measure ( ( ) => {
643- module . runPasses ( [ "trap-mode-js" ] ) ;
653+ module . runPass ( "trap-mode-js" ) ;
644654 } ) ;
645655 } else if ( args . trapMode !== "allow" ) {
646656 module . dispose ( ) ;
647657 return callback ( Error ( "Unsupported trap mode" ) ) ;
648658 }
649659
650- // Implicitly run costly non-LLVM optimizations on -O3 or -Oz
651- // see: https://github.com/WebAssembly/binaryen/pull/1596
652- if ( optimizeLevel >= 3 || shrinkLevel >= 2 ) optimizeLevel = 4 ;
653-
654- module . setOptimizeLevel ( optimizeLevel ) ;
655- module . setShrinkLevel ( shrinkLevel ) ;
656- module . setDebugInfo ( args . debug ) ;
657-
660+ // Optimize the module
661+ const debugInfo = args . debug ;
662+ const usesARC = args . runtime == "half" || args . runtime == "full" ;
663+ const converge = args . converge ;
658664 const runPasses = [ ] ;
659665 if ( args . runPasses ) {
660666 if ( typeof args . runPasses === "string" ) {
@@ -668,201 +674,16 @@ exports.main = function main(argv, options, callback) {
668674 }
669675 }
670676
671- function doOptimize ( ) {
672- const hasARC = args . runtime == "half" || args . runtime == "full" ;
673- const passes = [ ] ;
674- function add ( pass ) { passes . push ( pass ) ; }
675-
676- if ( optimizeLevel >= 2 && shrinkLevel === 0 ) {
677- // tweak inlining options when speed more preferable than size
678- module . setAlwaysInlineMaxSize ( 12 ) ;
679- module . setFlexibleInlineMaxSize ( 70 ) ;
680- module . setOneCallerInlineMaxSize ( 200 ) ;
681- } else {
682- // tweak inlining options when size matters
683- optimizeLevel === 0 && shrinkLevel >= 0
684- ? module . setAlwaysInlineMaxSize ( 2 )
685- : module . setAlwaysInlineMaxSize ( 4 ) ; // default: 2
686- module . setFlexibleInlineMaxSize ( 65 ) ; // default: 20
687- module . setOneCallerInlineMaxSize ( 80 ) ; // default: 15
688- }
689-
690- // Optimize the module if requested
691- if ( optimizeLevel > 0 || shrinkLevel > 0 ) {
692- // Binaryen's default passes with Post-AssemblyScript passes added.
693- // see: Binaryen/src/pass.cpp
694-
695- // PassRunner::addDefaultGlobalOptimizationPrePasses
696- add ( "duplicate-function-elimination" ) ;
697-
698- // PassRunner::addDefaultFunctionOptimizationPasses
699- if ( optimizeLevel >= 3 || shrinkLevel >= 1 ) {
700- add ( "ssa-nomerge" ) ;
701- }
702- if ( optimizeLevel >= 3 ) {
703- add ( "simplify-locals-nostructure" ) ; // differs
704- add ( "vacuum" ) ; // differs
705- add ( "reorder-locals" ) ; // differs
706- add ( "flatten" ) ;
707- add ( "local-cse" ) ;
708- }
709- if ( optimizeLevel >= 2 || shrinkLevel >= 1 ) { // differs
710- add ( "rse" ) ;
711- }
712- if ( hasARC ) { // differs
713- if ( optimizeLevel < 3 ) {
714- add ( "flatten" ) ;
715- }
716- add ( "post-assemblyscript" ) ;
717- }
718- add ( "dce" ) ;
719- add ( "remove-unused-brs" ) ;
720- add ( "remove-unused-names" ) ;
721- // add("optimize-instructions"); // differs move 2 lines above
722- if ( optimizeLevel >= 2 || shrinkLevel >= 1 ) {
723- add ( "pick-load-signs" ) ;
724- add ( "simplify-globals-optimizing" ) ; // differs
725- }
726- add ( "optimize-instructions" ) ; // differs
727- if ( optimizeLevel >= 3 || shrinkLevel >= 2 ) {
728- add ( "precompute-propagate" ) ;
729- } else {
730- add ( "precompute" ) ;
731- }
732- if ( module . getLowMemoryUnused ( ) ) {
733- if ( optimizeLevel >= 3 || shrinkLevel >= 1 ) {
734- add ( "optimize-added-constants-propagate" ) ;
735- } else {
736- add ( "optimize-added-constants" ) ;
737- }
738- }
739- // this will be done later (1)
740- // if (optimizeLevel >= 2 || shrinkLevel >= 2) {
741- // add("code-pushing");
742- // }
743- if ( optimizeLevel >= 3 && shrinkLevel <= 1 ) { // differs
744- add ( "licm" ) ;
745- }
746- add ( "simplify-locals-nostructure" ) ;
747- add ( "vacuum" ) ;
748- add ( "reorder-locals" ) ;
749- add ( "remove-unused-brs" ) ;
750- // if (optimizeLevel >= 3 || shrinkLevel >= 2) { // do it later
751- // add("merge-locals");
752- // }
753- add ( "coalesce-locals" ) ;
754- add ( "simplify-locals" ) ;
755- add ( "vacuum" ) ;
756- add ( "reorder-locals" ) ;
757- add ( "coalesce-locals" ) ;
758- add ( "reorder-locals" ) ;
759- if ( optimizeLevel >= 3 || shrinkLevel >= 1 ) { // differs
760- add ( "merge-locals" ) ;
761- }
762- add ( "vacuum" ) ;
763- if ( optimizeLevel >= 3 || shrinkLevel >= 1 ) {
764- add ( "code-folding" ) ;
765- }
766- if ( optimizeLevel >= 2 || shrinkLevel >= 1 ) { // differs
767- add ( "simplify-globals-optimizing" ) ;
768- }
769- add ( "merge-blocks" ) ;
770- add ( "remove-unused-brs" ) ;
771- add ( "remove-unused-names" ) ;
772- add ( "merge-blocks" ) ;
773- // make this later & move to (2)
774- // if (optimizeLevel >= 3 || shrinkLevel >= 2) {
775- // add("precompute-propagate");
776- // } else {
777- // add("precompute");
778- // }
779- add ( "optimize-instructions" ) ;
780- if ( optimizeLevel >= 2 || shrinkLevel >= 1 ) {
781- add ( "rse" ) ;
782- }
783- add ( "vacuum" ) ;
784- // PassRunner::addDefaultGlobalOptimizationPostPasses
785- if ( optimizeLevel >= 2 || shrinkLevel >= 1 ) {
786- add ( "dae-optimizing" ) ;
787- }
788- if ( optimizeLevel >= 2 || shrinkLevel >= 2 ) {
789- add ( "inlining-optimizing" ) ;
790- }
791- // "duplicate-function-elimination" will better done later
792- // add("duplicate-function-elimination");
793- add ( "duplicate-import-elimination" ) ;
794- if ( optimizeLevel >= 2 || shrinkLevel >= 2 ) {
795- add ( "simplify-globals-optimizing" ) ;
796- } else {
797- add ( "simplify-globals" ) ;
798- }
799- // moved from (2)
800- // it works better after globals optimizations like simplify-globals, inlining-optimizing and etc
801- if ( optimizeLevel >= 2 || shrinkLevel >= 1 ) { // differs
802- add ( "precompute-propagate" ) ;
803- } else {
804- add ( "precompute" ) ;
805- }
806- // replace indirect calls with direct, reduce arity and
807- // inline this calls if possible
808- add ( "directize" ) ; // differs
809- add ( "dae-optimizing" ) ; // differs
810- add ( "inlining-optimizing" ) ; // differs
811- // ARC finalization should be done exactly after inlining for better release/retain reduction
812- if ( hasARC ) { // differs
813- add ( "post-assemblyscript-finalize" ) ;
814- }
815- if ( optimizeLevel >= 2 || shrinkLevel >= 1 ) { // differs
816- add ( "rse" ) ;
817- // rearrange / reduce switch cases again
818- add ( "remove-unused-brs" ) ;
819- add ( "vacuum" ) ;
820-
821- // move some code after early return which potentially could reduce computations
822- // do this after CFG cleanup (originally it was done before)
823- // moved from (1)
824- add ( "code-pushing" ) ;
825- if ( optimizeLevel >= 3 ) {
826- // this quite expensive so do this only for highest opt level
827- add ( "simplify-globals" ) ;
828- // replace indirect calls with direct and inline if possible again.
829- add ( "directize" ) ;
830- add ( "dae-optimizing" ) ;
831- add ( "precompute-propagate" ) ;
832- add ( "coalesce-locals" ) ;
833- add ( "merge-locals" ) ;
834- add ( "simplify-locals-nostructure" ) ;
835- add ( "vacuum" ) ;
836- add ( "inlining-optimizing" ) ;
837- add ( "precompute-propagate" ) ;
838- }
839- add ( "optimize-instructions" ) ;
840- add ( "simplify-globals-optimizing" ) ;
841- }
842- // remove unused elements of table and pack / reduce memory
843- add ( "duplicate-function-elimination" ) ; // differs
844- add ( "remove-unused-nonfunction-module-elements" ) ; // differs
845- add ( "memory-packing" ) ;
846- add ( "remove-unused-module-elements" ) ; // differs
847- // It seems stack-ir unuseful for our needs.
848- // if (optimizeLevel >= 3 || shrinkLevel >= 1) { // differs. was optimizeLevel >= 2
849- // add("generate-stack-ir");
850- // add("optimize-stack-ir");
851- // }
852- }
853-
854- // Append additional passes if requested and execute
855- module . runPasses ( passes . concat ( runPasses ) ) ;
856- }
857-
858677 stats . optimizeTime += measure ( ( ) => {
859678 stats . optimizeCount ++ ;
860- doOptimize ( ) ;
861- if ( args . converge ) {
679+ module . optimize ( optimizeLevel , shrinkLevel , debugInfo , usesARC ) ;
680+ module . runPasses ( runPasses ) ;
681+ if ( converge ) {
862682 let last = module . toBinary ( ) ;
863683 do {
864684 stats . optimizeCount ++ ;
865- doOptimize ( ) ;
685+ module . optimize ( optimizeLevel , shrinkLevel , debugInfo , usesARC ) ;
686+ module . runPasses ( runPasses ) ;
866687 let next = module . toBinary ( ) ;
867688 if ( next . output . length >= last . output . length ) {
868689 if ( next . output . length > last . output . length ) {
0 commit comments