diff options
Diffstat (limited to 'JavaScriptCore/runtime/Collector.cpp')
-rw-r--r-- | JavaScriptCore/runtime/Collector.cpp | 235 |
1 files changed, 50 insertions, 185 deletions
diff --git a/JavaScriptCore/runtime/Collector.cpp b/JavaScriptCore/runtime/Collector.cpp index 3fbd278..38845ce 100644 --- a/JavaScriptCore/runtime/Collector.cpp +++ b/JavaScriptCore/runtime/Collector.cpp @@ -171,9 +171,6 @@ void Heap::destroy() freeBlocks(); - for (unsigned i = 0; i < m_weakGCHandlePools.size(); ++i) - m_weakGCHandlePools[i].deallocate(); - #if ENABLE(JSC_MULTIPLE_THREADS) if (m_currentThreadRegistrar) { int error = pthread_key_delete(m_currentThreadRegistrar); @@ -187,13 +184,12 @@ void Heap::destroy() t = next; } #endif - m_blockallocator.destroy(); m_globalData = 0; } NEVER_INLINE CollectorBlock* Heap::allocateBlock() { - AlignedCollectorBlock allocation = m_blockallocator.allocate(); + PageAllocationAligned allocation = PageAllocationAligned::allocate(BLOCK_SIZE, BLOCK_SIZE, OSAllocator::JSGCHeapPages); CollectorBlock* block = static_cast<CollectorBlock*>(allocation.base()); if (!block) CRASH(); @@ -211,12 +207,12 @@ NEVER_INLINE CollectorBlock* Heap::allocateBlock() size_t numBlocks = m_heap.numBlocks; if (m_heap.usedBlocks == numBlocks) { - static const size_t maxNumBlocks = ULONG_MAX / sizeof(AlignedCollectorBlock) / GROWTH_FACTOR; + static const size_t maxNumBlocks = ULONG_MAX / sizeof(PageAllocationAligned) / GROWTH_FACTOR; if (numBlocks > maxNumBlocks) CRASH(); numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR); m_heap.numBlocks = numBlocks; - m_heap.blocks = static_cast<AlignedCollectorBlock*>(fastRealloc(m_heap.blocks, numBlocks * sizeof(AlignedCollectorBlock))); + m_heap.blocks = static_cast<PageAllocationAligned*>(fastRealloc(m_heap.blocks, numBlocks * sizeof(PageAllocationAligned))); } m_heap.blocks[m_heap.usedBlocks++] = allocation; @@ -239,7 +235,7 @@ NEVER_INLINE void Heap::freeBlock(size_t block) if (m_heap.numBlocks > MIN_ARRAY_SIZE && m_heap.usedBlocks < m_heap.numBlocks / LOW_WATER_FACTOR) { m_heap.numBlocks = m_heap.numBlocks / GROWTH_FACTOR; - m_heap.blocks = static_cast<AlignedCollectorBlock*>(fastRealloc(m_heap.blocks, m_heap.numBlocks * sizeof(AlignedCollectorBlock))); + m_heap.blocks = static_cast<PageAllocationAligned*>(fastRealloc(m_heap.blocks, m_heap.numBlocks * sizeof(PageAllocationAligned))); } } @@ -389,175 +385,6 @@ void Heap::shrinkBlocks(size_t neededBlocks) m_heap.collectorBlock(i)->marked.set(HeapConstants::cellsPerBlock - 1); } -#if OS(WINCE) -JS_EXPORTDATA void* g_stackBase = 0; - -inline bool isPageWritable(void* page) -{ - MEMORY_BASIC_INFORMATION memoryInformation; - DWORD result = VirtualQuery(page, &memoryInformation, sizeof(memoryInformation)); - - // return false on error, including ptr outside memory - if (result != sizeof(memoryInformation)) - return false; - - DWORD protect = memoryInformation.Protect & ~(PAGE_GUARD | PAGE_NOCACHE); - return protect == PAGE_READWRITE - || protect == PAGE_WRITECOPY - || protect == PAGE_EXECUTE_READWRITE - || protect == PAGE_EXECUTE_WRITECOPY; -} - -static void* getStackBase(void* previousFrame) -{ - // find the address of this stack frame by taking the address of a local variable - bool isGrowingDownward; - void* thisFrame = (void*)(&isGrowingDownward); - - isGrowingDownward = previousFrame < &thisFrame; - static DWORD pageSize = 0; - if (!pageSize) { - SYSTEM_INFO systemInfo; - GetSystemInfo(&systemInfo); - pageSize = systemInfo.dwPageSize; - } - - // scan all of memory starting from this frame, and return the last writeable page found - register char* currentPage = (char*)((DWORD)thisFrame & ~(pageSize - 1)); - if (isGrowingDownward) { - while (currentPage > 0) { - // check for underflow - if (currentPage >= (char*)pageSize) - currentPage -= pageSize; - else - currentPage = 0; - if (!isPageWritable(currentPage)) - return currentPage + pageSize; - } - return 0; - } else { - while (true) { - // guaranteed to complete because isPageWritable returns false at end of memory - currentPage += pageSize; - if (!isPageWritable(currentPage)) - return currentPage; - } - } -} -#endif - -#if OS(QNX) -static inline void *currentThreadStackBaseQNX() -{ - static void* stackBase = 0; - static size_t stackSize = 0; - static pthread_t stackThread; - pthread_t thread = pthread_self(); - if (stackBase == 0 || thread != stackThread) { - struct _debug_thread_info threadInfo; - memset(&threadInfo, 0, sizeof(threadInfo)); - threadInfo.tid = pthread_self(); - int fd = open("/proc/self", O_RDONLY); - if (fd == -1) { - LOG_ERROR("Unable to open /proc/self (errno: %d)", errno); - return 0; - } - devctl(fd, DCMD_PROC_TIDSTATUS, &threadInfo, sizeof(threadInfo), 0); - close(fd); - stackBase = reinterpret_cast<void*>(threadInfo.stkbase); - stackSize = threadInfo.stksize; - ASSERT(stackBase); - stackThread = thread; - } - return static_cast<char*>(stackBase) + stackSize; -} -#endif - -static inline void* currentThreadStackBase() -{ -#if OS(DARWIN) - pthread_t thread = pthread_self(); - return pthread_get_stackaddr_np(thread); -#elif OS(WINDOWS) && CPU(X86) && COMPILER(MSVC) - // offset 0x18 from the FS segment register gives a pointer to - // the thread information block for the current thread - NT_TIB* pTib; - __asm { - MOV EAX, FS:[18h] - MOV pTib, EAX - } - return static_cast<void*>(pTib->StackBase); -#elif OS(WINDOWS) && CPU(X86) && COMPILER(GCC) - // offset 0x18 from the FS segment register gives a pointer to - // the thread information block for the current thread - NT_TIB* pTib; - asm ( "movl %%fs:0x18, %0\n" - : "=r" (pTib) - ); - return static_cast<void*>(pTib->StackBase); -#elif OS(WINDOWS) && CPU(X86_64) - PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb()); - return reinterpret_cast<void*>(pTib->StackBase); -#elif OS(QNX) - AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); - MutexLocker locker(mutex); - return currentThreadStackBaseQNX(); -#elif OS(SOLARIS) - stack_t s; - thr_stksegment(&s); - return s.ss_sp; -#elif OS(OPENBSD) - pthread_t thread = pthread_self(); - stack_t stack; - pthread_stackseg_np(thread, &stack); - return stack.ss_sp; -#elif OS(SYMBIAN) - TThreadStackInfo info; - RThread thread; - thread.StackInfo(info); - return (void*)info.iBase; -#elif OS(HAIKU) - thread_info threadInfo; - get_thread_info(find_thread(NULL), &threadInfo); - return threadInfo.stack_end; -#elif OS(UNIX) - AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); - MutexLocker locker(mutex); - static void* stackBase = 0; - static size_t stackSize = 0; - static pthread_t stackThread; - pthread_t thread = pthread_self(); - if (stackBase == 0 || thread != stackThread) { - pthread_attr_t sattr; - pthread_attr_init(&sattr); -#if HAVE(PTHREAD_NP_H) || OS(NETBSD) - // e.g. on FreeBSD 5.4, neundorf@kde.org - pthread_attr_get_np(thread, &sattr); -#else - // FIXME: this function is non-portable; other POSIX systems may have different np alternatives - pthread_getattr_np(thread, &sattr); -#endif - int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize); - (void)rc; // FIXME: Deal with error code somehow? Seems fatal. - ASSERT(stackBase); - pthread_attr_destroy(&sattr); - stackThread = thread; - } - return static_cast<char*>(stackBase) + stackSize; -#elif OS(WINCE) - AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); - MutexLocker locker(mutex); - if (g_stackBase) - return g_stackBase; - else { - int dummy; - return getStackBase(&dummy); - } -#else -#error Need a way to get the stack base on this platform -#endif -} - #if ENABLE(JSC_MULTIPLE_THREADS) static inline PlatformThread getCurrentPlatformThread() @@ -587,7 +414,7 @@ void Heap::registerThread() return; pthread_setspecific(m_currentThreadRegistrar, this); - Heap::Thread* thread = new Heap::Thread(pthread_self(), getCurrentPlatformThread(), currentThreadStackBase()); + Heap::Thread* thread = new Heap::Thread(pthread_self(), getCurrentPlatformThread(), m_globalData->stack().origin()); MutexLocker lock(m_registeredThreadsMutex); @@ -654,11 +481,15 @@ static inline bool isPossibleCell(void* p) void Heap::markConservatively(MarkStack& markStack, void* start, void* end) { +#if OS(WINCE) if (start > end) { void* tmp = start; start = end; end = tmp; } +#else + ASSERT(start <= end); +#endif ASSERT((static_cast<char*>(end) - static_cast<char*>(start)) < 0x1000000); ASSERT(isPointerAligned(start)); @@ -685,7 +516,6 @@ void Heap::markConservatively(MarkStack& markStack, void* start, void* end) if (m_heap.collectorBlock(block) != blockAddr) continue; markStack.append(reinterpret_cast<JSCell*>(xAsBits)); - markStack.drain(); } } } @@ -693,10 +523,8 @@ void Heap::markConservatively(MarkStack& markStack, void* start, void* end) void NEVER_INLINE Heap::markCurrentThreadConservativelyInternal(MarkStack& markStack) { - void* dummy; - void* stackPointer = &dummy; - void* stackBase = currentThreadStackBase(); - markConservatively(markStack, stackPointer, stackBase); + markConservatively(markStack, m_globalData->stack().current(), m_globalData->stack().origin()); + markStack.drain(); } #if COMPILER(GCC) @@ -859,9 +687,11 @@ void Heap::markOtherThreadConservatively(MarkStack& markStack, Thread* thread) // mark the thread's registers markConservatively(markStack, static_cast<void*>(®s), static_cast<void*>(reinterpret_cast<char*>(®s) + regSize)); + markStack.drain(); void* stackPointer = otherThreadStackPointer(regs); markConservatively(markStack, stackPointer, thread->stackBase); + markStack.drain(); resumeThread(thread->platformThread); } @@ -920,10 +750,10 @@ WeakGCHandle* Heap::addWeakGCHandle(JSCell* ptr) if (!weakGCHandlePool(i)->isFull()) return weakGCHandlePool(i)->allocate(ptr); - AlignedMemory<WeakGCHandlePool::poolSize> allocation = m_weakGCHandlePoolAllocator.allocate(); + PageAllocationAligned allocation = PageAllocationAligned::allocate(WeakGCHandlePool::poolSize, WeakGCHandlePool::poolSize, OSAllocator::JSGCHeapPages); m_weakGCHandlePools.append(allocation); - WeakGCHandlePool* pool = new (allocation) WeakGCHandlePool(); + WeakGCHandlePool* pool = new (allocation.base()) WeakGCHandlePool(); return pool->allocate(ptr); } @@ -958,6 +788,33 @@ void Heap::markProtectedObjects(MarkStack& markStack) } } +void Heap::pushTempSortVector(Vector<ValueStringPair>* tempVector) +{ + m_tempSortingVectors.append(tempVector); +} + +void Heap::popTempSortVector(Vector<ValueStringPair>* tempVector) +{ + ASSERT_UNUSED(tempVector, tempVector == m_tempSortingVectors.last()); + m_tempSortingVectors.removeLast(); +} + +void Heap::markTempSortVectors(MarkStack& markStack) +{ + typedef Vector<Vector<ValueStringPair>* > VectorOfValueStringVectors; + + VectorOfValueStringVectors::iterator end = m_tempSortingVectors.end(); + for (VectorOfValueStringVectors::iterator it = m_tempSortingVectors.begin(); it != end; ++it) { + Vector<ValueStringPair>* tempSortingVector = *it; + + Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end(); + for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt) + if (vectorIt->first) + markStack.append(vectorIt->first); + markStack.drain(); + } +} + void Heap::clearMarkBits() { for (size_t i = 0; i < m_heap.usedBlocks; ++i) @@ -1045,6 +902,9 @@ void Heap::markRoots() // Mark explicitly registered roots. markProtectedObjects(markStack); + + // Mark temporary vector for Array sorting + markTempSortVectors(markStack); // Mark misc. other roots. if (m_markListSet && m_markListSet->size()) @@ -1232,4 +1092,9 @@ void Heap::setActivityCallback(PassOwnPtr<GCActivityCallback> activityCallback) m_activityCallback = activityCallback; } +GCActivityCallback* Heap::activityCallback() +{ + return m_activityCallback.get(); +} + } // namespace JSC |