Changeset 74360 in webkit
- Timestamp:
- Dec 20, 2010 1:16:14 PM (13 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/Android.mk
r74357 r74360 166 166 wtf/RandomNumber.cpp \ 167 167 wtf/RefCountedLeakCounter.cpp \ 168 wtf/StackBounds.cpp \ 168 169 wtf/TCSystemAlloc.cpp \ 169 170 wtf/ThreadIdentifierDataPthreads.cpp \ -
trunk/JavaScriptCore/Android.v8.wtf.mk
r70198 r74360 43 43 wtf/RandomNumber.cpp \ 44 44 wtf/RefCountedLeakCounter.cpp \ 45 wtf/StackBounds.cpp \ 45 46 wtf/TCSystemAlloc.cpp \ 46 47 wtf/ThreadIdentifierDataPthreads.cpp \ -
trunk/JavaScriptCore/ChangeLog
r74357 r74360 1 2010-12-18 Gavin Barraclough <barraclough@apple.com> 2 3 Reviewed by Oliver Hunt. 4 5 Bug 26276 - Need a mechanism to determine stack extent 6 7 This patch adds a class 'StackBounds', to hold information about the machine stack. 8 The implementation of this class broadly adheres to the current implmentation of 9 stack limit checking, and as such does not solve the problem of determining stack 10 extent, but gives us a common place to do so. 11 12 Currently two mechanism are provided to determine the stack origin (the point the 13 stack is growing away from). currentThreadStackBase() in Collector provides a 14 more accurate determination of the stack origin, so use this to calculate 15 StackBounds::m_origin; WTFThreadData::approximatedStackStart is less accurate, and 16 as such can be removed. Cache the StackBounds on WTFThreadData such that they 17 need only be determined once per thread, and for non-API contexts cache this 18 information in JSGlobalData, to save a thread-specific access. 19 20 For the time being retain the estimate of stack size used by JSC's parser 21 (128 * sizeof(void*) * 1024), with a view to replacing this with something more 22 accurate in the near future. 23 24 * parser/JSParser.cpp: 25 (JSC::JSParser::canRecurse): 26 (JSC::JSParser::JSParser): 27 Change to use StackBounds. 28 * runtime/Collector.cpp: 29 (JSC::Heap::registerThread): 30 (JSC::Heap::markCurrentThreadConservativelyInternal): 31 Change to use StackBounds, cached on JSGlobalData. 32 * runtime/JSGlobalData.cpp: 33 (JSC::JSGlobalData::JSGlobalData): 34 * runtime/JSGlobalData.h: 35 (JSC::JSGlobalData::stack): 36 Add a cached copy of StackBounds. 37 * wtf/StackBounds.cpp: Copied from JavaScriptCore/runtime/Collector.cpp. 38 (WTF::estimateStackBound): 39 (WTF::StackBounds::initialize): 40 (WTF::getStackMax): 41 Copy code from Collector.cpp to determine stack origin. 42 * wtf/StackBounds.h: Added. 43 (WTF::StackBounds::StackBounds): 44 No argument constructor; returns a null StackBounds. 45 (WTF::StackBounds::currentThreadStackBounds): 46 Returns a StackBounds object representing the stack limits 47 of the current thread. 48 (WTF::StackBounds::origin): 49 Returns to stack origin (the point the stack is growing away 50 from; the highest extent of the stack on machines where the 51 stack grows downwards. 52 (WTF::StackBounds::recursionLimit): 53 Returns a limit value that is 'a comfortable distance from 54 the end of the stack'. Our concept of this is currently 1 page 55 away from the end, however the default value may be tuned in 56 the future, and clients may override passing a larger delta; 57 should only be called on StackBounds object representing the 58 stack of the thread this method is called on (checked by 59 checkConsistency). 60 (WTF::StackBounds::recursionCheck): 61 Checks whether we are currently 'a comfortable distance from 62 the end of the stack'. Our concept of this is currently 1 page 63 away from the end, however the default value may be tuned in 64 the future, and clients may override passing a larger delta 65 to apply when checking, if they wish to do so. This method 66 should only be called on StackBounds object representing the 67 stack of the thread this method is called on (checked by 68 checkConsistency). 69 (WTF::StackBounds::current): 70 Approximate current stack position. On machines where the stack 71 is growing downwards this is the lowest address that might need 72 conservative collection. 73 (WTF::StackBounds::isGrowingDownward): 74 True for all platforms other than WINCE, which has to check. 75 (WTF::StackBounds::checkConsistency): 76 This is called in methods that shoulds only be operating on a 77 valid set of bounds; as such we expect m_origin != m_bounds 78 (i.e. stack size != zero) - we're really testing that this 79 object is not null (the constructor initializes both fields 80 to zero). Also checks that current() is within the stack's 81 bounds. 82 * wtf/WTFThreadData.cpp: 83 (WTF::WTFThreadData::WTFThreadData): 84 * wtf/WTFThreadData.h: 85 (WTF::WTFThreadData::stack): 86 Add the StackBounds member variable. 87 1 88 2010-12-17 Geoffrey Garen <ggaren@apple.com> 2 89 -
trunk/JavaScriptCore/GNUmakefile.am
r74357 r74360 495 495 JavaScriptCore/wtf/RetainPtr.h \ 496 496 JavaScriptCore/wtf/SegmentedVector.h \ 497 JavaScriptCore/wtf/StackBounds.cpp \ 498 JavaScriptCore/wtf/StackBounds.h \ 497 499 JavaScriptCore/wtf/StaticConstructors.h \ 498 500 JavaScriptCore/wtf/StdLibExtras.h \ -
trunk/JavaScriptCore/JavaScriptCore.gypi
r74357 r74360 425 425 'wtf/SegmentedVector.h', 426 426 'wtf/SizeLimits.cpp', 427 'wtf/StackBounds.cpp', 428 'wtf/StackBounds.h', 427 429 'wtf/StaticConstructors.h', 428 430 'wtf/StdLibExtras.h', -
trunk/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj
r74357 r74360 778 778 </File> 779 779 <File 780 RelativePath="..\..\wtf\StackBounds.cpp" 781 > 782 </File> 783 <File 784 RelativePath="..\..\wtf\StackBounds.h" 785 > 786 </File> 787 <File 780 788 RelativePath="..\..\wtf\StaticConstructors.h" 781 789 > -
trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r74357 r74360 253 253 86D3B3C310159D7F002865E7 /* LinkBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B3C110159D7F002865E7 /* LinkBuffer.h */; }; 254 254 86D3B3C410159D7F002865E7 /* RepatchBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B3C210159D7F002865E7 /* RepatchBuffer.h */; }; 255 86D87DAE12BCA7D1008E73A1 /* StackBounds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86D87DA512BC4B14008E73A1 /* StackBounds.cpp */; }; 256 86D87DDB12BCAF94008E73A1 /* StackBounds.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D87DA612BC4B14008E73A1 /* StackBounds.h */; settings = {ATTRIBUTES = (Private, ); }; }; 255 257 86DB64640F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */; }; 256 258 86E116B10FE75AC800B512BC /* CodeLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E116B00FE75AC800B512BC /* CodeLocation.h */; }; … … 870 872 86D3B3C110159D7F002865E7 /* LinkBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkBuffer.h; sourceTree = "<group>"; }; 871 873 86D3B3C210159D7F002865E7 /* RepatchBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RepatchBuffer.h; sourceTree = "<group>"; }; 874 86D87DA512BC4B14008E73A1 /* StackBounds.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StackBounds.cpp; sourceTree = "<group>"; }; 875 86D87DA612BC4B14008E73A1 /* StackBounds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StackBounds.h; sourceTree = "<group>"; }; 872 876 86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocatorFixedVMPool.cpp; sourceTree = "<group>"; }; 873 877 86E116B00FE75AC800B512BC /* CodeLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeLocation.h; sourceTree = "<group>"; }; … … 1559 1563 969A07290ED1CE6900F1F681 /* SegmentedVector.h */, 1560 1564 0BF28A2811A33DC300638F84 /* SizeLimits.cpp */, 1565 86D87DA512BC4B14008E73A1 /* StackBounds.cpp */, 1566 86D87DA612BC4B14008E73A1 /* StackBounds.h */, 1561 1567 868BFA5F117D048200B908B1 /* StaticConstructors.h */, 1562 1568 FE1B44790ECCD73B004F4DD1 /* StdLibExtras.h */, … … 2296 2302 BC18C4630E16F5CD00B34460 /* SourceProvider.h in Headers */, 2297 2303 A7386554118697B400540279 /* SpecializedThunkJIT.h in Headers */, 2304 86D87DDB12BCAF94008E73A1 /* StackBounds.h in Headers */, 2298 2305 868BFA60117D048200B908B1 /* StaticConstructors.h in Headers */, 2299 2306 FE1B447A0ECCD73B004F4DD1 /* StdLibExtras.h in Headers */, … … 2798 2805 0BF28A2911A33DC300638F84 /* SizeLimits.cpp in Sources */, 2799 2806 9330402C0E6A764000786E6A /* SmallStrings.cpp in Sources */, 2807 86D87DAE12BCA7D1008E73A1 /* StackBounds.cpp in Sources */, 2800 2808 14469DEB107EC7E700650446 /* StringConstructor.cpp in Sources */, 2801 2809 868BFA0E117CEFD100B908B1 /* StringImpl.cpp in Sources */, -
trunk/JavaScriptCore/parser/JSParser.cpp
r74299 r74360 65 65 66 66 COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens); 67 68 // This matches v869 static const ptrdiff_t kMaxParserStackUsage = 128 * sizeof(void*) * 1024;70 67 71 68 class JSParser { … … 194 191 bool canRecurse() 195 192 { 196 char sample = 0; 197 ASSERT(m_endAddress); 198 return &sample > m_endAddress; 193 return m_stack.recursionCheck(); 199 194 } 200 195 … … 206 201 ParserArena m_arena; 207 202 Lexer* m_lexer; 208 char* m_endAddress;203 StackBounds m_stack; 209 204 bool m_error; 210 205 JSGlobalData* m_globalData; … … 492 487 JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* parameters, bool inStrictContext, bool isFunction, SourceProvider* provider) 493 488 : m_lexer(lexer) 494 , m_ endAddress(0)489 , m_stack(globalData->stack()) 495 490 , m_error(false) 496 491 , m_globalData(globalData) … … 506 501 , m_lastIdentifier(0) 507 502 { 508 m_endAddress = wtfThreadData().approximatedStackStart() - kMaxParserStackUsage;509 503 ScopeRef scope = pushScope(); 510 504 if (isFunction) -
trunk/JavaScriptCore/runtime/Collector.cpp
r73623 r74360 390 390 } 391 391 392 #if OS(WINCE)393 JS_EXPORTDATA void* g_stackBase = 0;394 395 inline bool isPageWritable(void* page)396 {397 MEMORY_BASIC_INFORMATION memoryInformation;398 DWORD result = VirtualQuery(page, &memoryInformation, sizeof(memoryInformation));399 400 // return false on error, including ptr outside memory401 if (result != sizeof(memoryInformation))402 return false;403 404 DWORD protect = memoryInformation.Protect & ~(PAGE_GUARD | PAGE_NOCACHE);405 return protect == PAGE_READWRITE406 || protect == PAGE_WRITECOPY407 || protect == PAGE_EXECUTE_READWRITE408 || protect == PAGE_EXECUTE_WRITECOPY;409 }410 411 static void* getStackBase(void* previousFrame)412 {413 // find the address of this stack frame by taking the address of a local variable414 bool isGrowingDownward;415 void* thisFrame = (void*)(&isGrowingDownward);416 417 isGrowingDownward = previousFrame < &thisFrame;418 static DWORD pageSize = 0;419 if (!pageSize) {420 SYSTEM_INFO systemInfo;421 GetSystemInfo(&systemInfo);422 pageSize = systemInfo.dwPageSize;423 }424 425 // scan all of memory starting from this frame, and return the last writeable page found426 register char* currentPage = (char*)((DWORD)thisFrame & ~(pageSize - 1));427 if (isGrowingDownward) {428 while (currentPage > 0) {429 // check for underflow430 if (currentPage >= (char*)pageSize)431 currentPage -= pageSize;432 else433 currentPage = 0;434 if (!isPageWritable(currentPage))435 return currentPage + pageSize;436 }437 return 0;438 } else {439 while (true) {440 // guaranteed to complete because isPageWritable returns false at end of memory441 currentPage += pageSize;442 if (!isPageWritable(currentPage))443 return currentPage;444 }445 }446 }447 #endif448 449 #if OS(QNX)450 static inline void *currentThreadStackBaseQNX()451 {452 static void* stackBase = 0;453 static size_t stackSize = 0;454 static pthread_t stackThread;455 pthread_t thread = pthread_self();456 if (stackBase == 0 || thread != stackThread) {457 struct _debug_thread_info threadInfo;458 memset(&threadInfo, 0, sizeof(threadInfo));459 threadInfo.tid = pthread_self();460 int fd = open("/proc/self", O_RDONLY);461 if (fd == -1) {462 LOG_ERROR("Unable to open /proc/self (errno: %d)", errno);463 return 0;464 }465 devctl(fd, DCMD_PROC_TIDSTATUS, &threadInfo, sizeof(threadInfo), 0);466 close(fd);467 stackBase = reinterpret_cast<void*>(threadInfo.stkbase);468 stackSize = threadInfo.stksize;469 ASSERT(stackBase);470 stackThread = thread;471 }472 return static_cast<char*>(stackBase) + stackSize;473 }474 #endif475 476 static inline void* currentThreadStackBase()477 {478 #if OS(DARWIN)479 pthread_t thread = pthread_self();480 return pthread_get_stackaddr_np(thread);481 #elif OS(WINDOWS) && CPU(X86) && COMPILER(MSVC)482 // offset 0x18 from the FS segment register gives a pointer to483 // the thread information block for the current thread484 NT_TIB* pTib;485 __asm {486 MOV EAX, FS:[18h]487 MOV pTib, EAX488 }489 return static_cast<void*>(pTib->StackBase);490 #elif OS(WINDOWS) && CPU(X86) && COMPILER(GCC)491 // offset 0x18 from the FS segment register gives a pointer to492 // the thread information block for the current thread493 NT_TIB* pTib;494 asm ( "movl %%fs:0x18, %0\n"495 : "=r" (pTib)496 );497 return static_cast<void*>(pTib->StackBase);498 #elif OS(WINDOWS) && CPU(X86_64)499 PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb());500 return reinterpret_cast<void*>(pTib->StackBase);501 #elif OS(QNX)502 AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);503 MutexLocker locker(mutex);504 return currentThreadStackBaseQNX();505 #elif OS(SOLARIS)506 stack_t s;507 thr_stksegment(&s);508 return s.ss_sp;509 #elif OS(OPENBSD)510 pthread_t thread = pthread_self();511 stack_t stack;512 pthread_stackseg_np(thread, &stack);513 return stack.ss_sp;514 #elif OS(SYMBIAN)515 TThreadStackInfo info;516 RThread thread;517 thread.StackInfo(info);518 return (void*)info.iBase;519 #elif OS(HAIKU)520 thread_info threadInfo;521 get_thread_info(find_thread(NULL), &threadInfo);522 return threadInfo.stack_end;523 #elif OS(UNIX)524 AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);525 MutexLocker locker(mutex);526 static void* stackBase = 0;527 static size_t stackSize = 0;528 static pthread_t stackThread;529 pthread_t thread = pthread_self();530 if (stackBase == 0 || thread != stackThread) {531 pthread_attr_t sattr;532 pthread_attr_init(&sattr);533 #if HAVE(PTHREAD_NP_H) || OS(NETBSD)534 // e.g. on FreeBSD 5.4, neundorf@kde.org535 pthread_attr_get_np(thread, &sattr);536 #else537 // FIXME: this function is non-portable; other POSIX systems may have different np alternatives538 pthread_getattr_np(thread, &sattr);539 #endif540 int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize);541 (void)rc; // FIXME: Deal with error code somehow? Seems fatal.542 ASSERT(stackBase);543 pthread_attr_destroy(&sattr);544 stackThread = thread;545 }546 return static_cast<char*>(stackBase) + stackSize;547 #elif OS(WINCE)548 AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);549 MutexLocker locker(mutex);550 if (g_stackBase)551 return g_stackBase;552 else {553 int dummy;554 return getStackBase(&dummy);555 }556 #else557 #error Need a way to get the stack base on this platform558 #endif559 }560 561 392 #if ENABLE(JSC_MULTIPLE_THREADS) 562 393 … … 588 419 589 420 pthread_setspecific(m_currentThreadRegistrar, this); 590 Heap::Thread* thread = new Heap::Thread(pthread_self(), getCurrentPlatformThread(), currentThreadStackBase());421 Heap::Thread* thread = new Heap::Thread(pthread_self(), getCurrentPlatformThread(), m_globalData->stack().origin()); 591 422 592 423 MutexLocker lock(m_registeredThreadsMutex); … … 655 486 void Heap::markConservatively(MarkStack& markStack, void* start, void* end) 656 487 { 488 #if OS(WINCE) 657 489 if (start > end) { 658 490 void* tmp = start; … … 660 492 end = tmp; 661 493 } 494 #else 495 ASSERT(start <= end); 496 #endif 662 497 663 498 ASSERT((static_cast<char*>(end) - static_cast<char*>(start)) < 0x1000000); … … 693 528 void NEVER_INLINE Heap::markCurrentThreadConservativelyInternal(MarkStack& markStack) 694 529 { 695 void* dummy; 696 void* stackPointer = &dummy; 697 void* stackBase = currentThreadStackBase(); 698 markConservatively(markStack, stackPointer, stackBase); 530 markConservatively(markStack, m_globalData->stack().current(), m_globalData->stack().origin()); 699 531 markStack.drain(); 700 532 } -
trunk/JavaScriptCore/runtime/JSGlobalData.cpp
r72360 r74360 154 154 #endif 155 155 { 156 if (globalDataType == Default) 157 m_stack = wtfThreadData().stack(); 158 156 159 #if PLATFORM(MAC) 157 160 startProfilerServerIfNeeded(); -
trunk/JavaScriptCore/runtime/JSGlobalData.h
r72489 r74360 47 47 #include <wtf/RefCounted.h> 48 48 #include <wtf/ThreadSpecific.h> 49 #include <wtf/WTFThreadData.h> 49 50 #if ENABLE(REGEXP_TRACING) 50 51 #include <wtf/ListHashSet.h> … … 179 180 bool canUseJIT() { return m_canUseJIT; } 180 181 #endif 182 183 const StackBounds& stack() 184 { 185 return (globalDataType == Default) 186 ? m_stack 187 : wtfThreadData().stack(); 188 } 189 181 190 Lexer* lexer; 182 191 Parser* parser; … … 251 260 bool m_canUseJIT; 252 261 #endif 262 StackBounds m_stack; 253 263 }; 254 264 -
trunk/JavaScriptCore/wtf/CMakeLists.txt
r70201 r74360 10 10 RandomNumber.cpp 11 11 RefCountedLeakCounter.cpp 12 StackBounds.cpp 12 13 StringExtras.cpp 13 14 Threading.cpp -
trunk/JavaScriptCore/wtf/WTFThreadData.cpp
r66665 r74360 43 43 , m_currentIdentifierTable(m_defaultIdentifierTable) 44 44 #endif 45 , m_stackBounds(StackBounds::currentThreadStackBounds()) 45 46 { 46 char sample = 0;47 m_approximatedStackStart = &sample;48 47 } 49 48 -
trunk/JavaScriptCore/wtf/WTFThreadData.h
r69458 r74360 31 31 #include <wtf/HashSet.h> 32 32 #include <wtf/Noncopyable.h> 33 #include <wtf/StackBounds.h> 33 34 #include <wtf/text/StringHash.h> 34 35 … … 114 115 #endif 115 116 116 c har* approximatedStackStart() const117 const StackBounds& stack() const 117 118 { 118 return m_ approximatedStackStart;119 return m_stackBounds; 119 120 } 120 121 … … 136 137 friend class AtomicStringTable; 137 138 138 char* m_approximatedStackStart;139 StackBounds m_stackBounds; 139 140 }; 140 141 -
trunk/JavaScriptCore/wtf/wtf.pri
r74357 r74360 20 20 wtf/RandomNumber.cpp \ 21 21 wtf/RefCountedLeakCounter.cpp \ 22 wtf/StackBounds.cpp \ 22 23 wtf/ThreadingNone.cpp \ 23 24 wtf/Threading.cpp \ -
trunk/JavaScriptGlue/ChangeLog
r74357 r74360 1 2010-12-18 Gavin Barraclough <barraclough@apple.com> 2 3 Reviewed by Oliver Hunt. 4 5 Bug 26276 - Need a mechanism to determine stack extent 6 7 Add forwarding header for StackBounds.h. 8 9 * ForwardingHeaders/wtf/StackBounds.h: Added. 10 1 11 2010-12-20 Geoffrey Garen <ggaren@apple.com> 2 12 -
trunk/WebCore/ChangeLog
r74358 r74360 1 2010-12-18 Gavin Barraclough <barraclough@apple.com> 2 3 Reviewed by Oliver Hunt. 4 5 Bug 26276 - Need a mechanism to determine stack extent 6 7 Add forwarding header for StackBounds.h. 8 9 * ForwardingHeaders/wtf/StackBounds.h: Added. 10 1 11 2010-12-20 James Robinson <jamesr@chromium.org> 2 12
Note: See TracChangeset
for help on using the changeset viewer.