Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2011 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
     14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
     17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23  * THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef WriteBarrier_h
     27 #define WriteBarrier_h
     28 
     29 #include "JSValue.h"
     30 
     31 namespace JSC {
     32 class JSCell;
     33 class JSGlobalData;
     34 
     35 inline void writeBarrier(JSGlobalData&, const JSCell*, JSValue)
     36 {
     37 }
     38 
     39 inline void writeBarrier(JSGlobalData&, const JSCell*, JSCell*)
     40 {
     41 }
     42 
     43 typedef enum { } Unknown;
     44 typedef JSValue* HandleSlot;
     45 
     46 template <typename T> struct JSValueChecker {
     47     static const bool IsJSValue = false;
     48 };
     49 
     50 template <> struct JSValueChecker<JSValue> {
     51     static const bool IsJSValue = true;
     52 };
     53 
     54 // We have a separate base class with no constructors for use in Unions.
     55 template <typename T> class WriteBarrierBase {
     56 public:
     57     COMPILE_ASSERT(!JSValueChecker<T>::IsJSValue, WriteBarrier_JSValue_is_invalid__use_unknown);
     58     void set(JSGlobalData& globalData, const JSCell* owner, T* value)
     59     {
     60         this->m_cell = reinterpret_cast<JSCell*>(value);
     61         writeBarrier(globalData, owner, this->m_cell);
     62 #if ENABLE(JSC_ZOMBIES)
     63         ASSERT(!isZombie(owner));
     64         ASSERT(!isZombie(m_cell));
     65 #endif
     66     }
     67 
     68     T* get() const
     69     {
     70         return reinterpret_cast<T*>(m_cell);
     71     }
     72 
     73     T* operator*() const
     74     {
     75         ASSERT(m_cell);
     76 #if ENABLE(JSC_ZOMBIES)
     77         ASSERT(!isZombie(m_cell));
     78 #endif
     79         return static_cast<T*>(m_cell);
     80     }
     81 
     82     T* operator->() const
     83     {
     84         ASSERT(m_cell);
     85         return static_cast<T*>(m_cell);
     86     }
     87 
     88     void clear() { m_cell = 0; }
     89 
     90     JSCell** slot() { return &m_cell; }
     91 
     92     typedef T* (WriteBarrierBase::*UnspecifiedBoolType);
     93     operator UnspecifiedBoolType*() const { return m_cell ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
     94 
     95     bool operator!() const { return !m_cell; }
     96 
     97     void setWithoutWriteBarrier(T* value)
     98     {
     99         this->m_cell = reinterpret_cast<JSCell*>(value);
    100 #if ENABLE(JSC_ZOMBIES)
    101         ASSERT(!m_cell || !isZombie(m_cell));
    102 #endif
    103     }
    104 
    105 private:
    106     JSCell* m_cell;
    107 };
    108 
    109 template <> class WriteBarrierBase<Unknown> {
    110 public:
    111     void set(JSGlobalData& globalData, const JSCell* owner, JSValue value)
    112     {
    113 #if ENABLE(JSC_ZOMBIES)
    114         ASSERT(!isZombie(owner));
    115         ASSERT(!value.isZombie());
    116 #endif
    117         m_value = JSValue::encode(value);
    118         writeBarrier(globalData, owner, value);
    119     }
    120     void setWithoutWriteBarrier(JSValue value)
    121     {
    122 #if ENABLE(JSC_ZOMBIES)
    123         ASSERT(!value.isZombie());
    124 #endif
    125         m_value = JSValue::encode(value);
    126     }
    127 
    128     JSValue get() const
    129     {
    130         return JSValue::decode(m_value);
    131     }
    132     void clear() { m_value = JSValue::encode(JSValue()); }
    133     void setUndefined() { m_value = JSValue::encode(jsUndefined()); }
    134     bool isNumber() const { return get().isNumber(); }
    135     bool isObject() const { return get().isObject(); }
    136     bool isNull() const { return get().isNull(); }
    137     bool isGetterSetter() const { return get().isGetterSetter(); }
    138 
    139     JSValue* slot()
    140     {
    141         union {
    142             EncodedJSValue* v;
    143             JSValue* slot;
    144         } u;
    145         u.v = &m_value;
    146         return u.slot;
    147     }
    148 
    149     typedef JSValue (WriteBarrierBase::*UnspecifiedBoolType);
    150     operator UnspecifiedBoolType*() const { return get() ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
    151     bool operator!() const { return !get(); }
    152 
    153 private:
    154     EncodedJSValue m_value;
    155 };
    156 
    157 template <typename T> class WriteBarrier : public WriteBarrierBase<T> {
    158 public:
    159     WriteBarrier()
    160     {
    161         this->setWithoutWriteBarrier(0);
    162     }
    163 
    164     WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value)
    165     {
    166         this->set(globalData, owner, value);
    167     }
    168 };
    169 
    170 template <> class WriteBarrier<Unknown> : public WriteBarrierBase<Unknown> {
    171 public:
    172     WriteBarrier()
    173     {
    174         this->setWithoutWriteBarrier(JSValue());
    175     }
    176 
    177     WriteBarrier(JSGlobalData& globalData, const JSCell* owner, JSValue value)
    178     {
    179         this->set(globalData, owner, value);
    180     }
    181 };
    182 
    183 template <typename U, typename V> inline bool operator==(const WriteBarrierBase<U>& lhs, const WriteBarrierBase<V>& rhs)
    184 {
    185     return lhs.get() == rhs.get();
    186 }
    187 
    188 } // namespace JSC
    189 
    190 #endif // WriteBarrier_h
    191