/*
 * Copyright (C) 2009 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER OR 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.
 */

#include "config.h"
#include "DOMDataStore.h"

#include "DOMData.h"

namespace WebCore {

// DOM binding algorithm:
//
// There are two kinds of DOM objects:
// 1. DOM tree nodes, such as Document, HTMLElement, ...
//    there classes implement TreeShared<T> interface;
// 2. Non-node DOM objects, such as CSSRule, Location, etc.
//    these classes implement a ref-counted scheme.
//
// A DOM object may have a JS wrapper object. If a tree node
// is alive, its JS wrapper must be kept alive even it is not
// reachable from JS roots.
// However, JS wrappers of non-node objects can go away if
// not reachable from other JS objects. It works like a cache.
//
// DOM objects are ref-counted, and JS objects are traced from
// a set of root objects. They can create a cycle. To break
// cycles, we do following:
//   Handles from DOM objects to JS wrappers are always weak,
// so JS wrappers of non-node object cannot create a cycle.
//   Before starting a global GC, we create a virtual connection
// between nodes in the same tree in the JS heap. If the wrapper
// of one node in a tree is alive, wrappers of all nodes in
// the same tree are considered alive. This is done by creating
// object groups in GC prologue callbacks. The mark-compact
// collector will remove these groups after each GC.
//
// DOM objects should be deref-ed from the owning thread, not the GC thread
// that does not own them. In V8, GC can kick in from any thread. To ensure
// that DOM objects are always deref-ed from the owning thread when running
// V8 in multi-threading environment, we do following:
// 1. Maintain a thread specific DOM wrapper map for each object map.
//    (We're using TLS support from WTF instead of base since V8Bindings
//     does not depend on base. We further assume that all child threads
//     running V8 instances are created by WTF and thus a destructor will
//     be called to clean up all thread specific data.)
// 2. When GC happens:
//    2.1. If the dead object is in GC thread's map, remove the JS reference
//         and deref the DOM object.
//    2.2. Otherwise, go through all thread maps to find the owning thread.
//         Remove the JS reference from the owning thread's map and move the
//         DOM object to a delayed queue. Post a task to the owning thread
//         to have it deref-ed from the owning thread at later time.
// 3. When a thread is tearing down, invoke a cleanup routine to go through
//    all objects in the delayed queue and the thread map and deref all of
//    them.


DOMDataStore::DOMDataStore(DOMData* domData)
    : m_domNodeMap(0)
    , m_domObjectMap(0)
    , m_activeDomObjectMap(0)
#if ENABLE(SVG)
    , m_domSvgElementInstanceMap(0)
#endif
    , m_domData(domData)
{
    WTF::MutexLocker locker(DOMDataStore::allStoresMutex());
    DOMDataStore::allStores().append(this);
}

DOMDataStore::~DOMDataStore()
{
    WTF::MutexLocker locker(DOMDataStore::allStoresMutex());
    DOMDataStore::allStores().remove(DOMDataStore::allStores().find(this));
}

DOMDataList& DOMDataStore::allStores()
{
  DEFINE_STATIC_LOCAL(DOMDataList, staticDOMDataList, ());
  return staticDOMDataList;
}

WTF::Mutex& DOMDataStore::allStoresMutex()
{
    DEFINE_STATIC_LOCAL(WTF::Mutex, staticDOMDataListMutex, ());
    return staticDOMDataListMutex;
}

void* DOMDataStore::getDOMWrapperMap(DOMWrapperMapType type)
{
    switch (type) {
    case DOMNodeMap:
        return m_domNodeMap;
    case DOMObjectMap:
        return m_domObjectMap;
    case ActiveDOMObjectMap:
        return m_activeDomObjectMap;
#if ENABLE(SVG)
    case DOMSVGElementInstanceMap:
        return m_domSvgElementInstanceMap;
#endif
    }

    ASSERT_NOT_REACHED();
    return 0;
}

// Called when the object is near death (not reachable from JS roots).
// It is time to remove the entry from the table and dispose the handle.
void DOMDataStore::weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject)
{
    v8::HandleScope scope;
    ASSERT(v8Object->IsObject());
    DOMData::handleWeakObject(DOMDataStore::DOMObjectMap, v8::Persistent<v8::Object>::Cast(v8Object), domObject);
}

void DOMDataStore::weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject)
{
    v8::HandleScope scope;
    ASSERT(v8Object->IsObject());
    DOMData::handleWeakObject(DOMDataStore::ActiveDOMObjectMap, v8::Persistent<v8::Object>::Cast(v8Object), domObject);
}

void DOMDataStore::weakNodeCallback(v8::Persistent<v8::Value> value, void* domObject)
{
    ASSERT(WTF::isMainThread());

    Node* node = static_cast<Node*>(domObject);
    // Node wrappers must be JS objects.
    v8::Persistent<v8::Object> v8Object = v8::Persistent<v8::Object>::Cast(value);

    WTF::MutexLocker locker(DOMDataStore::allStoresMutex());
    DOMDataList& list = DOMDataStore::allStores();
    for (size_t i = 0; i < list.size(); ++i) {
        DOMDataStore* store = list[i];
        if (store->domNodeMap().removeIfPresent(node, v8Object)) {
            ASSERT(store->domData()->owningThread() == WTF::currentThread());
            node->deref(); // Nobody overrides Node::deref so it's safe
            return; // There might be at most one wrapper for the node in world's maps
        }
    }

    // If not found, it means map for the wrapper has been already destroyed, just dispose the
    // handle and deref the object to fight memory leak.
    v8Object.Dispose();
    node->deref(); // Nobody overrides Node::deref so it's safe
}

#if ENABLE(SVG)

void DOMDataStore::weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject)
{
    v8::HandleScope scope;
    ASSERT(v8Object->IsObject());
    DOMData::handleWeakObject(DOMDataStore::DOMSVGElementInstanceMap, v8::Persistent<v8::Object>::Cast(v8Object), static_cast<SVGElementInstance*>(domObject));
}

#endif  // ENABLE(SVG)

} // namespace WebCore
