Get rid of wtf/StackBounds
All we need is the starting address of the stack, not the entire class. Change-Id: I447482f6900afa0a66efce2dcc32239828b64f8e Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
parent
5e496cc7bd
commit
215c0458e6
|
@ -6,9 +6,6 @@ SOURCES += $$PWD/assembler/MacroAssemblerARM.cpp
|
|||
SOURCES += $$PWD/assembler/MacroAssemblerSH4.cpp
|
||||
SOURCES += $$PWD/assembler/LinkBuffer.cpp
|
||||
|
||||
SOURCES += $$PWD/wtf/StackBounds.cpp
|
||||
HEADERS += $$PWD/wtf/StackBounds.h
|
||||
|
||||
SOURCES += $$PWD/wtf/PrintStream.cpp
|
||||
HEADERS += $$PWD/wtf/PrintStream.h
|
||||
|
||||
|
@ -43,6 +40,8 @@ DEFINES += ENABLE_JIT_CONSTANT_BLINDING=0
|
|||
DEFINES += ENABLE_ASSEMBLER=1
|
||||
DEFINES += USE_SYSTEM_MALLOC=1
|
||||
|
||||
DEFINES += BUILDING_QT__
|
||||
|
||||
INCLUDEPATH += $$PWD/jit
|
||||
INCLUDEPATH += $$PWD/assembler
|
||||
INCLUDEPATH += $$PWD/wtf
|
||||
|
|
|
@ -1,261 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
|
||||
* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "StackBounds.h"
|
||||
|
||||
#if OS(DARWIN)
|
||||
|
||||
#include <mach/task.h>
|
||||
#include <mach/thread_act.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#elif OS(WINDOWS)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#elif OS(SOLARIS)
|
||||
|
||||
#include <thread.h>
|
||||
|
||||
#elif OS(QNX)
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/procfs.h>
|
||||
|
||||
#elif OS(UNIX)
|
||||
|
||||
#include <pthread.h>
|
||||
#if HAVE(PTHREAD_NP_H)
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
namespace WTF {
|
||||
|
||||
// Bug 26276 - Need a mechanism to determine stack extent
|
||||
//
|
||||
// These platforms should now be working correctly:
|
||||
// DARWIN, QNX, UNIX
|
||||
// These platforms are not:
|
||||
// WINDOWS, SOLARIS, OPENBSD, WINCE
|
||||
//
|
||||
// FIXME: remove this! - this code unsafely guesses at stack sizes!
|
||||
#if OS(WINDOWS) || OS(SOLARIS) || OS(OPENBSD)
|
||||
// Based on the current limit used by the JSC parser, guess the stack size.
|
||||
static const ptrdiff_t estimatedStackSize = 128 * sizeof(void*) * 1024;
|
||||
// This method assumes the stack is growing downwards.
|
||||
static void* estimateStackBound(void* origin)
|
||||
{
|
||||
return static_cast<char*>(origin) - estimatedStackSize;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS(DARWIN)
|
||||
|
||||
void StackBounds::initialize()
|
||||
{
|
||||
pthread_t thread = pthread_self();
|
||||
m_origin = pthread_get_stackaddr_np(thread);
|
||||
m_bound = static_cast<char*>(m_origin) - pthread_get_stacksize_np(thread);
|
||||
}
|
||||
|
||||
#elif OS(QNX)
|
||||
|
||||
void StackBounds::initialize()
|
||||
{
|
||||
void* stackBase = 0;
|
||||
size_t stackSize = 0;
|
||||
|
||||
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);
|
||||
CRASH();
|
||||
}
|
||||
devctl(fd, DCMD_PROC_TIDSTATUS, &threadInfo, sizeof(threadInfo), 0);
|
||||
close(fd);
|
||||
stackBase = reinterpret_cast<void*>(threadInfo.stkbase);
|
||||
stackSize = threadInfo.stksize;
|
||||
ASSERT(stackBase);
|
||||
|
||||
m_bound = static_cast<char*>(stackBase) + 0x1000; // 4kb guard page
|
||||
m_origin = static_cast<char*>(stackBase) + stackSize;
|
||||
}
|
||||
|
||||
#elif OS(SOLARIS)
|
||||
|
||||
void StackBounds::initialize()
|
||||
{
|
||||
stack_t s;
|
||||
thr_stksegment(&s);
|
||||
m_origin = s.ss_sp;
|
||||
m_bound = estimateStackBound(m_origin);
|
||||
}
|
||||
|
||||
#elif OS(OPENBSD)
|
||||
|
||||
void StackBounds::initialize()
|
||||
{
|
||||
pthread_t thread = pthread_self();
|
||||
stack_t stack;
|
||||
pthread_stackseg_np(thread, &stack);
|
||||
m_origin = stack.ss_sp;
|
||||
m_bound = estimateStackBound(m_origin);
|
||||
}
|
||||
|
||||
#elif OS(UNIX)
|
||||
|
||||
void StackBounds::initialize()
|
||||
{
|
||||
void* stackBase = 0;
|
||||
size_t stackSize = 0;
|
||||
|
||||
pthread_t thread = pthread_self();
|
||||
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);
|
||||
m_bound = stackBase;
|
||||
m_origin = static_cast<char*>(stackBase) + stackSize;
|
||||
}
|
||||
|
||||
#elif OS(WINCE)
|
||||
|
||||
static bool detectGrowingDownward(void* previousFrame)
|
||||
{
|
||||
// Find the address of this stack frame by taking the address of a local variable.
|
||||
int thisFrame;
|
||||
return previousFrame > &thisFrame;
|
||||
}
|
||||
|
||||
static 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 inline void* getLowerStackBound(char* currentPage, DWORD pageSize)
|
||||
{
|
||||
while (currentPage > 0) {
|
||||
// check for underflow
|
||||
if (currentPage >= reinterpret_cast<char*>(pageSize))
|
||||
currentPage -= pageSize;
|
||||
else
|
||||
currentPage = 0;
|
||||
|
||||
if (!isPageWritable(currentPage))
|
||||
return currentPage + pageSize;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void* getUpperStackBound(char* currentPage, DWORD pageSize)
|
||||
{
|
||||
do {
|
||||
// guaranteed to complete because isPageWritable returns false at end of memory
|
||||
currentPage += pageSize;
|
||||
} while (isPageWritable(currentPage));
|
||||
|
||||
return currentPage - pageSize;
|
||||
}
|
||||
|
||||
void StackBounds::initialize()
|
||||
{
|
||||
// find the address of this stack frame by taking the address of a local variable
|
||||
void* thisFrame = &thisFrame;
|
||||
bool isGrowingDownward = detectGrowingDownward(thisFrame);
|
||||
|
||||
SYSTEM_INFO systemInfo;
|
||||
GetSystemInfo(&systemInfo);
|
||||
DWORD pageSize = systemInfo.dwPageSize;
|
||||
|
||||
// scan all of memory starting from this frame, and return the last writeable page found
|
||||
char* currentPage = reinterpret_cast<char*>(reinterpret_cast<DWORD>(thisFrame) & ~(pageSize - 1));
|
||||
void* lowerStackBound = getLowerStackBound(currentPage, pageSize);
|
||||
void* upperStackBound = getUpperStackBound(currentPage, pageSize);
|
||||
|
||||
m_origin = isGrowingDownward ? upperStackBound : lowerStackBound;
|
||||
m_bound = isGrowingDownward ? lowerStackBound : upperStackBound;
|
||||
}
|
||||
|
||||
#elif OS(WINDOWS)
|
||||
|
||||
void StackBounds::initialize()
|
||||
{
|
||||
#if 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
|
||||
}
|
||||
m_origin = static_cast<void*>(pTib->StackBase);
|
||||
#elif 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)
|
||||
);
|
||||
m_origin = static_cast<void*>(pTib->StackBase);
|
||||
#elif CPU(X86_64)
|
||||
PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb());
|
||||
m_origin = reinterpret_cast<void*>(pTib->StackBase);
|
||||
#else
|
||||
#error Need a way to get the stack bounds on this platform (Windows)
|
||||
#endif
|
||||
// Looks like we should be able to get pTib->StackLimit
|
||||
m_bound = estimateStackBound(m_origin);
|
||||
}
|
||||
|
||||
#else
|
||||
#error Need a way to get the stack bounds on this platform
|
||||
#endif
|
||||
|
||||
} // namespace WTF
|
|
@ -1,129 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Apple Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef StackBounds_h
|
||||
#define StackBounds_h
|
||||
|
||||
namespace WTF {
|
||||
|
||||
class StackBounds {
|
||||
// isSafeToRecurse() / recursionLimit() tests (by default)
|
||||
// that we are at least this far from the end of the stack.
|
||||
//
|
||||
// This 64k number was picked because a sampling of stack usage differences
|
||||
// between consecutive entries into one of the Interpreter::execute...()
|
||||
// functions was seen to be as high as 27k. Hence, 64k is chosen as a
|
||||
// conservative availability value that is not too large but comfortably
|
||||
// exceeds 27k with some buffer for error.
|
||||
const static size_t s_defaultAvailabilityDelta = 64 * 1024;
|
||||
|
||||
public:
|
||||
StackBounds()
|
||||
: m_origin(0)
|
||||
, m_bound(0)
|
||||
{
|
||||
}
|
||||
|
||||
static StackBounds currentThreadStackBounds()
|
||||
{
|
||||
StackBounds bounds;
|
||||
bounds.initialize();
|
||||
bounds.checkConsistency();
|
||||
return bounds;
|
||||
}
|
||||
|
||||
void* origin() const
|
||||
{
|
||||
ASSERT(m_origin);
|
||||
return m_origin;
|
||||
}
|
||||
|
||||
void* current() const
|
||||
{
|
||||
checkConsistency();
|
||||
void* currentPosition = ¤tPosition;
|
||||
return currentPosition;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return isGrowingDownward()
|
||||
? static_cast<char*>(m_origin) - static_cast<char*>(m_bound)
|
||||
: static_cast<char*>(m_bound) - static_cast<char*>(m_origin);
|
||||
}
|
||||
|
||||
void* recursionLimit(size_t minAvailableDelta = s_defaultAvailabilityDelta) const
|
||||
{
|
||||
checkConsistency();
|
||||
return isGrowingDownward()
|
||||
? static_cast<char*>(m_bound) + minAvailableDelta
|
||||
: static_cast<char*>(m_bound) - minAvailableDelta;
|
||||
}
|
||||
|
||||
bool isSafeToRecurse(size_t minAvailableDelta = s_defaultAvailabilityDelta) const
|
||||
{
|
||||
checkConsistency();
|
||||
return isGrowingDownward()
|
||||
? current() >= recursionLimit(minAvailableDelta)
|
||||
: current() <= recursionLimit(minAvailableDelta);
|
||||
}
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
|
||||
|
||||
bool isGrowingDownward() const
|
||||
{
|
||||
ASSERT(m_origin && m_bound);
|
||||
#if OS(WINCE)
|
||||
return m_origin > m_bound;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void checkConsistency() const
|
||||
{
|
||||
#if !ASSERT_DISABLED
|
||||
void* currentPosition = ¤tPosition;
|
||||
ASSERT(m_origin != m_bound);
|
||||
ASSERT(isGrowingDownward()
|
||||
? (currentPosition < m_origin && currentPosition > m_bound)
|
||||
: (currentPosition > m_origin && currentPosition < m_bound));
|
||||
#endif
|
||||
}
|
||||
|
||||
void* m_origin;
|
||||
void* m_bound;
|
||||
|
||||
friend class StackStats;
|
||||
};
|
||||
|
||||
} // namespace WTF
|
||||
|
||||
using WTF::StackBounds;
|
||||
|
||||
#endif
|
17
qv4mm.cpp
17
qv4mm.cpp
|
@ -31,7 +31,6 @@
|
|||
#include "qmljs_objects.h"
|
||||
#include "qv4ecmaobjects_p.h"
|
||||
#include "qv4mm.h"
|
||||
#include "StackBounds.h"
|
||||
#include "PageAllocation.h"
|
||||
#include "StdLibExtras.h"
|
||||
|
||||
|
@ -363,8 +362,20 @@ void MemoryManager::collectRootsOnStack(QVector<VM::Object *> &roots) const
|
|||
return;
|
||||
|
||||
Value valueOnStack = Value::undefinedValue();
|
||||
StackBounds bounds = StackBounds::currentThreadStackBounds();
|
||||
Value* top = reinterpret_cast<Value*>(bounds.origin()) - 1;
|
||||
|
||||
void* stackTop = 0;
|
||||
#if USE(PTHREADS)
|
||||
#if OS(DARWIN)
|
||||
stackTop = pthread_get_stackaddr_np(pthread_self());
|
||||
#else
|
||||
pthread_attr_t attr;
|
||||
pthread_getattr_np(pthread_self(), &attr);
|
||||
size_t stackSize = 0;
|
||||
pthread_attr_getstack(&attr, &stackTop, &stackSize);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Value* top = reinterpret_cast<Value*>(stackTop) - 1;
|
||||
Value* current = (&valueOnStack) + 1;
|
||||
|
||||
char** heapChunkBoundaries = (char**)alloca(m_d->heapChunks.count() * 2 * sizeof(char*));
|
||||
|
|
Loading…
Reference in New Issue