summaryrefslogtreecommitdiff
path: root/rts/Stable.c
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2013-02-27 09:57:09 +0000
committerSimon Peyton Jones <simonpj@microsoft.com>2013-02-27 09:57:09 +0000
commit47d226544fc3fb11d024740a162f8ae4e1d044c9 (patch)
tree8a024b97de71216f6b3606d3cda7bf16ae1f98a6 /rts/Stable.c
parent7b5e514d85c086be8dc6d938b526c97b6ced56eb (diff)
parent0ee31659afe7a6819f9eb5e233f98e5592f1b439 (diff)
downloadhaskell-tc-arrows.tar.gz
Merge remote-tracking branch 'origin/master' into tc-arrowstc-arrows
Diffstat (limited to 'rts/Stable.c')
-rw-r--r--rts/Stable.c46
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