diff options
Diffstat (limited to 'rts/Stable.c')
-rw-r--r-- | rts/Stable.c | 46 |
1 files changed, 27 insertions, 19 deletions
diff --git a/rts/Stable.c b/rts/Stable.c index e1807faa72..0dade10105 100644 --- a/rts/Stable.c +++ b/rts/Stable.c @@ -278,28 +278,36 @@ freeStablePtr(StgStablePtr sp) /* * get at the real stuff...remove indirections. - * It untags pointers before dereferencing and - * retags the real stuff with its tag (if there - * is any) when returning. - * - * ToDo: move to a better home. */ -static -StgClosure* -removeIndirections(StgClosure* p) +static StgClosure* +removeIndirections (StgClosure* p) { - StgWord tag = GET_CLOSURE_TAG(p); - StgClosure* q = UNTAG_CLOSURE(p); - - while (get_itbl(q)->type == IND || - get_itbl(q)->type == IND_STATIC || - get_itbl(q)->type == IND_PERM) { - q = ((StgInd *)q)->indirectee; - tag = GET_CLOSURE_TAG(q); - q = UNTAG_CLOSURE(q); - } + StgClosure* q; + + while (1) + { + q = UNTAG_CLOSURE(p); + + switch (get_itbl(q)->type) { + case IND: + case IND_STATIC: + case IND_PERM: + p = ((StgInd *)q)->indirectee; + continue; + + case BLACKHOLE: + p = ((StgInd *)q)->indirectee; + if (GET_CLOSURE_TAG(p) != 0) { + continue; + } else { + break; + } - return TAG_CLOSURE(tag,q); + default: + break; + } + return p; + } } StgWord |