/* GC scanning for CID cache. I would prefer to have a hook to finalisation, so we can delete the cache entry when the object is GC'ed. */ static mps_res_t MPS_CALL cid0_scan(mps_ss_t ss, void *p, size_t s) { CID0_CACHE *cid_font ; UNUSED_PARAM(void *, p); UNUSED_PARAM(size_t, s); MPS_SCAN_BEGIN( ss ) for ( cid_font = cid0_font_cache ; cid_font ; cid_font = cid_font->next ) { VERIFY_OBJECT(cid_font, CID0_CACHE_NAME) ; /* If we're GC scanning, we are probably in a low-memory situation. Mark this font entry as freeable if it's not in use, fix the source pointer if it is. The MPS is not reentrant, so we can't actually free it now. */ if ( cid_font->font_data == NULL ) MPS_SCAN_UPDATE( cid_font->source, NULL ); else /* Fix the font data source objects, so they won't be collected. */ MPS_RETAIN( &cid_font->source, TRUE ); } MPS_SCAN_END( ss ); return MPS_RES_OK ; }
static mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit) { int i; INCCOUNT(SCANCALL_COUNT); MPS_SCAN_BEGIN(ss) { while (base < limit) { mycell *obj = base; mps_res_t res; mps_addr_t p; switch (obj->tag) { case MCpadsingle: INCCOUNT(SCANPS_COUNT); base = (mps_addr_t) ((char *) obj + MPS_PF_ALIGN); break; case MCpadmany: INCCOUNT(SCANPM_COUNT); base = (obj->padmulti.next); break; case MCdata: INCCOUNT(SCANOBJ_COUNT); /* actual scanning is done in here */ asserts(obj->data.id != MCerrorid, "scan on error object"); commentif(formatcomments, "scan %li at %p.", obj->data.id, base); for (i=0; i<(obj->data.numrefs); i++) { p = obj->data.ref[i].addr; if (p != NULL) { /* copy ref to p for fixing, to avoid a pun (although the pun would probably work fine almost everywhere) */ commentif(fixcomments, "fix %li[%i] -> %li", obj->data.id, i, obj->data.ref[i].id); res = MPS_FIX(ss, (mps_addr_t *) &p); if (res != MPS_RES_OK) return res; obj->data.ref[i].addr = p; } } base = (mps_addr_t) ((char *) obj + (obj->data.size)); break; case MCheart: INCCOUNT(SCANHEART_COUNT); base = (mps_addr_t) ((char *) obj + (obj->heart.size)); break; default: asserts(0, "scan: bizarre obj tag at %p.", obj); } } } MPS_SCAN_END(ss); return MPS_RES_OK; }
static mps_res_t MPS_CALL scan_saves(mps_ss_t ss, void *p, size_t s) { size_t i; saveRecord *sr; testlib_unused(p); testlib_unused(s); MPS_SCAN_BEGIN(ss) for (i = 0; i < MAXSAVELEVELS; ++i) for (sr = saves[i]; sr != NULL; sr = sr->next) { MPS_RETAIN((mps_addr_t*)&sr->slot, TRUE); MPS_SCAN_CALL((void)ps_scan(ss, &sr->oldvalue, &sr->oldvalue + 1)); } MPS_SCAN_END(ss); return MPS_RES_OK; }
static mps_res_t MPS_CALL xml_file_root_scan(mps_ss_t ss, void *p, size_t s) { XML_FILE *curr = first_file ; UNUSED_PARAM(void*, p) ; UNUSED_PARAM(size_t, s) ; MPS_SCAN_BEGIN(ss) ; while (curr != NULL) { MPS_RETAIN(&curr->flptr, TRUE); curr = curr->next ; } MPS_SCAN_END(ss) ; return MPS_RES_OK ; }
mps_res_t MPS_CALL ps_scan(mps_ss_t scan_state, mps_addr_t base, mps_addr_t limit) { register OBJECT *obj; OBJECT *obj_limit; register mps_addr_t ref; size_t len = 0; obj_limit = limit; MPS_SCAN_BEGIN( scan_state ) for ( obj = base; obj < obj_limit; obj++ ) { ref = (mps_addr_t)oOther( *obj ); switch ( oType( *obj )) { case ONAME: MPS_RETAIN( (mps_addr_t *)&oName( *obj ), TRUE ); continue; case OSAVE: continue; case ODICTIONARY: NOTREACHED; break; case OSTRING: { mps_addr_t ref_limit; ref_limit = ADDR_ADD( ref, theLen(*obj)); /* ref could point into the middle of a string, so align it. */ ref = PTR_ALIGN_DOWN( mps_addr_t, ref, MM_PS_ALIGNMENT ); len = ADDR_OFFSET( ref, ref_limit ); } break; case OFILE: NOTREACHED; break; case OARRAY: case OPACKEDARRAY: len = theLen(*obj) * sizeof( OBJECT ); break; case OGSTATE: case OLONGSTRING: NOTREACHED; break; default: continue; /* not a composite object */ } PS_MARK_BLOCK( scan_state, ref, len ); } MPS_SCAN_END(scan_state); return MPS_RES_OK; }
static mps_res_t MPS_CALL ps_typed_scan(mps_ss_t scan_state, mps_addr_t base, mps_addr_t limit) { TypeTag tag; mps_addr_t obj; size_t size; mps_res_t res = MPS_RES_OK; MPS_SCAN_BEGIN(scan_state) obj = base; while ( obj < limit ) { /* The tag is in the same place in all types, that's the point of it. */ tag = ( (struct generic_typed_object *)obj )->typetag; switch (tag) { case tag_NCACHE: { NAMECACHE *nc = (NAMECACHE *)obj; /* The next, dictobj and dictcpy fields are not fixed because we * don't use them in the test. The dictsid field is not fixed, * because it's a weak reference cleared by finalization. * * The length calculation is relying on the name being allocated * as a part of the NAMECACHE object. */ if (!MPS_IS_RETAINED((mps_addr_t*)&nc->dictval, TRUE)) nc->dictval = NULL; size = sizeof(NAMECACHE) + nc->len; } break; default: { HQFAIL("Invalid tag in scan"); res = MPS_RES_FAIL; size = 4; /* No value correct here; this to silence the compiler. */ break; } } obj = ADDR_ADD( obj, SIZE_ALIGN_UP( size, MM_PS_TYPED_ALIGNMENT )); } MPS_SCAN_END(scan_state); return res; }
static mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit) { MPS_SCAN_BEGIN(ss) MPS_SCAN_END(ss); return MPS_RES_OK; }