collector.cpp
来自「将konqueror浏览器移植到ARM9 2410中」· C++ 代码 · 共 268 行
CPP
268 行
/* * This file is part of the KDE libraries * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include "collector.h"#include "object.h"#include "internal.h"#include <stdio.h>#include <string.h>#include <assert.h>namespace KJS { class CollectorBlock { public: CollectorBlock(int s); ~CollectorBlock(); int size; int filled; void** mem; CollectorBlock *prev, *next;#ifdef KJS_DEBUG_MEM static int count;#endif };}; // namespaceusing namespace KJS;CollectorBlock::CollectorBlock(int s) : size(s), filled(0), prev(0L), next(0L){ mem = new void*[size]; memset(mem, 0, size * sizeof(void*));#ifdef KJS_DEBUG_MEM count++;#endif}CollectorBlock::~CollectorBlock(){ delete [] mem; mem = 0L;#ifdef KJS_DEBUG_MEM count--;#endif}CollectorBlock* Collector::root = 0L;CollectorBlock* Collector::currentBlock = 0L;unsigned long Collector::filled = 0;unsigned long Collector::softLimit = KJS_MEM_INCREMENT;#ifdef KJS_DEBUG_MEMint CollectorBlock::count = 0;bool Collector::collecting = false;#endifvoid* Collector::allocate(size_t s){ if (s == 0) return 0L; if (filled >= softLimit) { collect(); if (filled >= softLimit && softLimit < KJS_MEM_LIMIT) // we are actually using all this memory softLimit *= 2; } void *m = malloc(s); // hack to ensure obj is protected from GC before any constructors are run // (prev = marked, next = gcallowed) static_cast<Imp*>(m)->prev = 0; static_cast<Imp*>(m)->next = 0; if (!root) { root = new CollectorBlock(BlockSize); currentBlock = root; } CollectorBlock *block = currentBlock; if (!block) block = root; // search for a block with space left while (block->next && block->filled == block->size) block = block->next; if (block->filled >= block->size) {#if defined(KJS_DEBUG_MEM) && defined(KJS_VERBOSE) printf("allocating new block of size %d\n", block->size);#endif CollectorBlock *tmp = new CollectorBlock(BlockSize); block->next = tmp; tmp->prev = block; block = tmp; } currentBlock = block; // look for a free spot in the block void **r = block->mem; while (*r) r++; *r = m; filled++; block->filled++; if (softLimit >= KJS_MEM_LIMIT) { KJScriptImp::setException("Out of memory"); } return m;}/** * Mark-sweep garbage collection. */void Collector::collect(){#ifdef KJS_DEBUG_MEM printf("collecting: %d objects, %lu allocated, %d blocks\n", Imp::count, filled, CollectorBlock::count); collecting = true;#endif // MARK: first set all ref counts to 0 .... CollectorBlock *block = root; while (block) {#if defined(KJS_DEBUG_MEM) && defined(KJS_VERBOSE) printf("cleaning block filled %d out of %d\n", block->filled, block->size);#endif Imp **r = (Imp**)block->mem; assert(r); for (int i = 0; i < block->size; i++, r++) if (*r) { (*r)->setMarked(false); } block = block->next; } // ... increase counter for all referenced objects recursively // starting out from the set of root objects if (KJScriptImp::hook) { KJScriptImp *scr = KJScriptImp::hook; do { scr->mark(); scr = scr->next; } while (scr != KJScriptImp::hook); } // mark any other objects that we wouldn't delete anyway block = root; while (block) { Imp **r = (Imp**)block->mem; assert(r); for (int i = 0; i < block->size; i++, r++) if (*r && (*r)->created() && ((*r)->refcount || !(*r)->gcAllowed()) && !(*r)->marked()) (*r)->mark(); block = block->next; } // SWEEP: delete everything with a zero refcount (garbage) block = root; while (block) { Imp **r = (Imp**)block->mem; int del = 0; for (int i = 0; i < block->size; i++, r++) { if (*r && ((*r)->refcount == 0) && !(*r)->marked() && (*r)->gcAllowed()) { // emulate destructing part of 'operator delete()' (*r)->~Imp(); free(*r); *r = 0L; del++; } }#if defined(KJS_DEBUG_MEM) && defined(KJS_VERBOSE) if (del) printf("deleted %d objects\n", del);#endif filled -= del; block->filled -= del; block = block->next; } // delete the emtpy containers block = root; while (block) { CollectorBlock *next = block->next; if (block->filled == 0) { if (block->prev) block->prev->next = next; if (block == root) root = next; if (next) next->prev = block->prev; if (block == currentBlock) // we don't want a dangling pointer currentBlock = 0L; assert(block != root); delete block; } block = next; }#ifdef KJS_DEBUG_MEM collecting = false; printf("remaining: %d objects, %lu allocated, %d blocks\n", Imp::count, filled, CollectorBlock::count); printf("memory: %d KJS objects, %d Lists, softlimit=%lu\n", KJSO::count, List::count, softLimit);#endif}#ifdef KJS_DEBUG_MEMnamespace KJS { // This must be kept in sync with object.cpp struct Property { UString name; Imp *object; int attribute; Property *next; };};void Collector::dumpObjects(){ printf("dumping: %ld objects in %d blocks\n", filled, CollectorBlock::count); CollectorBlock *block = root; while (block) { Imp **r = (Imp**)block->mem; assert(r); for (int i = 0; i < block->size; i++, r++) if (*r) { Imp *o = *r; printf(" object at %p, refcount=%d, prototype at %p%s\n", o, o->refcount, o->prototype(), (o->gcAllowed() ? "" : " (no GC)")); const TypeInfo *info = o->typeInfo(); if (info) printf(" - typeinfo '%s' (%d)\n",info->name,info->type); Property *p = o->prop; while (p) { printf(" - property '%s' at %p\n",p->name.ascii(),p->object); p = p->next; } } block = block->next; } printf("dumping: finished\n");}#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?