port: advance VC6 typeobject frontier and preserve regression coverage
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Guard insert_to_freepool's C89 locals and complete operation order."""
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
source = Path(sys.argv[1]).read_text()
|
||||
match = re.search(
|
||||
r"\ninsert_to_freepool\(poolp pool\)\s*\{(.*?)\n\}",
|
||||
source, re.S,
|
||||
)
|
||||
assert match, "insert_to_freepool definition not found"
|
||||
body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S)
|
||||
declarations = """
|
||||
poolp next;
|
||||
poolp prev;
|
||||
struct arena_object *ao;
|
||||
uint nf;
|
||||
struct arena_object* lastnf;
|
||||
struct arena_object* p;
|
||||
"""
|
||||
assert body.split()[:len(declarations.split())] == declarations.split(), (
|
||||
"insert_to_freepool must declare all six locals without initializers at function entry"
|
||||
)
|
||||
|
||||
# Assignments stay at the original evaluation points, including p inside its
|
||||
# branch. Preserve every assertion, branch, return, and pointer update, as well
|
||||
# as the radix-tree conditional, throughout all four arena-management cases.
|
||||
expected = declarations + """
|
||||
next = pool->nextpool;
|
||||
prev = pool->prevpool;
|
||||
next->prevpool = prev;
|
||||
prev->nextpool = next;
|
||||
ao = &arenas[pool->arenaindex];
|
||||
pool->nextpool = ao->freepools;
|
||||
ao->freepools = pool;
|
||||
nf = ao->nfreepools;
|
||||
lastnf = nfp2lasta[nf];
|
||||
assert((nf == 0 && lastnf == NULL) ||
|
||||
(nf > 0 &&
|
||||
lastnf != NULL &&
|
||||
lastnf->nfreepools == nf &&
|
||||
(lastnf->nextarena == NULL ||
|
||||
nf < lastnf->nextarena->nfreepools)));
|
||||
if (lastnf == ao) {
|
||||
p = ao->prevarena;
|
||||
nfp2lasta[nf] = (p != NULL && p->nfreepools == nf) ? p : NULL;
|
||||
}
|
||||
ao->nfreepools = ++nf;
|
||||
if (nf == ao->ntotalpools && ao->nextarena != NULL) {
|
||||
assert(ao->prevarena == NULL ||
|
||||
ao->prevarena->address != 0);
|
||||
assert(ao ->nextarena == NULL ||
|
||||
ao->nextarena->address != 0);
|
||||
if (ao->prevarena == NULL) {
|
||||
usable_arenas = ao->nextarena;
|
||||
assert(usable_arenas == NULL ||
|
||||
usable_arenas->address != 0);
|
||||
}
|
||||
else {
|
||||
assert(ao->prevarena->nextarena == ao);
|
||||
ao->prevarena->nextarena =
|
||||
ao->nextarena;
|
||||
}
|
||||
if (ao->nextarena != NULL) {
|
||||
assert(ao->nextarena->prevarena == ao);
|
||||
ao->nextarena->prevarena =
|
||||
ao->prevarena;
|
||||
}
|
||||
ao->nextarena = unused_arena_objects;
|
||||
unused_arena_objects = ao;
|
||||
#if WITH_PYMALLOC_RADIX_TREE
|
||||
arena_map_mark_used(ao->address, 0);
|
||||
#endif
|
||||
_PyObject_Arena.free(_PyObject_Arena.ctx,
|
||||
(void *)ao->address, ARENA_SIZE);
|
||||
ao->address = 0;
|
||||
--narenas_currently_allocated;
|
||||
return;
|
||||
}
|
||||
if (nf == 1) {
|
||||
ao->nextarena = usable_arenas;
|
||||
ao->prevarena = NULL;
|
||||
if (usable_arenas)
|
||||
usable_arenas->prevarena = ao;
|
||||
usable_arenas = ao;
|
||||
assert(usable_arenas->address != 0);
|
||||
if (nfp2lasta[1] == NULL) {
|
||||
nfp2lasta[1] = ao;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (nfp2lasta[nf] == NULL) {
|
||||
nfp2lasta[nf] = ao;
|
||||
}
|
||||
if (ao == lastnf) {
|
||||
return;
|
||||
}
|
||||
assert(ao->nextarena != NULL);
|
||||
if (ao->prevarena != NULL) {
|
||||
assert(ao->prevarena->nextarena == ao);
|
||||
ao->prevarena->nextarena = ao->nextarena;
|
||||
}
|
||||
else {
|
||||
assert(usable_arenas == ao);
|
||||
usable_arenas = ao->nextarena;
|
||||
}
|
||||
ao->nextarena->prevarena = ao->prevarena;
|
||||
ao->prevarena = lastnf;
|
||||
ao->nextarena = lastnf->nextarena;
|
||||
if (ao->nextarena != NULL) {
|
||||
ao->nextarena->prevarena = ao;
|
||||
}
|
||||
lastnf->nextarena = ao;
|
||||
assert(ao->nextarena == NULL || nf <= ao->nextarena->nfreepools);
|
||||
assert(ao->prevarena == NULL || nf > ao->prevarena->nfreepools);
|
||||
assert(ao->nextarena == NULL || ao->nextarena->prevarena == ao);
|
||||
assert((usable_arenas == ao && ao->prevarena == NULL)
|
||||
|| ao->prevarena->nextarena == ao);
|
||||
"""
|
||||
assert body.split() == expected.split(), (
|
||||
"preserve insert_to_freepool evaluation, assertion, control-flow, and pointer-update order"
|
||||
)
|
||||
print("obmalloc insert_to_freepool entry declarations and original operation order: PASS")
|
||||
Reference in New Issue
Block a user