more optimizations for some break/continue cases
This commit is contained in:
@@ -186,6 +186,14 @@ merge(Compressor.prototype, {
|
||||
return false;
|
||||
};
|
||||
|
||||
function loop_body(x) {
|
||||
if (x instanceof AST_Switch) return x;
|
||||
if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) {
|
||||
return (x.body instanceof AST_BlockStatement ? x.body : x);
|
||||
}
|
||||
return x;
|
||||
};
|
||||
|
||||
function tighten_body(statements, compressor) {
|
||||
var CHANGED;
|
||||
do {
|
||||
@@ -303,8 +311,13 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
|
||||
var ab = aborts(stat.body);
|
||||
var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
|
||||
if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
|
||||
|| (ab instanceof AST_Continue && self === compressor.loopcontrol_target(ab.label)))) {
|
||||
|| (ab instanceof AST_Continue && self === loop_body(lct))
|
||||
|| (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
|
||||
if (ab.label) {
|
||||
remove(ab.label.thedef.references, ab.label);
|
||||
}
|
||||
CHANGED = true;
|
||||
var body = as_statement_array(stat.body).slice(0, -1);
|
||||
stat = stat.clone();
|
||||
@@ -320,8 +333,13 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
|
||||
var ab = aborts(stat.alternative);
|
||||
var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
|
||||
if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
|
||||
|| (ab instanceof AST_Continue && self === compressor.loopcontrol_target(ab.label)))) {
|
||||
|| (ab instanceof AST_Continue && self === loop_body(lct))
|
||||
|| (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
|
||||
if (ab.label) {
|
||||
remove(ab.label.thedef.references, ab.label);
|
||||
}
|
||||
CHANGED = true;
|
||||
stat = stat.clone();
|
||||
stat.body = make_node(AST_BlockStatement, stat.body, {
|
||||
@@ -347,11 +365,26 @@ merge(Compressor.prototype, {
|
||||
function eliminate_dead_code(statements, compressor) {
|
||||
var has_quit = false;
|
||||
var orig = statements.length;
|
||||
var self = compressor.self();
|
||||
statements = statements.reduce(function(a, stat){
|
||||
if (has_quit) {
|
||||
extract_declarations_from_unreachable_code(compressor, stat, a);
|
||||
} else {
|
||||
a.push(stat);
|
||||
if (stat instanceof AST_LoopControl) {
|
||||
var lct = compressor.loopcontrol_target(stat.label);
|
||||
if ((stat instanceof AST_Break
|
||||
&& lct instanceof AST_BlockStatement
|
||||
&& loop_body(lct) === self) || (stat instanceof AST_Continue
|
||||
&& loop_body(lct) === self)) {
|
||||
if (stat.label) {
|
||||
remove(stat.label.thedef.references, stat.label);
|
||||
}
|
||||
} else {
|
||||
a.push(stat);
|
||||
}
|
||||
} else {
|
||||
a.push(stat);
|
||||
}
|
||||
if (aborts(stat)) has_quit = true;
|
||||
}
|
||||
return a;
|
||||
@@ -795,6 +828,10 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
|
||||
OPT(AST_LabeledStatement, function(self, compressor){
|
||||
if (self.body instanceof AST_Break
|
||||
&& compressor.loopcontrol_target(self.body.label) === self.body) {
|
||||
return make_node(AST_EmptyStatement, self);
|
||||
}
|
||||
return self.label.references.length == 0 ? self.body : self;
|
||||
});
|
||||
|
||||
@@ -1227,7 +1264,7 @@ merge(Compressor.prototype, {
|
||||
var last_branch = self.body[self.body.length - 1];
|
||||
if (last_branch) {
|
||||
var stat = last_branch.body[last_branch.body.length - 1]; // last statement
|
||||
if (stat instanceof AST_Break && compressor.loopcontrol_target(stat.label) === self)
|
||||
if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self)
|
||||
last_branch.body.pop();
|
||||
}
|
||||
return self;
|
||||
|
||||
Reference in New Issue
Block a user