+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.
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;
return jvm;
}
-JNIEnv *getJNIEnv()
+JNIEnv* getJNIEnv()
{
- 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;
class TCMalloc_PageHeap {
public:
- TCMalloc_PageHeap();
+ void init();
// Allocate a run of "n" pages. Returns zero if out of memory.
Span* New(Length n);
}
};
-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]);
// 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
for (size_t i = 0; i < kNumClasses; ++i) {
central_cache[i].Init(i);
}
- new ((void*)pageheap_memory) TCMalloc_PageHeap;
+ pageheap->init();
phinited = 1;
}
}
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);
}
};
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);
}
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); }
{
if (location == StorageTraits::deletedValue())
location = StorageTraits::emptyValue();
- *(ValueType*)&location = key;
+ Assigner<ValueTraits::needsRef, ValueType, StorageType, ValueTraits>::assign(key, location);
}
};
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);
}
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>
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);
}
};
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
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
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);
}
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_));
}
public:
typedef uintptr_t Number;
- explicit TCMalloc_PageMap3(void* (*allocator)(size_t)) {
+ void init(void* (*allocator)(size_t)) {
allocator_ = allocator;
root_ = NewNode();
}
+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.
0867D690FE84028FC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */;
+ compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
knownRegions = (
English,
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