void GfxPorts::processEngineHunkList(WorklistManager &wm) { for (PortList::const_iterator it = _windowList.begin(); it != _windowList.end(); ++it) { if ((*it)->isWindow()) { Window *wnd = ((Window *)*it); wm.push(wnd->hSaved1); wm.push(wnd->hSaved2); } } }
static void processWorkList(SegManager *segMan, WorklistManager &wm, const Common::Array<SegmentObj *> &heap) { SegmentId stackSegment = segMan->findSegmentByType(SEG_TYPE_STACK); while (!wm._worklist.empty()) { reg_t reg = wm._worklist.back(); wm._worklist.pop_back(); if (reg.getSegment() != stackSegment) { // No need to repeat this one debugC(kDebugLevelGC, "[GC] Checking %04x:%04x", PRINT_REG(reg)); if (reg.getSegment() < heap.size() && heap[reg.getSegment()]) { // Valid heap object? Find its outgoing references! wm.pushArray(heap[reg.getSegment()]->listAllOutgoingReferences(reg)); } } } }
reg_t_hash_map *find_all_used_references(EngineState *s) { SegManager *sm = s->seg_manager; reg_t_hash_map *normal_map = NULL; WorklistManager wm; uint i; // Initialise // Init: Registers wm.push(s->r_acc); wm.push(s->r_prev); // Init: Value Stack // We do this one by hand since the stack doesn't know the current execution stack { ExecStack &xs = s->_executionStack.back(); reg_t *pos; for (pos = s->stack_base; pos < xs.sp; pos++) wm.push(*pos); } debugC(2, kDebugLevelGC, "[GC] -- Finished adding value stack"); // Init: Execution Stack Common::List<ExecStack>::iterator iter; for (iter = s->_executionStack.begin(); iter != s->_executionStack.end(); ++iter) { ExecStack &es = *iter; if (es.type != EXEC_STACK_TYPE_KERNEL) { wm.push(es.objp); wm.push(es.sendp); if (es.type == EXEC_STACK_TYPE_VARSELECTOR) wm.push(*(es.getVarPointer(s))); } } debugC(2, kDebugLevelGC, "[GC] -- Finished adding execution stack"); // Init: Explicitly loaded scripts for (i = 1; i < sm->_heap.size(); i++) if (sm->_heap[i] && sm->_heap[i]->getType() == MEM_OBJ_SCRIPT) { Script *script = (Script *)sm->_heap[i]; if (script->lockers) { // Explicitly loaded? // Locals, if present wm.push(make_reg(script->locals_segment, 0)); // All objects (may be classes, may be indirectly reachable) for (uint obj_nr = 0; obj_nr < script->_objects.size(); obj_nr++) { wm.push(script->_objects[obj_nr].pos); } } } debugC(2, kDebugLevelGC, "[GC] -- Finished explicitly loaded scripts, done with root set\n"); // Run Worklist Algorithm while (!wm._worklist.empty()) { reg_t reg = wm._worklist.back(); wm._worklist.pop_back(); if (reg.segment != s->stack_segment) { // No need to repeat this one debugC(2, kDebugLevelGC, "[GC] Checking %04x:%04x\n", PRINT_REG(reg)); if (reg.segment < sm->_heap.size() && sm->_heap[reg.segment]) sm->_heap[reg.segment]->listAllOutgoingReferences(s, reg, &wm, add_outgoing_refs); } } // Normalise normal_map = normalise_hashmap_ptrs(sm, wm._map); return normal_map; }
AddrSet *findAllActiveReferences(EngineState *s) { assert(!s->_executionStack.empty()); WorklistManager wm; // Initialize registers wm.push(s->r_acc); wm.push(s->r_prev); // Initialize value stack // We do this one by hand since the stack doesn't know the current execution stack Common::List<ExecStack>::const_iterator iter = s->_executionStack.reverse_begin(); // Skip fake kernel stack frame if it's on top if ((*iter).type == EXEC_STACK_TYPE_KERNEL) --iter; assert((iter != s->_executionStack.end()) && ((*iter).type != EXEC_STACK_TYPE_KERNEL)); const StackPtr sp = iter->sp; for (reg_t *pos = s->stack_base; pos < sp; pos++) wm.push(*pos); debugC(kDebugLevelGC, "[GC] -- Finished adding value stack"); // Init: Execution Stack for (iter = s->_executionStack.begin(); iter != s->_executionStack.end(); ++iter) { const ExecStack &es = *iter; if (es.type != EXEC_STACK_TYPE_KERNEL) { wm.push(es.objp); wm.push(es.sendp); if (es.type == EXEC_STACK_TYPE_VARSELECTOR) wm.push(*(es.getVarPointer(s->_segMan))); } } debugC(kDebugLevelGC, "[GC] -- Finished adding execution stack"); const Common::Array<SegmentObj *> &heap = s->_segMan->getSegments(); uint heapSize = heap.size(); for (uint i = 1; i < heapSize; i++) { if (heap[i]) { // Init: Explicitly loaded scripts if (heap[i]->getType() == SEG_TYPE_SCRIPT) { Script *script = (Script *)heap[i]; if (script->getLockers()) { // Explicitly loaded? wm.pushArray(script->listObjectReferences()); } } #ifdef ENABLE_SCI32 // Init: Explicitly opted-out bitmaps else if (heap[i]->getType() == SEG_TYPE_BITMAP) { BitmapTable *bt = static_cast<BitmapTable *>(heap[i]); for (uint j = 0; j < bt->_table.size(); j++) { if (bt->_table[j].data && bt->_table[j].data->getShouldGC() == false) { wm.push(make_reg(i, j)); } } } #endif } } debugC(kDebugLevelGC, "[GC] -- Finished explicitly loaded scripts, done with root set"); processWorkList(s->_segMan, wm, heap); if (g_sci->_gfxPorts) g_sci->_gfxPorts->processEngineHunkList(wm); return normalizeAddresses(s->_segMan, wm._map); }
void add_outgoing_refs(void *refcon, reg_t addr) { WorklistManager *wm = (WorklistManager *)refcon; wm->push(addr); }