Changeset 19209 in webkit for trunk/JavaScriptCore


Ignore:
Timestamp:
Jan 28, 2007, 10:17:38 PM (18 years ago)
Author:
ggaren
Message:

Reviewed by Maciej Stachowiak.


First step in fixing <rdar://problem/4485644> REGRESSION: JavaScriptCore
has init routines


Don't rely on a static initializer to store the main thread's ID (which
we would use to detect allocations on secondary threads). Instead, require
the caller to notify fastMalloc if it might allocate on a secondary thread.


Also fixed what seemed like a race condition in do_malloc.


tcmalloc_unittest and my custom versions of JS iBench and PLT show no
regressions.

  • wtf/FastMalloc.cpp: (WTF::fastMallocSetIsMultiThreaded): (1) Renamed from "fastMallocRegisterThread", which was a misleading name because not all threads need to register with fastMalloc -- only secondary threads need to, and only for the purpose of disabling its single-threaded optimization.

(2) Use the pageheap_lock instead of a custom one, since we need to synchronize
with the read of isMultiThreaded inside CreateCacheIfNecessary. This is a new
requirement, now that we can't guarantee that the first call to CreateCacheIfNecessary
will occur on the main thread at init time, before any other threads have been created.

(WTF::TCMalloc_ThreadCache::CreateCacheIfNecessary):
(WTF::do_malloc): Reverted WTF change only to call GetCache() if size <= kMaxSize.
The WTF code would read phinited without holding the pageheap_lock, which
seemed like a race condition. Regardless, calling GetCache reduces the number
of code paths to module initialization, which will help in writing the
final fix for this bug.

Location:
trunk/JavaScriptCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r19203 r19209  
     12007-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
    1352007-01-28  David Kilzer  <[email protected]>
    236
  • trunk/JavaScriptCore/kjs/collector.cpp

    r18888 r19209  
    262262
    263263  if (!pthread_getspecific(registeredThreadKey)) {
     264    if (!pthread_main_np())
     265        WTF::fastMallocSetIsMultiThreaded();
    264266    pthread_t pthread = pthread_self();
    265     WTF::fastMallocRegisterThread(pthread);
    266267    Collector::Thread *thread = new Collector::Thread(pthread, pthread_mach_thread_np(pthread));
    267268    thread->next = registeredThreads;
  • trunk/JavaScriptCore/wtf/FastMalloc.cpp

    r17065 r19209  
    104104
    105105#if !PLATFORM(WIN_OS)
    106 void fastMallocRegisterThread(pthread_t)
     106void fastMallocSetIsMultiThreaded()
    107107{
    108108}
     
    382382 private:
    383383  // How much to allocate from system at a time
    384   static const int kAllocIncrement = 32 << 10;
     384  static const size_t kAllocIncrement = 32 << 10;
    385385
    386386  // Aligned size of T
     
    13941394bool isMultiThreaded;
    13951395TCMalloc_ThreadCache *mainThreadCache;
    1396 pthread_t mainThreadID;
    1397 static SpinLock multiThreadedLock = SPINLOCK_INITIALIZER;
    1398 
    1399 void fastMallocRegisterThread(pthread_t thread)
     1396
     1397void fastMallocSetIsMultiThreaded()
    14001398{
    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;
    14131412}
    14141413
     
    15241523      thread_heap_count++;
    15251524      RecomputeThreadCacheSize();
    1526       if (!isMultiThreaded) {
    1527           mainThreadCache = heap;
    1528           mainThreadID = pthread_self();
    1529       }
     1525      if (!isMultiThreaded)
     1526        mainThreadCache = heap;
    15301527    }
    15311528  }
     
    18571854static ALWAYS_INLINE void* do_malloc(size_t size) {
    18581855
     1856#ifdef WTF_CHANGES
     1857    ASSERT(isMultiThreaded || pthread_main_np());
     1858#endif
     1859
    18591860#ifndef WTF_CHANGES
    18601861  if (TCMallocDebug::level >= TCMallocDebug::kVerbose)
    18611862    MESSAGE("In tcmalloc do_malloc(%" PRIuS")\n", size);
    18621863#endif
    1863 
    1864 #ifndef WTF_CHANGES
    18651864  // The following call forces module initialization
    18661865  TCMalloc_ThreadCache* heap = TCMalloc_ThreadCache::GetCache();
     1866#ifndef WTF_CHANGES
    18671867  if (heap->SampleAllocation(size)) {
    18681868    Span* span = DoSampledAllocation(size);
     
    18731873  if (size > kMaxSize) {
    18741874    // Use page-level allocator
    1875     if (!tsd_inited && !phinited)
    1876       TCMalloc_ThreadCache::InitModule();
    1877 
    18781875    SpinLockHolder h(&pageheap_lock);
    1879 
    1880 
    18811876    Span* span = pageheap->New(pages(size));
    18821877    if (span == NULL) return NULL;
    18831878    return reinterpret_cast<void*>(span->start << kPageShift);
    18841879  } else {
    1885 #ifdef WTF_CHANGES
    1886       TCMalloc_ThreadCache* heap = TCMalloc_ThreadCache::GetCache();
    1887 #endif
    1888       return heap->Allocate(size);
     1880    return heap->Allocate(size);
    18891881  }
    18901882}
  • trunk/JavaScriptCore/wtf/FastMallocInternal.h

    r17127 r19209  
    2929
    3030namespace WTF {
    31     void fastMallocRegisterThread(pthread_t thread);
     31    // Clients must call this function before allocating memory on a secondary thread.
     32    void fastMallocSetIsMultiThreaded();
    3233}
    3334
Note: See TracChangeset for help on using the changeset viewer.