/* Inserts in order a chunk into the free list. Caller adjusts heap state */ static PmReturn_t heap_linkToFreelist(pPmHeapDesc_t pchunk) { uint16_t size; pPmHeapDesc_t pscan; /* Ensure the object is already free */ C_ASSERT(OBJ_GET_FREE(pchunk) != 0); /* If free list is empty, add to head of list */ if (pmHeap.pfreelist == C_NULL) { pmHeap.pfreelist = pchunk; pchunk->next = C_NULL; pchunk->prev = C_NULL; return PM_RET_OK; } /* Scan free list for insertion point */ pscan = pmHeap.pfreelist; size = OBJ_GET_SIZE(pchunk); while ((OBJ_GET_SIZE(pscan) < size) && (pscan->next != C_NULL)) { pscan = pscan->next; } /* * Insert chunk after the scan chunk (next is NULL). * This is a slightly rare case where the last chunk in the free list * is smaller than the chunk being freed. */ if (size > OBJ_GET_SIZE(pscan)) { pchunk->next = pscan->next; pscan->next = pchunk; pchunk->prev = pscan; } /* Insert chunk before the scan chunk */ else { pchunk->next = pscan; pchunk->prev = pscan->prev; /* If chunk will be first item in free list */ if (pscan->prev == C_NULL) { pmHeap.pfreelist = pchunk; } else { pscan->prev->next = pchunk; } pscan->prev = pchunk; } return PM_RET_OK; }
/* * Marks the given object and the objects it references. * * @param pobj Any non-free heap object * @return Return code */ static PmReturn_t heap_gcMarkObj(pPmObj_t pobj) { PmReturn_t retval = PM_RET_OK; int16_t i = 0; int16_t n; PmType_t type; /* Return if ptr is null or object is already marked */ if (pobj == C_NULL) { return retval; } if (OBJ_GET_GCVAL(pobj) == pmHeap.gcval) { return retval; } /* The pointer must be within the heap (native frame is special case) */ C_ASSERT((((uint8_t *)pobj >= &pmHeap.base[0]) && ((uint8_t *)pobj <= &pmHeap.base[PM_HEAP_SIZE])) || ((uint8_t *)pobj == (uint8_t *)&gVmGlobal.nativeframe)); /* The object must not already be free */ C_ASSERT(OBJ_GET_FREE(pobj) == 0); type = (PmType_t)OBJ_GET_TYPE(pobj); switch (type) { /* Objects with no references to other objects */ case OBJ_TYPE_NON: case OBJ_TYPE_INT: case OBJ_TYPE_FLT: case OBJ_TYPE_STR: case OBJ_TYPE_NOB: case OBJ_TYPE_BOOL: case OBJ_TYPE_CIO: OBJ_SET_GCVAL(pobj, pmHeap.gcval); break; case OBJ_TYPE_TUP: i = ((pPmTuple_t)pobj)->length; /* Mark tuple head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark each obj in tuple */ while (--i >= 0) { retval = heap_gcMarkObj(((pPmTuple_t)pobj)->val[i]); PM_RETURN_IF_ERROR(retval); } break; case OBJ_TYPE_LST: /* Mark the list */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the seglist */ retval = heap_gcMarkObj((pPmObj_t)((pPmList_t)pobj)->val); break; case OBJ_TYPE_DIC: /* Mark the dict head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the keys seglist */ retval = heap_gcMarkObj((pPmObj_t)((pPmDict_t)pobj)->d_keys); PM_RETURN_IF_ERROR(retval); /* Mark the vals seglist */ retval = heap_gcMarkObj((pPmObj_t)((pPmDict_t)pobj)->d_vals); break; case OBJ_TYPE_COB: /* Mark the code obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the names tuple */ retval = heap_gcMarkObj((pPmObj_t)((pPmCo_t)pobj)->co_names); PM_RETURN_IF_ERROR(retval); /* Mark the consts tuple */ retval = heap_gcMarkObj((pPmObj_t)((pPmCo_t)pobj)->co_consts); PM_RETURN_IF_ERROR(retval); /* #122: Mark the code image if it is in RAM */ if (((pPmCo_t)pobj)->co_memspace == MEMSPACE_RAM) { retval = heap_gcMarkObj((pPmObj_t) (((pPmCo_t)pobj)->co_codeimgaddr)); PM_RETURN_IF_ERROR(retval); } #ifdef HAVE_CLOSURES /* #256: Add support for closures */ /* Mark the cellvars tuple */ retval = heap_gcMarkObj((pPmObj_t)((pPmCo_t)pobj)->co_cellvars); #endif /* HAVE_CLOSURES */ break; case OBJ_TYPE_MOD: case OBJ_TYPE_FXN: /* Module and Func objs are implemented via the PmFunc_t */ /* Mark the func obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the code obj */ retval = heap_gcMarkObj((pPmObj_t)((pPmFunc_t)pobj)->f_co); PM_RETURN_IF_ERROR(retval); /* Mark the attr dict */ retval = heap_gcMarkObj((pPmObj_t)((pPmFunc_t)pobj)->f_attrs); PM_RETURN_IF_ERROR(retval); /* Mark the globals dict */ retval = heap_gcMarkObj((pPmObj_t)((pPmFunc_t)pobj)->f_globals); PM_RETURN_IF_ERROR(retval); #ifdef HAVE_DEFAULTARGS /* Mark the default args tuple */ retval = heap_gcMarkObj((pPmObj_t)((pPmFunc_t)pobj)->f_defaultargs); PM_RETURN_IF_ERROR(retval); #endif /* HAVE_DEFAULTARGS */ #ifdef HAVE_CLOSURES /* #256: Mark the closure tuple */ retval = heap_gcMarkObj((pPmObj_t)((pPmFunc_t)pobj)->f_closure); #endif /* HAVE_CLOSURES */ break; #ifdef HAVE_CLASSES case OBJ_TYPE_CLI: /* Mark the obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the class */ retval = heap_gcMarkObj((pPmObj_t)((pPmInstance_t)pobj)->cli_class); PM_RETURN_IF_ERROR(retval); /* Mark the attrs dict */ retval = heap_gcMarkObj((pPmObj_t)((pPmInstance_t)pobj)->cli_attrs); break; case OBJ_TYPE_MTH: /* Mark the obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the instance */ retval = heap_gcMarkObj((pPmObj_t)((pPmMethod_t)pobj)->m_instance); PM_RETURN_IF_ERROR(retval); /* Mark the func */ retval = heap_gcMarkObj((pPmObj_t)((pPmMethod_t)pobj)->m_func); PM_RETURN_IF_ERROR(retval); /* Mark the attrs dict */ retval = heap_gcMarkObj((pPmObj_t)((pPmMethod_t)pobj)->m_attrs); break; case OBJ_TYPE_CLO: /* Mark the obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the attrs dict */ retval = heap_gcMarkObj((pPmObj_t)((pPmClass_t)pobj)->cl_attrs); PM_RETURN_IF_ERROR(retval); /* Mark the base tuple */ retval = heap_gcMarkObj((pPmObj_t)((pPmClass_t)pobj)->cl_bases); break; #endif /* HAVE_CLASSES */ /* * An obj in ram should not be of these types. * Images arrive in RAM as string objects (image is array of bytes) */ case OBJ_TYPE_CIM: case OBJ_TYPE_NIM: PM_RAISE(retval, PM_RET_EX_SYS); return retval; case OBJ_TYPE_FRM: { pPmObj_t *ppobj2 = C_NULL; /* Mark the frame obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the previous frame, if this isn't a generator's frame */ /* Issue #129: Fix iterator losing its object */ if ((((pPmFrame_t)pobj)->fo_func->f_co->co_flags & CO_GENERATOR) == 0) { retval = heap_gcMarkObj((pPmObj_t)((pPmFrame_t)pobj)->fo_back); PM_RETURN_IF_ERROR(retval); } /* Mark the fxn obj */ retval = heap_gcMarkObj((pPmObj_t)((pPmFrame_t)pobj)->fo_func); PM_RETURN_IF_ERROR(retval); /* Mark the blockstack */ retval = heap_gcMarkObj((pPmObj_t) ((pPmFrame_t)pobj)->fo_blockstack); PM_RETURN_IF_ERROR(retval); /* Mark the attrs dict */ retval = heap_gcMarkObj((pPmObj_t)((pPmFrame_t)pobj)->fo_attrs); PM_RETURN_IF_ERROR(retval); /* Mark the globals dict */ retval = heap_gcMarkObj((pPmObj_t)((pPmFrame_t)pobj)->fo_globals); PM_RETURN_IF_ERROR(retval); /* Mark each obj in the locals list and the stack */ ppobj2 = ((pPmFrame_t)pobj)->fo_locals; while (ppobj2 < ((pPmFrame_t)pobj)->fo_sp) { retval = heap_gcMarkObj(*ppobj2); PM_RETURN_IF_ERROR(retval); ppobj2++; } break; } case OBJ_TYPE_BLK: /* Mark the block obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the next block in the stack */ retval = heap_gcMarkObj((pPmObj_t)((pPmBlock_t)pobj)->next); break; case OBJ_TYPE_SGL: /* Mark the seglist obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the seglist's segments */ n = ((pSeglist_t)pobj)->sl_length; pobj = (pPmObj_t)((pSeglist_t)pobj)->sl_rootseg; for (i = 0; i < n; i++) { /* Mark the segment item */ retval = heap_gcMarkObj(((pSegment_t)pobj)->s_val[i % SEGLIST_OBJS_PER_SEG]); PM_RETURN_IF_ERROR(retval); /* Mark the segment obj head */ if ((i % SEGLIST_OBJS_PER_SEG) == 0) { OBJ_SET_GCVAL(pobj, pmHeap.gcval); } /* Point to the next segment */ else if ((i % SEGLIST_OBJS_PER_SEG) == (SEGLIST_OBJS_PER_SEG - 1)) { pobj = (pPmObj_t)((pSegment_t)pobj)->next; if (pobj == C_NULL) { break; } } } break; case OBJ_TYPE_SQI: /* Mark the sequence iterator obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the sequence */ retval = heap_gcMarkObj(((pPmSeqIter_t)pobj)->si_sequence); break; case OBJ_TYPE_THR: /* Mark the thread obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the current frame */ retval = heap_gcMarkObj((pPmObj_t)((pPmThread_t)pobj)->pframe); break; case OBJ_TYPE_NFM: /* * Mark the obj desc. This doesn't really do much since the * native frame is declared static (not from the heap), but this * is here in case that ever changes */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the native frame's remaining fields if active */ if (gVmGlobal.nativeframe.nf_active) { /* Mark the frame stack */ retval = heap_gcMarkObj((pPmObj_t) gVmGlobal.nativeframe.nf_back); PM_RETURN_IF_ERROR(retval); /* Mark the function object */ retval = heap_gcMarkObj((pPmObj_t) gVmGlobal.nativeframe.nf_func); PM_RETURN_IF_ERROR(retval); /* Mark the stack object */ retval = heap_gcMarkObj(gVmGlobal.nativeframe.nf_stack); PM_RETURN_IF_ERROR(retval); /* Mark the args to the native func */ for (i = 0; i < NATIVE_GET_NUM_ARGS(); i++) { retval = heap_gcMarkObj(gVmGlobal.nativeframe.nf_locals[i]); PM_RETURN_IF_ERROR(retval); } } break; #ifdef HAVE_BYTEARRAY case OBJ_TYPE_BYA: OBJ_SET_GCVAL(pobj, pmHeap.gcval); retval = heap_gcMarkObj((pPmObj_t)((pPmBytearray_t)pobj)->val); break; case OBJ_TYPE_BYS: OBJ_SET_GCVAL(pobj, pmHeap.gcval); break; #endif /* HAVE_BYTEARRAY */ default: /* There should be no invalid types */ PM_RAISE(retval, PM_RET_EX_SYS); break; } return retval; }
/* * Reclaims any object that does not have a current mark. * Puts it in the free list. Coalesces all contiguous free chunks. */ static PmReturn_t heap_gcSweep(void) { PmReturn_t retval; pPmObj_t pobj; pPmHeapDesc_t pchunk; uint16_t totalchunksize; #if USE_STRING_CACHE retval = heap_purgeStringCache(pmHeap.gcval); #endif /* Start at the base of the heap */ pobj = (pPmObj_t)pmHeap.base; while ((uint8_t *)pobj < &pmHeap.base[PM_HEAP_SIZE]) { /* Skip to the next unmarked or free chunk within the heap */ while (!OBJ_GET_FREE(pobj) && (OBJ_GET_GCVAL(pobj) == pmHeap.gcval) && ((uint8_t *)pobj < &pmHeap.base[PM_HEAP_SIZE])) { pobj = (pPmObj_t)((uint8_t *)pobj + OBJ_GET_SIZE(pobj)); } /* Stop if reached the end of the heap */ if ((uint8_t *)pobj >= &pmHeap.base[PM_HEAP_SIZE]) { break; } /* Accumulate the sizes of all consecutive unmarked or free chunks */ totalchunksize = 0; /* Coalesce all contiguous free chunks */ pchunk = (pPmHeapDesc_t)pobj; while (OBJ_GET_FREE(pchunk) || (!OBJ_GET_FREE(pchunk) && (OBJ_GET_GCVAL(pchunk) != pmHeap.gcval))) { if ((totalchunksize + OBJ_GET_SIZE(pchunk)) > HEAP_MAX_FREE_CHUNK_SIZE) { break; } totalchunksize = totalchunksize + OBJ_GET_SIZE(pchunk); /* * If the chunk is already free, unlink it because its size * is about to change */ if (OBJ_GET_FREE(pchunk)) { retval = heap_unlinkFromFreelist(pchunk); PM_RETURN_IF_ERROR(retval); } /* Otherwise free and reclaim the unmarked chunk */ else { OBJ_SET_TYPE(pchunk, 0); OBJ_SET_FREE(pchunk, 1); } C_DEBUG_PRINT(VERBOSITY_HIGH, "heap_gcSweep(), id=%p, s=%d\n", pchunk, OBJ_GET_SIZE(pchunk)); /* Proceed to the next chunk */ pchunk = (pPmHeapDesc_t) ((uint8_t *)pchunk + OBJ_GET_SIZE(pchunk)); /* Stop if it's past the end of the heap */ if ((uint8_t *)pchunk >= &pmHeap.base[PM_HEAP_SIZE]) { break; } } /* Set the heap descriptor data */ OBJ_SET_FREE(pobj, 1); OBJ_SET_SIZE(pobj, totalchunksize); /* Insert chunk into free list */ retval = heap_linkToFreelist((pPmHeapDesc_t)pobj); PM_RETURN_IF_ERROR(retval); /* Continue to the next chunk */ pobj = (pPmObj_t)pchunk; } return PM_RET_OK; }
/* * Reclaims any object that doesn't have a current mark. * Puts it in the free list. Coalesces all contiguous free chunks. */ static PmReturn_t heap_gcSweep(void) { PmReturn_t retval; pPmObj_t pobj; pPmHeapDesc_t pchunk; uint16_t totalchunksize; uint16_t additionalheapsize; /* Start at the base of the heap */ pobj = (pPmObj_t)pmHeap.base; while ((uint8_t *)pobj < &pmHeap.base[HEAP_SIZE]) { /* Skip to the next unmarked or free chunk within the heap */ while (!OBJ_GET_FREE(pobj) && (OBJ_GET_GCVAL(pobj) == pmHeap.gcval) && ((uint8_t *)pobj < &pmHeap.base[HEAP_SIZE])) { pobj = (pPmObj_t)((uint8_t *)pobj + OBJ_GET_SIZE(pobj)); /*printf("Object is at addr <%x>\n",(uint32_t)pobj);*/ #if 0 printf("pobj=");obj_print(pobj,0);printf("; type=%x; size=%x\n",OBJ_GET_TYPE(pobj),OBJ_GET_SIZE(pobj)); #endif } /* Stop if reached the end of the heap */ if ((uint8_t *)pobj >= &pmHeap.base[HEAP_SIZE]) { break; } /* Accumulate the sizes of all consecutive unmarked or free chunks */ totalchunksize = 0; additionalheapsize = 0; /* Coalesce all contiguous free chunks */ pchunk = (pPmHeapDesc_t)pobj; while (OBJ_GET_FREE(pchunk) || (!OBJ_GET_FREE(pchunk) && (OBJ_GET_GCVAL(pchunk) != pmHeap.gcval))) { totalchunksize += OBJ_GET_SIZE(pchunk); /* * If the chunk is already free, unlink it because its size * is about to change */ if (OBJ_GET_FREE(pchunk)) { retval = heap_unlinkFromFreelist(pchunk); PM_RETURN_IF_ERROR(retval); } /* Otherwise free and reclaim the unmarked chunk */ else { OBJ_SET_TYPE(pchunk, 0); OBJ_SET_FREE(pchunk, 1); additionalheapsize += OBJ_GET_SIZE(pchunk); } C_DEBUG_PRINT(VERBOSITY_HIGH, "heap_gcSweep(), id=%p, s=%d\n", pchunk, OBJ_GET_SIZE(pchunk)); #if 0 /* It's possible for 0-sized chunks to exist (which makes no sense) TODO:solve */ /* They result in infinite loops, so we must curtail them */ if (OBJ_GET_SIZE(pchunk) == 0) { break; } #endif /* Proceed to the next chunk */ pchunk = (pPmHeapDesc_t) ((uint8_t *)pchunk + OBJ_GET_SIZE(pchunk)); /* Stop if it's past the end of the heap */ if ((uint8_t *)pchunk >= &pmHeap.base[HEAP_SIZE]) { break; } } /* Adjust the heap stats */ pmHeap.avail += additionalheapsize; /* Set the heap descriptor data */ OBJ_SET_FREE(pobj, 1); OBJ_SET_SIZE(pobj, totalchunksize); #if 0 /* avoid loops by breaking on 0-size */ if (totalchunksize == 0) { break; } #endif /* Insert chunk into free list */ retval = heap_linkToFreelist((pPmHeapDesc_t)pobj); PM_RETURN_IF_ERROR(retval); /* Continue to the next chunk */ pobj = (pPmObj_t)pchunk; } return PM_RET_OK; }
/* * Marks the given object and the objects it references. * * @param pobj Any non-free heap object * @return Return code */ static PmReturn_t heap_gcMarkObj(pPmObj_t pobj) { PmReturn_t retval = PM_RET_OK; int16_t i = 0; PmType_t type; /* Return if ptr is null or object is already marked */ if ((pobj == C_NULL) || (OBJ_GET_GCVAL(pobj) == pmHeap.gcval)) { return retval; } /* The pointer must be within the heap (native frame is special case) */ C_ASSERT((((uint8_t *)pobj >= &pmHeap.base[0]) && ((uint8_t *)pobj <= &pmHeap.base[HEAP_SIZE])) || ((uint8_t *)pobj == (uint8_t *)&gVmGlobal.nativeframe)); /* The object must not already be free */ C_ASSERT(OBJ_GET_FREE(pobj) == 0); type = OBJ_GET_TYPE(pobj); /*if (type == 0x03){ printf("came across string; value is "); string_print(pobj,0); printf("\n"); }*/ switch (type) { /* Objects with no references to other objects */ case OBJ_TYPE_NON: case OBJ_TYPE_INT: case OBJ_TYPE_FLT: case OBJ_TYPE_NOB: OBJ_SET_GCVAL(pobj, pmHeap.gcval); break; case OBJ_TYPE_STR: OBJ_SET_GCVAL(pobj, pmHeap.gcval); #if USE_STRING_CACHE retval = heap_gcMarkObj((pPmObj_t)((pPmString_t)pobj)->next); #endif break; case OBJ_TYPE_TUP: i = ((pPmTuple_t)pobj)->length; /* Mark tuple head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark each obj in tuple */ while (--i >= 0) { retval = heap_gcMarkObj(((pPmTuple_t)pobj)->val[i]); PM_RETURN_IF_ERROR(retval); } break; case OBJ_TYPE_LST: /* Mark the list */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the seglist */ retval = heap_gcMarkObj((pPmObj_t)((pPmList_t)pobj)->val); break; case OBJ_TYPE_DIC: /* Mark the dict head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the keys seglist */ retval = heap_gcMarkObj((pPmObj_t)((pPmDict_t)pobj)->d_keys); PM_RETURN_IF_ERROR(retval); /* Mark the vals seglist */ retval = heap_gcMarkObj((pPmObj_t)((pPmDict_t)pobj)->d_vals); break; case OBJ_TYPE_COB: /* Mark the code obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the names tuple */ retval = heap_gcMarkObj((pPmObj_t)((pPmCo_t)pobj)->co_names); PM_RETURN_IF_ERROR(retval); /* Mark the consts tuple */ retval = heap_gcMarkObj((pPmObj_t)((pPmCo_t)pobj)->co_consts); PM_RETURN_IF_ERROR(retval); /* #122: Mark the code image if it is in RAM */ if (((pPmCo_t)pobj)->co_memspace == MEMSPACE_RAM) { /* Special case: The image is contained in a string object */ retval = heap_gcMarkObj((pPmObj_t) (((pPmCo_t)pobj)->co_codeimgaddr - sizeof(PmObjDesc_t))); } break; case OBJ_TYPE_MOD: case OBJ_TYPE_FXN: /* Module and Func objs are implemented via the PmFunc_t */ /* Mark the func obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the code obj */ retval = heap_gcMarkObj((pPmObj_t)((pPmFunc_t)pobj)->f_co); PM_RETURN_IF_ERROR(retval); /* Mark the attr dict */ retval = heap_gcMarkObj((pPmObj_t)((pPmFunc_t)pobj)->f_attrs); PM_RETURN_IF_ERROR(retval); /* Mark the default args tuple */ retval = heap_gcMarkObj((pPmObj_t) ((pPmFunc_t)pobj)->f_defaultargs); break; case OBJ_TYPE_CLO: case OBJ_TYPE_CLI: case OBJ_TYPE_EXN: /* Mark the obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the attrs dict */ retval = heap_gcMarkObj((pPmObj_t)((pPmClass_t)pobj)->attrs); PM_RETURN_IF_ERROR(retval); /* Mark the name */ retval = heap_gcMarkObj((pPmObj_t)((pPmClass_t)pobj)->name); PM_RETURN_IF_ERROR(retval); /* Mark the bases */ retval = heap_gcMarkObj((pPmObj_t)((pPmClass_t)pobj)->bases); break; /* * An obj in ram should not be of these types. * Images arrive in RAM as string objects (image is array of bytes) */ case OBJ_TYPE_CIM: case OBJ_TYPE_NIM: PM_RAISE(retval, PM_RET_EX_SYS); return retval; case OBJ_TYPE_FRM: { pPmObj_t *ppobj2 = C_NULL; /* Mark the frame obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the previous frame */ retval = heap_gcMarkObj((pPmObj_t)((pPmFrame_t)pobj)->fo_back); PM_RETURN_IF_ERROR(retval); /* Mark the fxn obj */ retval = heap_gcMarkObj((pPmObj_t)((pPmFrame_t)pobj)->fo_func); PM_RETURN_IF_ERROR(retval); /* Mark the blockstack */ retval = heap_gcMarkObj((pPmObj_t) ((pPmFrame_t)pobj)->fo_blockstack); PM_RETURN_IF_ERROR(retval); /* Mark the attrs dict */ retval = heap_gcMarkObj((pPmObj_t)((pPmFrame_t)pobj)->fo_attrs); PM_RETURN_IF_ERROR(retval); /* Mark the globals dict */ retval = heap_gcMarkObj((pPmObj_t)((pPmFrame_t)pobj)->fo_globals); PM_RETURN_IF_ERROR(retval); /* Mark each obj in the locals list and the stack */ ppobj2 = ((pPmFrame_t)pobj)->fo_locals; while (ppobj2 < ((pPmFrame_t)pobj)->fo_sp) { retval = heap_gcMarkObj(*ppobj2); PM_RETURN_IF_ERROR(retval); ppobj2++; } break; } case OBJ_TYPE_BLK: /* Mark the block obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the next block in the stack */ retval = heap_gcMarkObj((pPmObj_t)((pPmBlock_t)pobj)->next); break; case OBJ_TYPE_SEG: /* Mark the segment obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark each obj in the segment */ for (i = 0; i < SEGLIST_OBJS_PER_SEG; i++) { retval = heap_gcMarkObj(((pSegment_t)pobj)->s_val[i]); PM_RETURN_IF_ERROR(retval); } /* Mark the next segment */ retval = heap_gcMarkObj((pPmObj_t)((pSegment_t)pobj)->next); break; case OBJ_TYPE_SGL: /* Mark the seglist obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the root segment */ retval = heap_gcMarkObj((pPmObj_t)((pSeglist_t)pobj)->sl_rootseg); break; case OBJ_TYPE_SQI: /* Mark the sequence iterator obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the sequence */ retval = heap_gcMarkObj(((pPmSeqIter_t)pobj)->si_sequence); break; case OBJ_TYPE_THR: /* Mark the thread obj head */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the current frame */ retval = heap_gcMarkObj((pPmObj_t)((pPmThread_t)pobj)->pframe); break; case OBJ_TYPE_NFM: /* * Mark the obj desc. This doesn't really do much since the * native frame is declared static (not from the heap), but this * is here in case that ever changes */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the native frame's fields if it is active */ if (gVmGlobal.nativeframe.nf_active) { /* Mark the frame stack */ retval = heap_gcMarkObj((pPmObj_t) gVmGlobal.nativeframe.nf_back); PM_RETURN_IF_ERROR(retval); /* Mark the function object */ retval = heap_gcMarkObj((pPmObj_t) gVmGlobal.nativeframe.nf_func); PM_RETURN_IF_ERROR(retval); /* Mark the stack object */ retval = heap_gcMarkObj(gVmGlobal.nativeframe.nf_stack); PM_RETURN_IF_ERROR(retval); /* Mark the args to the native func */ for (i = 0; i < NATIVE_GET_NUM_ARGS(); i++) { retval = heap_gcMarkObj(gVmGlobal.nativeframe .nf_locals[i]); PM_RETURN_IF_ERROR(retval); } } break; case OBJ_TYPE_IIS: /* Mark the obj desc */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the name string */ retval = heap_gcMarkObj((pPmObj_t)((pPmImgInfo_t)pobj)->ii_name); PM_RETURN_IF_ERROR(retval); /* Mark the next node in the list */ retval = heap_gcMarkObj((pPmObj_t)((pPmImgInfo_t)pobj)->next); break; case OBJ_TYPE_SLC: /* Mark the obj desc */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the indices */ retval = heap_gcMarkObj((pPmObj_t)((pPmSlice_t)pobj)->start); PM_RETURN_IF_ERROR(retval); retval = heap_gcMarkObj((pPmObj_t)((pPmSlice_t)pobj)->end); PM_RETURN_IF_ERROR(retval); retval = heap_gcMarkObj((pPmObj_t)((pPmSlice_t)pobj)->step); PM_RETURN_IF_ERROR(retval); break; case OBJ_TYPE_MTH: /* Mark the obj desc */ OBJ_SET_GCVAL(pobj, pmHeap.gcval); /* Mark the function and self */ retval = heap_gcMarkObj((pPmObj_t)((pPmMethod_t)pobj)->self); PM_RETURN_IF_ERROR(retval); retval = heap_gcMarkObj((pPmObj_t)((pPmMethod_t)pobj)->func); PM_RETURN_IF_ERROR(retval); break; } return retval; }