Changeset 19209 in webkit for trunk/JavaScriptCore
- Timestamp:
- Jan 28, 2007, 10:17:38 PM (18 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r19203 r19209 1 2007-01-28 Geoffrey Garen <[email protected]> 2 3 Reviewed by Maciej Stachowiak. 4 5 First step in fixing <rdar://problem/4485644> REGRESSION: JavaScriptCore 6 has init routines 7 8 Don't rely on a static initializer to store the main thread's ID (which 9 we would use to detect allocations on secondary threads). Instead, require 10 the caller to notify fastMalloc if it might allocate on a secondary thread. 11 12 Also fixed what seemed like a race condition in do_malloc. 13 14 tcmalloc_unittest and my custom versions of JS iBench and PLT show no 15 regressions. 16 17 * wtf/FastMalloc.cpp: 18 (WTF::fastMallocSetIsMultiThreaded): 19 (1) Renamed from "fastMallocRegisterThread", which was a misleading name because 20 not all threads need to register with fastMalloc -- only secondary threads 21 need to, and only for the purpose of disabling its single-threaded optimization. 22 23 (2) Use the pageheap_lock instead of a custom one, since we need to synchronize 24 with the read of isMultiThreaded inside CreateCacheIfNecessary. This is a new 25 requirement, now that we can't guarantee that the first call to CreateCacheIfNecessary 26 will occur on the main thread at init time, before any other threads have been created. 27 28 (WTF::TCMalloc_ThreadCache::CreateCacheIfNecessary): 29 (WTF::do_malloc): Reverted WTF change only to call GetCache() if size <= kMaxSize. 30 The WTF code would read phinited without holding the pageheap_lock, which 31 seemed like a race condition. Regardless, calling GetCache reduces the number 32 of code paths to module initialization, which will help in writing the 33 final fix for this bug. 34 1 35 2007-01-28 David Kilzer <[email protected]> 2 36 -
trunk/JavaScriptCore/kjs/collector.cpp
r18888 r19209 262 262 263 263 if (!pthread_getspecific(registeredThreadKey)) { 264 if (!pthread_main_np()) 265 WTF::fastMallocSetIsMultiThreaded(); 264 266 pthread_t pthread = pthread_self(); 265 WTF::fastMallocRegisterThread(pthread);266 267 Collector::Thread *thread = new Collector::Thread(pthread, pthread_mach_thread_np(pthread)); 267 268 thread->next = registeredThreads; -
trunk/JavaScriptCore/wtf/FastMalloc.cpp
r17065 r19209 104 104 105 105 #if !PLATFORM(WIN_OS) 106 void fastMalloc RegisterThread(pthread_t)106 void fastMallocSetIsMultiThreaded() 107 107 { 108 108 } … … 382 382 private: 383 383 // How much to allocate from system at a time 384 static const int kAllocIncrement = 32 << 10;384 static const size_t kAllocIncrement = 32 << 10; 385 385 386 386 // Aligned size of T … … 1394 1394 bool isMultiThreaded; 1395 1395 TCMalloc_ThreadCache *mainThreadCache; 1396 pthread_t mainThreadID; 1397 static SpinLock multiThreadedLock = SPINLOCK_INITIALIZER; 1398 1399 void fastMallocRegisterThread(pthread_t thread) 1396 1397 void fastMallocSetIsMultiThreaded() 1400 1398 { 1401 if (thread != mainThreadID) { 1402 // We lock when writing isMultiThreaded but not when reading it. 1403 // It's ok if the main thread gets it wrong - for the main thread, the 1404 // global variable cache is the same as the thread-specific cache. 1405 // And other threads can't get it wrong because they must have gone through 1406 // this function before allocating so they've synchronized. 1407 // Also, mainThreadCache is only set when isMultiThreaded is false, 1408 // to save a branch in some cases. 1409 SpinLockHolder lock(&multiThreadedLock); 1410 isMultiThreaded = true; 1411 mainThreadCache = 0; 1412 } 1399 // We lock when writing mainThreadCache but not when reading it. It's OK if 1400 // the main thread reads a stale, non-NULL value for mainThreadCache because 1401 // mainThreadCache is the same as the main thread's thread-specific cache. 1402 // Other threads can't read a stale, non-NULL value for mainThreadCache because 1403 // clients must call this function before allocating on other threads, so they'll 1404 // have synchronized before reading mainThreadCache. 1405 1406 // mainThreadCache is only set when isMultiThreaded is false, to save a 1407 // branch in some cases. 1408 1409 SpinLockHolder lock(&pageheap_lock); 1410 isMultiThreaded = true; 1411 mainThreadCache = 0; 1413 1412 } 1414 1413 … … 1524 1523 thread_heap_count++; 1525 1524 RecomputeThreadCacheSize(); 1526 if (!isMultiThreaded) { 1527 mainThreadCache = heap; 1528 mainThreadID = pthread_self(); 1529 } 1525 if (!isMultiThreaded) 1526 mainThreadCache = heap; 1530 1527 } 1531 1528 } … … 1857 1854 static ALWAYS_INLINE void* do_malloc(size_t size) { 1858 1855 1856 #ifdef WTF_CHANGES 1857 ASSERT(isMultiThreaded || pthread_main_np()); 1858 #endif 1859 1859 1860 #ifndef WTF_CHANGES 1860 1861 if (TCMallocDebug::level >= TCMallocDebug::kVerbose) 1861 1862 MESSAGE("In tcmalloc do_malloc(%" PRIuS")\n", size); 1862 1863 #endif 1863 1864 #ifndef WTF_CHANGES1865 1864 // The following call forces module initialization 1866 1865 TCMalloc_ThreadCache* heap = TCMalloc_ThreadCache::GetCache(); 1866 #ifndef WTF_CHANGES 1867 1867 if (heap->SampleAllocation(size)) { 1868 1868 Span* span = DoSampledAllocation(size); … … 1873 1873 if (size > kMaxSize) { 1874 1874 // Use page-level allocator 1875 if (!tsd_inited && !phinited)1876 TCMalloc_ThreadCache::InitModule();1877 1878 1875 SpinLockHolder h(&pageheap_lock); 1879 1880 1881 1876 Span* span = pageheap->New(pages(size)); 1882 1877 if (span == NULL) return NULL; 1883 1878 return reinterpret_cast<void*>(span->start << kPageShift); 1884 1879 } else { 1885 #ifdef WTF_CHANGES 1886 TCMalloc_ThreadCache* heap = TCMalloc_ThreadCache::GetCache(); 1887 #endif 1888 return heap->Allocate(size); 1880 return heap->Allocate(size); 1889 1881 } 1890 1882 } -
trunk/JavaScriptCore/wtf/FastMallocInternal.h
r17127 r19209 29 29 30 30 namespace WTF { 31 void fastMallocRegisterThread(pthread_t thread); 31 // Clients must call this function before allocating memory on a secondary thread. 32 void fastMallocSetIsMultiThreaded(); 32 33 } 33 34
Note:
See TracChangeset
for help on using the changeset viewer.