Changeset 1126 in webkit for trunk/JavaScriptCore/kjs


Ignore:
Timestamp:
May 10, 2002, 9:41:01 AM (23 years ago)
Author:
mjs
Message:

Reviewed by: Ken Kocienda and Darin Adler

Fixed the following bug:

Radar 2890573 - JavaScriptCore needs to be thread-safe

Actually this is only a weak form of thread-safety - you can safely
use different interpreters from different threads at the same
time. If you try to use a single interpreter object from multiple
threads, you need to provide your own locking.

  • kjs/collector.h, kjs/collector.cpp: (Collector::lock, Collector::unlock): Trivial implementation of a recursive mutex. (Collector::allocate): Lock around the body of this function. (Collector::collect): Likewise. (Collector::finalCheck): Likewise. (Collector::numInterpreters): Likewise. (Collector::numGCNotAllowedObjects): Likewise. (Collector::numReferencedObjects): Likewise.
  • kjs/internal.cpp: (Parser::parse): use a mutex to lock around the whole parse, since it uses a bunch of global state. (InterpreterImp::InterpreterImp): Grab the Collector lock here, both the mutually exclude calls to the body of this function, and to protect the s_hook static member which the collector pokes at. (InterpreterImp::clear): Likewise.
  • kjs/ustring.cpp: (statBufferKeyCleanup, statBufferKeyInit, UString::ascii): Convert use of static variable
  • kjs/value.cpp: (ValueImp::ValueImp, ValueImp::mark, ValueImp::marked, ValueImp::setGcAllowed): Grab the GC lock around any flag changes.
