mirror of
https://github.com/urbit/shrub.git
synced 2024-12-13 16:03:36 +03:00
u3: refactors unifying equality unification
This commit is contained in:
parent
a5599eaab1
commit
aa25024e83
@ -316,16 +316,25 @@ _sing_one(u3_noun* a, u3_noun* b)
|
||||
static void
|
||||
_sung_one(u3_noun* a, u3_noun* b)
|
||||
{
|
||||
|
||||
// already unified, we're done
|
||||
//
|
||||
if ( *a == *b ) {
|
||||
return;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// stash our road pointer
|
||||
//
|
||||
// XX do we need signal exclusion to safely mutate u3R?
|
||||
//
|
||||
u3_road* rod_u = u3R;
|
||||
|
||||
while ( 1 ) {
|
||||
//
|
||||
// we can't perform this kind of butchery on the home road,
|
||||
// where asynchronous things can allocate.
|
||||
//
|
||||
// XX anything other than u3t_samp?
|
||||
//
|
||||
if ( u3R == &u3H->rod_u ) {
|
||||
break;
|
||||
}
|
||||
@ -333,7 +342,14 @@ _sung_one(u3_noun* a, u3_noun* b)
|
||||
c3_o asr_o = u3a_is_senior(u3R, *a);
|
||||
c3_o bsr_o = u3a_is_senior(u3R, *b);
|
||||
|
||||
if ( _(asr_o) && _(bsr_o) ) {
|
||||
// both [a] and [b] are in a senior road
|
||||
//
|
||||
// we can't switch to a senior road if GC is enabled,
|
||||
// as we may be forced to (temporarily) leak a reference.
|
||||
//
|
||||
if ( (c3y == asr_o) &&
|
||||
(c3y == bsr_o) )
|
||||
{
|
||||
//
|
||||
// when unifying on a higher road, we can't free nouns,
|
||||
// because we can't track junior nouns that point into
|
||||
@ -349,46 +365,70 @@ _sung_one(u3_noun* a, u3_noun* b)
|
||||
// itself, constantly running into duplicates.
|
||||
//
|
||||
#ifdef U3_MEMORY_DEBUG
|
||||
return;
|
||||
break;
|
||||
#else
|
||||
u3R = u3to(u3_road, u3R->par_p);
|
||||
continue;
|
||||
#endif
|
||||
}
|
||||
|
||||
if ( _(asr_o) && !_(bsr_o) ){
|
||||
if ( u3R == rod_u ) { u3z(*b); }
|
||||
*b = *a;
|
||||
}
|
||||
if ( _(bsr_o) && !_(asr_o) ) {
|
||||
if ( u3R == rod_u ) { u3z(*a); }
|
||||
*a = *b;
|
||||
}
|
||||
if ( u3a_is_north(u3R) ) {
|
||||
if ( *a <= *b ) {
|
||||
u3k(*a);
|
||||
if ( u3R == rod_u ) { u3z(*b); }
|
||||
*b = *a;
|
||||
} else {
|
||||
u3k(*b);
|
||||
if ( u3R == rod_u ) { u3z(*a); }
|
||||
*a = *b;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( *a >= *b ) {
|
||||
u3k(*a);
|
||||
if ( u3R == rod_u ) { u3z(*b); }
|
||||
// if we're on our road, we can free
|
||||
//
|
||||
// it's safe to leak on inner roads;
|
||||
// memory will be reclaimed when we return home.
|
||||
//
|
||||
// XX we should stash [b] on its road and lose it
|
||||
// when return to that road.
|
||||
//
|
||||
c3_t loc_t = ( u3R == rod_u );
|
||||
|
||||
// keep [a]; it's senior
|
||||
//
|
||||
if ( (c3y == asr_o) &&
|
||||
(c3n == bsr_o) )
|
||||
{
|
||||
if ( loc_t ) { u3z(*b); }
|
||||
*b = *a;
|
||||
} else {
|
||||
u3k(*b);
|
||||
if ( u3R == rod_u ) { u3z(*a); }
|
||||
}
|
||||
// keep [b]; it's senior
|
||||
//
|
||||
else if ( (c3n == asr_o) &&
|
||||
(c3y == bsr_o) )
|
||||
{
|
||||
if ( loc_t ) { u3z(*a); }
|
||||
*a = *b;
|
||||
}
|
||||
// both are on the current road; gain a reference
|
||||
// to whichever we keep
|
||||
//
|
||||
else {
|
||||
// keep [a]; it's deeper in the heap
|
||||
//
|
||||
// (N && >) || (S && <)
|
||||
//
|
||||
if ( (*a > *b) ==
|
||||
(c3y == u3a_is_north(u3R)) )
|
||||
{
|
||||
u3k(*a);
|
||||
if ( loc_t ) { u3z(*b); }
|
||||
*b = *a;
|
||||
}
|
||||
// keep [b]; it's deeper in the heap
|
||||
//
|
||||
else {
|
||||
u3k(*b);
|
||||
if ( loc_t ) { u3z(*a); }
|
||||
*a = *b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// restore our road pointer
|
||||
//
|
||||
u3R = rod_u;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user