⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 collector.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    // FIXME: Consider doing this in NDEBUG builds too (see comment above).    heap.operationInProgress = NoOperation;#endif    return newCell;}void* Heap::allocate(size_t s){    return heapAllocate<PrimaryHeap>(s);}void* Heap::allocateNumber(size_t s){    return heapAllocate<NumberHeap>(s);}static inline void* currentThreadStackBase(){#if PLATFORM(DARWIN)    pthread_t thread = pthread_self();    return pthread_get_stackaddr_np(thread);#elif PLATFORM(WIN_OS) && PLATFORM(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 PLATFORM(WIN_OS) && PLATFORM(X86_64) && COMPILER(MSVC)    PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb());    return reinterpret_cast<void*>(pTib->StackBase);#elif PLATFORM(WIN_OS) && PLATFORM(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 PLATFORM(SOLARIS)    stack_t s;    thr_stksegment(&s);    return s.ss_sp;#elif PLATFORM(OPENBSD)    pthread_t thread = pthread_self();    stack_t stack;    pthread_stackseg_np(thread, &stack);    return stack.ss_sp;#elif PLATFORM(UNIX)    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) || PLATFORM(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 PLATFORM(SYMBIAN)    static void* stackBase = 0;    if (stackBase == 0) {        TThreadStackInfo info;        RThread thread;        thread.StackInfo(info);        stackBase = (void*)info.iBase;    }    return (void*)stackBase;#else#error Need a way to get the stack base on this platform#endif}#if ENABLE(JSC_MULTIPLE_THREADS)static inline PlatformThread getCurrentPlatformThread(){#if PLATFORM(DARWIN)    return pthread_mach_thread_np(pthread_self());#elif PLATFORM(WIN_OS)    HANDLE threadHandle = pthread_getw32threadhandle_np(pthread_self());    return PlatformThread(GetCurrentThreadId(), threadHandle);#endif}void Heap::makeUsableFromMultipleThreads(){    if (m_currentThreadRegistrar)        return;    int error = pthread_key_create(&m_currentThreadRegistrar, unregisterThread);    if (error)        CRASH();}void Heap::registerThread(){    if (!m_currentThreadRegistrar || pthread_getspecific(m_currentThreadRegistrar))        return;    pthread_setspecific(m_currentThreadRegistrar, this);    Heap::Thread* thread = new Heap::Thread(pthread_self(), getCurrentPlatformThread(), currentThreadStackBase());    MutexLocker lock(m_registeredThreadsMutex);    thread->next = m_registeredThreads;    m_registeredThreads = thread;}void Heap::unregisterThread(void* p){    if (p)        static_cast<Heap*>(p)->unregisterThread();}void Heap::unregisterThread(){    pthread_t currentPosixThread = pthread_self();    MutexLocker lock(m_registeredThreadsMutex);    if (pthread_equal(currentPosixThread, m_registeredThreads->posixThread)) {        Thread* t = m_registeredThreads;        m_registeredThreads = m_registeredThreads->next;        delete t;    } else {        Heap::Thread* last = m_registeredThreads;        Heap::Thread* t;        for (t = m_registeredThreads->next; t; t = t->next) {            if (pthread_equal(t->posixThread, currentPosixThread)) {                last->next = t->next;                break;            }            last = t;        }        ASSERT(t); // If t is NULL, we never found ourselves in the list.        delete t;    }}#else // ENABLE(JSC_MULTIPLE_THREADS)void Heap::registerThread(){}#endif#define IS_POINTER_ALIGNED(p) (((intptr_t)(p) & (sizeof(char*) - 1)) == 0)// cell size needs to be a power of two for this to be valid#define IS_HALF_CELL_ALIGNED(p) (((intptr_t)(p) & (CELL_MASK >> 1)) == 0)void Heap::markConservatively(void* start, void* end){    if (start > end) {        void* tmp = start;        start = end;        end = tmp;    }    ASSERT((static_cast<char*>(end) - static_cast<char*>(start)) < 0x1000000);    ASSERT(IS_POINTER_ALIGNED(start));    ASSERT(IS_POINTER_ALIGNED(end));    char** p = static_cast<char**>(start);    char** e = static_cast<char**>(end);    size_t usedPrimaryBlocks = primaryHeap.usedBlocks;    size_t usedNumberBlocks = numberHeap.usedBlocks;    CollectorBlock** primaryBlocks = primaryHeap.blocks;    CollectorBlock** numberBlocks = numberHeap.blocks;    const size_t lastCellOffset = sizeof(CollectorCell) * (CELLS_PER_BLOCK - 1);    while (p != e) {        char* x = *p++;        if (IS_HALF_CELL_ALIGNED(x) && x) {            uintptr_t xAsBits = reinterpret_cast<uintptr_t>(x);            xAsBits &= CELL_ALIGN_MASK;            uintptr_t offset = xAsBits & BLOCK_OFFSET_MASK;            CollectorBlock* blockAddr = reinterpret_cast<CollectorBlock*>(xAsBits - offset);            // Mark the the number heap, we can mark these Cells directly to avoid the virtual call cost            for (size_t block = 0; block < usedNumberBlocks; block++) {                if ((numberBlocks[block] == blockAddr) & (offset <= lastCellOffset)) {                    Heap::markCell(reinterpret_cast<JSCell*>(xAsBits));                    goto endMarkLoop;                }            }                      // Mark the primary heap            for (size_t block = 0; block < usedPrimaryBlocks; block++) {                if ((primaryBlocks[block] == blockAddr) & (offset <= lastCellOffset)) {                    if (reinterpret_cast<CollectorCell*>(xAsBits)->u.freeCell.zeroIfFree != 0) {                        JSCell* imp = reinterpret_cast<JSCell*>(xAsBits);                        if (!imp->marked())                            imp->mark();                    }                    break;                }            }        endMarkLoop:            ;        }    }}void NEVER_INLINE Heap::markCurrentThreadConservativelyInternal(){    void* dummy;    void* stackPointer = &dummy;    void* stackBase = currentThreadStackBase();    markConservatively(stackPointer, stackBase);}void Heap::markCurrentThreadConservatively(){    // setjmp forces volatile registers onto the stack    jmp_buf registers;#if COMPILER(MSVC)#pragma warning(push)#pragma warning(disable: 4611)#endif    setjmp(registers);#if COMPILER(MSVC)#pragma warning(pop)#endif    markCurrentThreadConservativelyInternal();}#if ENABLE(JSC_MULTIPLE_THREADS)static inline void suspendThread(const PlatformThread& platformThread){#if PLATFORM(DARWIN)    thread_suspend(platformThread);#elif PLATFORM(WIN_OS)    SuspendThread(platformThread.handle);#else#error Need a way to suspend threads on this platform#endif}static inline void resumeThread(const PlatformThread& platformThread){#if PLATFORM(DARWIN)    thread_resume(platformThread);#elif PLATFORM(WIN_OS)    ResumeThread(platformThread.handle);#else#error Need a way to resume threads on this platform#endif}typedef unsigned long usword_t; // word size, assumed to be either 32 or 64 bit#if PLATFORM(DARWIN)#if PLATFORM(X86)typedef i386_thread_state_t PlatformThreadRegisters;#elif PLATFORM(X86_64)typedef x86_thread_state64_t PlatformThreadRegisters;#elif PLATFORM(PPC)typedef ppc_thread_state_t PlatformThreadRegisters;#elif PLATFORM(PPC64)typedef ppc_thread_state64_t PlatformThreadRegisters;#elif PLATFORM(ARM)typedef arm_thread_state_t PlatformThreadRegisters;#else#error Unknown Architecture#endif#elif PLATFORM(WIN_OS)&& PLATFORM(X86)typedef CONTEXT PlatformThreadRegisters;#else#error Need a thread register struct for this platform#endifstatic size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs){#if PLATFORM(DARWIN)#if PLATFORM(X86)    unsigned user_count = sizeof(regs)/sizeof(int);    thread_state_flavor_t flavor = i386_THREAD_STATE;#elif PLATFORM(X86_64)    unsigned user_count = x86_THREAD_STATE64_COUNT;    thread_state_flavor_t flavor = x86_THREAD_STATE64;#elif PLATFORM(PPC)     unsigned user_count = PPC_THREAD_STATE_COUNT;    thread_state_flavor_t flavor = PPC_THREAD_STATE;#elif PLATFORM(PPC64)    unsigned user_count = PPC_THREAD_STATE64_COUNT;    thread_state_flavor_t flavor = PPC_THREAD_STATE64;#elif PLATFORM(ARM)    unsigned user_count = ARM_THREAD_STATE_COUNT;    thread_state_flavor_t flavor = ARM_THREAD_STATE;#else#error Unknown Architecture#endif    kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)&regs, &user_count);    if (result != KERN_SUCCESS) {        WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION,                             "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result);        CRASH();    }    return user_count * sizeof(usword_t);// end PLATFORM(DARWIN)#elif PLATFORM(WIN_OS) && PLATFORM(X86)    regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS;    GetThreadContext(platformThread.handle, &regs);    return sizeof(CONTEXT);#else#error Need a way to get thread registers on this platform#endif}static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs){#if PLATFORM(DARWIN)#if __DARWIN_UNIX03#if PLATFORM(X86)    return reinterpret_cast<void*>(regs.__esp);#elif PLATFORM(X86_64)    return reinterpret_cast<void*>(regs.__rsp);#elif PLATFORM(PPC) || PLATFORM(PPC64)    return reinterpret_cast<void*>(regs.__r1);#elif PLATFORM(ARM)    return reinterpret_cast<void*>(regs.__sp);#else#error Unknown Architecture#endif#else // !__DARWIN_UNIX03#if PLATFORM(X86)    return reinterpret_cast<void*>(regs.esp);#elif PLATFORM(X86_64)    return reinterpret_cast<void*>(regs.rsp);#elif (PLATFORM(PPC) || PLATFORM(PPC64))    return reinterpret_cast<void*>(regs.r1);#else#error Unknown Architecture#endif#endif // __DARWIN_UNIX03// end PLATFORM(DARWIN)#elif PLATFORM(X86) && PLATFORM(WIN_OS)    return reinterpret_cast<void*>((uintptr_t) regs.Esp);#else#error Need a way to get the stack pointer for another thread on this platform#endif}void Heap::markOtherThreadConservatively(Thread* thread)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -