https://bugs.webkit.org/show_bug.cgi?id=33236
authorbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 6 Jan 2010 19:33:29 +0000 (19:33 +0000)
committerbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 6 Jan 2010 19:33:29 +0000 (19:33 +0000)
Remove m_identifierTable pointer from UString

Reviewed by Sam Weinig.

JavaScriptCore:

Currently every string holds a pointer so that during destruction,
if a string has been used as an identifier, it can remove itself
from the table.  By instead accessing the identifierTable via a
thread specific tracking the table associated with the current
globaldata, we can save the memory cost of this pointer.

* API/APIShims.h:
(JSC::APIEntryShimWithoutLock::APIEntryShimWithoutLock):
(JSC::APIEntryShimWithoutLock::~APIEntryShimWithoutLock):
(JSC::APICallbackShim::APICallbackShim):
(JSC::APICallbackShim::~APICallbackShim):

    - change the API shims to track the identifierTable of the current JSGlobalData.

* API/JSContextRef.cpp:
(JSContextGroupCreate):

    - update creation of JSGlobalData for API usage to use new create method.
    - fix shim instanciation bug in JSGlobalContextCreateInGroup.

* JavaScriptCore.exp:
* runtime/Completion.cpp:
(JSC::checkSyntax):
(JSC::evaluate):

    - add asserts to check the identifierTable is being tracked correctly.

* runtime/Identifier.cpp:
(JSC::IdentifierTable::~IdentifierTable):
(JSC::IdentifierTable::add):
(JSC::Identifier::remove):
(JSC::Identifier::checkSameIdentifierTable):
(JSC::createIdentifierTableSpecificCallback):
(JSC::createIdentifierTableSpecific):
(JSC::createDefaultDataSpecific):

    - Use currentIdentifierTable() instead of UStringImpl::m_identifierTable.
    - Define methods to access the thread specific identifier tables.

* runtime/Identifier.h:
(JSC::ThreadIdentifierTableData::ThreadIdentifierTableData):
(JSC::defaultIdentifierTable):
(JSC::setDefaultIdentifierTable):
(JSC::currentIdentifierTable):
(JSC::setCurrentIdentifierTable):
(JSC::resetCurrentIdentifierTable):

    - Declare methods to access the thread specific identifier tables.

* runtime/JSGlobalData.cpp:
(JSC::JSGlobalData::createNonDefault):
(JSC::JSGlobalData::create):
(JSC::JSGlobalData::sharedInstance):

    - creation of JSGlobalData objects, other than for API usage, associate themselves with the current thread.

* runtime/JSGlobalData.h:
* runtime/UStringImpl.cpp:
(JSC::UStringImpl::destroy):

    - destroy() method should be using isIdentifier().

* runtime/UStringImpl.h:
(JSC::UStringImpl::isIdentifier):
(JSC::UStringImpl::setIsIdentifier):
(JSC::UStringImpl::checkConsistency):
(JSC::UStringImpl::UStringImpl):

    - replace m_identifierTable with a single m_isIdentifier bit.

* wtf/StringHashFunctions.h:
(WTF::stringHash):

    - change string hash result from 32-bit to 31-bit, to free a bit in UStringImpl for m_isIdentifier.

JavaScriptGlue:

Add API shims similar to those used in the JSC API to track the current identifierTable.

* JSBase.cpp:
(JSBase::Release):
* JSUtils.cpp:
(JSObjectKJSValue):
(KJSValueToCFTypeInternal):
(unprotectGlobalObject):
(JSGlueAPIEntry::JSGlueAPIEntry):
(JSGlueAPIEntry::~JSGlueAPIEntry):
(JSGlueAPICallback::JSGlueAPICallback):
(JSGlueAPICallback::~JSGlueAPICallback):
* JSUtils.h:
* JSValueWrapper.cpp:
(JSValueWrapper::JSObjectCopyPropertyNames):
(JSValueWrapper::JSObjectCopyProperty):
(JSValueWrapper::JSObjectSetProperty):
(JSValueWrapper::JSObjectCallFunction):
(JSValueWrapper::JSObjectCopyCFValue):
* JavaScriptGlue.cpp:
(JSRunCreate):
(JSRunEvaluate):
(JSRunCheckSyntax):
(JSCollect):
* JavaScriptGlue.xcodeproj/project.pbxproj:
* UserObjectImp.cpp:
(UserObjectImp::callAsFunction):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@52856 268f45cc-cd09-0410-ab3c-d52691b4dbfc

