Changeset 798 in webkit for trunk/JavaScriptCore/kjs/collector.cpp
- Timestamp:
- Mar 21, 2002, 4:31:57 PM (23 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/collector.cpp
r6 r798 1 // -*- c-basic-offset: 2 -*- 1 2 /* 2 3 * This file is part of the KDE libraries 3 4 * Copyright (C) 1999-2000 Harri Porten ([email protected]) 5 * Copyright (C) 2001 Peter Kelly ([email protected]) 4 6 * 5 7 * This library is free software; you can redistribute it and/or … … 16 18 * License along with this library; if not, write to the Free Software 17 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * 21 * $Id$ 18 22 */ 19 23 20 24 #include "collector.h" 21 #include "object.h"22 25 #include "internal.h" 23 26 … … 25 28 #include <string.h> 26 29 #include <assert.h> 30 #ifdef KJS_DEBUG_MEM 31 #include <typeinfo> 32 #endif 27 33 28 34 namespace KJS { … … 62 68 unsigned long Collector::filled = 0; 63 69 unsigned long Collector::softLimit = KJS_MEM_INCREMENT; 70 71 unsigned long Collector::timesFilled = 0; 72 unsigned long Collector::increaseLimitAt = 1; 73 74 bool Collector::memLimitReached = false; 75 64 76 #ifdef KJS_DEBUG_MEM 65 77 bool Collector::collecting = false; … … 71 83 return 0L; 72 84 85 // Try and deal with memory requirements in a scalable way. Simple scripts 86 // should only require small amounts of memory, but for complex scripts we don't 87 // want to end up running the garbage collector hundreds of times a second. 73 88 if (filled >= softLimit) { 89 timesFilled++; 74 90 collect(); 75 if (filled >= softLimit && softLimit < KJS_MEM_LIMIT) // we are actually using all this memory 91 92 if (filled >= softLimit && softLimit < KJS_MEM_LIMIT) { 93 // Even after collection we are still using more than the limit, so increase 94 // the limit 76 95 softLimit *= 2; 96 } 97 else if (timesFilled == increaseLimitAt && increaseLimitAt < 128) { 98 // The allowed memory limit keeps getting reached (lots of objects created 99 // and deleted). Increase it a bit so GC gets run less often. 100 timesFilled = 0; 101 softLimit *= 2; 102 increaseLimitAt *= 2; 103 } 77 104 } 78 105 79 106 void *m = malloc(s); 80 81 // hack to ensure obj is protected from GC before any constructors are run 82 // (prev = marked, next = gcallowed) 83 static_cast<Imp*>(m)->prev = 0; 84 static_cast<Imp*>(m)->next = 0; 107 #ifdef KJS_DEBUG_MEM 108 //fprintf( stderr, "allocate: size=%d valueimp=%p\n",s,m); 109 #endif 110 111 // VI_CREATED and VI_GCALLOWED being unset ensure that value 112 // is protected from GC before any constructors are run 113 static_cast<ValueImp*>(m)->_flags = 0; 85 114 86 115 if (!root) { … … 99 128 if (block->filled >= block->size) { 100 129 #ifdef KJS_DEBUG_MEM 101 printf("allocating new block of size %d\n", block->size);130 //fprintf( stderr, "allocating new block of size %d\n", block->size); 102 131 #endif 103 132 CollectorBlock *tmp = new CollectorBlock(BlockSize); … … 116 145 117 146 if (softLimit >= KJS_MEM_LIMIT) { 118 KJScriptImp::setException("Out of memory"); 147 memLimitReached = true; 148 fprintf(stderr,"Out of memory"); 119 149 } 120 150 … … 125 155 * Mark-sweep garbage collection. 126 156 */ 127 void Collector::collect() 128 { 129 #ifdef KJS_DEBUG_MEM 130 printf("collecting %d objects total\n", Imp::count); 131 collecting = true; 132 #endif 133 134 // MARK: first set all ref counts to 0 .... 157 bool Collector::collect() 158 { 159 #ifdef KJS_DEBUG_MEM 160 fprintf(stderr,"Collector::collect()\n"); 161 #endif 162 bool deleted = false; 163 // MARK: first unmark everything 135 164 CollectorBlock *block = root; 136 165 while (block) { 137 #ifdef KJS_DEBUG_MEM 138 printf("cleaning block filled %d out of %d\n", block->filled, block->size); 139 #endif 140 Imp **r = (Imp**)block->mem; 166 ValueImp **r = (ValueImp**)block->mem; 141 167 assert(r); 142 168 for (int i = 0; i < block->size; i++, r++) 143 169 if (*r) { 144 (*r)-> setMarked(false);145 } 146 block = block->next; 147 } 148 149 // ... increase counter forall referenced objects recursively170 (*r)->_flags &= ~ValueImp::VI_MARKED; 171 } 172 block = block->next; 173 } 174 175 // mark all referenced objects recursively 150 176 // starting out from the set of root objects 151 if ( KJScriptImp::hook) {152 KJScriptImp *scr = KJScriptImp::hook;177 if (InterpreterImp::s_hook) { 178 InterpreterImp *scr = InterpreterImp::s_hook; 153 179 do { 180 //fprintf( stderr, "Collector marking interpreter %p\n",(void*)scr); 154 181 scr->mark(); 155 182 scr = scr->next; 156 } while (scr != KJScriptImp::hook);183 } while (scr != InterpreterImp::s_hook); 157 184 } 158 185 … … 160 187 block = root; 161 188 while (block) { 162 Imp **r = (Imp**)block->mem;189 ValueImp **r = (ValueImp**)block->mem; 163 190 assert(r); 164 191 for (int i = 0; i < block->size; i++, r++) 165 if (*r && (*r)->created() && ((*r)->refcount || !(*r)->gcAllowed()) && !(*r)->marked()) 166 (*r)->mark(); 192 { 193 ValueImp *imp = (*r); 194 // Check for created=true, marked=false and (gcallowed=false or refcount>0) 195 if (imp && 196 (imp->_flags & (ValueImp::VI_CREATED|ValueImp::VI_MARKED)) == ValueImp::VI_CREATED && 197 ( (imp->_flags & ValueImp::VI_GCALLOWED) == 0 || imp->refcount ) ) { 198 //fprintf( stderr, "Collector marking imp=%p\n",(void*)imp); 199 imp->mark(); 200 } 201 } 167 202 block = block->next; 168 203 } … … 171 206 block = root; 172 207 while (block) { 173 Imp **r = (Imp**)block->mem;208 ValueImp **r = (ValueImp**)block->mem; 174 209 int del = 0; 175 210 for (int i = 0; i < block->size; i++, r++) { 176 if (*r && ((*r)->refcount == 0) && !(*r)->marked() && (*r)->gcAllowed()) { 177 // emulate destructing part of 'operator delete()' 178 (*r)->~Imp(); 179 free(*r); 180 *r = 0L; 181 del++; 211 ValueImp *imp = (*r); 212 // Can delete if refcount==0, created==true, gcAllowed==true, and marked==false 213 // Make sure to update the test if you add more bits to _flags. 214 if (imp && 215 !imp->refcount && imp->_flags == (ValueImp::VI_GCALLOWED | ValueImp::VI_CREATED)) { 216 // emulate destructing part of 'operator delete()' 217 //fprintf( stderr, "Collector::deleting ValueImp %p (%s)\n", (void*)imp, typeid(*imp).name()); 218 imp->~ValueImp(); 219 free(imp); 220 *r = 0L; 221 del++; 182 222 } 183 223 } … … 185 225 block->filled -= del; 186 226 block = block->next; 187 } 188 189 // delete the emtpy containers 227 if (del) 228 deleted = true; 229 } 230 231 // delete the empty containers 190 232 block = root; 191 233 while (block) { … … 193 235 if (block->filled == 0) { 194 236 if (block->prev) 195 237 block->prev->next = next; 196 238 if (block == root) 197 239 root = next; 198 240 if (next) 199 241 next->prev = block->prev; 200 242 if (block == currentBlock) // we don't want a dangling pointer 201 243 currentBlock = 0L; 202 244 assert(block != root); 203 245 delete block; … … 205 247 block = next; 206 248 } 207 208 #ifdef KJS_DEBUG_MEM 209 collecting = false; 210 #endif 211 } 249 #if 0 250 // This is useful to track down memory leaks 251 static int s_count = 0; 252 fprintf(stderr, "Collector done (was run %d)\n",s_count); 253 if (s_count++ % 50 == 2) 254 finalCheck(); 255 #endif 256 return deleted; 257 } 258 259 #ifdef KJS_DEBUG_MEM 260 void Collector::finalCheck() 261 { 262 CollectorBlock *block = root; 263 while (block) { 264 ValueImp **r = (ValueImp**)block->mem; 265 for (int i = 0; i < block->size; i++, r++) { 266 if (*r ) { 267 fprintf( stderr, "Collector::finalCheck() still having ValueImp %p (%s) [marked:%d gcAllowed:%d created:%d refcount:%d]\n", 268 (void*)(*r), typeid( **r ).name(), 269 (bool)((*r)->_flags & ValueImp::VI_MARKED), 270 (bool)((*r)->_flags & ValueImp::VI_GCALLOWED), 271 (bool)((*r)->_flags & ValueImp::VI_CREATED), 272 (*r)->refcount); 273 } 274 } 275 block = block->next; 276 } 277 } 278 #endif
Note:
See TracChangeset
for help on using the changeset viewer.