| /* |
| * 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 Handle_h |
| #define Handle_h |
| |
| #include "WriteBarrier.h" |
| #include <wtf/Assertions.h> |
| |
| namespace JSC { |
| |
| /* |
| A Handle is a smart pointer that updates automatically when the garbage |
| collector moves the object to which it points. |
| |
| The base Handle class represents a temporary reference to a pointer whose |
| lifetime is guaranteed by something else. |
| */ |
| |
| template <class T> class Handle; |
| |
| // Creating a JSValue Handle is invalid |
| template <> class Handle<JSValue>; |
| |
| // Forward declare WeakGCMap |
| template<typename KeyType, typename MappedType, typename FinalizerCallback, typename HashArg, typename KeyTraitsArg> class WeakGCMap; |
| |
| class HandleBase { |
| friend class HandleHeap; |
| friend struct JSCallbackObjectData; |
| template <typename KeyType, typename MappedType, typename FinalizerCallback, typename HashArg, typename KeyTraitsArg> friend class WeakGCMap; |
| |
| public: |
| bool operator!() const { return !m_slot || !*m_slot; } |
| |
| // This conversion operator allows implicit conversion to bool but not to other integer types. |
| typedef JSValue (HandleBase::*UnspecifiedBoolType); |
| operator UnspecifiedBoolType*() const { return (m_slot && *m_slot) ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; } |
| |
| protected: |
| HandleBase(HandleSlot slot) |
| : m_slot(slot) |
| { |
| } |
| |
| void swap(HandleBase& other) { std::swap(m_slot, other.m_slot); } |
| |
| HandleSlot slot() const { return m_slot; } |
| void setSlot(HandleSlot slot) |
| { |
| m_slot = slot; |
| } |
| |
| 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->() |
| { |
| #if ENABLE(JSC_ZOMBIES) |
| ASSERT(!static_cast<const Base*>(this)->get() || !static_cast<const Base*>(this)->get()->isZombie()); |
| #endif |
| return static_cast<Base*>(this)->get(); |
| } |
| const T* operator->() const |
| { |
| #if ENABLE(JSC_ZOMBIES) |
| ASSERT(!static_cast<const Base*>(this)->get() || !static_cast<const Base*>(this)->get()->isZombie()); |
| #endif |
| return static_cast<const Base*>(this)->get(); |
| } |
| |
| T* operator*() |
| { |
| #if ENABLE(JSC_ZOMBIES) |
| ASSERT(!static_cast<const Base*>(this)->get() || !static_cast<const Base*>(this)->get()->isZombie()); |
| #endif |
| return static_cast<Base*>(this)->get(); |
| } |
| const T* operator*() const |
| { |
| #if ENABLE(JSC_ZOMBIES) |
| ASSERT(!static_cast<const Base*>(this)->get() || !static_cast<const Base*>(this)->get()->isZombie()); |
| #endif |
| return static_cast<const Base*>(this)->get(); |
| } |
| }; |
| |
| template <typename Base> struct HandleConverter<Base, Unknown> { |
| Handle<JSObject> asObject() const; |
| bool isObject() const { return jsValue().isObject(); } |
| bool getNumber(double number) const { return jsValue().getNumber(number); } |
| UString getString(ExecState*) const; |
| bool isUndefinedOrNull() const { return jsValue().isUndefinedOrNull(); } |
| |
| private: |
| JSValue jsValue() const |
| { |
| #if ENABLE(JSC_ZOMBIES) |
| ASSERT(!static_cast<const Base*>(this)->get() || !static_cast<const Base*>(this)->get().isZombie()); |
| #endif |
| return static_cast<const Base*>(this)->get(); |
| } |
| }; |
| |
| template <typename T> class Handle : public HandleBase, public HandleConverter<Handle<T>, T> { |
| public: |
| template <typename A, typename B> friend class HandleConverter; |
| typedef typename HandleTypes<T>::ExternalType ExternalType; |
| template <typename U> Handle(Handle<U> o) |
| { |
| typename HandleTypes<T>::template validateUpcast<U>(); |
| setSlot(o.slot()); |
| } |
| |
| void swap(Handle& other) { HandleBase::swap(other); } |
| |
| ExternalType get() const { return HandleTypes<T>::getFromSlot(this->slot()); } |
| |
| protected: |
| Handle(HandleSlot slot = 0) |
| : HandleBase(slot) |
| { |
| } |
| |
| private: |
| friend class HandleHeap; |
| |
| static Handle<T> wrapSlot(HandleSlot slot) |
| { |
| return Handle<T>(slot); |
| } |
| }; |
| |
| template <typename Base> Handle<JSObject> HandleConverter<Base, Unknown>::asObject() const |
| { |
| return Handle<JSObject>::wrapSlot(static_cast<const Base*>(this)->slot()); |
| } |
| |
| template <typename T, typename U> inline bool operator==(const Handle<T>& a, const Handle<U>& b) |
| { |
| return a.get() == b.get(); |
| } |
| |
| template <typename T, typename U> inline bool operator==(const Handle<T>& a, U* b) |
| { |
| return a.get() == b; |
| } |
| |
| template <typename T, typename U> inline bool operator==(T* a, const Handle<U>& b) |
| { |
| return a == b.get(); |
| } |
| |
| template <typename T, typename U> inline bool operator!=(const Handle<T>& a, const Handle<U>& b) |
| { |
| return a.get() != b.get(); |
| } |
| |
| template <typename T, typename U> inline bool operator!=(const Handle<T>& a, U* b) |
| { |
| return a.get() != b; |
| } |
| |
| template <typename T, typename U> inline bool operator!=(T* a, const Handle<U>& b) |
| { |
| return a != b.get(); |
| } |
| |
| template <typename T, typename U> inline bool operator!=(const Handle<T>& a, JSValue b) |
| { |
| return a.get() != b; |
| } |
| |
| template <typename T, typename U> inline bool operator!=(JSValue a, const Handle<U>& b) |
| { |
| return a != b.get(); |
| } |
| |
| } |
| |
| #endif |