Reviewed by Maciej.
Make JSGlobalData per-thread.
No change on SunSpider total.
* wtf/ThreadSpecific.h: Re-enabled the actual implementation.
* kjs/JSGlobalObject.cpp:
(KJS::JSGlobalObject::~JSGlobalObject): Re-added a JSLock-related assertion. We'll probably
want to preserve these somehow to keep legacy behavior in working condition.
(KJS::JSGlobalObject::init): Initialize globalData pointer earlier, so that it is ready
when updating JSGlobalObject linked list.
* kjs/JSGlobalObject.h: (KJS::JSGlobalObject::head): Changed head() to be non-static, and
to use JSGlobalData associated with the current object.
* kjs/InitializeThreading.cpp: (KJS::initializeThreadingOnce): Removed a no longer needed
Heap::registerAsMainThread() call.
* kjs/JSGlobalData.h: Removed a lying lie comment - parserObjectExtraRefCounts is not
transient, and while newParserObjects may conceptually be such, there is still some node
manipulation going on outside Parser::parse which touches it.
* kjs/JSGlobalData.cpp:
(KJS::JSGlobalData::~JSGlobalData): Delete recently added members.
(KJS::JSGlobalData::sharedInstance): Actually use a separate instance.
* kjs/collector.cpp:
(KJS::Heap::Heap):
(KJS::Heap::~Heap): Added a destructor, which unconditionally deletes everything.
(KJS::Heap::sweep): Removed code related to "collect on main thread only" logic.
(KJS::Heap::collect): Ditto.
(KJS::Heap::globalObjectCount): Explicitly use per-thread instance of JSGlobalObject linked
list now that JSGlobalObject::head() is not static. Curently, WebCoreStatistics methods only
work with the main thread currently anyway.
(KJS::Heap::protectedGlobalObjectCount): Ditto.
* kjs/collector.h: Removed code related to "collect on main thread only" logic.
* JavaScriptCore.exp: Removed Heap::collectOnMainThreadOnly.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@34810 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/kjs/collector.cpp b/JavaScriptCore/kjs/collector.cpp
index 206266d..152d43c 100644
--- a/JavaScriptCore/kjs/collector.cpp
+++ b/JavaScriptCore/kjs/collector.cpp
@@ -87,14 +87,29 @@
// a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
#define MIN_ARRAY_SIZE (static_cast<size_t>(14))
+static void freeHeap(CollectorHeap*);
+
Heap::Heap()
- : mainThreadOnlyObjectCount(0)
- , m_markListSet(0)
+ : m_markListSet(0)
{
memset(&primaryHeap, 0, sizeof(CollectorHeap));
memset(&numberHeap, 0, sizeof(CollectorHeap));
}
+Heap::~Heap()
+{
+ JSLock lock;
+
+ delete m_markListSet;
+ sweep<PrimaryHeap>();
+ // No need to sweep number heap, because the JSNumber destructor doesn't do anything.
+
+ ASSERT(!primaryHeap.numLiveObjects);
+
+ freeHeap(&primaryHeap);
+ freeHeap(&numberHeap);
+}
+
static NEVER_INLINE CollectorBlock* allocateBlock()
{
#if PLATFORM(DARWIN)
@@ -151,6 +166,15 @@
#endif
}
+static void freeHeap(CollectorHeap* heap)
+{
+ for (size_t i = 0; i < heap->usedBlocks; ++i)
+ if (heap->blocks[i])
+ freeBlock(heap->blocks[i]);
+ fastFree(heap->blocks);
+ memset(heap, 0, sizeof(CollectorHeap));
+}
+
void Heap::recordExtraCost(size_t cost)
{
// Our frequency of garbage collection tries to balance memory use against speed
@@ -367,30 +391,6 @@
}
#if USE(MULTIPLE_THREADS)
-static pthread_t mainThread;
-#endif
-
-void Heap::registerAsMainThread()
-{
-#if USE(MULTIPLE_THREADS)
- mainThread = pthread_self();
-#endif
-}
-
-static inline bool onMainThread()
-{
-#if USE(MULTIPLE_THREADS)
-#if PLATFORM(DARWIN)
- return pthread_main_np();
-#else
- return !!pthread_equal(pthread_self(), mainThread);
-#endif
-#else
- return true;
-#endif
-}
-
-#if USE(MULTIPLE_THREADS)
#if PLATFORM(DARWIN)
typedef mach_port_t PlatformThread;
@@ -770,20 +770,6 @@
protectedValues.remove(k->asCell());
}
-void Heap::collectOnMainThreadOnly(JSValue* value)
-{
- ASSERT(value);
- ASSERT(JSLock::lockCount() > 0);
- ASSERT(JSLock::currentThreadIsHoldingLock());
-
- if (JSImmediate::isImmediate(value))
- return;
-
- JSCell* cell = value->asCell();
- cellBlock(cell)->collectOnMainThreadOnly.set(cellOffset(cell));
- ++mainThreadOnlyObjectCount;
-}
-
Heap* Heap::heap(const JSValue* v)
{
if (JSImmediate::isImmediate(v))
@@ -801,54 +787,11 @@
}
}
-void Heap::markMainThreadOnlyObjects()
-{
-#if USE(MULTIPLE_THREADS)
- ASSERT(!onMainThread());
-#endif
-
- // Optimization for clients that never register "main thread only" objects.
- if (!mainThreadOnlyObjectCount)
- return;
-
- // FIXME: We can optimize this marking algorithm by keeping an exact set of
- // "main thread only" objects when the "main thread only" object count is
- // small. We don't want to keep an exact set all the time, because WebCore
- // tends to create lots of "main thread only" objects, and all that set
- // thrashing can be expensive.
-
- size_t count = 0;
-
- // We don't look at the numberHeap as primitive values can never be marked as main thread only
- for (size_t block = 0; block < primaryHeap.usedBlocks; block++) {
- ASSERT(count < mainThreadOnlyObjectCount);
-
- CollectorBlock* curBlock = primaryHeap.blocks[block];
- size_t minimumCellsToProcess = curBlock->usedCells;
- for (size_t i = 0; (i < minimumCellsToProcess) & (i < CELLS_PER_BLOCK); i++) {
- CollectorCell* cell = curBlock->cells + i;
- if (cell->u.freeCell.zeroIfFree == 0)
- ++minimumCellsToProcess;
- else {
- if (curBlock->collectOnMainThreadOnly.get(i)) {
- if (!curBlock->marked.get(i)) {
- JSCell* imp = reinterpret_cast<JSCell*>(cell);
- imp->mark();
- }
- if (++count == mainThreadOnlyObjectCount)
- return;
- }
- }
- }
- }
-}
-
-template <Heap::HeapType heapType> size_t Heap::sweep(bool currentThreadIsMainThread)
+template <Heap::HeapType heapType> size_t Heap::sweep()
{
typedef typename HeapConstants<heapType>::Block Block;
typedef typename HeapConstants<heapType>::Cell Cell;
- UNUSED_PARAM(currentThreadIsMainThread); // currentThreadIsMainThread is only used in ASSERTs
// SWEEP: delete everything with a zero refcount (garbage) and unmark everything else
CollectorHeap& heap = heapType == Heap::PrimaryHeap ? primaryHeap : numberHeap;
@@ -875,11 +818,6 @@
if (cell->u.freeCell.zeroIfFree == 0)
continue;
- ASSERT(currentThreadIsMainThread || !curBlock->collectOnMainThreadOnly.get(i));
- if (curBlock->collectOnMainThreadOnly.get(i)) {
- curBlock->collectOnMainThreadOnly.clear(i);
- --mainThreadOnlyObjectCount;
- }
imp->~JSCell();
}
@@ -902,11 +840,6 @@
if (!curBlock->marked.get(i >> HeapConstants<heapType>::bitmapShift)) {
if (heapType != Heap::NumberHeap) {
JSCell* imp = reinterpret_cast<JSCell*>(cell);
- ASSERT(currentThreadIsMainThread || !curBlock->collectOnMainThreadOnly.get(i));
- if (curBlock->collectOnMainThreadOnly.get(i)) {
- curBlock->collectOnMainThreadOnly.clear(i);
- --mainThreadOnlyObjectCount;
- }
imp->~JSCell();
}
--usedCells;
@@ -969,22 +902,16 @@
primaryHeap.operationInProgress = Collection;
numberHeap.operationInProgress = Collection;
- bool currentThreadIsMainThread = onMainThread();
-
// MARK: first mark all referenced objects recursively starting out from the set of root objects
markStackObjectsConservatively();
markProtectedObjects();
if (m_markListSet && m_markListSet->size())
ArgList::markLists(*m_markListSet);
-#if USE(MULTIPLE_THREADS)
- if (!currentThreadIsMainThread)
- markMainThreadOnlyObjects();
-#endif
size_t originalLiveObjects = primaryHeap.numLiveObjects + numberHeap.numLiveObjects;
- size_t numLiveObjects = sweep<PrimaryHeap>(currentThreadIsMainThread);
- numLiveObjects += sweep<NumberHeap>(currentThreadIsMainThread);
+ size_t numLiveObjects = sweep<PrimaryHeap>();
+ numLiveObjects += sweep<NumberHeap>();
primaryHeap.operationInProgress = NoOperation;
numberHeap.operationInProgress = NoOperation;
@@ -1000,12 +927,12 @@
size_t Heap::globalObjectCount()
{
size_t count = 0;
- if (JSGlobalObject::head()) {
- JSGlobalObject* o = JSGlobalObject::head();
+ if (JSGlobalObject* head = JSGlobalData::threadInstance().head) {
+ JSGlobalObject* o = head;
do {
++count;
o = o->next();
- } while (o != JSGlobalObject::head());
+ } while (o != head);
}
return count;
}
@@ -1013,13 +940,13 @@
size_t Heap::protectedGlobalObjectCount()
{
size_t count = 0;
- if (JSGlobalObject::head()) {
- JSGlobalObject* o = JSGlobalObject::head();
+ if (JSGlobalObject* head = JSGlobalData::threadInstance().head) {
+ JSGlobalObject* o = head;
do {
if (protectedValues.contains(o))
++count;
o = o->next();
- } while (o != JSGlobalObject::head());
+ } while (o != head);
}
return count;
}