JavaScriptCore:
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 6 Jul 2007 12:09:08 +0000 (12:09 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 6 Jul 2007 12:09:08 +0000 (12:09 +0000)
        Reviewed by Antti.

        - <rdar://problem/5311093> JavaScriptCore fails to build with strict-aliasing warnings

        * Configurations/Base.xcconfig: Re-enable -Wstrict-aliasing
        * bindings/jni/jni_utility.cpp:
        (KJS::Bindings::getJNIEnv): Type-pun via a union instead of a pointer cast.
        * wtf/HashMap.h:
        (WTF::): Instead of doing type-punned assignments via pointer cast, do one of three things:
        (1) assign directly w/o cast if storage type matches real type; (2) assign using cast
        via union if type does not need reffing; (3) copy with memcpy and ref/deref manually if type
        needs reffing. This is ok peref-wise because memcpy of a constant length gets optomized.
        HashTraits are now expected to make ref()/deref() take the storage type, not the true type.
        * wtf/HashSet.h:
        (WTF::): Same basic idea.
        * wtf/HashTable.h:
        (WTF::): Added Assigner template for use by HashMap/HashSet. Change RefCounter to call ref()
        and deref() via storage type, avoiding the need to
        type-pun.
        (WTF::RefCounter::ref): ditto
        (WTF::RefCounter::deref): ditto
        * wtf/HashTraits.h:
        (WTF::): Change ref() and deref() for RefPtr HashTraits to take the storage type; cast
        via union to pointer type.
        * wtf/FastMalloc.cpp:
        (WTF::TCMalloc_PageHeap::init): Changed from constructor to init function so this can go in a union.
        (WTF::): redefine pageheap macro in terms of getPageHeap().
        (WTF::getPageHeap): new inline function, helper for pageheap macro. This hides the cast in a union.
        (WTF::TCMalloc_ThreadCache::InitModule): Call init() instead of using placement new to initialize page
        heap.
        * wtf/TCPageMap.h:
        (TCMalloc_PageMap1::init): Changed from constructor to init function.
        (TCMalloc_PageMap2::init): ditto
        (TCMalloc_PageMap3::init): ditto

WebCore:

        Reviewed by Antti.

        - <rdar://problem/5311093> JavaScriptCore fails to build with strict-aliasing warnings

        * platform/StringHash.h:
        (WTF::): Adapt to newer way to do storage types.

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

12 files changed:
JavaScriptCore/ChangeLog
JavaScriptCore/Configurations/Base.xcconfig
JavaScriptCore/bindings/jni/jni_utility.cpp
JavaScriptCore/wtf/FastMalloc.cpp
JavaScriptCore/wtf/HashMap.h
JavaScriptCore/wtf/HashSet.h
JavaScriptCore/wtf/HashTable.h
JavaScriptCore/wtf/HashTraits.h
JavaScriptCore/wtf/TCPageMap.h
WebCore/ChangeLog
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/platform/StringHash.h

index 4272f0c..8a60b25 100644 (file)
@@ -1,3 +1,41 @@
+2007-07-06  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Antti.
+
+        - <rdar://problem/5311093> JavaScriptCore fails to build with strict-aliasing warnings
+        
+        * Configurations/Base.xcconfig: Re-enable -Wstrict-aliasing
+        * bindings/jni/jni_utility.cpp:
+        (KJS::Bindings::getJNIEnv): Type-pun via a union instead of a pointer cast.
+        * wtf/HashMap.h:
+        (WTF::): Instead of doing type-punned assignments via pointer cast, do one of three things:
+        (1) assign directly w/o cast if storage type matches real type; (2) assign using cast
+        via union if type does not need reffing; (3) copy with memcpy and ref/deref manually if type
+        needs reffing. This is ok peref-wise because memcpy of a constant length gets optomized.
+        HashTraits are now expected to make ref()/deref() take the storage type, not the true type.
+        * wtf/HashSet.h:
+        (WTF::): Same basic idea.
+        * wtf/HashTable.h:
+        (WTF::): Added Assigner template for use by HashMap/HashSet. Change RefCounter to call ref()
+        and deref() via storage type, avoiding the need to
+        type-pun.
+        (WTF::RefCounter::ref): ditto
+        (WTF::RefCounter::deref): ditto
+        * wtf/HashTraits.h:
+        (WTF::): Change ref() and deref() for RefPtr HashTraits to take the storage type; cast
+        via union to pointer type.
+        * wtf/FastMalloc.cpp:
+        (WTF::TCMalloc_PageHeap::init): Changed from constructor to init function so this can go in a union.
+        (WTF::): redefine pageheap macro in terms of getPageHeap().
+        (WTF::getPageHeap): new inline function, helper for pageheap macro. This hides the cast in a union.
+        (WTF::TCMalloc_ThreadCache::InitModule): Call init() instead of using placement new to initialize page
+        heap.
+        * wtf/TCPageMap.h:
+        (TCMalloc_PageMap1::init): Changed from constructor to init function.
+        (TCMalloc_PageMap2::init): ditto
+        (TCMalloc_PageMap3::init): ditto
+
+
 2007-07-06  George Staikos  <staikos@kde.org>
 
         Reviewed by Maciej.
index 7418b0c..6ab5207 100644 (file)
@@ -23,4 +23,4 @@ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
 LINKER_DISPLAYS_MANGLED_NAMES = YES;
 PREBINDING = NO;
 VALID_ARCHS = i386 ppc x86_64 ppc64;
-WARNING_CFLAGS = -Wall -W -Wcast-align -Wchar-subscripts -Wformat-security -Wmissing-format-attribute -Wpointer-arith -Wwrite-strings -Wno-format-y2k -Wno-unused-parameter -Wno-long-double -Wundef -Wshorten-64-to-32 -Wno-strict-aliasing;
+WARNING_CFLAGS = -Wall -W -Wcast-align -Wchar-subscripts -Wformat-security -Wmissing-format-attribute -Wpointer-arith -Wwrite-strings -Wno-format-y2k -Wno-unused-parameter -Wno-long-double -Wundef -Wshorten-64-to-32;
index d837607..2e491da 100644 (file)
@@ -85,14 +85,17 @@ JavaVM *getJavaVM()
     return jvm;
 }
 
