2011-02-17 Oliver Hunt <oliver@apple.com>
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 17 Feb 2011 20:35:59 +0000 (20:35 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 17 Feb 2011 20:35:59 +0000 (20:35 +0000)
        Reviewed by Geoffrey Garen.

        Refactor WriteBarrier and DeprecatedPtr to have less code duplication.
        https://bugs.webkit.org/show_bug.cgi?id=54608

        Make use of the tricks used for Handle, et al to avoid duplicating all
        of the logic for DeprecatedPtr and WriteBarrier simply to support known
        vs. unknown types.

        * JavaScriptCore.xcodeproj/project.pbxproj:
        * collector/handles/Global.h:
        (JSC::Global::internalSet):
        * collector/handles/Handle.h:
        (JSC::Handle::Handle):
        (JSC::Handle::get):
        * runtime/JSArray.cpp:
        (JSC::JSArray::sortNumeric):
        * runtime/JSObject.h:
        (JSC::JSObject::inlineGetOwnPropertySlot):
        * runtime/SlotAccessor.h: Added.
        (JSC::SlotTypes::getFromBaseType):
        (JSC::SlotTypes::convertToBaseType):
        (JSC::SlotTypes::getFromSlot):
        (JSC::SlotTypes::toJSValue):
        (JSC::SlotTypes::validateUpcast):
        (JSC::SlotAccessor::operator->):
        (JSC::SlotAccessor::operator*):
        * runtime/WeakGCPtr.h:
        (JSC::WeakGCPtr::get):
        (JSC::WeakGCPtr::internalSet):
        * runtime/WriteBarrier.h:
        (JSC::DeprecatedPtr::DeprecatedPtr):
        (JSC::DeprecatedPtr::get):
        (JSC::DeprecatedPtr::slot):
        (JSC::DeprecatedPtr::operator=):
        (JSC::WriteBarrierTranslator::convertToStorage):
        (JSC::WriteBarrierTranslator::convertFromStorage):
        (JSC::WriteBarrierBase::set):
        (JSC::WriteBarrierBase::get):
        (JSC::WriteBarrierBase::clear):
        (JSC::WriteBarrierBase::slot):
        (JSC::WriteBarrierBase::operator UnspecifiedBoolType*):
        (JSC::WriteBarrierBase::operator!):
        (JSC::WriteBarrierBase::setWithoutWriteBarrier):
        (JSC::WriteBarrier::WriteBarrier):

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

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/collector/handles/Global.h
Source/JavaScriptCore/collector/handles/Handle.h
Source/JavaScriptCore/runtime/JSArray.cpp
Source/JavaScriptCore/runtime/JSObject.h
Source/JavaScriptCore/runtime/SlotAccessor.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/WeakGCPtr.h
Source/JavaScriptCore/runtime/WriteBarrier.h

index 428e32a..5f6f08f 100644 (file)
@@ -1,3 +1,51 @@
+2011-02-17  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Geoffrey Garen.
+
+        Refactor WriteBarrier and DeprecatedPtr to have less code duplication.
+        https://bugs.webkit.org/show_bug.cgi?id=54608
+
+        Make use of the tricks used for Handle, et al to avoid duplicating all
+        of the logic for DeprecatedPtr and WriteBarrier simply to support known
+        vs. unknown types.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * collector/handles/Global.h:
+        (JSC::Global::internalSet):
+        * collector/handles/Handle.h:
+        (JSC::Handle::Handle):
+        (JSC::Handle::get):
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::sortNumeric):
+        * runtime/JSObject.h:
+        (JSC::JSObject::inlineGetOwnPropertySlot):
+        * runtime/SlotAccessor.h: Added.
+        (JSC::SlotTypes::getFromBaseType):
+        (JSC::SlotTypes::convertToBaseType):
+        (JSC::SlotTypes::getFromSlot):
+        (JSC::SlotTypes::toJSValue):
+        (JSC::SlotTypes::validateUpcast):
+        (JSC::SlotAccessor::operator->):
+        (JSC::SlotAccessor::operator*):
+        * runtime/WeakGCPtr.h:
+        (JSC::WeakGCPtr::get):
+        (JSC::WeakGCPtr::internalSet):
+        * runtime/WriteBarrier.h:
+        (JSC::DeprecatedPtr::DeprecatedPtr):
+        (JSC::DeprecatedPtr::get):
+        (JSC::DeprecatedPtr::slot):
+        (JSC::DeprecatedPtr::operator=):
+        (JSC::WriteBarrierTranslator::convertToStorage):
+        (JSC::WriteBarrierTranslator::convertFromStorage):
+        (JSC::WriteBarrierBase::set):
+        (JSC::WriteBarrierBase::get):
+        (JSC::WriteBarrierBase::clear):
+        (JSC::WriteBarrierBase::slot):
+        (JSC::WriteBarrierBase::operator UnspecifiedBoolType*):
+        (JSC::WriteBarrierBase::operator!):
+        (JSC::WriteBarrierBase::setWithoutWriteBarrier):
+        (JSC::WriteBarrier::WriteBarrier):
+
 2011-02-17  Kevin Ollivier  <kevino@theolliviers.com>
 
         [wx] Revert incorrect blind fix and restore previous working code.
