Changeset 2779 in webkit for trunk/JavaScriptCore/kjs


Ignore:
Timestamp:
Nov 20, 2002, 1:34:02 AM (23 years ago)
Author:
mjs
Message:

JavaScriptCore:

Rewrote garbage collector to make blocks of actual memory instead
of blocks of pointers. 7% improvement on JavaScript
iBench. There's still lots of room to tune the new GC, this is
just my first cut.

  • kjs/collector.cpp: (Collector::allocate): (Collector::collect): (Collector::size): (Collector::outOfMemory): (Collector::finalCheck): (Collector::numGCNotAllowedObjects): (Collector::numReferencedObjects): (Collector::liveObjectClasses):
  • kjs/collector.h:
  • kjs/function.cpp: (ActivationImp::ActivationImp):
  • kjs/function.h:

WebCore:

  • force-js-clean-timestamp: Work around PB lameness yet again.
Location:
trunk/JavaScriptCore/kjs
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/collector.cpp

    r2483 r2779  
    2727#endif
    2828
    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>
    5232
    5333using namespace KJS;
    5434
    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
     36static const int CELL_SIZE = 64;
     37static const int BLOCK_SIZE = (4 * 4096);
     38static const int SPARE_EMPTY_BLOCKS = 1;
     39static const int MIN_ARRAY_SIZE = 14;
     40static const int GROWTH_FACTOR = 2;
     41static const int LOW_WATER_FACTOR = 4;
     42
     43// derived constants
     44static const int WORD_SIZE = sizeof(uint32_t);
     45static const int BITS_PER_WORD = WORD_SIZE * 8;
     46static const int CELLS_PER_BLOCK = ((BLOCK_SIZE * 8 - 32) / (CELL_SIZE * 8 + 1));
     47static const int BITMAP_SIZE = (CELLS_PER_BLOCK / BITS_PER_WORD) + (CELLS_PER_BLOCK % BITS_PER_WORD != 0 ? 1 : 0);
     48
     49
     50struct CollectorCell {
     51  char memory[CELL_SIZE];
     52};
     53
     54static const int ALLOCATIONS_PER_COLLECTION = 1000;
     55
     56struct 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
     64struct 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
     77static CollectorHeap heap = {NULL, 0, 0, NULL, 0, 0, 0, 0};
    8978
    9079void* Collector::allocate(size_t s)
     
    9281  if (s == 0)
    9382    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)
    9786    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
    172155bool Collector::collect()
    173156{
    174 #ifdef KJS_DEBUG_MEM
    175   fprintf(stderr,"Collector::collect()\n");
    176 #endif
    177157  bool deleted = false;
    178158  // 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 
    190168  // mark all referenced objects recursively
    191169  // starting out from the set of root objects
     
    198176    } while (scr != InterpreterImp::s_hook);
    199177  }
    200 
     178 
    201179  // 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 
    220203  // 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--;
    245260      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 
    273278  return deleted;
     279}
     280
     281int Collector::size()
     282{
     283  return heap.numLiveObjects;
     284}
     285
     286bool Collector::outOfMemory()
     287{
     288  return heap.numLiveObjects >= KJS_MEM_LIMIT;
    274289}
    275290
     
    277292void Collector::finalCheck()
    278293{
    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   }
    294294}
    295295#endif
    296296
    297297#if APPLE_CHANGES
    298 
    299298int Collector::numInterpreters()
    300299{
     
    313312{
    314313  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) {
    323331        ++count;
    324332      }
    325     }
    326     block = block->next;
    327   }
     333  }
     334
    328335  return count;
    329336}
     
    332339{
    333340  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) {
    342358        ++count;
    343359      }
    344     }
    345     block = block->next;
    346   }
     360  }
     361
    347362  return count;
    348363}
     
    352367  CFMutableSetRef classes = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
    353368
    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
    374402  return classes;
    375403}
    376404
    377 #endif // APPLE_CHANGES
     405#endif
  • trunk/JavaScriptCore/kjs/collector.h

    r2483 r2779  
    2424#define _KJSCOLLECTOR_H_
    2525
    26 // KJS_MEM_LIMIT and KJS_MEM_INCREMENT can be tweaked to adjust how the
    27 // garbage collector allocates memory. KJS_MEM_LIMIT is the largest # of objects
    28 // 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 is
    32 // increased when the memory gets filled up. The soft limit is the amount after
    33 // 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 garbage
    37 // 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 500000
    41 #define KJS_MEM_INCREMENT 1000
    42 
    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 
    5126#if APPLE_CHANGES
    5227#if !defined(__OBJC__) && !defined(_COLLECTOR)
     
    5530#endif
    5631
     32#define KJS_MEM_LIMIT 500000
     33
    5734namespace KJS {
    58 
    59   class CollectorBlock;
    6035
    6136  /**
     
    8257     */
    8358    static bool collect();
    84     static int size() { return filled; }
    85     static bool outOfMemory() { return memLimitReached; }
     59    static int size();
     60    static bool outOfMemory();
    8661
    8762#ifdef KJS_DEBUG_MEM
     
    9065     */
    9166    static void finalCheck();
    92     /**
    93      * @internal
    94      */
    95     static bool collecting;
    9667#endif
     68
    9769#if APPLE_CHANGES
    9870    static int numInterpreters();
     
    10173    static CFSetRef liveObjectClasses();
    10274#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 };
    11275  };
    11376
    11477};
    11578
    116 #endif
     79
     80#endif /* _KJSCOLLECTOR_H_ */
  • trunk/JavaScriptCore/kjs/function.cpp

    r2778 r2779  
    342342  Value protect(this);
    343343  arguments = new ArgumentsImp(exec,f, args);
     344  arguments->setGcAllowed();
    344345  put(exec, argumentsPropertyName, Object(arguments), Internal|DontDelete);
    345 }
    346 
    347 ActivationImp::~ActivationImp()
    348 {
    349   arguments->setGcAllowed();
    350346}
    351347
  • trunk/JavaScriptCore/kjs/function.h

    r2778 r2779  
    102102  public:
    103103    ActivationImp(ExecState *exec, FunctionImp *f, const List &args);
    104     ~ActivationImp();
     104
     105    Object argumentsObject() { return Object(arguments); }
    105106
    106107    virtual const ClassInfo *classInfo() const { return &info; }
Note: See TracChangeset for help on using the changeset viewer.