~ubuntu-branches/ubuntu/lucid/webkit/lucid-security

« back to all changes in this revision

Viewing changes to JavaScriptCore/runtime/Collector.h

  • Committer: Bazaar Package Importer
  • Author(s): Gustavo Noronha Silva
  • Date: 2010-01-06 21:25:06 UTC
  • mfrom: (1.2.6 upstream) (4.3.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100106212506-gd0czn4zrwf1j19l
* New upstream release
- adds basic Content-Encoding support, thanks to soup
  (Closes: #529271)
- fixes over-advertising content types as supported by
  the media player (Closes: #559420)
* debian/control:
- updated libsoup build requirement (>= 2.28.2)
* debian/libwebkit-1.0-2.symbols:
- updated with new symbols
* debian/copyright:
- updated information since 1.1.17
* Imported patch from https://bugs.webkit.org/show_bug.cgi?id=30623
- I am shipping this patch because I believe it is correct, it is the
  way to go, it fixes a race, and it needs testing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
#include <wtf/HashSet.h>
29
29
#include <wtf/Noncopyable.h>
30
30
#include <wtf/OwnPtr.h>
 
31
#include <wtf/StdLibExtras.h>
31
32
#include <wtf/Threading.h>
32
33
 
33
 
// This is supremely lame that we require pthreads to build on windows.
34
34
#if ENABLE(JSC_MULTIPLE_THREADS)
35
35
#include <pthread.h>
36
36
#endif
47
47
    class MarkStack;
48
48
 
49
49
    enum OperationInProgress { NoOperation, Allocation, Collection };
50
 
    enum HeapType { PrimaryHeap, NumberHeap };
51
50
 
52
 
    template <HeapType> class CollectorHeapIterator;
 
51
    class LiveObjectIterator;
53
52
 
54
53
    struct CollectorHeap {
 
54
        size_t nextBlock;
 
55
        size_t nextCell;
55
56
        CollectorBlock** blocks;
 
57
        
 
58
        void* nextNumber;
 
59
 
56
60
        size_t numBlocks;
57
61
        size_t usedBlocks;
58
 
        size_t firstBlockWithPossibleSpace;
59
62
 
60
 
        size_t numLiveObjects;
61
 
        size_t numLiveObjectsAtLastCollect;
62
63
        size_t extraCost;
 
64
        bool didShrink;
63
65
 
64
66
        OperationInProgress operationInProgress;
65
67
    };
67
69
    class Heap : public Noncopyable {
68
70
    public:
69
71
        class Thread;
70
 
        typedef CollectorHeapIterator<PrimaryHeap> iterator;
71
72
 
72
73
        void destroy();
73
74
 
74
75
        void* allocateNumber(size_t);
75
76
        void* allocate(size_t);
76
77
 
77
 
        bool collect();
78
78
        bool isBusy(); // true if an allocation or collection is in progress
 
79
        void collectAllGarbage();
79
80
 
80
 
        static const size_t minExtraCostSize = 256;
 
81
        static const size_t minExtraCost = 256;
 
82
        static const size_t maxExtraCost = 1024 * 1024;
81
83
 
82
84
        void reportExtraMemoryCost(size_t cost);
83
85
 
84
 
        size_t objectCount();
 
86
        size_t objectCount() const;
85
87
        struct Statistics {
86
88
            size_t size;
87
89
            size_t free;
111
113
        JSGlobalData* globalData() const { return m_globalData; }
112
114
        static bool isNumber(JSCell*);
113
115
        
114
 
        // Iterators for the object heap.
115
 
        iterator primaryHeapBegin();
116
 
        iterator primaryHeapEnd();
 
116
        LiveObjectIterator primaryHeapBegin();
 
117
        LiveObjectIterator primaryHeapEnd();
117
118
 
118
119
    private:
119
 
        template <HeapType heapType> void* heapAllocate(size_t);
120
 
        template <HeapType heapType> size_t sweep();
 
120
        void reset();
 
121
        void sweep();
121
122
        static CollectorBlock* cellBlock(const JSCell*);
122
123
        static size_t cellOffset(const JSCell*);
123
124
 
125
126
        Heap(JSGlobalData*);
126
127
        ~Heap();
127
128
 
128
 
        template <HeapType heapType> NEVER_INLINE CollectorBlock* allocateBlock();
129
 
        template <HeapType heapType> NEVER_INLINE void freeBlock(size_t);
130
 
        NEVER_INLINE void freeBlock(CollectorBlock*);
131
 
        void freeBlocks(CollectorHeap*);
 
129
        NEVER_INLINE CollectorBlock* allocateBlock();
 
130
        NEVER_INLINE void freeBlock(size_t);
 
131
        NEVER_INLINE void freeBlockPtr(CollectorBlock*);
 
132
        void freeBlocks();
 
133
        void resizeBlocks();
 
134
        void growBlocks(size_t neededBlocks);
 
135
        void shrinkBlocks(size_t neededBlocks);
 
136
        void clearMarkBits();
 
137
        void clearMarkBits(CollectorBlock*);
 
138
        size_t markedCells(size_t startBlock = 0, size_t startCell = 0) const;
132
139
 
133
140
        void recordExtraCost(size_t);
 
141
 
 
142
        void addToStatistics(Statistics&) const;
 
143
 
 
144
        void markRoots();
134
145
        void markProtectedObjects(MarkStack&);
135
146
        void markCurrentThreadConservatively(MarkStack&);
136
147
        void markCurrentThreadConservativelyInternal(MarkStack&);
139
150
 
140
151
        typedef HashCountedSet<JSCell*> ProtectCountSet;
141
152
 
142
 
        CollectorHeap primaryHeap;
143
 
        CollectorHeap numberHeap;
 
153
        CollectorHeap m_heap;
144
154
 
145
155
        ProtectCountSet m_protectedValues;
146
156
 
171
181
#endif
172
182
    template<> struct CellSize<sizeof(uint64_t)> { static const size_t m_value = 64; };
173
183
 
174
 
#if PLATFORM(WINCE) || PLATFORM(SYMBIAN)
 
184
#if OS(WINCE) || OS(SYMBIAN)
175
185
    const size_t BLOCK_SIZE = 64 * 1024; // 64k
176
186
#else
177
187
    const size_t BLOCK_SIZE = 64 * 4096; // 256k
186
196
    const size_t SMALL_CELL_SIZE = CELL_SIZE / 2;
187
197
    const size_t CELL_MASK = CELL_SIZE - 1;
188
198
    const size_t CELL_ALIGN_MASK = ~CELL_MASK;
189
 
    const size_t CELLS_PER_BLOCK = (BLOCK_SIZE * 8 - sizeof(uint32_t) * 8 - sizeof(void *) * 8 - 2 * (7 + 3 * 8)) / (CELL_SIZE * 8 + 2);
190
 
    const size_t SMALL_CELLS_PER_BLOCK = 2 * CELLS_PER_BLOCK;
 
199
    const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*)) * 8 * CELL_SIZE / (8 * CELL_SIZE + 1) / CELL_SIZE; // one bitmap byte can represent 8 cells.
 
200
    
191
201
    const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8;
192
202
    const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t);
193
 
  
 
203
 
194
204
    struct CollectorBitmap {
195
205
        uint32_t bits[BITMAP_WORDS];
196
206
        bool get(size_t n) const { return !!(bits[n >> 5] & (1 << (n & 0x1F))); } 
197
207
        void set(size_t n) { bits[n >> 5] |= (1 << (n & 0x1F)); } 
198
208
        void clear(size_t n) { bits[n >> 5] &= ~(1 << (n & 0x1F)); } 
199
209
        void clearAll() { memset(bits, 0, sizeof(bits)); }
 
210
        size_t count(size_t startCell = 0)
 
211
        {
 
212
            size_t result = 0;
 
213
            for ( ; (startCell & 0x1F) != 0; ++startCell) {
 
214
                if (get(startCell))
 
215
                    ++result;
 
216
            }
 
217
            for (size_t i = startCell >> 5; i < BITMAP_WORDS; ++i)
 
218
                result += WTF::bitCount(bits[i]);
 
219
            return result;
 
220
        }
 
221
        size_t isEmpty() // Much more efficient than testing count() == 0.
 
222
        {
 
223
            for (size_t i = 0; i < BITMAP_WORDS; ++i)
 
224
                if (bits[i] != 0)
 
225
                    return false;
 
226
            return true;
 
227
        }
200
228
    };
201
229
  
202
230
    struct CollectorCell {
203
 
        union {
204
 
            double memory[CELL_ARRAY_LENGTH];
205
 
            struct {
206
 
                void* zeroIfFree;
207
 
                ptrdiff_t next;
208
 
            } freeCell;
209
 
        } u;
210
 
    };
211
 
 
212
 
    struct SmallCollectorCell {
213
 
        union {
214
 
            double memory[CELL_ARRAY_LENGTH / 2];
215
 
            struct {
216
 
                void* zeroIfFree;
217
 
                ptrdiff_t next;
218
 
            } freeCell;
219
 
        } u;
 
231
        double memory[CELL_ARRAY_LENGTH];
220
232
    };
221
233
 
222
234
    class CollectorBlock {
223
235
    public:
224
236
        CollectorCell cells[CELLS_PER_BLOCK];
225
 
        uint32_t usedCells;
226
 
        CollectorCell* freeList;
227
 
        CollectorBitmap marked;
228
 
        Heap* heap;
229
 
        HeapType type;
230
 
    };
231
 
 
232
 
    class SmallCellCollectorBlock {
233
 
    public:
234
 
        SmallCollectorCell cells[SMALL_CELLS_PER_BLOCK];
235
 
        uint32_t usedCells;
236
 
        SmallCollectorCell* freeList;
237
 
        CollectorBitmap marked;
238
 
        Heap* heap;
239
 
        HeapType type;
240
 
    };
241
 
    
242
 
    template <HeapType heapType> struct HeapConstants;
243
 
 
244
 
    template <> struct HeapConstants<PrimaryHeap> {
 
237
        CollectorBitmap marked;
 
238
        Heap* heap;
 
239
    };
 
240
 
 
241
    struct HeapConstants {
245
242
        static const size_t cellSize = CELL_SIZE;
246
243
        static const size_t cellsPerBlock = CELLS_PER_BLOCK;
247
 
        static const size_t bitmapShift = 0;
248
244
        typedef CollectorCell Cell;
249
245
        typedef CollectorBlock Block;
250
246
    };
251
247
 
252
 
    template <> struct HeapConstants<NumberHeap> {
253
 
        static const size_t cellSize = SMALL_CELL_SIZE;
254
 
        static const size_t cellsPerBlock = SMALL_CELLS_PER_BLOCK;
255
 
        static const size_t bitmapShift = 1;
256
 
        typedef SmallCollectorCell Cell;
257
 
        typedef SmallCellCollectorBlock Block;
258
 
    };
259
 
 
260
248
    inline CollectorBlock* Heap::cellBlock(const JSCell* cell)
261
249
    {
262
250
        return reinterpret_cast<CollectorBlock*>(reinterpret_cast<uintptr_t>(cell) & BLOCK_MASK);
263
251
    }
264
252
 
265
 
    inline bool Heap::isNumber(JSCell* cell)
266
 
    {
267
 
        return Heap::cellBlock(cell)->type == NumberHeap;
268
 
    }
269
 
 
270
253
    inline size_t Heap::cellOffset(const JSCell* cell)
271
254
    {
272
255
        return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE;
284
267
 
285
268
    inline void Heap::reportExtraMemoryCost(size_t cost)
286
269
    {
287
 
        if (cost > minExtraCostSize) 
288
 
            recordExtraCost(cost / (CELL_SIZE * 2)); 
 
270
        if (cost > minExtraCost) 
 
271
            recordExtraCost(cost);
 
272
    }
 
273
    
 
274
    inline void* Heap::allocateNumber(size_t s)
 
275
    {
 
276
        if (void* result = m_heap.nextNumber) {
 
277
            m_heap.nextNumber = 0;
 
278
            return result;
 
279
        }
 
280
 
 
281
        void* result = allocate(s);
 
282
        m_heap.nextNumber = static_cast<char*>(result) + (CELL_SIZE / 2);
 
283
        return result;
289
284
    }
290
285
 
291
286
} // namespace JSC