mirror of https://github.com/svaarala/duktape.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
2.9 KiB
118 lines
2.9 KiB
10 years ago
|
/*
|
||
|
* https://github.com/svaarala/duktape/issues/115
|
||
|
*
|
||
|
* Corner case in compiler:
|
||
|
*
|
||
|
* - Pass 1 indicates shuffling is not needed
|
||
|
* - Pass 2 turns out to need shuffling after all
|
||
|
* - Shuffle registers will all be zero
|
||
|
*
|
||
|
* If an instruction needs just one shuffle register, it will use register 0
|
||
|
* and corrupt function 1st argument. If an instruction needs multiple shuffle
|
||
|
* registers, they will trample on each other and can result e.g in "CSPROPI
|
||
|
* target is not a number".
|
||
|
*
|
||
|
* The root issue is that because variables are mapped to registers, pass 2
|
||
|
* may disagree on whether or not shuffling is needed: pass 1 has more registers
|
||
|
* available.
|
||
|
*/
|
||
|
|
||
|
/*===
|
||
|
test 1
|
||
|
test 2
|
||
|
test 3
|
||
|
done
|
||
|
===*/
|
||
|
|
||
|
function genfunc(nvar, nconst, gencsprop, avoidmputobj) {
|
||
|
var res = [];
|
||
|
var i;
|
||
|
|
||
|
res.push('(function test(arg1) {');
|
||
|
|
||
|
// arg1 eats one registers, variables eat a register each
|
||
|
for (i = 0; i < nvar; i++) {
|
||
|
res.push(' var v' + i + ';');
|
||
|
}
|
||
|
|
||
|
// each constant eats a constant index
|
||
|
for (i = 0; i < nconst; i++) {
|
||
|
res.push(' v0 = "tempstr' + i + '";');
|
||
|
}
|
||
|
|
||
|
// generate a CSPROP(I)
|
||
|
if (gencsprop) {
|
||
|
if (avoidmputobj) {
|
||
|
res.push(' v' + (nvar - 1) + ' = Object.create(Object.prototype);');
|
||
|
res.push(' v' + (nvar - 1) + '.fn = function() { return "csprop return"; };');
|
||
|
} else {
|
||
|
res.push(' v' + (nvar - 1) + ' = { fn: function() { return "csprop return"; } };');
|
||
|
}
|
||
|
res.push(' void v' + (nvar - 1) + '.fn();');
|
||
|
}
|
||
|
|
||
|
res.push(' return arg1;');
|
||
|
res.push('})');
|
||
|
return res.join('\n');
|
||
|
}
|
||
|
|
||
|
function test() {
|
||
|
var i, j, src, fn, ret;
|
||
|
|
||
|
// Triggers clobbering of arg1
|
||
|
print('test 1');
|
||
|
for (i = 1; i < 512; i++) {
|
||
|
try {
|
||
|
src = genfunc(i, i, false, false);
|
||
|
fn = eval(src);
|
||
|
ret = fn('foo');
|
||
|
if (ret != 'foo') {
|
||
|
print(i, ret);
|
||
|
}
|
||
|
} catch (e) {
|
||
|
print(i, e);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Triggers "MPUTOBJ target not an object"
|
||
|
print('test 2');
|
||
|
for (i = 1; i < 512; i++) {
|
||
|
try {
|
||
|
src = genfunc(i, i, true, false);
|
||
|
fn = eval(src);
|
||
|
ret = fn('foo');
|
||
|
if (ret != 'foo') {
|
||
|
print(i, ret);
|
||
|
}
|
||
|
} catch (e) {
|
||
|
print(i, e);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Tried to trigger the CSPROPI issue (but avoid triggering the MPUTOBJ
|
||
|
// issue above), but didn't work
|
||
|
print('test 3');
|
||
|
for (i = 200; i < 400; i++) {
|
||
|
for (j = -10; j <= 10; j++) {
|
||
|
try {
|
||
|
src = genfunc(i, i + j, true, false);
|
||
|
fn = eval(src);
|
||
|
ret = fn('foo');
|
||
|
if (ret != 'foo') {
|
||
|
print(i, j, ret);
|
||
|
}
|
||
|
} catch (e) {
|
||
|
print(i, e);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
print('done');
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
test('foo');
|
||
|
} catch (e) {
|
||
|
print(e.stack || e);
|
||
|
}
|