diff options
author | Alon Zakai <alonzakai@gmail.com> | 2011-10-31 16:58:56 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2011-10-31 16:58:56 -0700 |
commit | 8ef6b1bade9a7a8a29894feb4e6fe3ca8dad711c (patch) | |
tree | 4c0617c027ad628d5246f10d286b46b0cdbe10f6 | |
parent | a349c5df70c2e2c6e5aaa82b22742161adfeec0b (diff) |
explicitly identify emscripten-generated functions (as opposed to library ones, or handwritten ones appended to the same file), and run eliminator only on those
-rw-r--r-- | src/jsifier.js | 9 | ||||
-rw-r--r-- | src/modules.js | 3 | ||||
-rw-r--r-- | tools/eliminator/eliminator-test.js | 2 | ||||
-rw-r--r-- | tools/eliminator/eliminator.coffee | 26 |
4 files changed, 28 insertions, 12 deletions
diff --git a/src/jsifier.js b/src/jsifier.js index bd432001..6cbc0eb9 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -931,7 +931,12 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) { } generated = generated.concat(itemsDict.function).concat(data.unparsedFunctions); - if (!mainPass) return generated.map(function(item) { return item.JS }).join('\n'); + if (!mainPass) { + Functions.allIdents = Functions.allIdents.concat(itemsDict.function.map(function(func) { + return func.ident; + })); + return generated.map(function(item) { return item.JS }).join('\n'); + } // We are ready to print out the data, but must do so carefully - we are // dealing with potentially *huge* strings. Convenient replacements and @@ -967,6 +972,8 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) { print(Functions.generateIndexing()); // done last, as it may rely on aliases set in postsets print(postParts[1]); print(shellParts[1]); + // Print out some useful metadata (for additional optimizations later, like the eliminator) + print('// EMSCRIPTEN_GENERATED_FUNCTIONS: ' + JSON.stringify(Functions.allIdents) + '\n'); return null; } diff --git a/src/modules.js b/src/modules.js index 3b370878..f04731f8 100644 --- a/src/modules.js +++ b/src/modules.js @@ -228,6 +228,9 @@ var Functions = { // All functions that will be implemented in this file implementedFunctions: null, + // All the function idents seen so far + allIdents: [], + indexedFunctions: [0, 0], // Start at a non-0 (even, see below) value // Mark a function as needing indexing, and returns the index diff --git a/tools/eliminator/eliminator-test.js b/tools/eliminator/eliminator-test.js index 8a364c0a..d3ee88cb 100644 --- a/tools/eliminator/eliminator-test.js +++ b/tools/eliminator/eliminator-test.js @@ -91,3 +91,5 @@ function py() { var $8 = $4 + 12; HEAP[$8] = $7; } +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["f", "g", "h"] + diff --git a/tools/eliminator/eliminator.coffee b/tools/eliminator/eliminator.coffee index c07e5974..891718e2 100644 --- a/tools/eliminator/eliminator.coffee +++ b/tools/eliminator/eliminator.coffee @@ -20,6 +20,10 @@ uglify = require 'uglify-js' fs = require 'fs' +# Functions which have been generated by Emscripten. We optimize only those. +generatedFunctions = [] +GENERATED_FUNCTIONS_MARKER = '// EMSCRIPTEN_GENERATED_FUNCTIONS:' + # Maximum number of uses to consider a variable not worth eliminating. MAX_USES = 3 @@ -79,6 +83,8 @@ traverse = (node, callback) -> # function/defun node and call run() to apply the optimization (in-place). class Eliminator constructor: (func) -> + @ident = func[1] + # The statements of the function to analyze. @body = func[3] @@ -107,7 +113,7 @@ class Eliminator # @returns: The number of variables eliminated, or undefined if skipped. run: -> # Our optimization does not account for closures. - if @hasClosures @body then return undefined + if not @isGenerated then return undefined @calculateBasicVarStats() @analyzeInitialValues() @@ -128,16 +134,8 @@ class Eliminator return eliminated # Determines if a function is Emscripten-generated. - hasClosures: -> - closureFound = false - - traverse @body, (node, type) -> - if type in ['defun', 'function', 'with'] - closureFound = true - return false - return undefined - - return closureFound + isGenerated: -> + return @ident in generatedFunctions # Runs the basic variable scan pass. Fills the following member variables: # isLocal @@ -337,6 +335,12 @@ class Eliminator main = -> # Get the parse tree. src = fs.readFileSync('/dev/stdin').toString() + + throw 'Cannot identify generated functions' if GENERATED_FUNCTIONS_MARKER in src + generatedFunctionsLine = src.split('\n').filter (line) -> + return line.indexOf(GENERATED_FUNCTIONS_MARKER) == 0 + generatedFunctions = eval(generatedFunctionsLine[0].replace(GENERATED_FUNCTIONS_MARKER, '')) + ast = uglify.parser.parse src # Run the eliminator on all functions. |