Browse Source

add more variety to large expression test

pull/2/head
Sami Vaarala 11 years ago
parent
commit
d832fe5043
  1. 213
      ecmascript-testcases/test-misc-large-expressions.js

213
ecmascript-testcases/test-misc-large-expressions.js

@ -5,7 +5,11 @@
* If a large expression contains function calls deep inside the expression * If a large expression contains function calls deep inside the expression
* structure, register shuffling alone is not enough to handle the call * structure, register shuffling alone is not enough to handle the call
* correctly: an ordinary DUK_OP_CALL cannot reach the registers, so an * correctly: an ordinary DUK_OP_CALL cannot reach the registers, so an
* indirect call is needed instead. * indirect call is needed instead. Object literal related instructions
* (NEWOBJ, NEWARR, MPUTOBJ, MPUTARR) also need some indirection.
*
* In addition to indirection, several instructions need shuffling which
* is exercised in this test case.
* *
* To exercise all the indirect call related opcodes: * To exercise all the indirect call related opcodes:
* *
@ -17,71 +21,19 @@
* *
* Constructor calls (DUK_OP_NEW) are independent of call setups, so it * Constructor calls (DUK_OP_NEW) are independent of call setups, so it
* suffices to test DUK_OP_NEW with any of the call setup variants. * suffices to test DUK_OP_NEW with any of the call setup variants.
*
* Other opcodes to test:
*
* - NEWARR and MPUTARR: array literal
* - NEWOBJ and MPUTOBJ: object literal
* - LDTHIS: 'this'
* - LDTRUE and LDFALSE: true and false literals
* - TYPEOF: typeof of a local variable or a constant
* - TYPEOFID: typeof of a non-local variable
*/ */
/*=== /*===
large expressions large expressions
no func calls
100
200
300
400
500
600
700
800
900
1000
1100
1200
1300
1400
1500
1600
1700
1800
1900
first func call
100
200
300
400
500
600
700
800
900
1000
1100
1200
1300
1400
1500
1600
1700
1800
1900
last func call
100
200
300
400
500
600
700
800
900
1000
1100
1200
1300
1400
1500
1600
1700
1800
1900
all func calls
100 100
200 200
300 300
@ -110,25 +62,60 @@ function returnTrue() {
function MyConstructor() { function MyConstructor() {
} }
function buildExpr(count, firstFuncCall, lastFuncCall, allFuncCalls, callStyle) { function buildExpr(count) {
var terms = []; var terms = [];
var i; var i;
for (i = 0; i < count; i++) { /* The returned expression is a giant &&-expression with a lot of terms.
if (allFuncCalls || (i == 0) && firstFuncCall || (i == count - 1) && lastFuncCall) { * Every term should be "truthy" to keep the evaluation going. The last
if (callStyle === 'newextvar') { * term is always a fixed string which is tested against.
terms.push('new MyConstructor("dummy")'); */
} else if (callStyle === 'extvar') {
terms.push('returnTrue("dummy")'); for (i = 0; i < count - 1; i++) {
} else if (callStyle === 'locvar') { switch (i % 10) {
terms.push('returnTrueLocal("dummy")'); case 0:
} else { // constructor call
terms.push('obj.ret("dummy")'); terms.push('new MyConstructor("dummy")');
} break;
} else { case 1:
terms.push('true'); // external variable call
} terms.push('returnTrue("dummy")');
break;
case 2:
// local variable call
terms.push('returnTrueLocal("dummy")');
break;
case 3:
// property call
terms.push('obj.ret("dummy")');
break;
case 4:
// object literal
terms.push('{foo:1,bar:2}');
break;
case 5:
// array literal
terms.push('["foo","bar"]');
break;
case 6:
// true and false
terms.push('(false || true)');
break;
case 7:
// typeof local variable
terms.push('typeof returnTrueLocal'); // 'function' -> truthy
break;
case 8:
// typeof constant
terms.push('typeof "strval"'); // 'string' -> truthy
break;
case 9:
// typeof non-local variable
terms.push('typeof Math'); // 'string' -> truthy
break;
}
} }
terms.push('"last-term"');
return "(function() {\n" + return "(function() {\n" +
" var returnTrueLocal = returnTrue;\n" + " var returnTrueLocal = returnTrue;\n" +
@ -139,78 +126,32 @@ function buildExpr(count, firstFuncCall, lastFuncCall, allFuncCalls, callStyle)
function largeExprTest() { function largeExprTest() {
var i, limit; var i, limit;
var expr;
function test(expr, name, expectTrue) { var res;
var res;
try {
res = eval(expr);
if (expectTrue && res !== true) {
throw new Error('result does not match expected value');
} else if (!expectTrue && (typeof res !== 'object')) {
// Constructor calls return an object ("truthy")
throw new Error('result does not match expected value');
}
} catch (e) {
print('failed ' + name + ': ' + e);
throw e;
}
}
// Compiler recursion limit currently bites around 2500 // Compiler recursion limit currently bites around 2500
limit = 2000; limit = 2000;
print('no func calls');
for (i = 1; i < limit; i++) {
if ((i % 100) == 0) { print(i); }
test(buildExpr(i, false, false, false, 'ignore'), 'no-func-calls:' + i, true);
}
print('first func call');
for (i = 2; i < limit; i++) { for (i = 2; i < limit; i++) {
if ((i % 100) == 0) { print(i); } if ((i % 100) == 0) { print(i); }
test(buildExpr(i, true, false, false, 'newextvar'), 'first-func-call-newextvar:' + i, true);
test(buildExpr(i, true, false, false, 'extvar'), 'first-func-call-extvar:' + i, true);
test(buildExpr(i, true, false, false, 'locvar'), 'first-func-call-locvar:' + i, true);
test(buildExpr(i, true, false, false, 'object'), 'first-func-call-object:' + i, true);
}
print('last func call'); expr = buildExpr(i);
for (i = 2; i < limit; i++) { //print(expr);
if ((i % 100) == 0) { print(i); }
test(buildExpr(i, false, true, false, 'newextvar'), 'last-func-call-newextvar:' + i, false);
test(buildExpr(i, false, true, false, 'extvar'), 'last-func-call-extvar:' + i, true);
test(buildExpr(i, false, true, false, 'locvar'), 'last-func-call-locvar:' + i, true);
test(buildExpr(i, false, true, false, 'object'), 'last-func-call-object:' + i, true);
}
print('all func calls'); try {
for (i = 2; i < limit; i++) { res = eval(expr)
if ((i % 100) == 0) { print(i); } if (res !== 'last-term') {
test(buildExpr(i, false, false, true, 'newextvar'), 'all-func-calls-newextvar:' + i, false); throw new Error('result does not match expected value, result was: ' + res);
test(buildExpr(i, false, false, true, 'extvar'), 'all-func-calls-extvar:' + i, true); }
test(buildExpr(i, false, false, true, 'locvar'), 'all-func-calls-locvar:' + i, true); } catch (e) {
test(buildExpr(i, false, false, true, 'object'), 'all-func-calls-object:' + i, true); print('failed with i=' + i + ': ' + e);
throw e;
}
} }
} }
print('large expressions') print('large expressions')
if (false) {
print(buildExpr(3, false, false, false, null));
print(buildExpr(3, true, false, false, 'newextvar'));
print(buildExpr(3, true, false, false, 'extvar'));
print(buildExpr(3, true, false, false, 'locvar'));
print(buildExpr(3, true, false, false, 'object'));
print(buildExpr(3, false, true, false, 'newextvar'));
print(buildExpr(3, false, true, false, 'extvar'));
print(buildExpr(3, false, true, false, 'locvar'));
print(buildExpr(3, false, true, false, 'object'));
print(buildExpr(3, false, false, true, 'newextvar'));
print(buildExpr(3, false, false, true, 'extvar'));
print(buildExpr(3, false, false, true, 'locvar'));
print(buildExpr(3, false, false, true, 'object'));
}
try { try {
largeExprTest(); largeExprTest();
} catch (e) { } catch (e) {

Loading…
Cancel
Save