void InflatedHeaders::deallocate_headers(unsigned int mark) { std::vector<bool> chunk_marks(allocator_->chunks_.size(), false); diagnostics_.objects_ = 0; for(std::vector<int>::size_type i = 0; i < allocator_->chunks_.size(); ++i) { InflatedHeader* chunk = allocator_->chunks_[i]; for(size_t j = 0; j < allocator_->cChunkSize; j++) { InflatedHeader* header = &chunk[j]; if(header->marked_p(mark)) { chunk_marks[i] = true; diagnostics_.objects_++; } else { header->clear(); } } } allocator_->rebuild_freelist(&chunk_marks); diagnostics_.bytes_ = allocator_->in_use_ * sizeof(InflatedHeader); diagnostics_.modify(); }
void ObjectMemory::inflate_for_handle(STATE, ObjectHeader* obj, capi::Handle* handle) { utilities::thread::SpinLock::LockGuard guard(inflation_lock_); HeaderWord orig = obj->header; if(orig.f.meaning == eAuxWordInflated) { obj->inflated_header(state)->set_handle(state, handle); return; } uint32_t ih_index = 0; InflatedHeader* ih = inflated_headers_->allocate(state, obj, &ih_index); ih->update(state, orig); ih->set_handle(state, handle); ih->mark(this, mark_); while(!obj->set_inflated_header(state, ih_index, orig)) { orig = obj->header; if(orig.f.meaning == eAuxWordInflated) { obj->inflated_header(state)->set_handle(state, handle); ih->clear(); return; } ih->update(state, orig); ih->set_handle(state, handle); } }
bool ObjectMemory::inflate_for_contention(STATE, ObjectHeader* obj) { utilities::thread::SpinLock::LockGuard guard(inflation_lock_); for(;;) { HeaderWord orig = obj->header; InflatedHeader* ih = 0; uint32_t ih_header = 0; switch(orig.f.meaning) { case eAuxWordEmpty: ih = inflated_headers_->allocate(obj, &ih_header); break; case eAuxWordObjID: // We could be have made a header before trying again, so // keep using the original one. ih = inflated_headers_->allocate(obj, &ih_header); ih->set_object_id(orig.f.aux_word); break; case eAuxWordHandle: ih = inflated_headers_->allocate(obj, &ih_header); ih->set_handle(state, obj->handle(state)); break; case eAuxWordLock: // We have to be locking the object to inflate it, thats the law. if(orig.f.aux_word >> cAuxLockTIDShift != state->vm()->thread_id()) { if(cDebugThreading) { std::cerr << "[LOCK " << state->vm()->thread_id() << " object locked by another thread while inflating for contention]" << std::endl; } return false; } if(cDebugThreading) { std::cerr << "[LOCK " << state->vm()->thread_id() << " being unlocked and inflated atomicly]" << std::endl; } ih = inflated_headers_->allocate(obj, &ih_header); break; case eAuxWordInflated: if(cDebugThreading) { std::cerr << "[LOCK " << state->vm()->thread_id() << " asked to inflated already inflated lock]" << std::endl; } return false; } // Try it all over again if it fails. if(!obj->set_inflated_header(state, ih_header, orig)) { ih->clear(); continue; } obj->clear_lock_contended(); if(cDebugThreading) { std::cerr << "[LOCK " << state->vm()->thread_id() << " inflated lock for contention.]" << std::endl; } // Now inflated but not locked, which is what we want. return true; } }
/** * Scans the list of InflatedHeader objects checking to see which are in use. * Those that do not have the appropriate mark value set are cleared and * added back to the free list. Chunks that are completely unused are removed * from the linked list. * * /param mark The current value of the mark; only InflatedHeaders that bear * this mark will be retained. */ void InflatedHeaders::deallocate_headers(int mark) { // Detect and free any full chunks first! for(Chunks::iterator i = chunks_.begin(); i != chunks_.end();) { InflatedHeader* chunk = *i; bool used = false; for(size_t j = 0; j < cChunkSize; j++) { InflatedHeader* header = &chunk[j]; if(header->marked_p(mark)) { used = true; break; } } // No header was marked, so it's completely empty. Free it. if(!used) { delete[] chunk; i = chunks_.erase(i); } else { ++i; } } // Ok, now, rebuild the free_list free_list_ = 0; in_use_ = 0; for(Chunks::iterator i = chunks_.begin(); i != chunks_.end(); ++i) { InflatedHeader* chunk = *i; for(size_t j = 0; j < cChunkSize; j++) { InflatedHeader* header = &chunk[j]; if(!header->marked_p(mark)) { header->clear(); header->set_next(free_list_); free_list_ = header; } else { in_use_++; } } } }
void InflatedHeaders::deallocate_headers(unsigned int mark) { std::vector<bool> chunk_marks(allocator_->chunks_.size(), false); for(std::vector<int>::size_type i = 0; i < allocator_->chunks_.size(); ++i) { InflatedHeader* chunk = allocator_->chunks_[i]; for(size_t j = 0; j < allocator_->cChunkSize; j++) { InflatedHeader* header = &chunk[j]; if(header->marked_p(mark)) { chunk_marks[i] = true; } else { header->clear(); } } } allocator_->rebuild_freelist(&chunk_marks); }