-JNIEnv *getJNIEnv()
+JNIEnvgetJNIEnv()
 {
-    JNIEnv *env;
+    union {
+        JNIEnv* env;
+        void* dummy;
+    } u;
     jint jniError = 0;
 
-    jniError = (getJavaVM())->AttachCurrentThread((void**)&env, (void *)NULL);
-    if ( jniError == JNI_OK )
-        return env;
+    jniError = (getJavaVM())->AttachCurrentThread(&u.dummy, NULL);
+    if (jniError == JNI_OK)
+        return u.env;
     else
         fprintf(stderr, "%s: AttachCurrentThread failed, returned %ld\n", __PRETTY_FUNCTION__, (long)jniError);
     return NULL;
index a08a6d0..14b2247 100644 (file)
@@ -676,7 +676,7 @@ template <> class MapSelector<32> {
 
 class TCMalloc_PageHeap {
  public:
-  TCMalloc_PageHeap();
+  void init();
 
   // Allocate a run of "n" pages.  Returns zero if out of memory.
   Span* New(Length n);
@@ -757,9 +757,12 @@ class TCMalloc_PageHeap {
   }
 };
 
-TCMalloc_PageHeap::TCMalloc_PageHeap() : pagemap_(MetaDataAlloc),
-                                         free_pages_(0),
-                                         system_bytes_(0) {
+void TCMalloc_PageHeap::init()
+{
+  pagemap_.init(MetaDataAlloc);
+  free_pages_ = 0;
+  system_bytes_ = 0;
+  
   DLL_Init(&large_);
   for (size_t i = 0; i < kMaxPages; i++) {
     DLL_Init(&free_[i]);
@@ -1173,7 +1176,18 @@ static bool phinited = false;
 
 // Avoid extra level of indirection by making "pageheap" be just an alias
 // of pageheap_memory.
-#define pageheap ((TCMalloc_PageHeap*) pageheap_memory)
+
+typedef union {
+    void* m_memory;
+    TCMalloc_PageHeap m_pageHeap;
+} PageHeapUnion;
+
+static inline TCMalloc_PageHeap* getPageHeap()
+{
+    return &reinterpret_cast<PageHeapUnion*>(&pageheap_memory[0])->m_pageHeap;
+}
+
+#define pageheap getPageHeap()
 
 // Thread-specific key.  Initialization here is somewhat tricky
 // because some Linux startup code invokes malloc() before it
@@ -1543,7 +1557,7 @@ void TCMalloc_ThreadCache::InitModule() {
     for (size_t i = 0; i < kNumClasses; ++i) {
       central_cache[i].Init(i);
     }
-    new ((void*)pageheap_memory) TCMalloc_PageHeap;
+    pageheap->init();
     phinited = 1;
   }
 }
index 717224d..76474de 100644 (file)
@@ -111,42 +111,50 @@ namespace WTF {
         static const typename PairType::first_type& extract(const PairType& p) { return p.first; }
     };
 
-    template<bool canReplaceDeletedKey, typename ValueType, typename ValueStorageTraits, typename HashFunctions>
+    template<bool canReplaceDeletedKey, typename ValueType, typename ValueTraits, typename ValueStorageTraits, typename HashFunctions>
     struct HashMapTranslator;
 
-    template<typename ValueType, typename ValueStorageTraits, typename HashFunctions>
-    struct HashMapTranslator<true, ValueType, ValueStorageTraits, HashFunctions> {
+    template<typename ValueType, typename ValueTraits, typename ValueStorageTraits, typename HashFunctions>
+    struct HashMapTranslator<true, ValueType, ValueTraits, ValueStorageTraits, HashFunctions> {
         typedef typename ValueType::first_type KeyType;
         typedef typename ValueType::second_type MappedType;
         typedef typename ValueStorageTraits::TraitType ValueStorageType;
         typedef typename ValueStorageTraits::FirstTraits KeyStorageTraits;
         typedef typename KeyStorageTraits::TraitType KeyStorageType;
+        typedef typename ValueStorageTraits::SecondTraits MappedStorageTraits;
+        typedef typename MappedStorageTraits::TraitType MappedStorageType;
+        typedef typename ValueTraits::FirstTraits KeyTraits;
+        typedef typename ValueTraits::SecondTraits MappedTraits;
 
         static unsigned hash(const KeyType& key) { return HashFunctions::hash(key); }
         static bool equal(const KeyStorageType& a, const KeyType& b) { return HashFunctions::equal(*(KeyType*)&a, b); }
         static void translate(ValueStorageType& location, const KeyType& key, const MappedType& mapped, unsigned)
         {
-            *(KeyType*)&location.first = key;
-            *(MappedType*)&location.second = mapped;
+            Assigner<KeyTraits::needsRef, KeyType, KeyStorageType, KeyTraits>::assign(key, location.first);
+            Assigner<MappedTraits::needsRef, MappedType, MappedStorageType, MappedTraits>::assign(mapped, location.second);
         }
     };
 
-    template<typename ValueType, typename ValueStorageTraits, typename HashFunctions>
-    struct HashMapTranslator<false, ValueType, ValueStorageTraits, HashFunctions> {
+    template<typename ValueType, typename ValueTraits, typename ValueStorageTraits, typename HashFunctions>
+    struct HashMapTranslator<false, ValueType, ValueTraits, ValueStorageTraits, HashFunctions> {
         typedef typename ValueType::first_type KeyType;
         typedef typename ValueType::second_type MappedType;
         typedef typename ValueStorageTraits::TraitType ValueStorageType;
         typedef typename ValueStorageTraits::FirstTraits KeyStorageTraits;
         typedef typename KeyStorageTraits::TraitType KeyStorageType;
-
+        typedef typename ValueStorageTraits::SecondTraits MappedStorageTraits;
+        typedef typename MappedStorageTraits::TraitType MappedStorageType;
+        typedef typename ValueTraits::FirstTraits KeyTraits;
+        typedef typename ValueTraits::SecondTraits MappedTraits;
+        
         static unsigned hash(const KeyType& key) { return HashFunctions::hash(key); }
         static bool equal(const KeyStorageType& a, const KeyType& b) { return HashFunctions::equal(*(KeyType*)&a, b); }
         static void translate(ValueStorageType& location, const KeyType& key, const MappedType& mapped, unsigned)
         {
             if (location.first == KeyStorageTraits::deletedValue())
                 location.first = KeyStorageTraits::emptyValue();
-            *(KeyType*)&location.first = key;
-            *(MappedType*)&location.second = mapped;
+            Assigner<KeyTraits::needsRef, KeyType, KeyStorageType, KeyTraits>::assign(key, location.first);
+            Assigner<MappedTraits::needsRef, MappedType, MappedStorageType, MappedTraits>::assign(mapped, location.second);
         }
     };
 
@@ -259,7 +267,7 @@ namespace WTF {
     HashMap<T, U, V, W, X>::inlineAdd(const KeyType& key, const MappedType& mapped) 
     {
         const bool canReplaceDeletedKey = !KeyTraits::needsDestruction || KeyStorageTraits::needsDestruction;
-        typedef HashMapTranslator<canReplaceDeletedKey, ValueType, ValueStorageTraits, HashFunctions> TranslatorType;
+        typedef HashMapTranslator<canReplaceDeletedKey, ValueType, ValueTraits, ValueStorageTraits, HashFunctions> TranslatorType;
         return m_impl.template add<KeyType, MappedType, TranslatorType>(key, mapped);
     }
 
index 3fbba77..2cac61b 100644 (file)
@@ -102,22 +102,22 @@ namespace WTF {
         static const T& extract(const T& t) { return t; }
     };
 
-    template<bool canReplaceDeletedValue, typename ValueType, typename StorageTraits, typename HashFunctions>
+    template<bool canReplaceDeletedValue, typename ValueType, typename ValueTraits, typename StorageTraits, typename HashFunctions>
     struct HashSetTranslator;
 
-    template<typename ValueType, typename StorageTraits, typename HashFunctions>
-    struct HashSetTranslator<true, ValueType, StorageTraits, HashFunctions> {
+    template<typename ValueType, typename ValueTraits, typename StorageTraits, typename HashFunctions>
+    struct HashSetTranslator<true, ValueType, ValueTraits, StorageTraits, HashFunctions> {
         typedef typename StorageTraits::TraitType StorageType;
         static unsigned hash(const ValueType& key) { return HashFunctions::hash(key); }
         static bool equal(const StorageType& a, const ValueType& b) { return HashFunctions::equal(*(const ValueType*)&a, b); }
         static void translate(StorageType& location, const ValueType& key, const ValueType&, unsigned)
         {
-            *(ValueType*)&location = key;
+            Assigner<ValueTraits::needsRef, ValueType, StorageType, ValueTraits>::assign(key, location);
         }
     };
 
-    template<typename ValueType, typename StorageTraits, typename HashFunctions>
-    struct HashSetTranslator<false, ValueType, StorageTraits, HashFunctions> {
+    template<typename ValueType, typename ValueTraits, typename StorageTraits, typename HashFunctions>
+    struct HashSetTranslator<false, ValueType, ValueTraits, StorageTraits, HashFunctions> {
         typedef typename StorageTraits::TraitType StorageType;
         static unsigned hash(const ValueType& key) { return HashFunctions::hash(key); }
         static bool equal(const StorageType& a, const ValueType& b) { return HashFunctions::equal(*(const ValueType*)&a, b); }
@@ -125,7 +125,7 @@ namespace WTF {
         {
             if (location == StorageTraits::deletedValue())
                 location = StorageTraits::emptyValue();
-            *(ValueType*)&location = key;
+            Assigner<ValueTraits::needsRef, ValueType, StorageType, ValueTraits>::assign(key, location);
         }
     };
 
@@ -264,7 +264,7 @@ namespace WTF {
     pair<typename HashSet<T, U, V>::iterator, bool> HashSet<T, U, V>::add(const ValueType &value)
     {
         const bool canReplaceDeletedValue = !ValueTraits::needsDestruction || StorageTraits::needsDestruction;
-        typedef HashSetTranslator<canReplaceDeletedValue, ValueType, StorageTraits, HashFunctions> Translator;
+        typedef HashSetTranslator<canReplaceDeletedValue, ValueType, ValueTraits, StorageTraits, HashFunctions> Translator;
         return m_impl.template add<ValueType, ValueType, Translator>(value, value);
     }
 
index e41e816..b3c9647 100644 (file)
@@ -850,29 +850,29 @@ namespace WTF {
         static const bool value = firstNeedsRef || secondNeedsRef;
     };
 
-    template<bool needsRef, typename ValueTraits> struct RefCounterBase;
+    template<bool needsRef, typename ValueTraits, typename ValueStorageTraits> struct RefCounterBase;
 
-    template<typename ValueTraits>
-    struct RefCounterBase<false, ValueTraits> {
-        typedef typename ValueTraits::TraitType ValueType;
-        static void ref(const ValueType&) { }
-        static void deref(const ValueType&) { }
+    template<typename ValueTraits, typename ValueStorageTraits>
+    struct RefCounterBase<false, ValueTraits, ValueStorageTraits> {
+        typedef typename ValueStorageTraits::TraitType ValueStorageType;
+        static void ref(const ValueStorageType&) { }
+        static void deref(const ValueStorageType&) { }
     };
 
-    template<typename ValueTraits>
-    struct RefCounterBase<true, ValueTraits> {
-        typedef typename ValueTraits::TraitType ValueType;
-        static void ref(const ValueType& v) { ValueTraits::ref(*(const ValueType*)&v); }
-        static void deref(const ValueType& v) { ValueTraits::deref(*(const ValueType*)&v); }
+    template<typename ValueTraits, typename ValueStorageTraits>
+    struct RefCounterBase<true, ValueTraits, ValueStorageTraits> {
+        typedef typename ValueStorageTraits::TraitType ValueStorageType;
+        static void ref(const ValueStorageType& v) { ValueTraits::ref(v); }
+        static void deref(const ValueStorageType& v) { ValueTraits::deref(v); }
     };
 
     template<typename ValueTraits, typename ValueStorageTraits> struct RefCounter {
         typedef typename ValueTraits::TraitType ValueType;
         typedef typename ValueStorageTraits::TraitType ValueStorageType;
         static const bool needsRef = NeedsRef<ValueTraits, ValueStorageTraits>::value;
-        typedef RefCounterBase<needsRef, ValueTraits> Base;
-        static void ref(const ValueStorageType& v) { Base::ref(*(const ValueType*)&v); }
-        static void deref(const ValueStorageType& v) { Base::deref(*(const ValueType*)&v); }
+        typedef RefCounterBase<needsRef, ValueTraits, ValueStorageTraits> Base;
+        static void ref(const ValueStorageType& v) { Base::ref(v); }
+        static void deref(const ValueStorageType& v) { Base::deref(v); }
     };
 
     template<typename FirstTraits, typename SecondTraits, typename ValueStorageTraits>
@@ -884,15 +884,15 @@ namespace WTF {
         typedef typename ValueStorageTraits::TraitType ValueStorageType;
         static const bool firstNeedsRef = NeedsRef<FirstTraits, FirstStorageTraits>::value;
         static const bool secondNeedsRef = NeedsRef<SecondTraits, SecondStorageTraits>::value;
-        typedef RefCounterBase<firstNeedsRef, FirstTraits> FirstBase;
-        typedef RefCounterBase<secondNeedsRef, SecondTraits> SecondBase;
+        typedef RefCounterBase<firstNeedsRef, FirstTraits, FirstStorageTraits> FirstBase;
+        typedef RefCounterBase<secondNeedsRef, SecondTraits, SecondStorageTraits> SecondBase;
         static void ref(const ValueStorageType& v) {
-            FirstBase::ref(*(const FirstType*)&v.first);
-            SecondBase::ref(*(const SecondType*)&v.second);
+            FirstBase::ref(v.first);
+            SecondBase::ref(v.second);
         }
         static void deref(const ValueStorageType& v) {
-            FirstBase::deref(*(const FirstType*)&v.first);
-            SecondBase::deref(*(const SecondType*)&v.second);
+            FirstBase::deref(v.first);
+            SecondBase::deref(v.second);
         }
     };
 
@@ -937,6 +937,36 @@ namespace WTF {
         static void derefAll(HashTableType& table) { Base::derefAll(table); }
     };
 
+    // helper template for HashMap and HashSet.
+    template<bool needsRef, typename FromType, typename ToType, typename FromTraits> struct Assigner;
+    
+    template<typename FromType, typename ToType, typename FromTraits> struct Assigner<false, FromType, ToType, FromTraits> {
+        typedef union { 
+            FromType m_from; 
+            ToType m_to; 
+        } UnionType;
+
+        static void assign(const FromType& from, ToType& to) { reinterpret_cast<UnionType*>(&to)->m_from = from; }
+    };
+    
+    template<typename FromType, typename ToType, typename FromTraits> struct Assigner<true, FromType, ToType, FromTraits> {
+        static void assign(const FromType& from, ToType& to) 
+        { 
+            ToType oldTo = to; 
+            memcpy(&to, &from, sizeof(FromType)); 
+            FromTraits::ref(to);
+            FromTraits::deref(oldTo);
+        }
+    };
+    
+    template<typename FromType, typename FromTraits> struct Assigner<false, FromType, FromType, FromTraits> {
+        static void assign(const FromType& from, FromType& to) { to = from; }
+    };    
+    
+    template<typename FromType, typename FromTraits> struct Assigner<true, FromType, FromType, FromTraits> {
+        static void assign(const FromType& from, FromType& to) { to = from; }
+    };    
+
 } // namespace WTF
 
 #endif // WTF_HashTable_h
index 13e7eac..7c99ff9 100644 (file)
@@ -103,10 +103,25 @@ namespace WTF {
 
     template<typename P> struct HashTraits<RefPtr<P> > : GenericHashTraits<RefPtr<P> > {
         typedef HashTraits<typename IntTypes<sizeof(P*)>::SignedType> StorageTraits;
+        typedef typename StorageTraits::TraitType StorageType;
         static const bool emptyValueIsZero = true;
         static const bool needsRef = true;
-        static void ref(const RefPtr<P>& p) { if (p) p->ref(); }
-        static void deref(const RefPtr<P>& p) { if (p) p->deref(); }
+
+        typedef union { 
+            P* m_p; 
+            StorageType m_s; 
+        } UnionType;
+
+        static void ref(const StorageType& s) 
+        { 
+            if (const P* p = reinterpret_cast<const UnionType*>(&s)->m_p) 
+                const_cast<P*>(p)->ref(); 
+        }
+        static void deref(const StorageType& s) 
+        { 
+            if (const P* p = reinterpret_cast<const UnionType*>(&s)->m_p) 
+                const_cast<P*>(p)->deref(); 
+        }
     };
 
     // template to set deleted values
index 018e324..86086ce 100644 (file)
@@ -68,7 +68,7 @@ class TCMalloc_PageMap1 {
  public:
   typedef uintptr_t Number;
 
-  explicit TCMalloc_PageMap1(void* (*allocator)(size_t)) {
+  void init(void* (*allocator)(size_t)) {
     array_ = reinterpret_cast<void**>((*allocator)(sizeof(void*) << BITS));
     memset(array_, 0, sizeof(void*) << BITS);
   }
@@ -120,7 +120,7 @@ class TCMalloc_PageMap2 {
  public:
   typedef uintptr_t Number;
 
-  explicit TCMalloc_PageMap2(void* (*allocator)(size_t)) {
+  void init(void* (*allocator)(size_t)) {
     allocator_ = allocator;
     memset(root_, 0, sizeof(root_));
   }
@@ -194,7 +194,7 @@ class TCMalloc_PageMap3 {
  public:
   typedef uintptr_t Number;
 
-  explicit TCMalloc_PageMap3(void* (*allocator)(size_t)) {
+  void init(void* (*allocator)(size_t)) {
     allocator_ = allocator;
     root_ = NewNode();
   }
index 15e845e..d330901 100644 (file)
@@ -1,3 +1,12 @@
+2007-07-05  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Antti.
+
+        - <rdar://problem/5311093> JavaScriptCore fails to build with strict-aliasing warnings
+
+        * platform/StringHash.h:
+        (WTF::): Adapt to newer way to do storage types.
+
 2007-07-06  Bernhard Rosenkraenzer  <bero@arklinux.org>
 
         Reviewed by Sam.
index b5ea342..74585c8 100644 (file)
                0867D690FE84028FC02AAC07 /* Project object */ = {
                        isa = PBXProject;
                        buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */;
+                       compatibilityVersion = "Xcode 2.4";
                        hasScannedForEncodings = 1;
                        knownRegions = (
                                English,
index a9bbffa..12ec1a9 100644 (file)
@@ -216,10 +216,20 @@ namespace WTF {
 
     template<> struct HashTraits<WebCore::String> : GenericHashTraits<WebCore::String> {
         typedef HashTraits<WebCore::StringImpl*>::StorageTraits StorageTraits;
+        typedef StorageTraits::TraitType StorageType;
         static const bool emptyValueIsZero = true;
         static const bool needsRef = true;
-        static void ref(const WebCore::String& s) { if (s.impl()) s.impl()->ref(); }
-        static void deref(const WebCore::String& s) { if (s.impl()) s.impl()->deref(); }
+        
+        typedef union { 
+            WebCore::StringImpl* m_p; 
+            StorageType m_s; 
+        } UnionType;
+
+        static void ref(const StorageType& s) { ref(reinterpret_cast<const UnionType*>(&s)->m_p); }
+        static void deref(const StorageType& s) { deref(reinterpret_cast<const UnionType*>(&s)->m_p); }
+        
+        static void ref(const WebCore::StringImpl* str) { if (str) const_cast<WebCore::StringImpl*>(str)->ref(); }
+        static void deref(const WebCore::StringImpl* str) { if (str) const_cast<WebCore::StringImpl*>(str)->deref(); }
     };
 
     // share code between StringImpl*, RefPtr<StringImpl>, and String