satyr 4e39e2e -- efficient closures in loops -- pulling them out.

This commit is contained in:
Jeremy Ashkenas
2010-11-03 21:39:54 -04:00
parent 5eb255a649
commit 304a120429
2 changed files with 62 additions and 0 deletions

View File

@@ -1600,6 +1600,9 @@
if (namePart) {
varPart = idt + namePart + ';\n';
}
if (!this.pattern) {
defPart += this.pluckDirectCall(o, body, name, index);
}
code = guardPart + varPart;
if (!body.isEmpty()) {
if (o.level > LEVEL_TOP || this.returns) {
@@ -1619,6 +1622,40 @@
}
return defPart + this.tab + ("for (" + forPart + ") {" + code + "}") + retPart;
};
For.prototype.pluckDirectCall = function(o, body, name, index) {
var arg, args, base, defs, expr, fn, i, idx, ref, val, _len, _len2, _ref, _ref2, _ref3;
defs = '';
_ref = body.expressions;
for (idx = 0, _len = _ref.length; idx < _len; idx++) {
expr = _ref[idx];
expr = expr.unwrapAll();
if (!(expr instanceof Call)) {
continue;
}
val = expr.variable.unwrapAll();
if (!(val instanceof Code && !expr.args.length || val instanceof Value && val.base instanceof Code && val.properties.length === 1 && ((_ref2 = val.properties[0].name) != null ? _ref2.value : void 0) === 'call')) {
continue;
}
fn = val.base || val;
ref = new Literal(o.scope.freeVariable('fn'));
base = new Value(ref);
args = compact([name, index]);
if (this.object) {
args.reverse();
}
for (i = 0, _len2 = args.length; i < _len2; i++) {
arg = args[i];
fn.params.push(new Param(args[i] = new Literal(arg)));
}
if (val.base) {
_ref3 = [base, val], val.base = _ref3[0], base = _ref3[1];
args.unshift(new Literal('this'));
}
body.expressions[idx] = new Call(base, args);
defs += this.tab + new Assign(ref, fn).compile(o, LEVEL_TOP) + ';\n';
}
return defs;
};
return For;
})();
exports.Switch = (function() {

View File

@@ -1335,6 +1335,7 @@ exports.For = class For extends Base
when -1 then '--'
else (if pvar < 0 then ' -= ' + pvar.slice 1 else ' += ' + pvar)
varPart = idt + namePart + ';\n' if namePart
defPart += @pluckDirectCall o, body, name, index unless @pattern
code = guardPart + varPart
unless body.isEmpty()
if o.level > LEVEL_TOP or @returns
@@ -1348,6 +1349,30 @@ exports.For = class For extends Base
code = '\n' + code + '\n' + @tab if code
defPart + @tab + "for (#{forPart}) {#{code}}" + retPart
pluckDirectCall: (o, body, name, index) ->
defs = ''
for expr, idx in body.expressions
expr = expr.unwrapAll()
continue unless expr instanceof Call
val = expr.variable.unwrapAll()
continue unless val instanceof Code and not expr.args.length or
val instanceof Value and val.base instanceof Code and
val.properties.length is 1 and
val.properties[0].name?.value is 'call'
fn = val.base or val
ref = new Literal o.scope.freeVariable 'fn'
base = new Value ref
args = compact [name, index]
args.reverse() if @object
for arg, i in args
fn.params.push new Param args[i] = new Literal arg
if val.base
[val.base, base] = [base, val]
args.unshift new Literal 'this'
body.expressions[idx] = new Call base, args
defs += @tab + new Assign(ref, fn).compile(o, LEVEL_TOP) + ';\n'
defs
#### Switch
# A JavaScript *switch* statement. Converts into a returnable expression on-demand.