aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2017-02-26 00:40:33 +0800
committerGitHub <noreply@github.com>2017-02-26 00:40:33 +0800
commit16cd5d57a5cf7f5750104df0e5af246708fd493f (patch)
treee9ea6b8432ce0bddeeeef317f96765de1467ceeb /lib
parent834f9f39245f1ddf5a29c579afd7ebcdb0afe585 (diff)
downloadtracifyjs-16cd5d57a5cf7f5750104df0e5af246708fd493f.tar.gz
tracifyjs-16cd5d57a5cf7f5750104df0e5af246708fd493f.zip
consolidate `evaluate` & `reduce_vars` (#1505)
- improve marking efficiency - apply smarter `const` replacement to `var` fixes #1501
Diffstat (limited to 'lib')
-rw-r--r--lib/compress.js81
-rw-r--r--lib/scope.js2
2 files changed, 45 insertions, 38 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 2bc1c5a5..ccd6e23c 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -118,7 +118,7 @@ merge(Compressor.prototype, {
var passes = +this.options.passes || 1;
for (var pass = 0; pass < passes && pass < 3; ++pass) {
if (pass > 0 || this.option("reduce_vars"))
- node.reset_opt_flags(this);
+ node.reset_opt_flags(this, true);
node = node.transform(this);
}
return node;
@@ -177,28 +177,26 @@ merge(Compressor.prototype, {
return this.print_to_string() == node.print_to_string();
});
- AST_Node.DEFMETHOD("reset_opt_flags", function(compressor){
- var reduce_vars = compressor.option("reduce_vars");
+ AST_Node.DEFMETHOD("reset_opt_flags", function(compressor, rescan){
+ var reduce_vars = rescan && compressor.option("reduce_vars");
+ var unsafe = compressor.option("unsafe");
var tw = new TreeWalker(function(node){
- if (reduce_vars && node instanceof AST_Scope) {
- node.variables.each(function(def) {
- delete def.modified;
- });
- }
- if (node instanceof AST_SymbolRef) {
- var d = node.definition();
- if (d.init) {
- delete d.init._evaluated;
+ if (reduce_vars) {
+ if (node instanceof AST_Toplevel) node.globals.each(reset_def);
+ if (node instanceof AST_Scope) node.variables.each(reset_def);
+ if (node instanceof AST_SymbolRef) {
+ var d = node.definition();
+ d.references.push(node);
+ if (!d.modified && (d.orig.length > 1 || isModified(node, 0))) {
+ d.modified = true;
+ }
}
- if (reduce_vars && (d.orig.length > 1 || isModified(node, 0))) {
- d.modified = true;
+ if (node instanceof AST_Call && node.expression instanceof AST_Function) {
+ node.expression.argnames.forEach(function(arg, i) {
+ arg.definition().init = node.args[i] || make_node(AST_Undefined, node);
+ });
}
}
- if (reduce_vars && node instanceof AST_Call && node.expression instanceof AST_Function) {
- node.expression.argnames.forEach(function(arg, i) {
- arg.definition().init = node.args[i] || make_node(AST_Undefined, node);
- });
- }
if (!(node instanceof AST_Directive || node instanceof AST_Constant)) {
node._squeezed = false;
node._optimized = false;
@@ -206,10 +204,18 @@ merge(Compressor.prototype, {
});
this.walk(tw);
+ function reset_def(def) {
+ def.modified = false;
+ def.references = [];
+ def.should_replace = undefined;
+ if (unsafe && def.init) {
+ def.init._evaluated = undefined;
+ }
+ }
+
function isModified(node, level) {
var parent = tw.parent(level);
- if (parent instanceof AST_Unary && (parent.operator === "++" || parent.operator === "--")
- || parent instanceof AST_Assign && parent.left === node
+ if (isLHS(node, parent)
|| parent instanceof AST_Call && parent.expression === node) {
return true;
} else if (parent instanceof AST_PropAccess && parent.expression === node) {
@@ -1254,7 +1260,7 @@ merge(Compressor.prototype, {
var d = this.definition();
if (compressor.option("reduce_vars") && !d.modified && d.init) {
if (compressor.option("unsafe")) {
- if (!HOP(d.init, '_evaluated')) {
+ if (d.init._evaluated === undefined) {
d.init._evaluated = ev(d.init, compressor);
}
return d.init._evaluated;
@@ -2403,9 +2409,6 @@ merge(Compressor.prototype, {
});
OPT(AST_Call, function(self, compressor){
- self.args = self.args.map(function(arg) {
- return arg.evaluate(compressor)[0];
- });
if (compressor.option("unsafe")) {
var exp = self.expression;
if (exp instanceof AST_SymbolRef && exp.undeclared()) {
@@ -3025,18 +3028,24 @@ merge(Compressor.prototype, {
return make_node(AST_Infinity, self).transform(compressor);
}
}
- if (compressor.option("evaluate")
- && compressor.option("reduce_vars")
- && !isLHS(self, compressor.parent())) {
+ if (compressor.option("evaluate") && compressor.option("reduce_vars")) {
var d = self.definition();
- if (d.constant && !d.modified && d.init && d.init.is_constant(compressor)) {
- var original_as_string = self.print_to_string();
- var const_node = make_node_from_constant(compressor, d.init.constant_value(compressor), self);
- var const_node_as_string = const_node.print_to_string();
- var per_const_overhead = d.global || !d.references.length ? 0
- : (d.name.length + 2 + const_node_as_string.length) / d.references.length;
- if (const_node_as_string.length <= original_as_string.length + per_const_overhead)
- return const_node;
+ if (!d.modified && d.init) {
+ if (d.should_replace === undefined) {
+ var init = d.init.evaluate(compressor);
+ if (init.length > 1) {
+ var value = init[0].print_to_string().length;
+ var name = d.name.length;
+ var freq = d.references.length;
+ var overhead = d.global || !freq ? 0 : (name + 2 + value) / freq;
+ d.should_replace = value <= name + overhead ? init[0] : false;
+ } else {
+ d.should_replace = false;
+ }
+ }
+ if (d.should_replace) {
+ return d.should_replace;
+ }
}
}
return self;
diff --git a/lib/scope.js b/lib/scope.js
index 29e4103a..ae0c5777 100644
--- a/lib/scope.js
+++ b/lib/scope.js
@@ -51,7 +51,6 @@ function SymbolDef(scope, index, orig) {
this.global = false;
this.mangled_name = null;
this.undeclared = false;
- this.constant = false;
this.index = index;
this.id = SymbolDef.next_id++;
};
@@ -156,7 +155,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
else if (node instanceof AST_SymbolVar
|| node instanceof AST_SymbolConst) {
var def = defun.def_variable(node);
- def.constant = node instanceof AST_SymbolConst;
def.init = tw.parent().value;
}
else if (node instanceof AST_SymbolCatch) {