index 5449471..a1f667e 100644 (file)
                A7C40C0A130B057D00D002A1 /* BlockStack.h in Headers */ = {isa = PBXBuildFile; fileRef = A7C40C07130B057D00D002A1 /* BlockStack.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A7C40C0B130B057D00D002A1 /* SentinelLinkedList.h in Headers */ = {isa = PBXBuildFile; fileRef = A7C40C08130B057D00D002A1 /* SentinelLinkedList.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A7C40C0C130B057D00D002A1 /* SinglyLinkedList.h in Headers */ = {isa = PBXBuildFile; fileRef = A7C40C09130B057D00D002A1 /* SinglyLinkedList.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               A7C40D2D130C8E4200D002A1 /* SlotAccessor.h in Headers */ = {isa = PBXBuildFile; fileRef = A7C40D2C130C8E4200D002A1 /* SlotAccessor.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A7C530E4102A3813005BC741 /* MarkStackPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7C530E3102A3813005BC741 /* MarkStackPosix.cpp */; };
                A7D649AA1015224E009B2E1B /* PossiblyNull.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D649A91015224E009B2E1B /* PossiblyNull.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A7DCB97312E5193F00911940 /* WriteBarrier.h in Headers */ = {isa = PBXBuildFile; fileRef = A7DCB77912E3D90500911940 /* WriteBarrier.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A7C40C07130B057D00D002A1 /* BlockStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockStack.h; sourceTree = "<group>"; };
                A7C40C08130B057D00D002A1 /* SentinelLinkedList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentinelLinkedList.h; sourceTree = "<group>"; };
                A7C40C09130B057D00D002A1 /* SinglyLinkedList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SinglyLinkedList.h; sourceTree = "<group>"; };
+               A7C40D2C130C8E4200D002A1 /* SlotAccessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SlotAccessor.h; sourceTree = "<group>"; };
                A7C530E3102A3813005BC741 /* MarkStackPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MarkStackPosix.cpp; sourceTree = "<group>"; };
                A7D649A91015224E009B2E1B /* PossiblyNull.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PossiblyNull.h; sourceTree = "<group>"; };
                A7DCB77912E3D90500911940 /* WriteBarrier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WriteBarrier.h; sourceTree = "<group>"; };
                                14035DB010DBFB2A00FFFFE7 /* WeakGCPtr.h */,
                                1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */,
                                A7DCB77912E3D90500911940 /* WriteBarrier.h */,
+                               A7C40D2C130C8E4200D002A1 /* SlotAccessor.h */,
                        );
                        path = runtime;
                        sourceTree = "<group>";
                                A7C40C0A130B057D00D002A1 /* BlockStack.h in Headers */,
                                A7C40C0B130B057D00D002A1 /* SentinelLinkedList.h in Headers */,
                                A7C40C0C130B057D00D002A1 /* SinglyLinkedList.h in Headers */,
+                               A7C40D2D130C8E4200D002A1 /* SlotAccessor.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 571fe31..ac600ad 100644 (file)
@@ -132,7 +132,7 @@ public:
 protected:
     void internalSet(ExternalType value)
     {
-        JSValue newValue(HandleTypes<T>::toJSValue(value));
+        JSValue newValue(SlotTypes<T>::toJSValue(value));
         HandleSlot slot = this->slot();
         ASSERT(slot);
         HandleHeap::heapFor(slot)->writeBarrier(slot, newValue);
index 98c60ec..5a9d49d 100644 (file)
@@ -26,7 +26,7 @@
 #ifndef Handle_h
 #define Handle_h
 
-#include "WriteBarrier.h"
+#include "SlotAccessor.h"
 
 #include <wtf/Assertions.h>
 
@@ -89,40 +89,16 @@ private:
     HandleSlot m_slot;
 };
 
-template <typename T> struct HandleTypes {
-    typedef T* ExternalType;
-    static ExternalType getFromSlot(HandleSlot slot) { return (slot && *slot) ? reinterpret_cast<ExternalType>(slot->asCell()) : 0; }
-    static JSValue toJSValue(T* cell) { return reinterpret_cast<JSCell*>(cell); }
-    template <typename U> static void validateUpcast() { T* temp; temp = (U*)0; }
-};
-
-template <> struct HandleTypes<Unknown> {
-    typedef JSValue ExternalType;
-    static ExternalType getFromSlot(HandleSlot slot) { return slot ? *slot : JSValue(); }
-    static JSValue toJSValue(const JSValue& v) { return v; }
-    template <typename U> static void validateUpcast() {}
-};
-
-template <typename Base, typename T> struct HandleConverter {
-    T* operator->() { return static_cast<Base*>(this)->get(); }
-    const T* operator->() const { return static_cast<const Base*>(this)->get(); }
-    T* operator*() { return static_cast<Base*>(this)->get(); }
-    const T* operator*() const { return static_cast<const Base*>(this)->get(); }
-};
-
-template <typename Base> struct HandleConverter<Base, Unknown> {
-};
-
-template <typename T> class Handle : public HandleBase, public HandleConverter<Handle<T>, T> {
+template <typename T> class Handle : public HandleBase, public SlotAccessor<Handle<T>, T> {
 public:
-    typedef typename HandleTypes<T>::ExternalType ExternalType;
+    typedef typename SlotTypes<T>::ExternalType ExternalType;
     template <typename U> Handle(Handle<U> o)
     {
-        typename HandleTypes<T>::template validateUpcast<U>();
+        typename SlotTypes<T>::template validateUpcast<U>();
         m_slot = o.slot();
     }
 
-    ExternalType get() const { return HandleTypes<T>::getFromSlot(this->slot()); }
+    ExternalType get() const { return SlotTypes<T>::getFromSlot(this->slot()); }
 
 protected:
 
index b0b26a5..e74266e 100644 (file)
@@ -898,7 +898,7 @@ void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType cal
     bool allValuesAreNumbers = true;
     size_t size = storage->m_numValuesInVector;
     for (size_t i = 0; i < size; ++i) {
-        if (!storage->m_vector[i].isNumber()) {
+        if (!storage->m_vector[i]->isNumber()) {
             allValuesAreNumbers = false;
             break;
         }
index b0f5499..1724132 100644 (file)
@@ -454,7 +454,7 @@ inline bool JSValue::inherits(const ClassInfo* classInfo) const
 ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
     if (WriteBarrierBase<Unknown>* location = getDirectLocation(propertyName)) {
-        if (m_structure->hasGetterSetterProperties() && location->isGetterSetter())
+        if (m_structure->hasGetterSetterProperties() && (*location)->isGetterSetter())
             fillGetterPropertySlot(slot, location);
         else
             slot.setValue(this, location->get(), offsetForLocation(location));
diff --git a/Source/JavaScriptCore/runtime/SlotAccessor.h b/Source/JavaScriptCore/runtime/SlotAccessor.h
new file mode 100644 (file)
index 0000000..ebe1970
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SlotAccessor_h
+#define SlotAccessor_h
+
+#include "JSValue.h"
+
+namespace JSC {
+
+class JSCell;
+
+typedef enum { } Unknown;
+typedef JSValue* HandleSlot;
+
+template <typename T> struct SlotTypes {
+    typedef T* ExternalType;
+    typedef JSCell* ExternalTypeBase;
+    static ExternalType getFromBaseType(ExternalTypeBase base) { return reinterpret_cast<ExternalType>(base); }
+    static ExternalTypeBase convertToBaseType(ExternalType value) { return reinterpret_cast<ExternalTypeBase>(value); }
+    static ExternalType getFromSlot(HandleSlot slot) { return (slot && *slot) ? reinterpret_cast<ExternalType>(slot->asCell()) : 0; }
+    static JSValue toJSValue(ExternalType cell) { return reinterpret_cast<ExternalTypeBase>(cell); }
+    template <typename U> static void validateUpcast() { T* temp; temp = (U*)0; }
+};
+
+template <> struct SlotTypes<Unknown> {
+    typedef JSValue ExternalType;
+    typedef JSValue ExternalTypeBase;
+    static ExternalType getFromBaseType(ExternalTypeBase base) { return base; }
+    static ExternalTypeBase convertToBaseType(ExternalType value) { return value; }
+    static ExternalType getFromSlot(HandleSlot slot) { return slot ? *slot : JSValue(); }
+    static JSValue toJSValue(const JSValue& v) { return v; }
+    template <typename U> static void validateUpcast() {}
+};
+
+template <typename Base, typename T> struct SlotAccessor {
+    T* operator->() { return static_cast<Base*>(this)->get(); }
+    const T* operator->() const { return static_cast<const Base*>(this)->get(); }
+    T* operator*() { return static_cast<Base*>(this)->get(); }
+    const T* operator*() const { return static_cast<const Base*>(this)->get(); }
+};
+
+template <typename Base> struct SlotAccessor<Base, Unknown> {
+    JSValue* operator->() { return static_cast<Base*>(this)->slot(); }
+    const JSValue* operator->() const { return static_cast<const Base*>(this)->slot(); }
+};
+
+// JSValue should not be used directly
+template <typename Base> struct SlotAccessor<Base, JSValue>;
+template <> struct SlotTypes<JSValue>;
+
+}
+
+#endif // SlotAccessor_h
index a0138c0..b609c1f 100644 (file)
 namespace JSC {
 // A smart pointer whose get() function returns 0 for cells that have died
 
-template <typename T> class WeakGCPtr : public HandleConverter<WeakGCPtr<T>, T> {
+template <typename T> class WeakGCPtr : public SlotAccessor<WeakGCPtr<T>, T> {
     WTF_MAKE_NONCOPYABLE(WeakGCPtr);
 
 public:
-    typedef typename HandleTypes<T>::ExternalType ExternalType;
+    typedef typename SlotTypes<T>::ExternalType ExternalType;
     
     WeakGCPtr()
         : m_slot(0)
@@ -56,7 +56,7 @@ public:
         internalSet(value);
     }
 
-    ExternalType get() const { return  HandleTypes<T>::getFromSlot(m_slot); }
+    ExternalType get() const { return  SlotTypes<T>::getFromSlot(m_slot); }
     
     void clear()
     {
@@ -91,7 +91,7 @@ private:
     void internalSet(ExternalType value)
     {
         ASSERT(m_slot);
-        JSValue newValue(HandleTypes<T>::toJSValue(value));
+        JSValue newValue(SlotTypes<T>::toJSValue(value));
         HandleHeap::heapFor(m_slot)->writeBarrier(m_slot, newValue);
         *m_slot = newValue;
     }
index 44840ad..1f3808a 100644 (file)
 #ifndef WriteBarrier_h
 #define WriteBarrier_h
 
-#include "JSValue.h"
+#include "SlotAccessor.h"
 
 namespace JSC {
 class JSCell;
 class JSGlobalData;
 
-typedef enum { } Unknown;
-typedef JSValue* HandleSlot;
-
-template <class T> class DeprecatedPtr {
+template <class T> class DeprecatedPtr : public SlotAccessor<DeprecatedPtr<T>, T> {
 public:
-    DeprecatedPtr() : m_cell(0) { }
-    DeprecatedPtr(T* cell) : m_cell(reinterpret_cast<JSCell*>(cell)) { }
-    T* get() const { return reinterpret_cast<T*>(m_cell); }
-    T* operator*() const { return static_cast<T*>(m_cell); }
-    T* operator->() const { return static_cast<T*>(m_cell); }
-    
-    JSCell** slot() { return &m_cell; }
+    typedef typename SlotTypes<T>::ExternalType ExternalType;
+    typedef typename SlotTypes<T>::ExternalTypeBase ExternalTypeBase;
     
-    typedef T* (DeprecatedPtr::*UnspecifiedBoolType);
-    operator UnspecifiedBoolType*() const { return m_cell ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
-
-    bool operator!() const { return !m_cell; }
-
-protected:
-    JSCell* m_cell;
-};
-
-template <> class DeprecatedPtr<Unknown> {
-public:
-    DeprecatedPtr() { }
-    DeprecatedPtr(JSValue value) : m_value(value) { }
-    DeprecatedPtr(JSCell* value) : m_value(value) { }
-    const JSValue& get() const { return m_value; }
-    const JSValue* operator*() const { return &m_value; }
-    const JSValue* operator->() const { return &m_value; }
+    DeprecatedPtr() : m_value() { }
+    DeprecatedPtr(ExternalType value) : m_value(SlotTypes<T>::convertToBaseType(value)) { }
+    ExternalType get() const { return SlotTypes<T>::getFromBaseType(m_value); }
     
-    JSValue* slot() { return &m_value; }
+    ExternalTypeBase* slot() { return &m_value; }
     
-    typedef JSValue (DeprecatedPtr::*UnspecifiedBoolType);
+    typedef ExternalType (DeprecatedPtr::*UnspecifiedBoolType);
     operator UnspecifiedBoolType*() const { return m_value ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
+    
     bool operator!() const { return !m_value; }
+    const DeprecatedPtr& operator=(ExternalType value)
+    {
+        m_value = SlotTypes<T>::convertToBaseType(value);
+        return *this;
+    }
     
-private:
-    JSValue m_value;
+protected:
+    ExternalTypeBase m_value;
 };
 
-template <typename T> struct WriteBarrierCheck {
-    static const bool IsJSValue = false;
+template <typename T> class WriteBarrierTranslator {
+public:
+    typedef JSCell* WriteBarrierStorageType;
+    static WriteBarrierStorageType convertToStorage(T* cell) { return reinterpret_cast<WriteBarrierStorageType>(cell); }
+    static T* convertFromStorage(WriteBarrierStorageType storage) { return reinterpret_cast<T*>(storage); }
 };
 
-template <> struct WriteBarrierCheck<JSValue> {
-    static const bool IsJSValue = true;
-};
+template <> class WriteBarrierTranslator<Unknown>;
 
-template <typename T> class WriteBarrierBase {
+template <typename T> class WriteBarrierBase : public SlotAccessor<DeprecatedPtr<T>, T>, public WriteBarrierTranslator<T> {
 public:
-    COMPILE_ASSERT(!WriteBarrierCheck<T>::IsJSValue, WriteBarrier_JSValue_is_invalid__use_unknown);
-    void set(JSGlobalData&, const JSCell*, T* value) { this->m_cell = reinterpret_cast<JSCell*>(value); }
+    typedef typename SlotTypes<T>::ExternalType ExternalType;
+    typedef typename SlotTypes<T>::ExternalTypeBase ExternalTypeBase;
+    typedef typename WriteBarrierTranslator<T>::WriteBarrierStorageType StorageType;
+
+    void set(JSGlobalData&, const JSCell*, ExternalType value) { this->m_value = WriteBarrierTranslator<T>::convertToStorage(value); }
     
-    T* get() const { return reinterpret_cast<T*>(m_cell); }
-    T* operator*() const { return static_cast<T*>(m_cell); }
-    T* operator->() const { return static_cast<T*>(m_cell); }
-    void clear() { m_cell = 0; }
+    ExternalType get() const { return WriteBarrierTranslator<T>::convertFromStorage(m_value); }
+    void clear() { m_value = 0; }
     
-    JSCell** slot() { return &m_cell; }
+    ExternalTypeBase* slot()
+    {
+        union {
+            StorageType* intype;
+            ExternalTypeBase* outtype;
+        } u;
+        u.intype = &m_value;
+        return u.outtype;
+    }
     
-    typedef T* (WriteBarrierBase::*UnspecifiedBoolType);
-    operator UnspecifiedBoolType*() const { return m_cell ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
+    typedef ExternalType (WriteBarrierBase::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType*() const { return m_value ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
     
-    bool operator!() const { return !m_cell; }
+    bool operator!() const { return !m_value; }
 
-    void setWithoutWriteBarrier(T* value) { this->m_cell = reinterpret_cast<JSCell*>(value); }
+    void setWithoutWriteBarrier(ExternalType value) { this->m_value = WriteBarrierTranslator<T>::convertToStorage(value); }
 
 protected:
-    JSCell* m_cell;
+    StorageType m_value;
 };
 
-template <typename T> class WriteBarrier : public WriteBarrierBase<T> {
+template <> class WriteBarrierTranslator<Unknown> {
 public:
-    WriteBarrier() { this->m_cell = 0; }
-    WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value)
-    {
-        this->set(globalData, owner, value);
-    }
-
+    void setUndefined() { static_cast<WriteBarrierBase<Unknown>*>(this)->setWithoutWriteBarrier(jsUndefined()); }
+    typedef EncodedJSValue WriteBarrierStorageType;
+    static WriteBarrierStorageType convertToStorage(JSValue value) { return JSValue::encode(value); }
+    static JSValue convertFromStorage(WriteBarrierStorageType storage) { return JSValue::decode(storage); }
 };
 
-template <> class WriteBarrierBase<Unknown> {
-public:
-    void set(JSGlobalData&, const JSCell*, JSValue value) { m_value = JSValue::encode(value); }
-    void setWithoutWriteBarrier(JSValue value) { m_value = JSValue::encode(value); }
-    JSValue get() const { return JSValue::decode(m_value); }
-    void clear() { m_value = JSValue::encode(JSValue()); }
-    void setUndefined() { m_value = JSValue::encode(jsUndefined()); }
-    bool isNumber() const { return get().isNumber(); }
-    bool isGetterSetter() const { return get().isGetterSetter(); }
-    
-    JSValue* slot()
-    { 
-        union {
-            EncodedJSValue* v;
-            JSValue* slot;
-        } u;
-        u.v = &m_value;
-        return u.slot;
-    }
-    
-    typedef JSValue (WriteBarrierBase::*UnspecifiedBoolType);
-    operator UnspecifiedBoolType*() const { return get() ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
-    bool operator!() const { return !get(); } 
-    
-protected:
-    EncodedJSValue m_value;
-};
-
-template <> class WriteBarrier<Unknown> : public WriteBarrierBase<Unknown> {
+template <typename T> class WriteBarrier : public WriteBarrierBase<T> {
 public:
-    WriteBarrier() { m_value = JSValue::encode(JSValue()); }
-    WriteBarrier(JSGlobalData& globalData, const JSCell* owner, JSValue value)
+    WriteBarrier() { this->clear(); }
+    WriteBarrier(JSGlobalData& globalData, const JSCell* owner, typename WriteBarrierBase<T>::ExternalType value)
     {
         this->set(globalData, owner, value);
     }
+
 };
 
 template <typename U, typename V> inline bool operator==(const DeprecatedPtr<U>& lhs, const DeprecatedPtr<V>& rhs)
@@ -161,6 +126,8 @@ template <typename U, typename V> inline bool operator==(const WriteBarrierBase<
     return lhs.get() == rhs.get();
 }
 
+COMPILE_ASSERT(sizeof(WriteBarrier<Unknown>) == sizeof(JSValue), WriteBarrier_Unknown_should_be_sizeof_JSValue);
+COMPILE_ASSERT(sizeof(WriteBarrier<JSCell>) == sizeof(JSCell*), WriteBarrier_Unknown_should_be_sizeof_JSCell_pointer);
 }
 
 #endif // WriteBarrier_h