Build fix, not reviewed.
[WebKit-https.git] / JavaScriptCore / kjs / collector.h
1 // -*- c-basic-offset: 2 -*-
2 /*
3  *  This file is part of the KDE libraries
4  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
5  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
6  *  Copyright (C) 2003 Apple Computer, Inc.
7  *
8  *  This library is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU Lesser General Public
10  *  License as published by the Free Software Foundation; either
11  *  version 2 of the License, or (at your option) any later version.
12  *
13  *  This library is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *  Lesser General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Lesser General Public
19  *  License along with this library; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #ifndef KJSCOLLECTOR_H_
25 #define KJSCOLLECTOR_H_
26
27 #include <wtf/HashCountedSet.h>
28
29 #define KJS_MEM_LIMIT 500000
30
31 namespace KJS {
32
33   class JSCell;
34   class JSValue;
35   class CollectorBlock;
36
37   class Collector {
38   public:
39     static void* allocate(size_t s);
40     static bool collect();
41
42     static size_t size();
43     static bool isOutOfMemory() { return memoryFull; }
44
45 #ifdef KJS_DEBUG_MEM
46     /**
47      * Check that nothing is left when the last interpreter gets deleted
48      */
49     static void finalCheck();
50 #endif
51
52     static void protect(JSValue*);
53     static void unprotect(JSValue*);
54     
55     static void collectOnMainThreadOnly(JSValue*);
56
57     static size_t numInterpreters();
58     static size_t numProtectedObjects();
59     static HashCountedSet<const char*>* rootObjectTypeCounts();
60
61     class Thread;
62     static void registerThread();
63     
64     static void registerAsMainThread();
65
66     static bool isCellMarked(const JSCell*);
67     static void markCell(JSCell*);
68
69   private:
70     static const CollectorBlock* cellBlock(const JSCell*);
71     static CollectorBlock* cellBlock(JSCell*);
72     static size_t cellOffset(const JSCell* cell);
73
74     Collector();
75
76     static void markProtectedObjects();
77     static void markMainThreadOnlyObjects();
78     static void markCurrentThreadConservatively();
79     static void markOtherThreadConservatively(Thread* thread);
80     static void markStackObjectsConservatively();
81     static void markStackObjectsConservatively(void* start, void* end);
82
83     static size_t mainThreadOnlyObjectCount;
84     static bool memoryFull;
85   };
86
87   // tunable parameters
88   template<size_t bytesPerWord> struct CellSize;
89
90   // cell size needs to be a power of two for certain optimizations in collector.cpp
91   template<> struct CellSize<sizeof(uint32_t)> { static const size_t m_value = 32; }; // 32-bit
92   template<> struct CellSize<sizeof(uint64_t)> { static const size_t m_value = 64; }; // 64-bit
93   const size_t BLOCK_SIZE = 16 * 4096; // 64k
94   
95   // derived constants
96   const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1;
97   const size_t BLOCK_MASK = ~BLOCK_OFFSET_MASK;
98   const size_t MINIMUM_CELL_SIZE = CellSize<sizeof(void*)>::m_value;
99   const size_t CELL_ARRAY_LENGTH = (MINIMUM_CELL_SIZE / sizeof(double)) + (MINIMUM_CELL_SIZE % sizeof(double) != 0 ? sizeof(double) : 0);
100   const size_t CELL_SIZE = CELL_ARRAY_LENGTH * sizeof(double);
101   const size_t CELL_MASK = CELL_SIZE - 1;
102   const size_t CELLS_PER_BLOCK = (BLOCK_SIZE * 8 - sizeof(uint32_t) * 8 - sizeof(void *) * 8 - 2 * (7 + 3 * 8)) / (CELL_SIZE * 8 + 2);
103   const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8;
104   const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t);
105   
106   struct CollectorBitmap {
107     uint32_t bits[BITMAP_WORDS];
108     bool get(size_t n) const { return !!(bits[n >> 5] & (1 << (n & 0x1F))); } 
109     void set(size_t n) { bits[n >> 5] |= (1 << (n & 0x1F)); } 
110     void clear(size_t n) { bits[n >> 5] &= ~(1 << (n & 0x1F)); } 
111     void clearAll() { memset(bits, 0, sizeof(bits)); }
112   };
113   
114   struct CollectorCell {
115     union {
116       double memory[CELL_ARRAY_LENGTH];
117       struct {
118         void* zeroIfFree;
119         ptrdiff_t next;
120       } freeCell;
121     } u;
122   };
123
124   class CollectorBlock {
125   public:
126     CollectorCell cells[CELLS_PER_BLOCK];
127     uint32_t usedCells;
128     CollectorCell* freeList;
129     CollectorBitmap marked;
130     CollectorBitmap collectOnMainThreadOnly;
131   };
132
133   inline const CollectorBlock* Collector::cellBlock(const JSCell* cell)
134   {
135     return reinterpret_cast<const CollectorBlock*>(reinterpret_cast<uintptr_t>(cell) & BLOCK_MASK);
136   }
137
138   inline CollectorBlock* Collector::cellBlock(JSCell* cell)
139   {
140     return const_cast<CollectorBlock*>(cellBlock(const_cast<const JSCell*>(cell)));
141   }
142
143   inline size_t Collector::cellOffset(const JSCell* cell)
144   {
145     return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE;
146   }
147
148   inline bool Collector::isCellMarked(const JSCell* cell)
149   {
150     return cellBlock(cell)->marked.get(cellOffset(cell));
151   }
152
153   inline void Collector::markCell(JSCell* cell)
154   {
155     cellBlock(cell)->marked.set(cellOffset(cell));
156   }
157
158 } // namespace KJS
159
160 #endif /* KJSCOLLECTOR_H_ */