Location:
trunk/JavaScriptCore/kjs
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/collector.cpp

    r1112 r1126  
    3030#include <typeinfo>
    3131#endif
     32#ifdef APPLE_CHANGES
     33#include <pthread.h>
     34#endif
    3235
    3336namespace KJS {
     
    4750using namespace KJS;
    4851
     52
    4953CollectorBlock::CollectorBlock(int s)
    5054  : size(s),
     
    6367}
    6468
     69#ifdef APPLE_CHANGES
     70// FIXME: fix these once static initializers for pthread_cond_t and
     71// pthread_mutex_t are fixed not to warn.
     72static pthread_mutex_t collectorLock = {_PTHREAD_MUTEX_SIG_init, {}};
     73static pthread_cond_t collectorCondition = {_PTHREAD_COND_SIG_init, {}};
     74static unsigned collectorLockCount = 0;
     75static pthread_t collectorLockThread;
     76#endif
    6577CollectorBlock* Collector::root = 0L;
    6678CollectorBlock* Collector::currentBlock = 0L;
     
    8193  if (s == 0)
    8294    return 0L;
     95
     96#ifdef APPLE_CHANGES
     97  lock();
     98#endif
    8399
    84100  // Try and deal with memory requirements in a scalable way. Simple scripts
     
    148164  }
    149165
     166#ifdef APPLE_CHANGES
     167  unlock();
     168#endif
     169
    150170  return m;
    151171}
     
    156176bool Collector::collect()
    157177{
     178#ifdef APPLE_CHANGES
     179  lock();
     180#endif
    158181#ifdef KJS_DEBUG_MEM
    159182  fprintf(stderr,"Collector::collect()\n");
     
    253276    finalCheck();
    254277#endif
     278#ifdef APPLE_CHANGES
     279  unlock();
     280#endif
    255281  return deleted;
    256282}
     
    259285void Collector::finalCheck()
    260286{
     287#ifdef APPLE_CHANGES
     288  lock();
     289#endif
    261290  CollectorBlock *block = root;
    262291  while (block) {
     
    274303    block = block->next;
    275304  }
     305#ifdef APPLE_CHANGES
     306  unlock();
     307#endif
    276308}
    277309#endif
     
    280312int Collector::numInterpreters()
    281313{
     314  lock();
    282315  int count = 0;
    283316  if (InterpreterImp::s_hook) {
     
    288321    } while (scr != InterpreterImp::s_hook);
    289322  }
     323  unlock();
    290324  return count;
    291325}
     
    293327int Collector::numGCNotAllowedObjects()
    294328{
     329  lock();
    295330  int count = 0;
    296331  CollectorBlock *block = root;
     
    307342    block = block->next;
    308343  }
     344  unlock();
    309345  return count;
    310346}
     
    312348int Collector::numReferencedObjects()
    313349{
     350  lock();
    314351  int count = 0;
    315352  CollectorBlock *block = root;
     
    326363    block = block->next;
    327364  }
     365  unlock();
    328366  return count;
    329367}
    330 #endif
     368
     369void Collector::lock()
     370{
     371  pthread_mutex_lock(&collectorLock);
     372  while (collectorLockCount > 0 &&
     373         !pthread_equal(pthread_self(), collectorLockThread)) {
     374    pthread_cond_wait(&collectorCondition, &collectorLock);
     375  }
     376  collectorLockThread = pthread_self();
     377  collectorLockCount++;
     378  pthread_mutex_unlock(&collectorLock);
     379}
     380
     381void Collector::unlock()
     382{
     383  pthread_mutex_lock(&collectorLock);
     384  collectorLockCount--;
     385  if (collectorLockCount == 0) {
     386    pthread_cond_signal(&collectorCondition);
     387  }
     388  pthread_mutex_unlock(&collectorLock);
     389}
     390
     391#endif
  • trunk/JavaScriptCore/kjs/collector.h

    r1112 r1126  
    9393    static int numGCNotAllowedObjects();
    9494    static int numReferencedObjects();
     95    static void lock();
     96    static void unlock();
    9597#endif
    9698  private:
  • trunk/JavaScriptCore/kjs/internal.cpp

    r1024 r1126  
    689689ProgramNode *Parser::progNode = 0;
    690690int Parser::sid = 0;
     691#ifdef APPLE_CHANGES
     692static pthread_mutex_t parserLock = {_PTHREAD_MUTEX_SIG_init, {}};
     693#endif
    691694
    692695ProgramNode *Parser::parse(const UChar *code, unsigned int length, int *sourceId,
    693696                           int *errLine, UString *errMsg)
    694697{
     698#ifdef APPLE_CHANGES
     699  pthread_mutex_lock(&parserLock);
     700#endif
    695701  if (errLine)
    696702    *errLine = -1;
     
    721727#endif
    722728    delete prog;
     729#ifdef APPLE_CHANGES
     730    pthread_mutex_unlock(&parserLock);
     731#endif
    723732    return 0;
    724733  }
    725734
     735#ifdef APPLE_CHANGES
     736  pthread_mutex_unlock(&parserLock);
     737#endif
    726738  return prog;
    727739}
     
    765777  // add this interpreter to the global chain
    766778  // as a root set for garbage collection
     779#ifdef APPLE_CHANGES
     780  Collector::lock();
     781#endif
    767782  if (s_hook) {
    768783    prev = s_hook;
     
    775790    globalInit();
    776791  }
     792#ifdef APPLE_CHANGES
     793  Collector::unlock();
     794#endif
    777795
    778796  m_interpreter = interp;
     
    927945  //fprintf(stderr,"InterpreterImp::clear\n");
    928946  // remove from global chain (see init())
     947#ifdef APPLE_CHANGES
     948  Collector::lock();
     949#endif
    929950  next->prev = prev;
    930951  prev->next = next;
     
    936957    globalClear();
    937958  }
     959#ifdef APPLE_CHANGES
     960  Collector::unlock();
     961#endif
    938962}
    939963
  • trunk/JavaScriptCore/kjs/ustring.cpp

    r1024 r1126  
    122122UString::Rep UString::Rep::null = { 0, 0, 1 };
    123123UString UString::null;
     124#ifdef APPLE_CHANGES
     125// FIXME: fix this once static initializers for pthread_once_t
     126pthread_once_t statBufferKeyOnce = {_PTHREAD_ONCE_SIG_init, {}};
     127pthread_key_t statBufferKey;
     128#else
    124129static char *statBuffer = 0L;
     130#endif
    125131
    126132UChar::UChar(const UCharReference &c)
     
    278284}
    279285
     286#ifdef APPLE_CHANGES
     287static void statBufferKeyCleanup(void *statBuffer)
     288{
     289  if (statBuffer != NULL)
     290    delete [] (char *)statBuffer;
     291}
     292
     293static void statBufferKeyInit(void)
     294{
     295  pthread_key_create(&statBufferKey, statBufferKeyCleanup);
     296}
     297#endif
     298
    280299char *UString::ascii() const
    281300{
     301#ifdef APPLE_CHANGES
     302  pthread_once(&statBufferKeyOnce, statBufferKeyInit);
     303  char *statBuffer = (char *)pthread_getspecific(statBufferKey);
     304#endif
    282305  if (statBuffer)
    283306    delete [] statBuffer;
     
    288311  statBuffer[size()] = '\0';
    289312
     313#ifdef APPLE_CHANGES
     314  pthread_setspecific(statBufferKey, statBuffer);
     315#endif
    290316  return statBuffer;
    291317}
  • trunk/JavaScriptCore/kjs/value.cpp

    r1024 r1126  
    4242// ------------------------------ ValueImp -------------------------------------
    4343
     44#if APPLE_CHANGES
     45ValueImp::ValueImp() :
     46  refcount(0)
     47{
     48  // Tell the garbage collector that this memory block corresponds to a real object now
     49  Collector::lock();
     50  _flags = VI_CREATED;
     51  //fprintf(stderr,"ValueImp::ValueImp %p\n",(void*)this);
     52  Collector::unlock();
     53}
     54#else
    4455ValueImp::ValueImp() :
    4556  refcount(0),
     
    4960  //fprintf(stderr,"ValueImp::ValueImp %p\n",(void*)this);
    5061}
     62#endif
    5163
    5264ValueImp::~ValueImp()
     
    6880void ValueImp::setGcAllowed()
    6981{
     82#ifdef APPLE_CHANGES
     83  Collector::lock();
     84#endif
    7085  //fprintf(stderr,"ValueImp::setGcAllowed %p\n",(void*)this);
    7186  _flags |= VI_GCALLOWED;
     87#ifdef APPLE_CHANGES
     88  Collector::unlock();
     89#endif
    7290}
    7391
  • trunk/JavaScriptCore/kjs/value.h

    r1024 r1126  
    9595    virtual ~ValueImp();
    9696
     97#ifdef APPLE_CHANGES
     98    // The collecter lock is not locked around the ref() and unref()
     99    // methods for the following reasons:
     100    //
     101    // - The only cases where chaging the refcount could possibly
     102    // affect the collector's behavior is incrementing from 0 to 1,
     103    // and decrementing from 1 to 0.
     104    //
     105    // - In the 0 to 1 case, the GC allowed flag will always be off
     106    // beforehand, and set right afterwards. And setting it grabs the
     107    // collector lock. So if this happens in the middle of GC, the
     108    // collector will see either a refcount 0 GC not allowed object,
     109    // or a refcount 1 GC not allowed object, and these cases are
     110    // treated exactly the same.
     111    //
     112    // - In the 1 to 0 case, the only possible bad effect is that the
     113    // object will live for one GC cycle longer than it should have
     114    // to, which is really not so bad.
     115    //
     116    // - In theory on some platforms increment or decrement could make
     117    // other threads see intermediate values that are different from
     118    // both the start and end value. If that turns out to really be
     119    // the case we will have to reconsider this scheme.
     120#endif
    97121    inline ValueImp* ref() { refcount++; return this; }
    98122    inline bool deref() { return (!--refcount); }
Note: See TracChangeset for help on using the changeset viewer.