20 files changed:
JavaScriptCore/API/APIShims.h
JavaScriptCore/API/JSContextRef.cpp
JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.exp
JavaScriptCore/runtime/Completion.cpp
JavaScriptCore/runtime/Identifier.cpp
JavaScriptCore/runtime/Identifier.h
JavaScriptCore/runtime/JSGlobalData.cpp
JavaScriptCore/runtime/JSGlobalData.h
JavaScriptCore/runtime/UStringImpl.cpp
JavaScriptCore/runtime/UStringImpl.h
JavaScriptCore/wtf/StringHashFunctions.h
JavaScriptGlue/ChangeLog
JavaScriptGlue/JSBase.cpp
JavaScriptGlue/JSUtils.cpp
JavaScriptGlue/JSUtils.h
JavaScriptGlue/JSValueWrapper.cpp
JavaScriptGlue/JavaScriptGlue.cpp
JavaScriptGlue/JavaScriptGlue.xcodeproj/project.pbxproj
JavaScriptGlue/UserObjectImp.cpp

index 59b36fd..f6975f8 100644 (file)
@@ -34,6 +34,7 @@ namespace JSC {
 class APIEntryShimWithoutLock {
 protected:
     APIEntryShimWithoutLock(JSGlobalData* globalData, bool registerThread)
+        : m_entryIdentifierTable(setCurrentIdentifierTable(globalData->identifierTable))
     {
         if (registerThread)
             globalData->heap.registerThread();
@@ -41,7 +42,11 @@ protected:
 
     ~APIEntryShimWithoutLock()
     {
+        setCurrentIdentifierTable(m_entryIdentifierTable);
     }
+
+private:
+    IdentifierTable* m_entryIdentifierTable;
 };
 
 class APIEntryShim : public APIEntryShimWithoutLock {
@@ -68,17 +73,21 @@ class APICallbackShim {
 public:
     APICallbackShim(ExecState* exec)
         : m_dropAllLocks(exec)
+        , m_globalData(&exec->globalData())
     {
+        resetCurrentIdentifierTable();
     }
 
     ~APICallbackShim()
     {
+        setCurrentIdentifierTable(m_globalData->identifierTable);
     }
 
 private:
     JSLock::DropAllLocks m_dropAllLocks;
+    JSGlobalData* m_globalData;
 };
 
 }
 
-#endif // APIShims_h
+#endif
index c821bb3..35eac04 100644 (file)
@@ -46,7 +46,7 @@ using namespace JSC;
 JSContextGroupRef JSContextGroupCreate()
 {
     initializeThreading();
-    return toRef(JSGlobalData::create().releaseRef());
+    return toRef(JSGlobalData::createNonDefault().releaseRef());
 }
 
 JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group)
@@ -84,8 +84,9 @@ JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClass
     initializeThreading();
 
     JSLock lock(LockForReal);
-    RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::create();
-    APIEntryShim(globalData.get(), false);
+    RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::createNonDefault();
+
+    APIEntryShim entryShim(globalData.get(), false);
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
     globalData->makeUsableFromMultipleThreads();
index acd5b0a..bbec816 100644 (file)
@@ -1,3 +1,85 @@
+2010-01-05  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        https://bugs.webkit.org/show_bug.cgi?id=33236
+        Remove m_identifierTable pointer from UString
+
+        Currently every string holds a pointer so that during destruction,
+        if a string has been used as an identifier, it can remove itself
+        from the table.  By instead accessing the identifierTable via a
+        thread specific tracking the table associated with the current
+        globaldata, we can save the memory cost of this pointer.
+
+        * API/APIShims.h:
+        (JSC::APIEntryShimWithoutLock::APIEntryShimWithoutLock):
+        (JSC::APIEntryShimWithoutLock::~APIEntryShimWithoutLock):
+        (JSC::APICallbackShim::APICallbackShim):
+        (JSC::APICallbackShim::~APICallbackShim):
+
+            - change the API shims to track the identifierTable of the current JSGlobalData.
+
+        * API/JSContextRef.cpp:
+        (JSContextGroupCreate):
+
+            - update creation of JSGlobalData for API usage to use new create method.
+            - fix shim instanciation bug in JSGlobalContextCreateInGroup.
+
+        * JavaScriptCore.exp:
+        * runtime/Completion.cpp:
+        (JSC::checkSyntax):
+        (JSC::evaluate):
+
+            - add asserts to check the identifierTable is being tracked correctly.
+
+        * runtime/Identifier.cpp:
+        (JSC::IdentifierTable::~IdentifierTable):
+        (JSC::IdentifierTable::add):
+        (JSC::Identifier::remove):
+        (JSC::Identifier::checkSameIdentifierTable):
+        (JSC::createIdentifierTableSpecificCallback):
+        (JSC::createIdentifierTableSpecific):
+        (JSC::createDefaultDataSpecific):
+
+            - Use currentIdentifierTable() instead of UStringImpl::m_identifierTable.
+            - Define methods to access the thread specific identifier tables.
+
+        * runtime/Identifier.h:
+        (JSC::ThreadIdentifierTableData::ThreadIdentifierTableData):
+        (JSC::defaultIdentifierTable):
+        (JSC::setDefaultIdentifierTable):
+        (JSC::currentIdentifierTable):
+        (JSC::setCurrentIdentifierTable):
+        (JSC::resetCurrentIdentifierTable):
+
+            - Declare methods to access the thread specific identifier tables.
+
+        * runtime/JSGlobalData.cpp:
+        (JSC::JSGlobalData::createNonDefault):
+        (JSC::JSGlobalData::create):
+        (JSC::JSGlobalData::sharedInstance):
+
+            - creation of JSGlobalData objects, other than for API usage, associate themselves with the current thread.
+
+        * runtime/JSGlobalData.h:
+        * runtime/UStringImpl.cpp:
+        (JSC::UStringImpl::destroy):
+
+            - destroy() method should be using isIdentifier().
+
+        * runtime/UStringImpl.h:
+        (JSC::UStringImpl::isIdentifier):
+        (JSC::UStringImpl::setIsIdentifier):
+        (JSC::UStringImpl::checkConsistency):
+        (JSC::UStringImpl::UStringImpl):
+
+            - replace m_identifierTable with a single m_isIdentifier bit.
+
+        * wtf/StringHashFunctions.h:
+        (WTF::stringHash):
+
+            - change string hash result from 32-bit to 31-bit, to free a bit in UStringImpl for m_isIdentifier.
+
 2009-12-25 Patrick Gansterer <paroga@paroga.com>
  
         Reviewed by Eric Seidel.
index 4a87e4e..5acd124 100644 (file)
@@ -116,7 +116,7 @@ __ZN3JSC12JSGlobalData13startSamplingEv
 __ZN3JSC12JSGlobalData14dumpSampleDataEPNS_9ExecStateE
 __ZN3JSC12JSGlobalData14resetDateCacheEv
 __ZN3JSC12JSGlobalData14sharedInstanceEv
-__ZN3JSC12JSGlobalData6createEb
+__ZN3JSC12JSGlobalData6createEv
 __ZN3JSC12JSGlobalDataD1Ev
 __ZN3JSC12SamplingTool5setupEv
 __ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE
@@ -181,6 +181,8 @@ __ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_
 __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
 __ZN3JSC25evaluateInGlobalCallFrameERKNS_7UStringERNS_7JSValueEPNS_14JSGlobalObjectE
+__ZN3JSC25g_identifierTableSpecificE
+__ZN3JSC29createIdentifierTableSpecificEv
 __ZN3JSC35createInterruptedExecutionExceptionEPNS_12JSGlobalDataE
 __ZN3JSC3NaNE
 __ZN3JSC4Heap14primaryHeapEndEv
index 2507698..2f88df9 100644 (file)
@@ -36,6 +36,7 @@ namespace JSC {
 Completion checkSyntax(ExecState* exec, const SourceCode& source)
 {
     JSLock lock(exec);
+    ASSERT(exec->globalData().identifierTable == currentIdentifierTable());
 
     RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source);
     JSObject* error = program->checkSyntax(exec);
@@ -48,6 +49,7 @@ Completion checkSyntax(ExecState* exec, const SourceCode& source)
 Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValue thisValue)
 {
     JSLock lock(exec);
+    ASSERT(exec->globalData().identifierTable == currentIdentifierTable());
 
     RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source);
     JSObject* error = program->compile(exec, scopeChain.node());
index 3cb35d4..1c0c3af 100644 (file)
@@ -28,6 +28,8 @@
 #include <wtf/FastMalloc.h>
 #include <wtf/HashSet.h>
 
+using WTF::ThreadSpecific;
+
 namespace JSC {
 
 typedef HashMap<const char*, RefPtr<UString::Rep>, PtrHash<const char*> > LiteralIdentifierTable;
@@ -38,13 +40,13 @@ public:
     {
         HashSet<UString::Rep*>::iterator end = m_table.end();
         for (HashSet<UString::Rep*>::iterator iter = m_table.begin(); iter != end; ++iter)
-            (*iter)->setIdentifierTable(0);
+            (*iter)->setIsIdentifier(false);
     }
     
     std::pair<HashSet<UString::Rep*>::iterator, bool> add(UString::Rep* value)
     {
         std::pair<HashSet<UString::Rep*>::iterator, bool> result = m_table.add(value);
-        (*result.first)->setIdentifierTable(this);
+        (*result.first)->setIsIdentifier(true);
         return result;
     }
 
@@ -52,7 +54,7 @@ public:
     std::pair<HashSet<UString::Rep*>::iterator, bool> add(U value)
     {
         std::pair<HashSet<UString::Rep*>::iterator, bool> result = m_table.add<U, V>(value);
-        (*result.first)->setIdentifierTable(this);
+        (*result.first)->setIsIdentifier(true);
         return result;
     }
 
@@ -238,19 +240,19 @@ PassRefPtr<UString::Rep> Identifier::addSlowCase(ExecState* exec, UString::Rep*
 
 void Identifier::remove(UString::Rep* r)
 {
-    r->identifierTable()->remove(r);
+    currentIdentifierTable()->remove(r);
 }
 
 #ifndef NDEBUG
 
-void Identifier::checkSameIdentifierTable(ExecState* exec, UString::Rep* rep)
+void Identifier::checkSameIdentifierTable(ExecState* exec, UString::Rep*)
 {
-    ASSERT(rep->identifierTable() == exec->globalData().identifierTable);
+    ASSERT(exec->globalData().identifierTable == currentIdentifierTable());
 }
 
-void Identifier::checkSameIdentifierTable(JSGlobalData* globalData, UString::Rep* rep)
+void Identifier::checkSameIdentifierTable(JSGlobalData* globalData, UString::Rep*)
 {
-    ASSERT(rep->identifierTable() == globalData->identifierTable);
+    ASSERT(globalData->identifierTable == currentIdentifierTable());
 }
 
 #else
@@ -265,4 +267,30 @@ void Identifier::checkSameIdentifierTable(JSGlobalData*, UString::Rep*)
 
 #endif
 
+ThreadSpecific<ThreadIdentifierTableData>* g_identifierTableSpecific = 0;
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+pthread_once_t createIdentifierTableSpecificOnce = PTHREAD_ONCE_INIT;
+void createIdentifierTableSpecificCallback()
+{
+    ASSERT(!g_identifierTableSpecific);
+    g_identifierTableSpecific = new ThreadSpecific<ThreadIdentifierTableData>();
+}
+void createIdentifierTableSpecific()
+{
+    pthread_once(&createIdentifierTableSpecificOnce, createIdentifierTableSpecificCallback);
+    ASSERT(g_identifierTableSpecific);
+}
+
+#else 
+
+void createDefaultDataSpecific()
+{
+    ASSERT(!g_identifierTableSpecific);
+    g_identifierTableSpecific = new ThreadSpecific<ThreadIdentifierTableData>();
+}
+
+#endif
+
 } // namespace JSC
index 0ef05fa..1d1bd18 100644 (file)
@@ -22,6 +22,7 @@
 #define Identifier_h
 
 #include "JSGlobalData.h"
+#include "ThreadSpecific.h"
 #include "UString.h"
 
 namespace JSC {
@@ -141,6 +142,67 @@ namespace JSC {
     IdentifierTable* createIdentifierTable();
     void deleteIdentifierTable(IdentifierTable*);
 
+    struct ThreadIdentifierTableData {
+        ThreadIdentifierTableData()
+            : defaultIdentifierTable(0)
+            , currentIdentifierTable(0)
+        {
+        }
+
+        IdentifierTable* defaultIdentifierTable;
+        IdentifierTable* currentIdentifierTable;
+    };
+
+    extern WTF::ThreadSpecific<ThreadIdentifierTableData>* g_identifierTableSpecific;
+    void createIdentifierTableSpecific();
+
+    inline IdentifierTable* defaultIdentifierTable()
+    {
+        if (!g_identifierTableSpecific)
+            createIdentifierTableSpecific();
+        ThreadIdentifierTableData& data = **g_identifierTableSpecific;
+
+        return data.defaultIdentifierTable;
+    }
+
+    inline void setDefaultIdentifierTable(IdentifierTable* identifierTable)
+    {
+        if (!g_identifierTableSpecific)
+            createIdentifierTableSpecific();
+        ThreadIdentifierTableData& data = **g_identifierTableSpecific;
+
+        data.defaultIdentifierTable = identifierTable;
+    }
+
+    inline IdentifierTable* currentIdentifierTable()
+    {
+        if (!g_identifierTableSpecific)
+            createIdentifierTableSpecific();
+        ThreadIdentifierTableData& data = **g_identifierTableSpecific;
+
+        return data.currentIdentifierTable;
+    }
+
+    inline IdentifierTable* setCurrentIdentifierTable(IdentifierTable* identifierTable)
+    {
+        if (!g_identifierTableSpecific)
+            createIdentifierTableSpecific();
+        ThreadIdentifierTableData& data = **g_identifierTableSpecific;
+
+        IdentifierTable* oldIdentifierTable = data.currentIdentifierTable;
+        data.currentIdentifierTable = identifierTable;
+        return oldIdentifierTable;
+    }
+
+    inline void resetCurrentIdentifierTable()
+    {
+        if (!g_identifierTableSpecific)
+            createIdentifierTableSpecific();
+        ThreadIdentifierTableData& data = **g_identifierTableSpecific;
+
+        data.currentIdentifierTable = data.defaultIdentifierTable;
+    }
+
 } // namespace JSC
 
 #endif // Identifier_h
index 7726f4d..79acd5e 100644 (file)
 #include "JSNotAnObject.h"
 #include "JSPropertyNameIterator.h"
 #include "JSStaticScopeObject.h"
-#include "Parser.h"
 #include "Lexer.h"
 #include "Lookup.h"
 #include "Nodes.h"
+#include "Parser.h"
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
 #include <wtf/Threading.h>
@@ -202,9 +202,17 @@ JSGlobalData::~JSGlobalData()
     delete clientData;
 }
 
-PassRefPtr<JSGlobalData> JSGlobalData::create(bool isShared)
+PassRefPtr<JSGlobalData> JSGlobalData::createNonDefault()
+{
+    return adoptRef(new JSGlobalData(false, VPtrSet()));
+}
+
+PassRefPtr<JSGlobalData> JSGlobalData::create()
 {
-    return adoptRef(new JSGlobalData(isShared, VPtrSet()));
+    JSGlobalData* globalData = new JSGlobalData(false, VPtrSet());
+    setDefaultIdentifierTable(globalData->identifierTable);
+    setCurrentIdentifierTable(globalData->identifierTable);
+    return adoptRef(globalData);
 }
 
 PassRefPtr<JSGlobalData> JSGlobalData::createLeaked()
@@ -224,7 +232,7 @@ JSGlobalData& JSGlobalData::sharedInstance()
 {
     JSGlobalData*& instance = sharedInstanceInternal();
     if (!instance) {
-        instance = create(true).releaseRef();
+        instance = new JSGlobalData(true, VPtrSet());
 #if ENABLE(JSC_MULTIPLE_THREADS)
         instance->makeUsableFromMultipleThreads();
 #endif
index 9f725c6..f6d5389 100644 (file)
@@ -93,8 +93,9 @@ namespace JSC {
         static bool sharedInstanceExists();
         static JSGlobalData& sharedInstance();
 
-        static PassRefPtr<JSGlobalData> create(bool isShared = false);
+        static PassRefPtr<JSGlobalData> create();
         static PassRefPtr<JSGlobalData> createLeaked();
+        static PassRefPtr<JSGlobalData> createNonDefault();
         ~JSGlobalData();
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
index 4288624..af9720b 100644 (file)
@@ -64,7 +64,7 @@ void UStringImpl::destroy()
     ASSERT(!isStatic());
     checkConsistency();
 
-    if (identifierTable())
+    if (isIdentifier())
         Identifier::remove(this);
 
     if (bufferOwnership() != BufferInternal) {
index d19ff4c..e610e29 100644 (file)
@@ -137,9 +137,8 @@ public:
     unsigned hash() const { if (!m_hash) m_hash = computeHash(data(), m_length); return m_hash; }
     unsigned computedHash() const { ASSERT(m_hash); return m_hash; } // fast path for Identifiers
     void setHash(unsigned hash) { ASSERT(hash == computeHash(data(), m_length)); m_hash = hash; } // fast path for Identifiers
-    bool isIdentifier() const { return m_identifierTable; }
-    IdentifierTable* identifierTable() const { return m_identifierTable; }
-    void setIdentifierTable(IdentifierTable* table) { ASSERT(!isStatic()); m_identifierTable = table; }
+    bool isIdentifier() const { return m_isIdentifier; }
+    void setIsIdentifier(bool isIdentifier) { m_isIdentifier = isIdentifier; }
 
     UStringImpl* ref() { m_refCount += s_refCountIncrement; return this; }
     ALWAYS_INLINE void deref() { if (!(m_refCount -= s_refCountIncrement)) destroy(); }
@@ -173,7 +172,7 @@ public:
         // There is no recursion of substrings.
         ASSERT(bufferOwnerString()->bufferOwnership() != BufferSubstring);
         // Static strings cannot be put in identifier tables, because they are globally shared.
-        ASSERT(!isStatic() || !identifierTable());
+        ASSERT(!isStatic() || !isIdentifier());
     }
 
 private:
@@ -193,7 +192,7 @@ private:
         , m_length(length)
         , m_refCount(s_refCountIncrement)
         , m_hash(0)
-        , m_identifierTable(0)
+        , m_isIdentifier(false)
         , m_dataBuffer(0, ownership)
     {
         ASSERT((ownership == BufferInternal) || (ownership == BufferOwned));
@@ -209,7 +208,7 @@ private:
         , m_length(length)
         , m_refCount(s_staticRefCountInitialValue)
         , m_hash(0)
-        , m_identifierTable(0)
+        , m_isIdentifier(false)
         , m_dataBuffer(0, BufferOwned)
     {
         checkConsistency();
@@ -221,7 +220,7 @@ private:
         , m_length(length)
         , m_refCount(s_refCountIncrement)
         , m_hash(0)
-        , m_identifierTable(0)
+        , m_isIdentifier(false)
         , m_dataBuffer(base.releaseRef(), BufferSubstring)
     {
         // Do use static strings as a base for substrings; UntypedPtrAndBitfield assumes
@@ -238,7 +237,7 @@ private:
         , m_length(length)
         , m_refCount(s_refCountIncrement)
         , m_hash(0)
-        , m_identifierTable(0)
+        , m_isIdentifier(false)
         , m_dataBuffer(sharedBuffer.releaseRef(), BufferShared)
     {
         checkConsistency();
@@ -268,8 +267,8 @@ private:
     UChar* m_data;
     int m_length;
     unsigned m_refCount;
-    mutable unsigned m_hash;
-    IdentifierTable* m_identifierTable;
+    mutable unsigned m_hash : 31;
+    mutable unsigned m_isIdentifier : 1;
     UntypedPtrAndBitfield m_dataBuffer;
 
     JS_EXPORTDATA static UStringImpl* s_null;
index 703182c..07f117f 100644 (file)
@@ -60,11 +60,13 @@ inline unsigned stringHash(const UChar* data, unsigned length)
     hash += hash >> 15;
     hash ^= hash << 10;
 
+    hash &= 0x7fffffff;
+
     // this avoids ever returning a hash code of 0, since that is used to
     // signal "hash not computed yet", using a value that is likely to be
     // effectively the same as 0 when the low bits are masked
     if (hash == 0)
-        hash = 0x80000000;
+        hash = 0x40000000;
 
     return hash;
 }
@@ -98,11 +100,13 @@ inline unsigned stringHash(const char* data, unsigned length)
     hash += hash >> 15;
     hash ^= hash << 10;
 
+    hash &= 0x7fffffff;
+
     // this avoids ever returning a hash code of 0, since that is used to
     // signal "hash not computed yet", using a value that is likely to be
     // effectively the same as 0 when the low bits are masked
     if (hash == 0)
-        hash = 0x80000000;
+        hash = 0x40000000;
 
     return hash;
 }
@@ -137,11 +141,13 @@ inline unsigned stringHash(const char* data)
     hash += hash >> 15;
     hash ^= hash << 10;
 
+    hash &= 0x7fffffff;
+
     // This avoids ever returning a hash code of 0, since that is used to
     // signal "hash not computed yet", using a value that is likely to be
     // effectively the same as 0 when the low bits are masked.
     if (hash == 0)
-        hash = 0x80000000;
+        hash = 0x40000000;
 
     return hash;
 }
index c1366a1..0bd7eed 100644 (file)
@@ -1,3 +1,38 @@
+2010-01-05  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        https://bugs.webkit.org/show_bug.cgi?id=33236
+        Remove m_identifierTable pointer from UString
+
+        Add API shims similar to those used in the JSC API to track the current identifierTable.
+
+        * JSBase.cpp:
+        (JSBase::Release):
+        * JSUtils.cpp:
+        (JSObjectKJSValue):
+        (KJSValueToCFTypeInternal):
+        (unprotectGlobalObject):
+        (JSGlueAPIEntry::JSGlueAPIEntry):
+        (JSGlueAPIEntry::~JSGlueAPIEntry):
+        (JSGlueAPICallback::JSGlueAPICallback):
+        (JSGlueAPICallback::~JSGlueAPICallback):
+        * JSUtils.h:
+        * JSValueWrapper.cpp:
+        (JSValueWrapper::JSObjectCopyPropertyNames):
+        (JSValueWrapper::JSObjectCopyProperty):
+        (JSValueWrapper::JSObjectSetProperty):
+        (JSValueWrapper::JSObjectCallFunction):
+        (JSValueWrapper::JSObjectCopyCFValue):
+        * JavaScriptGlue.cpp:
+        (JSRunCreate):
+        (JSRunEvaluate):
+        (JSRunCheckSyntax):
+        (JSCollect):
+        * JavaScriptGlue.xcodeproj/project.pbxproj:
+        * UserObjectImp.cpp:
+        (UserObjectImp::callAsFunction):
+
 2010-01-04  Gavin Barraclough <barraclough@apple.com>
 
         Reviewed by Sam Weinig.
index 7d44abc..39f24e5 100644 (file)
@@ -46,7 +46,7 @@ void JSBase::Release()
 {
     if (--fRetainCount == 0)
     {
-        JSLock lock(LockForReal);
+        JSGlueAPIEntry entry;
         delete this;
     }
 }
index 862ae2e..67dba86 100644 (file)
@@ -128,7 +128,7 @@ JSUserObject* KJSValueToJSObject(JSValue inValue, ExecState *exec)
 //--------------------------------------------------------------------------
 JSValue JSObjectKJSValue(JSUserObject* ptr)
 {
-    JSLock lock(LockForReal);
+    JSGlueAPIEntry entry;
 
     JSValue result = jsUndefined();
     if (ptr)
@@ -203,7 +203,7 @@ CFTypeRef KJSValueToCFTypeInternal(JSValue inValue, ExecState *exec, ObjectImpLi
 
     CFTypeRef result = 0;
 
-    JSLock lock(LockForReal);
+    JSGlueAPIEntry entry;
 
         if (inValue.isBoolean())
             {
@@ -394,7 +394,7 @@ static pthread_once_t globalObjectKeyOnce = PTHREAD_ONCE_INIT;
 
 static void unprotectGlobalObject(void* data) 
 {
-    JSLock lock(LockForReal);
+    JSGlueAPIEntry entry;
     gcUnprotect(static_cast<JSGlueGlobalObject*>(data));
 }
 
@@ -424,3 +424,26 @@ ExecState* getThreadGlobalExecState()
     exec->clearException();
     return exec;
 }
+
+JSGlueAPIEntry::JSGlueAPIEntry()
+    : m_lock(LockForReal)
+    , m_storedIdentifierTable(currentIdentifierTable())
+{
+    setCurrentIdentifierTable(getThreadGlobalObject()->globalExec()->globalData().identifierTable);
+}
+
+JSGlueAPIEntry::~JSGlueAPIEntry()
+{
+    setCurrentIdentifierTable(m_storedIdentifierTable);
+}
+
+JSGlueAPICallback::JSGlueAPICallback(ExecState* exec)
+    : m_dropLocks(exec)
+{
+    resetCurrentIdentifierTable();
+}
+
+JSGlueAPICallback::~JSGlueAPICallback()
+{
+    setCurrentIdentifierTable(getThreadGlobalObject()->globalExec()->globalData().identifierTable);
+}
index fee2663..05bce62 100644 (file)
@@ -34,6 +34,7 @@
 #include <JavaScriptCore/Collector.h>
 #include <JavaScriptCore/JSValue.h>
 #include <JavaScriptCore/Completion.h>
+#include <JavaScriptCore/Identifier.h>
 #include <JavaScriptCore/JSLock.h>
 #include <JavaScriptCore/JSObject.h>
 #include <JavaScriptCore/JSGlobalObject.h>
@@ -76,5 +77,23 @@ enum {
     kJSUserObjectDataTypeCFType
 };
 
+class JSGlueAPIEntry {
+public:
+    JSGlueAPIEntry();
+    ~JSGlueAPIEntry();
+
+private:
+    JSLock m_lock;
+    IdentifierTable* m_storedIdentifierTable;
+};
+
+class JSGlueAPICallback {
+public:
+    JSGlueAPICallback(ExecState*);
+    ~JSGlueAPICallback();
+
+private:
+    JSLock::DropAllLocks m_dropLocks;
+};
 
 #endif
index 24b6f28..e0879a0 100644 (file)
@@ -67,7 +67,7 @@ void JSValueWrapper::JSObjectDispose(void *data)
 
 CFArrayRef JSValueWrapper::JSObjectCopyPropertyNames(void *data)
 {
-    JSLock lock(LockForReal);
+    JSGlueAPIEntry entry;
 
     CFMutableArrayRef result = 0;
     JSValueWrapper* ptr = (JSValueWrapper*)data;
@@ -102,7 +102,7 @@ CFArrayRef JSValueWrapper::JSObjectCopyPropertyNames(void *data)
 
 JSObjectRef JSValueWrapper::JSObjectCopyProperty(void *data, CFStringRef propertyName)
 {
-    JSLock lock(LockForReal);
+    JSGlueAPIEntry entry;
 
     JSObjectRef result = 0;
     JSValueWrapper* ptr = (JSValueWrapper*)data;
@@ -126,7 +126,7 @@ JSObjectRef JSValueWrapper::JSObjectCopyProperty(void *data, CFStringRef propert
 
 void JSValueWrapper::JSObjectSetProperty(void *data, CFStringRef propertyName, JSObjectRef jsValue)
 {
-    JSLock lock(LockForReal);
+    JSGlueAPIEntry entry;
 
     JSValueWrapper* ptr = (JSValueWrapper*)data;
     if (ptr)
@@ -141,7 +141,7 @@ void JSValueWrapper::JSObjectSetProperty(void *data, CFStringRef propertyName, J
 
 JSObjectRef JSValueWrapper::JSObjectCallFunction(void *data, JSObjectRef thisObj, CFArrayRef args)
 {
-    JSLock lock(LockForReal);
+    JSGlueAPIEntry entry;
 
     JSObjectRef result = 0;
     JSValueWrapper* ptr = (JSValueWrapper*)data;
@@ -181,7 +181,7 @@ JSObjectRef JSValueWrapper::JSObjectCallFunction(void *data, JSObjectRef thisObj
 
 CFTypeRef JSValueWrapper::JSObjectCopyCFValue(void *data)
 {
-    JSLock lock(LockForReal);
+    JSGlueAPIEntry entry;
 
     CFTypeRef result = 0;
     JSValueWrapper* ptr = (JSValueWrapper*)data;
index e552f19..134d310 100644 (file)
@@ -246,7 +246,7 @@ JSRunRef JSRunCreate(CFStringRef jsSource, JSFlags inFlags)
     JSRunRef result = 0;
     if (jsSource)
     {
-        JSLock lock(LockForReal);
+        JSGlueAPIEntry entry;
         result = (JSRunRef) new JSRun(jsSource, inFlags);
     }
     return result;
@@ -291,7 +291,7 @@ JSObjectRef JSRunEvaluate(JSRunRef ref)
     JSRun* ptr = (JSRun*)ref;
     if (ptr)
     {
-        JSLock lock(LockForReal);
+        JSGlueAPIEntry entry;
         Completion completion = ptr->Evaluate();
         if (completion.isValueCompletion())
         {
@@ -325,7 +325,7 @@ bool JSRunCheckSyntax(JSRunRef ref)
     JSRun* ptr = (JSRun*)ref;
     if (ptr)
     {
-            JSLock lock(LockForReal);
+            JSGlueAPIEntry entry;
             result = ptr->CheckSyntax();
     }
     return result;
@@ -338,7 +338,7 @@ void JSCollect()
 {
     initializeThreading();
 
-    JSLock lock(LockForReal);
+    JSGlueAPIEntry entry;
     Heap* heap = getThreadGlobalExecState()->heap();
     if (!heap->isBusy())
         heap->collectAllGarbage();
index 7ea4bd6..677cf6f 100644 (file)
                        isa = XCBuildConfiguration;
                        baseConfigurationReference = 1C9051A10BA9F3050081E9D0 /* JavaScriptGlue.xcconfig */;
                        buildSettings = {
-                               BUILD_VARIANTS = (
-                                       normal,
-                               );
+                               BUILD_VARIANTS = normal;
                                SECTORDER_FLAGS = (
                                        "-sectorder",
                                        __TEXT,
index 125e349..7129475 100644 (file)
@@ -75,7 +75,7 @@ JSValue UserObjectImp::callAsFunction(ExecState *exec, JSObject *thisObj, const
 
         JSUserObject* jsResult;
         { // scope
-            JSLock::DropAllLocks dropLocks(exec);
+            JSGlueAPICallback apiCallback(exec);
 
             // getCallData should have guarded against a NULL fJSUserObject.
             assert(fJSUserObject);