Changeset 2779 in webkit for trunk/JavaScriptCore/kjs
- Timestamp:
- Nov 20, 2002, 1:34:02 AM (23 years ago)
- Location:
- trunk/JavaScriptCore/kjs
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/collector.cpp
r2483 r2779 27 27 #endif 28 28 29 #include "collector.h" 30 #include "internal.h" 31 32 #include <stdio.h> 33 #include <string.h> 34 #include <assert.h> 35 #ifdef KJS_DEBUG_MEM 36 #include <typeinfo> 37 #endif 38 39 namespace KJS { 40 41 class CollectorBlock { 42 public: 43 CollectorBlock(int s); 44 ~CollectorBlock(); 45 int size; 46 int filled; 47 void** mem; 48 CollectorBlock *prev, *next; 49 }; 50 51 }; // namespace 29 #include <collector.h> 30 #include <value.h> 31 #include <internal.h> 52 32 53 33 using namespace KJS; 54 34 55 56 CollectorBlock::CollectorBlock(int s) 57 : size(s), 58 filled(0), 59 prev(0L), 60 next(0L) 61 { 62 mem = new void*[size]; 63 memset(mem, 0, size * sizeof(void*)); 64 } 65 66 CollectorBlock::~CollectorBlock() 67 { 68 delete [] mem; 69 mem = 0L; 70 } 71 72 CollectorBlock* Collector::root = 0L; 73 CollectorBlock* Collector::currentBlock = 0L; 74 unsigned long Collector::filled = 0; 75 unsigned long Collector::softLimit = KJS_MEM_INCREMENT; 76 77 unsigned long Collector::timesFilled = 0; 78 unsigned long Collector::increaseLimitAt = 1; 79 80 bool Collector::memLimitReached = false; 81 82 #ifdef KJS_DEBUG_MEM 83 bool Collector::collecting = false; 84 #endif 85 86 #if APPLE_CHANGES 87 static int numAllocationsSinceLastCollect = 0; 88 #endif 35 // tunable parameters 36 static const int CELL_SIZE = 64; 37 static const int BLOCK_SIZE = (4 * 4096); 38 static const int SPARE_EMPTY_BLOCKS = 1; 39 static const int MIN_ARRAY_SIZE = 14; 40 static const int GROWTH_FACTOR = 2; 41 static const int LOW_WATER_FACTOR = 4; 42 43 // derived constants 44 static const int WORD_SIZE = sizeof(uint32_t); 45 static const int BITS_PER_WORD = WORD_SIZE * 8; 46 static const int CELLS_PER_BLOCK = ((BLOCK_SIZE * 8 - 32) / (CELL_SIZE * 8 + 1)); 47 static const int BITMAP_SIZE = (CELLS_PER_BLOCK / BITS_PER_WORD) + (CELLS_PER_BLOCK % BITS_PER_WORD != 0 ? 1 : 0); 48 49 50 struct CollectorCell { 51 char memory[CELL_SIZE]; 52 }; 53 54 static const int ALLOCATIONS_PER_COLLECTION = 1000; 55 56 struct CollectorBlock { 57 CollectorBlock() : usedCells(0) { memset(bitmap, 0, BITMAP_SIZE * WORD_SIZE); } 58 59 uint32_t bitmap[BITMAP_SIZE]; 60 int32_t usedCells; 61 CollectorCell cells[CELLS_PER_BLOCK]; 62 }; 63 64 struct CollectorHeap { 65 CollectorBlock **blocks; 66 int numBlocks; 67 int usedBlocks; 68 69 CollectorCell **oversizeCells; 70 int numOversizeCells; 71 int usedOversizeCells; 72 73 int numLiveObjects; 74 int numAllocationsSinceLastCollect; 75 }; 76 77 static CollectorHeap heap = {NULL, 0, 0, NULL, 0, 0, 0, 0}; 89 78 90 79 void* Collector::allocate(size_t s) … … 92 81 if (s == 0) 93 82 return 0L; 94 95 #if APPLE_CHANGES 96 if (++ numAllocationsSinceLastCollect >= KJS_MEM_INCREMENT)83 84 // collect if needed 85 if (++heap.numAllocationsSinceLastCollect >= ALLOCATIONS_PER_COLLECTION) 97 86 collect(); 98 #else 99 // Try and deal with memory requirements in a scalable way. Simple scripts 100 // should only require small amounts of memory, but for complex scripts we don't 101 // want to end up running the garbage collector hundreds of times a second. 102 if (filled >= softLimit) { 103 timesFilled++; 104 collect(); 105 106 if (filled >= softLimit && softLimit < KJS_MEM_LIMIT) { 107 // Even after collection we are still using more than the limit, so increase 108 // the limit 109 softLimit *= 2; 110 } 111 else if (timesFilled == increaseLimitAt && increaseLimitAt < 128) { 112 // The allowed memory limit keeps getting reached (lots of objects created 113 // and deleted). Increase it a bit so GC gets run less often. 114 timesFilled = 0; 115 softLimit *= 2; 116 increaseLimitAt *= 2; 117 } 118 } 119 #endif 120 121 void *m = malloc(s); 122 #ifdef KJS_DEBUG_MEM 123 //fprintf( stderr, "allocate: size=%d valueimp=%p\n",s,m); 124 #endif 125 126 // VI_CREATED and VI_GCALLOWED being unset ensure that value 127 // is protected from GC before any constructors are run 128 static_cast<ValueImp*>(m)->_flags = 0; 129 130 if (!root) { 131 root = new CollectorBlock(BlockSize); 132 currentBlock = root; 133 } 134 135 CollectorBlock *block = currentBlock; 136 if (!block) 137 block = root; 138 139 // search for a block with space left 140 while (block->next && block->filled == block->size) 141 block = block->next; 142 143 if (block->filled >= block->size) { 144 #ifdef KJS_DEBUG_MEM 145 //fprintf( stderr, "allocating new block of size %d\n", block->size); 146 #endif 147 CollectorBlock *tmp = new CollectorBlock(BlockSize); 148 block->next = tmp; 149 tmp->prev = block; 150 block = tmp; 151 } 152 currentBlock = block; 153 // look for a free spot in the block 154 void **r = block->mem; 155 while (*r) 156 r++; 157 *r = m; 158 filled++; 159 block->filled++; 160 161 if (softLimit >= KJS_MEM_LIMIT) { 162 memLimitReached = true; 163 fprintf(stderr,"Out of memory"); 164 } 165 166 return m; 167 } 168 169 /** 170 * Mark-sweep garbage collection. 171 */ 87 88 heap.numLiveObjects++; 89 90 if (heap.numLiveObjects >= KJS_MEM_LIMIT) { 91 // fprintf(stderr,"Out of memory"); 92 } 93 94 95 if (s > (unsigned)CELL_SIZE) { 96 // oversize allocator 97 if (heap.usedOversizeCells == heap.numOversizeCells) { 98 heap.numOversizeCells = MAX(MIN_ARRAY_SIZE, heap.numOversizeCells * GROWTH_FACTOR); 99 heap.oversizeCells = (CollectorCell **)realloc(heap.oversizeCells, heap.numOversizeCells * sizeof(CollectorCell *)); 100 } 101 102 void *newCell = malloc(s); 103 heap.oversizeCells[heap.usedOversizeCells] = (CollectorCell *)newCell; 104 heap.usedOversizeCells++; 105 106 return (void *)newCell; 107 } 108 109 // slab allocator 110 111 CollectorBlock *targetBlock = NULL; 112 113 // try to find free space in an existing block 114 for (int i = 0; i < heap.usedBlocks; i++) { 115 if (heap.blocks[i]->usedCells < CELLS_PER_BLOCK) { 116 targetBlock = heap.blocks[i]; 117 break; 118 } 119 } 120 121 if (targetBlock == NULL) { 122 // didn't find one, need to allocate a new block 123 124 if (heap.usedBlocks == heap.numBlocks) { 125 heap.numBlocks = MAX(MIN_ARRAY_SIZE, heap.numBlocks * GROWTH_FACTOR); 126 heap.blocks = (CollectorBlock **)realloc(heap.blocks, heap.numBlocks * sizeof(CollectorBlock *)); 127 } 128 129 targetBlock = new CollectorBlock(); 130 heap.blocks[heap.usedBlocks] = targetBlock; 131 heap.usedBlocks++; 132 } 133 134 // find a free spot in the block 135 for (int wordInBitmap = 0; wordInBitmap < BITMAP_SIZE; wordInBitmap++) { 136 uint32_t word = targetBlock->bitmap[wordInBitmap]; 137 for (int bitInWord = 0; bitInWord < BITS_PER_WORD; bitInWord++) { 138 if ((word & (1 << bitInWord)) == 0) { 139 int cellPos = BITS_PER_WORD * wordInBitmap + bitInWord; 140 if (cellPos < CELLS_PER_BLOCK) { 141 targetBlock->bitmap[wordInBitmap] |= (1 << bitInWord); 142 targetBlock->usedCells++; 143 return (void *)(targetBlock->cells + cellPos); 144 } 145 } 146 } 147 } 148 // unreachable, if the free count wasn't 0 there has to be a free 149 // cell in the block 150 assert(false); 151 152 return false; 153 } 154 172 155 bool Collector::collect() 173 156 { 174 #ifdef KJS_DEBUG_MEM175 fprintf(stderr,"Collector::collect()\n");176 #endif177 157 bool deleted = false; 178 158 // MARK: first unmark everything 179 CollectorBlock *block = root; 180 while (block) { 181 ValueImp **r = (ValueImp**)block->mem; 182 assert(r); 183 for (int i = 0; i < block->size; i++, r++) 184 if (*r) { 185 (*r)->_flags &= ~ValueImp::VI_MARKED; 186 } 187 block = block->next; 188 } 189 159 for (int block = 0; block < heap.usedBlocks; block++) { 160 for (int cell = 0; cell < CELLS_PER_BLOCK; cell++) { 161 ((ValueImp *)(heap.blocks[block]->cells + cell))->_flags &= ~ValueImp::VI_MARKED; 162 } 163 } 164 for (int cell = 0; cell < heap.usedOversizeCells; cell++) { 165 ((ValueImp *)heap.oversizeCells[cell])->_flags &= ~ValueImp::VI_MARKED; 166 } 167 190 168 // mark all referenced objects recursively 191 169 // starting out from the set of root objects … … 198 176 } while (scr != InterpreterImp::s_hook); 199 177 } 200 178 201 179 // mark any other objects that we wouldn't delete anyway 202 block = root; 203 while (block) { 204 ValueImp **r = (ValueImp**)block->mem; 205 assert(r); 206 for (int i = 0; i < block->size; i++, r++) 207 { 208 ValueImp *imp = (*r); 209 // Check for created=true, marked=false and (gcallowed=false or refcount>0) 210 if (imp && 211 (imp->_flags & (ValueImp::VI_CREATED|ValueImp::VI_MARKED)) == ValueImp::VI_CREATED && 212 ( (imp->_flags & ValueImp::VI_GCALLOWED) == 0 || imp->refcount ) ) { 213 //fprintf( stderr, "Collector marking imp=%p\n",(void*)imp); 214 imp->mark(); 215 } 216 } 217 block = block->next; 218 } 219 180 for (int block = 0; block < heap.usedBlocks; block++) { 181 for (int wordInBitmap = 0; wordInBitmap < BITMAP_SIZE; wordInBitmap++) { 182 uint32_t word = heap.blocks[block]->bitmap[wordInBitmap]; 183 for (int bitInWord = 0; bitInWord < BITS_PER_WORD; bitInWord++) { 184 ValueImp *imp = (ValueImp *)(heap.blocks[block]->cells + BITS_PER_WORD * wordInBitmap + bitInWord); 185 186 if ((word & (1 << bitInWord)) && 187 (imp->_flags & (ValueImp::VI_CREATED|ValueImp::VI_MARKED)) == ValueImp::VI_CREATED && 188 ((imp->_flags & ValueImp::VI_GCALLOWED) == 0 || imp->refcount != 0)) { 189 imp->mark(); 190 } 191 } 192 } 193 } 194 195 for (int cell = 0; cell < heap.usedOversizeCells; cell++) { 196 ValueImp *imp = (ValueImp *)heap.oversizeCells[cell]; 197 if ((imp->_flags & (ValueImp::VI_CREATED|ValueImp::VI_MARKED)) == ValueImp::VI_CREATED && 198 ((imp->_flags & ValueImp::VI_GCALLOWED) == 0 || imp->refcount != 0)) { 199 imp->mark(); 200 } 201 } 202 220 203 // SWEEP: delete everything with a zero refcount (garbage) 221 // 1st step: destruct all objects 222 block = root; 223 while (block) { 224 ValueImp **r = (ValueImp**)block->mem; 225 int del = 0; 226 for (int i = 0; i < block->size; i++, r++) { 227 ValueImp *imp = (*r); 228 // Can delete if refcount==0, created==true, gcAllowed==true, and marked==false 229 // Make sure to update the test if you add more bits to _flags. 230 if (imp && 231 !imp->refcount && imp->_flags == (ValueImp::VI_GCALLOWED | ValueImp::VI_CREATED)) { 232 // emulate destructing part of 'operator delete()' 233 //fprintf( stderr, "Collector::deleting ValueImp %p (%s)\n", (void*)imp, typeid(*imp).name()); 234 imp->~ValueImp(); 235 } 236 if (imp && (imp->_flags & ValueImp::VI_DESTRUCTED) != 0) { 237 free(imp); 238 *r = 0L; 239 del++; 240 } 241 } 242 filled -= del; 243 block->filled -= del; 244 if (del) 204 205 int emptyBlocks = 0; 206 207 for (int block = 0; block < heap.usedBlocks; block++) { 208 for (int wordInBitmap = 0; wordInBitmap < BITMAP_SIZE; wordInBitmap++) { 209 uint32_t word = heap.blocks[block]->bitmap[wordInBitmap]; 210 for (int bitInWord = 0; bitInWord < BITS_PER_WORD; bitInWord++) { 211 ValueImp *imp = (ValueImp *)(heap.blocks[block]->cells + BITS_PER_WORD * wordInBitmap + bitInWord); 212 213 if ((word & (1 << bitInWord)) && 214 !imp->refcount && imp->_flags == (ValueImp::VI_GCALLOWED | ValueImp::VI_CREATED)) { 215 // emulate destructing part of 'operator delete()' 216 //fprintf( stderr, "Collector::deleting ValueImp %p (%s)\n", (void*)imp, typeid(*imp).name()); 217 imp->~ValueImp(); 218 heap.blocks[block]->bitmap[wordInBitmap] &= ~(1 << bitInWord); 219 heap.blocks[block]->usedCells--; 220 heap.numLiveObjects--; 221 deleted = true; 222 } 223 } 224 } 225 226 if (heap.blocks[block]->usedCells == 0) { 227 emptyBlocks++; 228 if (emptyBlocks > SPARE_EMPTY_BLOCKS) { 229 delete heap.blocks[block]; 230 231 // swap with the last block so we compact as we go 232 heap.blocks[block] = heap.blocks[heap.usedBlocks - 1]; 233 heap.usedBlocks--; 234 block--; // Don't move forward a step in this case 235 236 if (heap.numBlocks > MIN_ARRAY_SIZE && heap.usedBlocks < heap.numBlocks / LOW_WATER_FACTOR) { 237 heap.numBlocks = heap.numBlocks / GROWTH_FACTOR; 238 heap.blocks = (CollectorBlock **)realloc(heap.blocks, heap.numBlocks * sizeof(CollectorBlock *)); 239 } 240 } 241 } 242 } 243 244 245 246 int cell = 0; 247 while (cell < heap.usedOversizeCells) { 248 ValueImp *imp = (ValueImp *)heap.oversizeCells[cell]; 249 250 if (!imp->refcount && 251 imp->_flags == (ValueImp::VI_GCALLOWED | ValueImp::VI_CREATED)) { 252 253 imp->~ValueImp(); 254 free((void *)imp); 255 256 // swap with the last oversize cell so we compact as we go 257 heap.oversizeCells[cell] = heap.oversizeCells[heap.usedOversizeCells - 1]; 258 259 heap.usedOversizeCells--; 245 260 deleted = true; 246 CollectorBlock *next = block->next; 247 if (block->filled == 0) { 248 if (block->prev) 249 block->prev->next = next; 250 if (block == root) 251 root = next; 252 if (next) 253 next->prev = block->prev; 254 if (block == currentBlock) // we don't want a dangling pointer 255 currentBlock = 0L; 256 assert(block != root); 257 delete block; 258 } 259 block = next; 260 } 261 262 #if APPLE_CHANGES 263 numAllocationsSinceLastCollect = 0; 264 #endif 265 266 #if 0 267 // This is useful to track down memory leaks 268 static int s_count = 0; 269 fprintf(stderr, "Collector done (was run %d)\n",s_count); 270 if (s_count++ % 50 == 2) 271 finalCheck(); 272 #endif 261 heap.numLiveObjects--; 262 263 if (heap.numOversizeCells > MIN_ARRAY_SIZE && heap.usedOversizeCells < heap.numOversizeCells / LOW_WATER_FACTOR) { 264 heap.numOversizeCells = heap.numOversizeCells / GROWTH_FACTOR; 265 heap.oversizeCells = (CollectorCell **)realloc(heap.oversizeCells, heap.numOversizeCells * sizeof(CollectorCell *)); 266 } 267 268 } else { 269 cell++; 270 } 271 } 272 273 // possibly free some completely empty collector blocks ? 274 // compact array of collector blocks 275 276 heap.numAllocationsSinceLastCollect = 0; 277 273 278 return deleted; 279 } 280 281 int Collector::size() 282 { 283 return heap.numLiveObjects; 284 } 285 286 bool Collector::outOfMemory() 287 { 288 return heap.numLiveObjects >= KJS_MEM_LIMIT; 274 289 } 275 290 … … 277 292 void Collector::finalCheck() 278 293 { 279 CollectorBlock *block = root;280 while (block) {281 ValueImp **r = (ValueImp**)block->mem;282 for (int i = 0; i < block->size; i++, r++) {283 if (*r ) {284 fprintf( stderr, "Collector::finalCheck() still having ValueImp %p (%s) [marked:%d gcAllowed:%d created:%d refcount:%d]\n",285 (void*)(*r), typeid( **r ).name(),286 (bool)((*r)->_flags & ValueImp::VI_MARKED),287 (bool)((*r)->_flags & ValueImp::VI_GCALLOWED),288 (bool)((*r)->_flags & ValueImp::VI_CREATED),289 (*r)->refcount);290 }291 }292 block = block->next;293 }294 294 } 295 295 #endif 296 296 297 297 #if APPLE_CHANGES 298 299 298 int Collector::numInterpreters() 300 299 { … … 313 312 { 314 313 int count = 0; 315 CollectorBlock *block = root; 316 while (block) { 317 ValueImp **r = (ValueImp**)block->mem; 318 assert(r); 319 for (int i = 0; i < block->size; i++, r++) 320 { 321 ValueImp *imp = *r; 322 if (imp && (imp->_flags & ValueImp::VI_GCALLOWED) == 0) { 314 for (int block = 0; block < heap.usedBlocks; block++) { 315 for (int wordInBitmap = 0; wordInBitmap < BITMAP_SIZE; wordInBitmap++) { 316 uint32_t word = heap.blocks[block]->bitmap[wordInBitmap]; 317 for (int bitInWord = 0; bitInWord < BITS_PER_WORD; bitInWord++) { 318 ValueImp *imp = (ValueImp *)(heap.blocks[block]->cells + BITS_PER_WORD * wordInBitmap + bitInWord); 319 320 if ((word & (1 << bitInWord)) && 321 (imp->_flags & ValueImp::VI_GCALLOWED) == 0) { 322 ++count; 323 } 324 } 325 } 326 } 327 328 for (int cell = 0; cell < heap.usedOversizeCells; cell++) { 329 ValueImp *imp = (ValueImp *)heap.oversizeCells[cell]; 330 if ((imp->_flags & ValueImp::VI_GCALLOWED) == 0) { 323 331 ++count; 324 332 } 325 } 326 block = block->next; 327 } 333 } 334 328 335 return count; 329 336 } … … 332 339 { 333 340 int count = 0; 334 CollectorBlock *block = root; 335 while (block) { 336 ValueImp **r = (ValueImp**)block->mem; 337 assert(r); 338 for (int i = 0; i < block->size; i++, r++) 339 { 340 ValueImp *imp = *r; 341 if (imp && imp->refcount) { 341 for (int block = 0; block < heap.usedBlocks; block++) { 342 for (int wordInBitmap = 0; wordInBitmap < BITMAP_SIZE; wordInBitmap++) { 343 uint32_t word = heap.blocks[block]->bitmap[wordInBitmap]; 344 for (int bitInWord = 0; bitInWord < BITS_PER_WORD; bitInWord++) { 345 ValueImp *imp = (ValueImp *)(heap.blocks[block]->cells + BITS_PER_WORD * wordInBitmap + bitInWord); 346 347 if ((word & (1 << bitInWord)) && 348 imp->refcount == 0) { 349 ++count; 350 } 351 } 352 } 353 } 354 355 for (int cell = 0; cell < heap.usedOversizeCells; cell++) { 356 ValueImp *imp = (ValueImp *)heap.oversizeCells[cell]; 357 if (imp->refcount == 0) { 342 358 ++count; 343 359 } 344 } 345 block = block->next; 346 } 360 } 361 347 362 return count; 348 363 } … … 352 367 CFMutableSetRef classes = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); 353 368 354 CollectorBlock *block = root; 355 while (block) { 356 ValueImp **r = (ValueImp**)block->mem; 357 assert(r); 358 for (int i = 0; i < block->size; i++, r++) 359 { 360 ValueImp *imp = *r; 361 if (imp != NULL) { 362 const char *mangled_name = typeid(*imp).name(); 363 int status; 364 char *demangled_name = __cxxabiv1::__cxa_demangle (mangled_name, NULL, NULL, &status); 365 366 CFStringRef className = CFStringCreateWithCString(NULL, demangled_name, kCFStringEncodingASCII); 367 free(demangled_name); 368 CFSetAddValue(classes, className); 369 CFRelease(className); 370 } 371 } 372 block = block->next; 373 } 369 for (int block = 0; block < heap.usedBlocks; block++) { 370 for (int wordInBitmap = 0; wordInBitmap < BITMAP_SIZE; wordInBitmap++) { 371 uint32_t word = heap.blocks[block]->bitmap[wordInBitmap]; 372 for (int bitInWord = 0; bitInWord < BITS_PER_WORD; bitInWord++) { 373 ValueImp *imp = (ValueImp *)(heap.blocks[block]->cells + BITS_PER_WORD * wordInBitmap + bitInWord); 374 375 if (word & (1 << bitInWord)) { 376 const char *mangled_name = typeid(*imp).name(); 377 int status; 378 char *demangled_name = __cxxabiv1::__cxa_demangle (mangled_name, NULL, NULL, &status); 379 380 CFStringRef className = CFStringCreateWithCString(NULL, demangled_name, kCFStringEncodingASCII); 381 free(demangled_name); 382 CFSetAddValue(classes, className); 383 CFRelease(className); 384 } 385 } 386 } 387 } 388 389 for (int cell = 0; cell < heap.usedOversizeCells; cell++) { 390 ValueImp *imp = (ValueImp *)heap.oversizeCells[cell]; 391 392 const char *mangled_name = typeid(*imp).name(); 393 int status; 394 char *demangled_name = __cxxabiv1::__cxa_demangle (mangled_name, NULL, NULL, &status); 395 396 CFStringRef className = CFStringCreateWithCString(NULL, demangled_name, kCFStringEncodingASCII); 397 free(demangled_name); 398 CFSetAddValue(classes, className); 399 CFRelease(className); 400 } 401 374 402 return classes; 375 403 } 376 404 377 #endif // APPLE_CHANGES405 #endif -
trunk/JavaScriptCore/kjs/collector.h
r2483 r2779 24 24 #define _KJSCOLLECTOR_H_ 25 25 26 // KJS_MEM_LIMIT and KJS_MEM_INCREMENT can be tweaked to adjust how the27 // garbage collector allocates memory. KJS_MEM_LIMIT is the largest # of objects28 // the collector will allow to be present in memory. Once this limit is reached,29 // a running script will get an "out of memory" exception.30 //31 // KJS_MEM_INCREMENT specifies the amount by which the "soft limit" on memory is32 // increased when the memory gets filled up. The soft limit is the amount after33 // which the GC will run and delete unused objects.34 //35 // If you are debugging seemingly random crashes where an object has been deleted,36 // try setting KJS_MEM_INCREMENT to something small, e.g. 300, to force garbage37 // collection to happen more often, and disable the softLimit increase &38 // out-of-memory testing code in Collector::allocate()39 40 #define KJS_MEM_LIMIT 50000041 #define KJS_MEM_INCREMENT 100042 43 #include <stdlib.h>44 45 // for DEBUG_*46 #include "value.h"47 #include "object.h"48 #include "types.h"49 #include "interpreter.h"50 51 26 #if APPLE_CHANGES 52 27 #if !defined(__OBJC__) && !defined(_COLLECTOR) … … 55 30 #endif 56 31 32 #define KJS_MEM_LIMIT 500000 33 57 34 namespace KJS { 58 59 class CollectorBlock;60 35 61 36 /** … … 82 57 */ 83 58 static bool collect(); 84 static int size() { return filled; }85 static bool outOfMemory() { return memLimitReached; }59 static int size(); 60 static bool outOfMemory(); 86 61 87 62 #ifdef KJS_DEBUG_MEM … … 90 65 */ 91 66 static void finalCheck(); 92 /**93 * @internal94 */95 static bool collecting;96 67 #endif 68 97 69 #if APPLE_CHANGES 98 70 static int numInterpreters(); … … 101 73 static CFSetRef liveObjectClasses(); 102 74 #endif 103 private:104 static CollectorBlock* root;105 static CollectorBlock* currentBlock;106 static unsigned long filled;107 static unsigned long softLimit;108 static unsigned long timesFilled;109 static unsigned long increaseLimitAt;110 static bool memLimitReached;111 enum { BlockSize = 100 };112 75 }; 113 76 114 77 }; 115 78 116 #endif 79 80 #endif /* _KJSCOLLECTOR_H_ */ -
trunk/JavaScriptCore/kjs/function.cpp
r2778 r2779 342 342 Value protect(this); 343 343 arguments = new ArgumentsImp(exec,f, args); 344 arguments->setGcAllowed(); 344 345 put(exec, argumentsPropertyName, Object(arguments), Internal|DontDelete); 345 }346 347 ActivationImp::~ActivationImp()348 {349 arguments->setGcAllowed();350 346 } 351 347 -
trunk/JavaScriptCore/kjs/function.h
r2778 r2779 102 102 public: 103 103 ActivationImp(ExecState *exec, FunctionImp *f, const List &args); 104 ~ActivationImp(); 104 105 Object argumentsObject() { return Object(arguments); } 105 106 106 107 virtual const ClassInfo *classInfo() const { return &info; }
Note:
See TracChangeset
for help on using the changeset viewer.