diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-05-16 10:50:32 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-05-16 10:50:32 -0700 |
commit | f0d31ed4996a3f194f81d40fc14d1cbc93dd9a42 (patch) | |
tree | 084b16246a8e0e9568d27c7c58dfb96cf965e6e6 /tools/js-optimizer.js | |
parent | cf3327087a4c16fba7b1d443f9dc6b44ddd4c13f (diff) |
properly lock variables to loops in registerize
Diffstat (limited to 'tools/js-optimizer.js')
-rw-r--r-- | tools/js-optimizer.js | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index ee067a19..e76f58f2 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1220,17 +1220,21 @@ function registerize(ast) { } // Go through the function's code, assigning 'registers'. // The only tricky bit is to keep variables locked on a register through loops, - // since they can potentially be returned to. We use a simple approach of - // locking the register to the topmost loop. + // since they can potentially be returned to. Optimizable variables lock onto + // loops that they enter, unoptimizable variables lock in a conservative way + // into the topmost loop. var varRegs = {}; // maps variables to the register they will use all their life var freeRegs = []; var nextReg = 1; var fullNames = {}; - var loopRegs = []; - var loops = 0; + var loopRegs = { 1: [] }; // for each loop nesting level, the list of bound variables + var loops = 0; // 0 is toplevel, 1 is first loop, etc var saved = 0; + var activeOptimizables = {}; + var optimizableLoops = {}; function decUse(name) { if (!varUses[name]) return false; // no uses left, or not a relevant variable + if (optimizables[name]) activeOptimizables[name] = 1; var reg = varRegs[name]; if (!reg) { // acquire register @@ -1246,11 +1250,20 @@ function registerize(ast) { varUses[name]--; assert(varUses[name] >= 0); if (varUses[name] == 0) { - if (loops == 0 || optimizables[name]) { + if (optimizables[name]) delete activeOptimizables[name]; + // If we are not in a loop, or we are optimizable and not bound to a loop + // (we might have been in one but left it), we can free the register now. + if (loops == 0 || (optimizables[name] && !optimizableLoops[name])) { // free register freeRegs.push(reg); } else { - loopRegs.push(reg); + // when the relevant loop is exited, we will free the register + if (optimizables[name]) { + if (!loopRegs[loops]) loopRegs[loops] = []; + loopRegs[loops].push(reg); + } else { + loopRegs[1].push(reg); + } } } return true; @@ -1263,14 +1276,21 @@ function registerize(ast) { } } else if (type in LOOP) { loops++; + // Active optimizables lock onto this loop, if not locked onto one that encloses this one + for (var name in activeOptimizables) { + if (!optimizableLoops[name]) { + optimizableLoops[name] = loops; + } + } } }, function(node, type) { if (type in LOOP) { - loops--; - if (loops == 0 && loopRegs.length > 0) { - freeRegs = freeRegs.concat(loopRegs); - loopRegs = []; + // Free registers that were locked to this loop + if (loopRegs[loops]) { + freeRegs = freeRegs.concat(loopRegs[loops]); + loopRegs[loops] = []; } + loops--; } }); // Add vars at the beginning |