migrate safe transformations out of unsafe_comps

fixes #2959
This commit is contained in:
alexlamsl 2018-02-26 13:38:10 +08:00
parent 36bca6934d
commit a47b24f29f
5 changed files with 27 additions and 53 deletions

View File

@ -605,8 +605,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
side effects permitting. side effects permitting.
- `comparisons` (default: `true`) -- apply certain optimizations to binary nodes, - `comparisons` (default: `true`) -- apply certain optimizations to binary nodes,
e.g. `!(a <= b) → a > b` (only when `unsafe_comps`), attempts to negate binary e.g. `!(a <= b) → a > b`, attempts to negate binary nodes, e.g.
nodes, e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.
- `conditionals` (default: `true`) -- apply optimizations for `if`-s and conditional - `conditionals` (default: `true`) -- apply optimizations for `if`-s and conditional
expressions expressions
@ -730,12 +730,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `unsafe` (default: `false`) -- apply "unsafe" transformations (discussion below) - `unsafe` (default: `false`) -- apply "unsafe" transformations (discussion below)
- `unsafe_comps` (default: `false`) -- Reverse `<` and `<=` to `>` and `>=` to - `unsafe_comps` (default: `false`) -- compress expressions like `a <= b` assuming
allow improved compression. This might be unsafe when an at least one of two none of the operands can be (coerced to) `NaN`.
operands is an object with computed values due the use of methods like `get`,
or `valueOf`. This could cause change in execution order after operands in the
comparison are switching. Compression only works if both `comparisons` and
`unsafe_comps` are both set to true.
- `unsafe_Function` (default: `false`) -- compress and mangle `Function(args, code)` - `unsafe_Function` (default: `false`) -- compress and mangle `Function(args, code)`
when both `args` and `code` are string literals. when both `args` and `code` are string literals.

View File

@ -5033,13 +5033,11 @@ merge(Compressor.prototype, {
}); });
self = best_of(compressor, self, negated); self = best_of(compressor, self, negated);
} }
if (compressor.option("unsafe_comps")) {
switch (self.operator) { switch (self.operator) {
case "<": reverse(">"); break; case "<": reverse(">"); break;
case "<=": reverse(">="); break; case "<=": reverse(">="); break;
} }
} }
}
if (self.operator == "+") { if (self.operator == "+") {
if (self.right instanceof AST_String if (self.right instanceof AST_String
&& self.right.getValue() == "" && self.right.getValue() == ""

View File

@ -91,7 +91,7 @@ asm_mixed: {
function logSum(start, end) { function logSum(start, end) {
start |= 0, end |= 0; start |= 0, end |= 0;
var sum = 0, p = 0, q = 0; var sum = 0, p = 0, q = 0;
for (p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) sum += +log(values[p >> 3]); for (p = start << 3, q = end << 3; (0 | q) > (0 | p); p = p + 8 | 0) sum += +log(values[p >> 3]);
return +sum; return +sum;
} }
function geometricMean(start, end) { function geometricMean(start, end) {

View File

@ -1,62 +1,42 @@
keep_comparisons: { comparisons: {
options = { options = {
comparisons: true, comparisons: true,
unsafe_comps: false
} }
input: { input: {
var obj1 = { var obj1, obj2;
valueOf: function() {triggeredFirst();}
}
var obj2 = {
valueOf: function() {triggeredSecond();}
}
var result1 = obj1 <= obj2; var result1 = obj1 <= obj2;
var result2 = obj1 < obj2; var result2 = obj1 < obj2;
var result3 = obj1 >= obj2; var result3 = obj1 >= obj2;
var result4 = obj1 > obj2; var result4 = obj1 > obj2;
} }
expect: { expect: {
var obj1 = { var obj1, obj2;
valueOf: function() {triggeredFirst();} var result1 = obj2 >= obj1;
} var result2 = obj2 > obj1;
var obj2 = {
valueOf: function() {triggeredSecond();}
}
var result1 = obj1 <= obj2;
var result2 = obj1 < obj2;
var result3 = obj1 >= obj2; var result3 = obj1 >= obj2;
var result4 = obj1 > obj2; var result4 = obj1 > obj2;
} }
} }
keep_comparisons_with_unsafe_comps: { unsafe_comps: {
options = { options = {
comparisons: true, comparisons: true,
unsafe_comps: true conditionals: true,
unsafe_comps: true,
} }
input: { input: {
var obj1 = { var obj1, obj2;
valueOf: function() {triggeredFirst();} obj1 <= obj2 ? f1() : g1();
} obj1 < obj2 ? f2() : g2();
var obj2 = { obj1 >= obj2 ? f3() : g3();
valueOf: function() {triggeredSecond();} obj1 > obj2 ? f4() : g4();
}
var result1 = obj1 <= obj2;
var result2 = obj1 < obj2;
var result3 = obj1 >= obj2;
var result4 = obj1 > obj2;
} }
expect: { expect: {
var obj1 = { var obj1, obj2;
valueOf: function() {triggeredFirst();} obj1 > obj2 ? g1() : f1();
} obj2 > obj1 ? f2() : g2();
var obj2 = { obj2 > obj1 ? g3() : f3();
valueOf: function() {triggeredSecond();} obj1 > obj2 ? f4() : g4();
}
var result1 = obj2 >= obj1;
var result2 = obj2 > obj1;
var result3 = obj1 >= obj2;
var result4 = obj1 > obj2;
} }
} }

View File

@ -40,6 +40,6 @@ conditional_false_stray_else_in_loop: {
console.log(i); console.log(i);
} }
} }
expect_exact: "for(var i=1;i<=4;++i)if(!(i<=2))console.log(i);" expect_exact: "for(var i=1;4>=i;++i)if(!(2>=i))console.log(i);"
expect_stdout: true expect_stdout: true
} }