aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Van de Gejuchte <anthonyvdgent@gmail.com>2016-06-13 18:19:06 +0200
committerAnthony Van de Gejuchte <anthonyvdgent@gmail.com>2016-06-15 23:11:08 +0200
commitd7971ba0e439eb042fd880762bc7fa77ce1f3e73 (patch)
treeb6ef83784efdffef3ae445c13a014690bcad551a
parent5c4cfaa0a75317582c979f9b50c1e562fbcfa40d (diff)
downloadtracifyjs-d7971ba0e439eb042fd880762bc7fa77ce1f3e73.tar.gz
tracifyjs-d7971ba0e439eb042fd880762bc7fa77ce1f3e73.zip
Fix test262 failures related to <, <=, in and instanceof
Fixed-by: @kzc
-rw-r--r--README.md13
-rw-r--r--lib/compress.js10
-rw-r--r--test/compress/asm.js2
-rw-r--r--test/compress/comparing.js76
4 files changed, 92 insertions, 9 deletions
diff --git a/README.md b/README.md
index 041a0709..b0ac7121 100644
--- a/README.md
+++ b/README.md
@@ -291,12 +291,19 @@ to set `true`; it's effectively a shortcut for `foo=true`).
- `unsafe` (default: false) -- apply "unsafe" transformations (discussion below)
+- `unsafe_comps` (default: false) -- Reverse `<` and `<=` to `>` and `>=` to
+ allow improved compression. This might be unsafe when an at least one of two
+ 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.
+
- `conditionals` -- apply optimizations for `if`-s and conditional
expressions
- `comparisons` -- apply certain optimizations to binary nodes, for example:
- `!(a <= b) → a > b` (only when `unsafe`), attempts to negate binary nodes,
- e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.
+ `!(a <= b) → a > b` (only when `unsafe_comps`), attempts to negate binary
+ nodes, e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.
- `evaluate` -- attempt to evaluate constant expressions
@@ -415,7 +422,7 @@ them. If you are targeting < ES6 environments, use `/** @const */ var`.
<a name="codegen-options"></a>
#### Conditional compilation, API
-You can also use conditional compilation via the programmatic API. With the difference that the
+You can also use conditional compilation via the programmatic API. With the difference that the
property name is `global_defs` and is a compressor property:
```js
diff --git a/lib/compress.js b/lib/compress.js
index 4e04e961..3200a66f 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -1079,8 +1079,6 @@ merge(Compressor.prototype, {
case "<=" : return ev(left, c) <= ev(right, c);
case ">" : return ev(left, c) > ev(right, c);
case ">=" : return ev(left, c) >= ev(right, c);
- case "in" : return ev(left, c) in ev(right, c);
- case "instanceof" : return ev(left, c) instanceof ev(right, c);
}
throw def;
});
@@ -2502,9 +2500,11 @@ merge(Compressor.prototype, {
});
self = best_of(self, negated);
}
- switch (self.operator) {
- case "<": reverse(">"); break;
- case "<=": reverse(">="); break;
+ if (compressor.option("unsafe_comps")) {
+ switch (self.operator) {
+ case "<": reverse(">"); break;
+ case "<=": reverse(">="); break;
+ }
}
}
if (self.operator == "+" && self.right instanceof AST_String
diff --git a/test/compress/asm.js b/test/compress/asm.js
index c3018485..f392e78e 100644
--- a/test/compress/asm.js
+++ b/test/compress/asm.js
@@ -92,7 +92,7 @@ asm_mixed: {
function logSum(start, end) {
start = 0 | start, end = 0 | end;
var sum = 0, p = 0, q = 0;
- for (p = start << 3, q = end << 3; (0 | q) > (0 | p); p = p + 8 | 0) sum += +log(values[p >> 3]);
+ for (p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) sum += +log(values[p >> 3]);
return +sum;
}
function geometricMean(start, end) {
diff --git a/test/compress/comparing.js b/test/compress/comparing.js
new file mode 100644
index 00000000..c51fac31
--- /dev/null
+++ b/test/compress/comparing.js
@@ -0,0 +1,76 @@
+keep_comparisons: {
+ options = {
+ comparisons: true,
+ unsafe_comps: false
+ }
+ input: {
+ var obj1 = {
+ valueOf: function() {triggeredFirst();}
+ }
+ var obj2 = {
+ valueOf: function() {triggeredSecond();}
+ }
+ var result1 = obj1 <= obj2;
+ var result2 = obj1 < obj2;
+ var result3 = obj1 >= obj2;
+ var result4 = obj1 > obj2;
+ }
+ expect: {
+ var obj1 = {
+ valueOf: function() {triggeredFirst();}
+ }
+ var obj2 = {
+ valueOf: function() {triggeredSecond();}
+ }
+ var result1 = obj1 <= obj2;
+ var result2 = obj1 < obj2;
+ var result3 = obj1 >= obj2;
+ var result4 = obj1 > obj2;
+ }
+}
+
+keep_comparisons_with_unsafe_comps: {
+ options = {
+ comparisons: true,
+ unsafe_comps: true
+ }
+ input: {
+ var obj1 = {
+ valueOf: function() {triggeredFirst();}
+ }
+ var obj2 = {
+ valueOf: function() {triggeredSecond();}
+ }
+ var result1 = obj1 <= obj2;
+ var result2 = obj1 < obj2;
+ var result3 = obj1 >= obj2;
+ var result4 = obj1 > obj2;
+ }
+ expect: {
+ var obj1 = {
+ valueOf: function() {triggeredFirst();}
+ }
+ var obj2 = {
+ valueOf: function() {triggeredSecond();}
+ }
+ var result1 = obj2 >= obj1;
+ var result2 = obj2 > obj1;
+ var result3 = obj1 >= obj2;
+ var result4 = obj1 > obj2;
+ }
+}
+
+dont_change_in_or_instanceof_expressions: {
+ input: {
+ 1 in 1;
+ null in null;
+ 1 instanceof 1;
+ null instanceof null;
+ }
+ expect: {
+ 1 in 1;
+ null in null;
+ 1 instanceof 1;
+ null instanceof null;
+ }
+} \ No newline at end of file