/* * 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 Global_h #define Global_h #include "Assertions.h" #include "Handle.h" #include "HandleHeap.h" #include "JSGlobalData.h" namespace JSC { /* A Global is a persistent handle whose lifetime is not limited to any given scope. Use Globals for data members and global variables. */ template class Global : public Handle { public: typedef typename Handle::ExternalType ExternalType; Global(JSGlobalData& globalData, ExternalType ptr = ExternalType()) : Handle(globalData.allocateGlobalHandle()) { internalSet(ptr); } Global(JSGlobalData& globalData, Handle handle) : Handle(globalData.allocateGlobalHandle()) { internalSet(handle.get()); } enum EmptyValueTag { EmptyValue }; Global(EmptyValueTag) : Handle(0, HandleBase::DontNullCheckSlot) { } ~Global() { HandleSlot slot = this->slot(); if (slot) HandleHeap::heapFor(slot)->deallocate(slot); } void set(JSGlobalData& globalData, ExternalType value) { if (!value) { clear(); return; } if (!this->slot()) this->setSlot(globalData.allocateGlobalHandle()); internalSet(value); } template Global& operator=(const Global& handle) { if (handle.slot()) { if (!this->slot()) this->setSlot(HandleHeap::heapFor(handle.slot())->allocate()); internalSet(handle.get()); } else clear(); return *this; } Global& operator=(const Global& handle) { if (handle.slot()) { if (!this->slot()) this->setSlot(HandleHeap::heapFor(handle.slot())->allocate()); internalSet(handle.get()); } else clear(); return *this; } void clear() { if (this->slot()) internalSet(ExternalType()); } enum HashTableDeletedValueType { HashTableDeletedValue }; const static intptr_t HashTableDeletedValueTag = 0x1; Global(HashTableDeletedValueType) : Handle(reinterpret_cast(HashTableDeletedValueTag)) { } bool isHashTableDeletedValue() const { return slot() == reinterpret_cast(HashTableDeletedValueTag); } template Global(const Global& other) : Handle(other.slot() ? HandleHeap::heapFor(other.slot())->allocate() : 0, Handle::DontNullCheckSlot) { if (other.slot()) internalSet(other.get()); } Global(const Global& other) : Handle(other.slot() ? HandleHeap::heapFor(other.slot())->allocate() : 0, Handle::DontNullCheckSlot) { if (other.slot()) internalSet(other.get()); } protected: void internalSet(ExternalType value) { JSValue newValue(HandleTypes::toJSValue(value)); HandleSlot slot = this->slot(); ASSERT(slot); HandleHeap::heapFor(slot)->writeBarrier(slot, newValue); *slot = newValue; } using Handle::slot; }; } namespace WTF { template struct HashTraits > : GenericHashTraits > { static const bool emptyValueIsZero = true; static JSC::Global

emptyValue() { return JSC::Global

(JSC::Global

::EmptyValue); } static void constructDeletedValue(JSC::Global

& slot) { new (&slot) JSC::Global

(JSC::Global

::HashTableDeletedValue); } static bool isDeletedValue(const JSC::Global

& value) { return value.isHashTableDeletedValue(); } }; } #endif // Global_h