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.
 
 
 
 
 
 

122 lines
2.5 KiB

/*
* Test Duktape specific mark-and-sweep initiated finalizer calling.
* In particular, test that "rescuing" and re-finalizing works
* correctly.
*
* Note: print messages for both finalizers are identical because
* the order in which they run is not guaranteed.
*
* Manipulation of 'a' and 'b' are in helper functions to guarantee
* that no references are held in temporary registers. Cleanup of
* references in temporary registers is currently NOT guaranteed
* while a function is running.
*/
/*---
{
"custom": true
}
---*/
/*===
object
object
finalizer: rescue
finalizer: rescue
object
object
finalizer: rescue
finalizer: rescue
object
object
finalizer: no rescue
finalizer: no rescue
undefined
undefined
===*/
var a;
var b;
var rescue;
function finalizer_a(x) {
if (rescue) {
print('finalizer: rescue');
a = x;
} else {
print('finalizer: no rescue');
}
}
function finalizer_b(x) {
if (rescue) {
print('finalizer: rescue');
b = x;
} else {
print('finalizer: no rescue');
}
}
function init() {
a = { name: 'a' };
b = { name: 'b' };
/* circular refs */
a.ref = b;
b.ref = a;
__duk__.setFinalizer(a, finalizer_a);
__duk__.setFinalizer(b, finalizer_b);
}
function delrefs() {
a = undefined;
b = undefined;
}
function testrefs() {
print(typeof a);
print(typeof b);
//print(__duk__.refc(a));
//print(__duk__.refc(b));
}
init();
testrefs();
rescue = true;
delrefs();
__duk__.gc(); // both a and b should be unreachable and have their finalizers executed
__duk__.gc(); // a second gc will rescue the objects, allowing their finalizer to run again
testrefs();
/* Note: a single gc above is NOT sufficient to ensure that the finalizer will run again.
* Consider the sequence:
*
* 1. Value X is made unreachable and GC runs. GC marks the value as finalizable,
* and runs the finalizer. Finally, GC places value X back to heap_allocated
* with the flag FINALIZED.
*
* 2. Application code makes X unreachable again before GC runs again.
*
* 3. GC detects that X is FINALIZED and not reachable, and will thus not be rescued,
* nor will finalization run again.
*
* If there is a GC between steps 2 and 3 (as there is here) the value will be rescued
* and FINALIZED flag will be cleared. This causes the object to be finalized again in
* step 3.
*/
rescue = true;
delrefs();
__duk__.gc(); // again
__duk__.gc();
testrefs();
rescue = false;
delrefs();
__duk__.gc(); // swept immediately
testrefs();