Changeset 19209 in webkit for trunk/JavaScriptCore/wtf


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/wtf
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • 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.