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.
108 lines
2.2 KiB
108 lines
2.2 KiB
/*
|
|
* Bug testcase for a stringtable memory leak in Duktape 0.7.0, reported
|
|
* by Greg Burns.
|
|
*
|
|
* In Duktape 0.7.0 the mark-and-sweep handling of strings, specifically
|
|
* the sweeping of strings, would mark a string reachable and never clear
|
|
* the reachable flag. As a result, strings were never garbage collected
|
|
* if they had once been marked reachable. This doesn't easily show any
|
|
* symptoms when reference counting is in use (circular references are
|
|
* needed). When only mark-and-sweep is used, the problem is easy to
|
|
* reproduce.
|
|
*
|
|
* The test1() variant below works when reference counting is enabled,
|
|
* even when the bug is present. test2() uses circular references to
|
|
* cause the bug to manifest itself even with reference counting.
|
|
*
|
|
* This testcase can also be run manually with valgrind massif to see that
|
|
* the memory behavior is correct.
|
|
*/
|
|
|
|
/*---
|
|
{
|
|
"custom": true,
|
|
"slow": true
|
|
}
|
|
---*/
|
|
|
|
/*===
|
|
0
|
|
1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
6
|
|
7
|
|
8
|
|
9
|
|
10
|
|
11
|
|
12
|
|
13
|
|
14
|
|
15
|
|
0
|
|
1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
6
|
|
7
|
|
8
|
|
9
|
|
10
|
|
11
|
|
12
|
|
13
|
|
14
|
|
15
|
|
===*/
|
|
|
|
var count = 0;
|
|
var kilo = Array.prototype.join.call({ length: 1024 + 1 }, 'x');
|
|
var meg = Array.prototype.join.call({ length: 1024 + 1 }, kilo); // 1 meg prefix
|
|
|
|
function createUniqueString() {
|
|
var res = meg + (count++);
|
|
return res;
|
|
}
|
|
|
|
function test1() {
|
|
// Goes through 16G of strings
|
|
for (var i = 0; i < 16; i++) {
|
|
print(i);
|
|
for (var j = 0; j < 1024; j++) {
|
|
var ignore = createUniqueString();
|
|
Duktape.gc();
|
|
}
|
|
}
|
|
}
|
|
|
|
function test2() {
|
|
for (var i = 0; i < 16; i++) {
|
|
print(i);
|
|
for (var j = 0; j < 1024; j++) {
|
|
var obj1 = {};
|
|
var obj2 = { str: createUniqueString(), ref: obj1 };
|
|
obj1.ref = obj2; // circular reference, object contains string to collect
|
|
Duktape.gc(); // force collection once: string gets marked reachable
|
|
obj1 = undefined;
|
|
obj2 = undefined; // unreachable but not collected when refcounts enabled
|
|
Duktape.gc(); // force collection: should be collected but isn't
|
|
}
|
|
}
|
|
}
|
|
|
|
try {
|
|
test1();
|
|
} catch (e) {
|
|
print(e);
|
|
}
|
|
|
|
try {
|
|
test2();
|
|
} catch (e) {
|
|
print(e);
|
|
}
|
|
|