- StgWord sn = lookupStableName(p);
- StgWord weight, n;
- weight = stable_ptr_table[sn].weight;
- if (weight == 0) {
- weight = (StgWord)1 << (BITS_IN(StgWord)-1);
- stable_ptr_table[sn].weight = weight;
- return (StgStablePtr)(sn + (BITS_IN(StgWord) << STABLEPTR_WEIGHT_SHIFT));
- }
- else if (weight == 1) {
- barf("getStablePtr: too light");
- }
- else {
- weight /= 2;
- /* find log2(weight) */
- for (n = 0; weight != 1; n++) {
- weight >>= 1;
+ StgWord sn;
+
+ sn = lookupStableName(p);
+ stable_ptr_table[sn].ref++;
+ return (StgStablePtr)(sn);
+}
+
+void
+freeStablePtr(StgStablePtr sp)
+{
+ snEntry *sn = &stable_ptr_table[(StgWord)sp];
+
+ ASSERT((StgWord)sp < SPT_size && sn->addr != NULL && sn->ref > 0);
+
+ sn->ref--;
+
+ // If this entry has no StableName attached, then just free it
+ // immediately. This is important; it might be a while before the
+ // next major GC which actually collects the entry.
+ if (sn->sn_obj == NULL && sn->ref == 0) {
+ freeStableName(sn);