Uncovered and fixed a subtle bug in free_reg//3.

non_alloc/1 for words that don't change the ref count of registers and can be delegated to their semantic relation.
This commit is contained in:
Simon Forman 2020-01-29 11:04:22 -08:00
parent 95df1fda8c
commit 8d1797c1b6
1 changed files with 19 additions and 10 deletions

View File

@ -672,7 +672,7 @@ get_reg(Reg, reggy(FreePool0, References, V), reggy(FreePool, [Reg|References],
free_reg(Reg, reggy(FreePool0, References0, V0), reggy(FreePool, References, V)) --> [],
{ select(Reg, References0, References),
( member(Reg, References) % If reg is still in use
-> FreePool= FreePool0 % we can't free it yet
-> FreePool= FreePool0, V0=V % we can't free it yet
; FreePool=[Reg|FreePool0], % otherwise we put it back in the pool.
del_assoc(Reg, V0, _, V)
)}.
@ -722,27 +722,32 @@ def_compile(Def, E, Si, So, FP0, FP) -->
append(Body, E, Eo)},
thun_compile(Eo, Si, So, FP0, FP).
% swap (et. al.) doesn't change register refs nor introspect values
% so we can delegate its effect to the semantic relation.
non_alloc(swap).
non_alloc(rollup).
non_alloc(rolldown).
% Functions delegate to a per-function compilation relation.
func_compile(+, E, [A, B|S], So, FP0, FP) --> !,
% If either register A or B is only used once we can reuse it.
( {reg_used_once(B, FP0)} -> [add(B, A, B)], free_reg(A, FP0, FP3), {Si=[B|S]}
; {reg_used_once(A, FP0)} -> [add(A, A, B)], free_reg(B, FP0, FP3), {Si=[A|S]}
; get_reg(R, FP0, FP1), [add(R, A, B)],
free_reg(A, FP1, FP2),
free_reg(B, FP2, FP3),
( {reg_used_once(B, FP0)} -> [add(B, A, B)], free_reg(A, FP0, FP4), {Si=[B|S]}
; {reg_used_once(A, FP0)} -> [add(A, A, B)], free_reg(B, FP0, FP4), {Si=[A|S]}
; get_reg(R, FP0, FP1), [add(R, A, B)],
assoc_reg(R, int(_), FP1, FP2),
free_reg(A, FP2, FP3),
free_reg(B, FP3, FP4),
{Si=[R|S]}
),
% Update value in the context?
thun_compile(E, Si, So, FP3, FP).
thun_compile(E, Si, So, FP4, FP).
func_compile(dup, E, [A|S], So, FP0, FP) --> !,
add_ref(A, FP0, FP1),
thun_compile(E, [A, A|S], So, FP1, FP).
func_compile(swap, E, [A, B|S], So, FP0, FP) --> !,
thun_compile( E, [B, A|S], So, FP0, FP).
func_compile(pop, E, [A|S], So, FP0, FP) --> !,
free_reg(A, FP0, FP1),
thun_compile(E, S, So, FP1, FP).
@ -751,6 +756,10 @@ func_compile(cons, E, [List, Item|S], So, FP0, FP) --> !,
% allocate a cons cell
thun_compile(E, S, So, FP0, FP).
func_compile(Func, E, Si, So, FP0, FP) -->
{ non_alloc(Func), !, func(Func, Si, S) },
thun_compile(E, S, So, FP0, FP).
func_compile(_Func, E, Si, So, FP0, FP) -->
% look up function, compile it...
{Si = S},