v8/test/mjsunit/wasm/asm-wasm-switch.js
aseemgarg 1d37d4216b [wasm] optimized switch implementation in asm.js to wasm builder
This change implements switch as a balanced if/else tree or break table or
hybrid. A lot of asm.js modules are expected to extensively use switch
alongside function tables that can benefit from a better implementation.

BUG=v8:4203
TEST=mjsunit/asm-wasm
R=titzer@chromium.org,bradnelson@chromium.org,ahaas@chromium.org
LOG=N

Review URL: https://codereview.chromium.org/1838973002

Cr-Commit-Position: refs/heads/master@{#35455}
2016-04-13 21:56:42 +00:00

443 lines
9.7 KiB
JavaScript

// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose-wasm
(function TestSwitch() {
function asmModule() {
"use asm"
function caller() {
var ret = 0;
var x = 7;
switch (x) {
case 1: return 0;
case 7: {
ret = 12;
break;
}
default: return 0;
}
switch (x) {
case 1: return 0;
case 8: return 0;
default: ret = (ret + 11)|0;
}
return ret|0;
}
return {caller:caller};
}
var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
assertEquals(23, wasm.caller());
})();
(function TestSwitchFallthrough() {
function asmModule() {
"use asm"
function caller() {
var x = 17;
var ret = 0;
switch (x) {
case 17:
case 14: ret = 39;
case 1: ret = (ret + 3)|0;
case 4: break;
default: ret = (ret + 1)|0;
}
return ret|0;
}
return {caller:caller};
}
var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
assertEquals(42, wasm.caller());
})();
(function TestNestedSwitch() {
function asmModule() {
"use asm"
function caller() {
var x = 3;
var y = -13;
switch (x) {
case 1: return 0;
case 3: {
switch (y) {
case 2: return 0;
case -13: return 43;
default: return 0;
}
}
default: return 0;
}
return 0;
}
return {caller:caller};
}
var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
assertEquals(43, wasm.caller());
})();
(function TestSwitchWithDefaultOnly() {
function asmModule() {
"use asm";
function main(x) {
x = x|0;
switch(x|0) {
default: return -10;
}
return 0;
}
return {
main: main,
};
}
var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
assertEquals(-10, wasm.main(2));
assertEquals(-10, wasm.main(54));
})();
(function TestEmptySwitch() {
function asmModule() {
"use asm";
function main(x) {
x = x|0;
switch(x|0) {
}
return 73;
}
return {
main: main,
};
}
var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
assertEquals(73, wasm.main(7));
})();
(function TestSwitchWithBrTable() {
function asmModule() {
"use asm";
function main(x) {
x = x|0;
switch(x|0) {
case 14: return 23;
case 12: return 25;
case 15: return 29;
case 19: return 34;
case 18: return 17;
case 16: return 16;
default: return -1;
}
return 0;
}
return {
main: main,
};
}
var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
assertEquals(25, wasm.main(12));
assertEquals(23, wasm.main(14));
assertEquals(29, wasm.main(15));
assertEquals(16, wasm.main(16));
assertEquals(17, wasm.main(18));
assertEquals(34, wasm.main(19));
assertEquals(-1, wasm.main(-1));
})();
(function TestSwitchWithBalancedTree() {
function asmModule() {
"use asm";
function main(x) {
x = x|0;
switch(x|0) {
case 5: return 52;
case 1: return 11;
case 6: return 63;
case 9: return 19;
case -4: return -4;
}
return 0;
}
return {
main: main,
};
}
var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
assertEquals(-4, wasm.main(-4));
assertEquals(11, wasm.main(1));
assertEquals(52, wasm.main(5));
assertEquals(63, wasm.main(6));
assertEquals(19, wasm.main(9));
assertEquals(0, wasm.main(11));
})();
(function TestSwitchHybrid() {
function asmModule() {
"use asm";
function main(x) {
x = x|0;
switch(x|0) {
case 1: return -4;
case 2: return 23;
case 3: return 32;
case 4: return 14;
case 7: return 17;
case 10: return 10;
case 11: return 121;
case 12: return 112;
case 13: return 31;
case 16: return 16;
default: return -1;
}
return 0;
}
return {
main: main,
};
}
var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
assertEquals(-4, wasm.main(1));
assertEquals(23, wasm.main(2));
assertEquals(32, wasm.main(3));
assertEquals(14, wasm.main(4));
assertEquals(17, wasm.main(7));
assertEquals(10, wasm.main(10));
assertEquals(121, wasm.main(11));
assertEquals(112, wasm.main(12));
assertEquals(31, wasm.main(13));
assertEquals(16, wasm.main(16));
assertEquals(-1, wasm.main(20));
})();
(function TestSwitchFallthroughWithBrTable() {
function asmModule() {
"use asm";
function main(x) {
x = x|0;
var ret = 0;
switch(x|0) {
case 1: {
ret = 21;
break;
}
case 2: {
ret = 12;
break;
}
case 3: {
ret = 43;
}
case 4: {
ret = 54;
break;
}
default: {
ret = 10;
break;
}
}
return ret|0;
}
return {
main: main,
};
}
var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
assertEquals(12, wasm.main(2));
assertEquals(10, wasm.main(10));
assertEquals(54, wasm.main(3));
})();
(function TestSwitchFallthroughHybrid() {
function asmModule() {
"use asm";
function main(x) {
x = x|0;
var ret = 0;
switch(x|0) {
case 1: {
ret = 1;
break;
}
case 2: {
ret = 2;
break;
}
case 3: {
ret = 3;
break;
}
case 4: {
ret = 4;
}
case 7: {
ret = 7;
break;
}
case 10: {
ret = 10;
}
case 16: {
ret = 16;
break;
}
case 17: {
ret = 17;
break;
}
case 18: {
ret = 18;
break;
}
case 19: {
ret = 19;
}
default: {
ret = -1;
break;
}
}
return ret|0;
}
return {
main: main,
};
}
var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
assertEquals(7, wasm.main(4));
assertEquals(16, wasm.main(10));
assertEquals(-1, wasm.main(19));
assertEquals(-1, wasm.main(23));
})();
(function TestSwitchHybridWithNoDefault() {
function asmModule() {
"use asm";
function main(x) {
x = x|0;
var ret = 19;
switch(x|0) {
case 1: {
ret = 1;
break;
}
case 2: {
ret = 2;
break;
}
case 3: {
ret = 3;
break;
}
case 4: {
ret = 4;
break;
}
case 7: {
ret = 7;
break;
}
}
return ret|0;
}
return {
main: main,
};
}
var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
assertEquals(2, wasm.main(2));
assertEquals(7, wasm.main(7));
assertEquals(19, wasm.main(-1));
})();
(function TestLargeSwitch() {
function LargeSwitchGenerator(begin, end, gap, handle_case) {
var str = "function asmModule() {\
\"use asm\";\
function main(x) {\
x = x|0;\
switch(x|0) {";
for (var i = begin; i <= end; i = i + gap) {
str = str.concat("case ", i.toString(), ": ", handle_case(i));
}
str = str.concat("default: return -1;\
}\
return -2;\
}\
return {main: main}; }");
var wasm = Wasm.instantiateModuleFromAsm(str);
return wasm;
}
var handle_case = function(k) {
return "return ".concat(k, ";");
}
var wasm = LargeSwitchGenerator(0, 513, 1, handle_case);
for (var i = 0; i <= 513; i++) {
assertEquals(i, wasm.main(i));
}
assertEquals(-1, wasm.main(-1));
wasm = LargeSwitchGenerator(0, 1024, 3, handle_case);
for (var i = 0; i <= 1024; i = i + 3) {
assertEquals(i, wasm.main(i));
}
assertEquals(-1, wasm.main(-1));
wasm = LargeSwitchGenerator(-2147483648, -2147483000, 1, handle_case);
for (var i = -2147483648; i <= -2147483000; i++) {
assertEquals(i, wasm.main(i));
}
assertEquals(-1, wasm.main(-1));
assertEquals(-1, wasm.main(214748647));
wasm = LargeSwitchGenerator(-2147483648, -2147483000, 3, handle_case);
for (var i = -2147483648; i <= -2147483000; i = i + 3) {
assertEquals(i, wasm.main(i));
}
assertEquals(-1, wasm.main(-1));
assertEquals(-1, wasm.main(214748647));
wasm = LargeSwitchGenerator(2147483000, 2147483647, 1, handle_case);
for (var i = 2147483000; i <= 2147483647; i++) {
assertEquals(i, wasm.main(i));
}
assertEquals(-1, wasm.main(-1));
assertEquals(-1, wasm.main(-214748647));
wasm = LargeSwitchGenerator(2147483000, 2147483647, 4, handle_case);
for (var i = 2147483000; i <= 2147483647; i = i + 4) {
assertEquals(i, wasm.main(i));
}
assertEquals(-1, wasm.main(-1));
assertEquals(-1, wasm.main(-214748647));
handle_case = function(k) {
if (k != 7) return "return ".concat(k, ";");
else return "break;";
}
wasm = LargeSwitchGenerator(0, 1499, 7, handle_case);
for (var i = 0; i <= 1499; i = i + 7) {
if (i == 7) assertEquals(-2, wasm.main(i));
else assertEquals(i, wasm.main(i));
}
assertEquals(-1, wasm.main(-1));
handle_case = function(k) {
if (k != 56) return "break;";
else return "return 23;";
}
wasm = LargeSwitchGenerator(0, 638, 2, handle_case);
for (var i = 0; i <= 638; i = i + 2) {
if (i == 56) assertEquals(23, wasm.main(i));
else assertEquals(-2, wasm.main(i));
}
assertEquals(-1, wasm.main(-1));
})();