summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-25 22:39:12 +0000
committerjianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-25 22:39:12 +0000
commit20ecf967af4883293aca18d69889d1f85d279446 (patch)
tree33ef10436c6a81e62d58e5e051dadfc1ea0604d7
parent6e1f48fb52edc5583db8c6deea2f00600bdddb8b (diff)
downloadchromium_src-20ecf967af4883293aca18d69889d1f85d279446.zip
chromium_src-20ecf967af4883293aca18d69889d1f85d279446.tar.gz
chromium_src-20ecf967af4883293aca18d69889d1f85d279446.tar.bz2
Fix the problem that DOM object is deleted in the GC thread, not owning thread.
Review URL: http://codereview.chromium.org/40088 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12507 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--webkit/build/V8Bindings/SConscript1
-rw-r--r--webkit/build/V8Bindings/V8Bindings.vcproj12
-rw-r--r--webkit/port/bindings/v8/DOMObjectsInclude.h181
-rw-r--r--webkit/port/bindings/v8/V8DOMMap.cpp510
-rw-r--r--webkit/port/bindings/v8/V8DOMMap.h58
-rw-r--r--webkit/port/bindings/v8/v8_proxy.cpp419
-rw-r--r--webkit/port/bindings/v8/v8_proxy.h7
-rw-r--r--webkit/webkit.gyp3
8 files changed, 803 insertions, 388 deletions
diff --git a/webkit/build/V8Bindings/SConscript b/webkit/build/V8Bindings/SConscript
index dd6a25a..7835adc 100644
--- a/webkit/build/V8Bindings/SConscript
+++ b/webkit/build/V8Bindings/SConscript
@@ -353,6 +353,7 @@ inputs = [
'$PORT_DIR/bindings/v8/V8NPObject.cpp',
'$PORT_DIR/bindings/v8/v8_proxy.cpp',
'$PORT_DIR/bindings/v8/V8CanvasPixelArrayCustom.cpp',
+ '$PORT_DIR/bindings/v8/V8DOMMap.cpp',
'$PORT_DIR/bindings/v8/V8MessagePortCustom.cpp',
'$PORT_DIR/bindings/v8/V8WorkerContextCustom.cpp',
'$PORT_DIR/bindings/v8/V8WorkerCustom.cpp',
diff --git a/webkit/build/V8Bindings/V8Bindings.vcproj b/webkit/build/V8Bindings/V8Bindings.vcproj
index c5d1326..61f25a1 100644
--- a/webkit/build/V8Bindings/V8Bindings.vcproj
+++ b/webkit/build/V8Bindings/V8Bindings.vcproj
@@ -2813,6 +2813,10 @@
>
</File>
<File
+ RelativePath="..\..\port\bindings\v8\DOMObjectsInclude.h"
+ >
+ </File>
+ <File
RelativePath="..\..\port\bindings\v8\JSDOMBinding.cpp"
>
</File>
@@ -2985,6 +2989,14 @@
>
</File>
<File
+ RelativePath="..\..\port\bindings\v8\V8DOMMap.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\port\bindings\v8\V8DOMMap.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\third_party\WebKit\WebCore\bindings\v8\V8Collection.h"
>
</File>
diff --git a/webkit/port/bindings/v8/DOMObjectsInclude.h b/webkit/port/bindings/v8/DOMObjectsInclude.h
new file mode 100644
index 0000000..7759065
--- /dev/null
+++ b/webkit/port/bindings/v8/DOMObjectsInclude.h
@@ -0,0 +1,181 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DOMObjectsInclude_h
+#define DOMObjectsInclude_h
+
+#include "BarInfo.h"
+#include "CanvasGradient.h"
+#include "CanvasPattern.h"
+#include "CanvasPixelArray.h"
+#include "CanvasRenderingContext2D.h"
+#include "CanvasStyle.h"
+#include "CharacterData.h"
+#include "ClientRect.h"
+#include "ClientRectList.h"
+#include "Clipboard.h"
+#include "Console.h"
+#include "Counter.h"
+#include "CSSCharsetRule.h"
+#include "CSSFontFaceRule.h"
+#include "CSSImportRule.h"
+#include "CSSMediaRule.h"
+#include "CSSPageRule.h"
+#include "CSSRule.h"
+#include "CSSRuleList.h"
+#include "CSSValueList.h"
+#include "CSSStyleRule.h"
+#include "CSSStyleSheet.h"
+#include "CSSVariablesDeclaration.h"
+#include "CSSVariablesRule.h"
+#include "Database.h"
+#include "DocumentType.h"
+#include "DocumentFragment.h"
+#include "DOMCoreException.h"
+#include "DOMImplementation.h"
+#include "DOMParser.h"
+#include "DOMSelection.h"
+#include "DOMStringList.h"
+#include "DOMWindow.h"
+#include "Entity.h"
+#include "EventListener.h"
+#include "EventTarget.h"
+#include "Event.h"
+#include "EventException.h"
+#include "ExceptionCode.h"
+#include "File.h"
+#include "FileList.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "FrameTree.h"
+#include "History.h"
+#include "HTMLNames.h"
+#include "HTMLDocument.h"
+#include "HTMLElement.h"
+#include "HTMLImageElement.h"
+#include "HTMLInputElement.h"
+#include "HTMLSelectElement.h"
+#include "HTMLOptionsCollection.h"
+#include "ImageData.h"
+#include "InspectorController.h"
+#include "KeyboardEvent.h"
+#include "Location.h"
+#include "MediaError.h"
+#include "MediaList.h"
+#include "MediaPlayer.h"
+#include "MessageChannel.h"
+#include "MessageEvent.h"
+#include "MessagePort.h"
+#include "MimeTypeArray.h"
+#include "MouseEvent.h"
+#include "MutationEvent.h"
+#include "Navigator.h" // for MimeTypeArray
+#include "NodeFilter.h"
+#include "Notation.h"
+#include "NodeList.h"
+#include "NodeIterator.h"
+#include "OverflowEvent.h"
+#include "Page.h"
+#include "Plugin.h"
+#include "PluginArray.h"
+#include "ProcessingInstruction.h"
+#include "ProgressEvent.h"
+#include "Range.h"
+#include "RangeException.h"
+#include "Rect.h"
+#include "RGBColor.h"
+#include "Screen.h"
+#include "ScriptExecutionContext.h"
+#include "SecurityOrigin.h"
+#include "Settings.h"
+#include "SQLTransaction.h"
+#include "SQLResultSet.h"
+#include "SQLResultSetRowList.h"
+#include "StyleSheet.h"
+#include "StyleSheetList.h"
+#include "SVGColor.h"
+#include "SVGPaint.h"
+#include "TextEvent.h"
+#include "TextMetrics.h"
+#include "TimeRanges.h"
+#include "TreeWalker.h"
+#include "XSLTProcessor.h"
+#include "V8AbstractEventListener.h"
+#include "V8CustomEventListener.h"
+#include "V8DOMWindow.h"
+#include "V8HTMLElement.h"
+#include "V8LazyEventListener.h"
+#include "V8ObjectEventListener.h"
+#include "WebKitAnimationEvent.h"
+#include "WebKitCSSKeyframeRule.h"
+#include "WebKitCSSKeyframesRule.h"
+#include "WebKitCSSMatrix.h"
+#include "WebKitCSSTransformValue.h"
+#include "WebKitPoint.h"
+#include "WebKitTransitionEvent.h"
+#include "WheelEvent.h"
+#include "XMLHttpRequest.h"
+#include "XMLHttpRequestException.h"
+#include "XMLHttpRequestProgressEvent.h"
+#include "XMLHttpRequestUpload.h"
+#include "XMLSerializer.h"
+#include "XPathException.h"
+#include "XPathExpression.h"
+#include "XPathNSResolver.h"
+#include "XPathResult.h"
+
+#if ENABLE(SVG)
+#include "SVGAngle.h"
+#include "SVGAnimatedPoints.h"
+#include "SVGElement.h"
+#include "SVGElementInstance.h"
+#include "SVGElementInstanceList.h"
+#include "SVGException.h"
+#include "SVGLength.h"
+#include "SVGLengthList.h"
+#include "SVGNumberList.h"
+#include "SVGPathSeg.h"
+#include "SVGPathSegArc.h"
+#include "SVGPathSegClosePath.h"
+#include "SVGPathSegCurvetoCubic.h"
+#include "SVGPathSegCurvetoCubicSmooth.h"
+#include "SVGPathSegCurvetoQuadratic.h"
+#include "SVGPathSegCurvetoQuadraticSmooth.h"
+#include "SVGPathSegLineto.h"
+#include "SVGPathSegLinetoHorizontal.h"
+#include "SVGPathSegLinetoVertical.h"
+#include "SVGPathSegList.h"
+#include "SVGPathSegMoveto.h"
+#include "SVGPointList.h"
+#include "SVGPreserveAspectRatio.h"
+#include "SVGRenderingIntent.h"
+#include "SVGStringList.h"
+#include "SVGTransform.h"
+#include "SVGTransformList.h"
+#include "SVGUnitTypes.h"
+#include "SVGURIReference.h"
+#include "SVGZoomEvent.h"
+#include "V8SVGPODTypeWrapper.h"
+#endif
+
+#if ENABLE(WORKERS)
+#include "Worker.h"
+#include "WorkerContext.h"
+#include "WorkerLocation.h"
+#include "WorkerNavigator.h"
+#endif
+
+#if ENABLE(XPATH)
+#include "XPathEvaluator.h"
+#endif
+
+namespace WebCore {
+
+// A helper class for undetectable document.all
+class UndetectableHTMLCollection : public HTMLCollection {
+};
+
+} // namespace WebCore
+
+#endif // DOMObjectsInclude_h
diff --git a/webkit/port/bindings/v8/V8DOMMap.cpp b/webkit/port/bindings/v8/V8DOMMap.cpp
new file mode 100644
index 0000000..912dad7
--- /dev/null
+++ b/webkit/port/bindings/v8/V8DOMMap.cpp
@@ -0,0 +1,510 @@
+/*
+ * 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 <v8.h>
+
+#include "DOMObjectsInclude.h"
+#include "V8DOMMap.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/MainThread.h>
+#include <wtf/Threading.h>
+#include <wtf/ThreadSpecific.h>
+
+namespace WebCore {
+
+// DOM binding algorithm:
+//
+// There are two kinds of DOM objects:
+// 1. DOM tree nodes, such as Document, HTMLElement, ...
+// there classes implements 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.
+
+static void weakDOMObjectCallback(v8::Persistent<v8::Value> obj, void* param);
+static void weakNodeCallback(v8::Persistent<v8::Value> obj, void* param);
+
+#if ENABLE(SVG)
+static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> obj, void* param);
+
+// SVG non-node elements may have a reference to a context node which should be notified when the element is change
+static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> obj, void* domObj);
+#endif
+
+// This is to ensure that we will deref DOM objects from the owning thread, not the GC thread.
+// The helper function will be scheduled by the GC thread to get called from the owning thread.
+static void derefDelayedObjectsInCurrentThread(void*);
+
+// This should be called to remove all DOM objects associated with the current thread when it is tearing down.
+static void removeAllDOMObjectsInCurrentThread();
+
+// A map from a thread ID to thread's specific data.
+class ThreadSpecificDOMData;
+typedef WTF::HashMap<WTF::ThreadIdentifier, ThreadSpecificDOMData*> DOMThreadMap;
+static DOMThreadMap domThreadMap;
+
+// Mutex to protect against concurrent access of domThreadMap.
+static WTF::Mutex domThreadMapMutex;
+
+class ThreadSpecificDOMData {
+public:
+ enum DOMWrapperMapType
+ {
+ DOMNodeMap,
+ DOMObjectMap,
+ ActiveDOMObjectMap,
+#if ENABLE(SVG)
+ DOMSVGElementInstanceMap,
+ DOMSVGObjectWithContextMap
+#endif
+ };
+
+ typedef WTF::HashMap<void*, V8ClassIndex::V8WrapperType> DelayedObjectMap;
+
+ template <class KeyType>
+ class InternalDOMWrapperMap : public DOMWrapperMap<KeyType> {
+ public:
+ InternalDOMWrapperMap(v8::WeakReferenceCallback callback)
+ : DOMWrapperMap<KeyType>(callback) { }
+
+ virtual void forget(KeyType* obj);
+
+ void forgetOnly(KeyType* obj)
+ {
+ DOMWrapperMap<KeyType>::forget(obj);
+ }
+ };
+
+ ThreadSpecificDOMData()
+ : m_domNodeMap(new InternalDOMWrapperMap<Node>(&weakNodeCallback))
+ , m_domObjectMap(new InternalDOMWrapperMap<void>(weakDOMObjectCallback))
+ , m_activeDomObjectMap(new InternalDOMWrapperMap<void>(weakActiveDOMObjectCallback))
+#if ENABLE(SVG)
+ , m_domSvgElementInstanceMap(new InternalDOMWrapperMap<SVGElementInstance>(weakSVGElementInstanceCallback))
+ , m_domSvgObjectWithContextMap(new InternalDOMWrapperMap<void>(weakSVGObjectWithContextCallback))
+#endif
+ , m_delayedProcessingScheduled(false)
+ , m_isMainThread(WTF::isMainThread())
+ {
+ WTF::MutexLocker locker(domThreadMapMutex);
+ domThreadMap.set(WTF::currentThread(), this);
+ }
+
+ // This is called when WTF thread is tearing down.
+ // We assume that all child threads running V8 instances are created by WTF.
+ ~ThreadSpecificDOMData()
+ {
+ removeAllDOMObjectsInCurrentThread();
+
+ delete m_domNodeMap;
+ delete m_domObjectMap;
+ delete m_activeDomObjectMap;
+#if ENABLE(SVG)
+ delete m_domSvgElementInstanceMap;
+ delete m_domSvgObjectWithContextMap;
+#endif
+
+ WTF::MutexLocker locker(domThreadMapMutex);
+ domThreadMap.remove(WTF::currentThread());
+ }
+
+ void* 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;
+ case DOMSVGObjectWithContextMap:
+ return m_domSvgObjectWithContextMap;
+#endif
+ default:
+ ASSERT(false);
+ return NULL;
+ }
+ }
+
+ InternalDOMWrapperMap<Node>& domNodeMap() { return *m_domNodeMap; }
+ InternalDOMWrapperMap<void>& domObjectMap() { return *m_domObjectMap; }
+ InternalDOMWrapperMap<void>& activeDomObjectMap() { return *m_activeDomObjectMap; }
+#if ENABLE(SVG)
+ InternalDOMWrapperMap<SVGElementInstance>& domSvgElementInstanceMap() { return *m_domSvgElementInstanceMap; }
+ InternalDOMWrapperMap<void>& domSvgObjectWithContextMap() { return *m_domSvgObjectWithContextMap; }
+#endif
+
+ DelayedObjectMap& delayedObjectMap() { return m_delayedObjectMap; }
+ bool delayedProcessingScheduled() const { return m_delayedProcessingScheduled; }
+ void setDelayedProcessingScheduled(bool value) { m_delayedProcessingScheduled = value; }
+ bool isMainThread() const { return m_isMainThread; }
+
+private:
+ InternalDOMWrapperMap<Node>* m_domNodeMap;
+ InternalDOMWrapperMap<void>* m_domObjectMap;
+ InternalDOMWrapperMap<void>* m_activeDomObjectMap;
+#if ENABLE(SVG)
+ InternalDOMWrapperMap<SVGElementInstance>* m_domSvgElementInstanceMap;
+ InternalDOMWrapperMap<void>* m_domSvgObjectWithContextMap;
+#endif
+
+ // Stores all the DOM objects that are delayed to be processed when the owning thread gains control.
+ DelayedObjectMap m_delayedObjectMap;
+
+ // The flag to indicate if the task to do the delayed process has already been posted.
+ bool m_delayedProcessingScheduled;
+
+ bool m_isMainThread;
+};
+
+static WTF::ThreadSpecific<ThreadSpecificDOMData> threadSpecificDOMData;
+
+template<typename T>
+static void handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMWrapperMapType mapType, V8ClassIndex::V8WrapperType objType, T* obj);
+
+template <class KeyType>
+void ThreadSpecificDOMData::InternalDOMWrapperMap<KeyType>::forget(KeyType* obj)
+{
+ DOMWrapperMap<KeyType>::forget(obj);
+
+ ThreadSpecificDOMData::DelayedObjectMap& delayedObjectMap = (*threadSpecificDOMData).delayedObjectMap();
+ delayedObjectMap.take(obj);
+}
+
+DOMWrapperMap<Node>& getDOMNodeMap()
+{
+ return (*threadSpecificDOMData).domNodeMap();
+}
+
+DOMWrapperMap<void>& getDOMObjectMap()
+{
+ return (*threadSpecificDOMData).domObjectMap();
+}
+
+DOMWrapperMap<void>& getActiveDOMObjectMap()
+{
+ return (*threadSpecificDOMData).activeDomObjectMap();
+}
+
+#if ENABLE(SVG)
+DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap()
+{
+ return (*threadSpecificDOMData).domSvgElementInstanceMap();
+}
+
+static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> obj, void* param)
+{
+ SVGElementInstance* instance = static_cast<SVGElementInstance*>(param);
+
+ ThreadSpecificDOMData::InternalDOMWrapperMap<SVGElementInstance>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<SVGElementInstance>&>(getDOMSVGElementInstanceMap());
+ if (map.contains(instance)) {
+ instance->deref();
+ map.forgetOnly(instance);
+ } else {
+ handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMSVGElementInstanceMap, V8ClassIndex::SVGELEMENTINSTANCE, instance);
+ }
+}
+
+// Map of SVG objects with contexts to V8 objects
+DOMWrapperMap<void>& getDOMSVGObjectWithContextMap()
+{
+ return (*threadSpecificDOMData).domSvgObjectWithContextMap();
+}
+
+static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> obj, void* domObj)
+{
+ v8::HandleScope scope;
+ ASSERT(obj->IsObject());
+
+ V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(obj));
+
+ ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<void>&>(getDOMSVGObjectWithContextMap());
+ if (map.contains(domObj)) {
+ // Forget function removes object from the map and dispose the wrapper.
+ map.forgetOnly(domObj);
+
+ switch (type) {
+#define MakeCase(TYPE, NAME) \
+ case V8ClassIndex::TYPE: static_cast<NAME*>(domObj)->deref(); break;
+ SVG_OBJECT_TYPES(MakeCase)
+#undef MakeCase
+#define MakeCase(TYPE, NAME) \
+ case V8ClassIndex::TYPE: \
+ static_cast<V8SVGPODTypeWrapper<NAME>*>(domObj)->deref(); break;
+ SVG_POD_NATIVE_TYPES(MakeCase)
+#undef MakeCase
+ default:
+ ASSERT(false);
+ }
+ } else {
+ handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMSVGObjectWithContextMap, type, domObj);
+ }
+}
+#endif
+
+// Called when the dead object is not in GC thread's map. Go through all thread maps to find the one containing it.
+// Then clear the JS reference and push the DOM object into the delayed queue for it to be deref-ed at later time from the owning thread.
+// * This is called when the GC thread is not the owning thread.
+// * This can be called on any thread that has GC running.
+// * Only one V8 instance is running at a time due to V8::Locker. So we don't need to worry about concurrency.
+template<typename T>
+static void handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMWrapperMapType mapType, V8ClassIndex::V8WrapperType objType, T* obj)
+{
+ WTF::MutexLocker locker(domThreadMapMutex);
+ for (typename DOMThreadMap::iterator iter(domThreadMap.begin()); iter != domThreadMap.end(); ++iter) {
+ WTF::ThreadIdentifier threadID = iter->first;
+ ThreadSpecificDOMData* threadData = iter->second;
+
+ // Skip the current thread that is GC thread.
+ if (threadID == WTF::currentThread()) {
+ ASSERT(!static_cast<DOMWrapperMap<T>*>(threadData->getDOMWrapperMap(mapType))->contains(obj));
+ continue;
+ }
+
+ ThreadSpecificDOMData::InternalDOMWrapperMap<T>* domMap = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<T>*>(threadData->getDOMWrapperMap(mapType));
+ if (domMap->contains(obj)) {
+ // Clear the JS reference.
+ domMap->forgetOnly(obj);
+
+ // Push into the delayed queue.
+ threadData->delayedObjectMap().set(obj, objType);
+
+ // Post a task to the owning thread in order to process the delayed queue.
+ // FIXME(jianli): For now, we can only post to main thread due to WTF task posting limitation. We will fix this when we work on nested worker.
+ if (!threadData->delayedProcessingScheduled()) {
+ threadData->setDelayedProcessingScheduled(true);
+ if (threadData->isMainThread())
+ WTF::callOnMainThread(&derefDelayedObjectsInCurrentThread, NULL);
+ }
+
+ break;
+ }
+ }
+}
+
+// Called when obj is near death (not reachable from JS roots).
+// It is time to remove the entry from the table and dispose the handle.
+static void weakDOMObjectCallback(v8::Persistent<v8::Value> obj, void* domObj)
+{
+ v8::HandleScope scope;
+ ASSERT(obj->IsObject());
+
+ V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(obj));
+
+ ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<void>&>(getDOMObjectMap());
+ if (map.contains(domObj)) {
+ // Forget function removes object from the map and dispose the wrapper.
+ map.forgetOnly(domObj);
+
+ switch (type) {
+#define MakeCase(TYPE, NAME) \
+ case V8ClassIndex::TYPE: static_cast<NAME*>(domObj)->deref(); break;
+ DOM_OBJECT_TYPES(MakeCase)
+#undef MakeCase
+ default:
+ ASSERT(false);
+ }
+ } else {
+ handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMObjectMap, type, domObj);
+ }
+}
+
+void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> obj, void* domObj)
+{
+ v8::HandleScope scope;
+ ASSERT(obj->IsObject());
+
+ V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(obj));
+
+ ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<void>&>(getActiveDOMObjectMap());
+ if (map.contains(domObj)) {
+ // Forget function removes object from the map and dispose the wrapper.
+ map.forgetOnly(domObj);
+
+ switch (type) {
+#define MakeCase(TYPE, NAME) \
+ case V8ClassIndex::TYPE: static_cast<NAME*>(domObj)->deref(); break;
+ ACTIVE_DOM_OBJECT_TYPES(MakeCase)
+#undef MakeCase
+ default:
+ ASSERT(false);
+ }
+ } else {
+ handleWeakObjectInOwningThread(ThreadSpecificDOMData::ActiveDOMObjectMap, type, domObj);
+ }
+}
+
+static void weakNodeCallback(v8::Persistent<v8::Value> obj, void* param)
+{
+ Node* node = static_cast<Node*>(param);
+
+ ThreadSpecificDOMData::InternalDOMWrapperMap<Node>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<Node>&>(getDOMNodeMap());
+ if (map.contains(node)) {
+ map.forgetOnly(node);
+ node->deref();
+ } else {
+ handleWeakObjectInOwningThread<Node>(ThreadSpecificDOMData::DOMNodeMap, V8ClassIndex::NODE, node);
+ }
+}
+
+static void derefObject(V8ClassIndex::V8WrapperType type, void* domObj)
+{
+ switch (type) {
+ case V8ClassIndex::NODE:
+ static_cast<Node*>(domObj)->deref();
+ break;
+
+#define MakeCase(TYPE, NAME) \
+ case V8ClassIndex::TYPE: static_cast<NAME*>(domObj)->deref(); break;
+ DOM_OBJECT_TYPES(MakeCase) // This includes both active and non-active.
+#undef MakeCase
+
+#if ENABLE(SVG)
+#define MakeCase(TYPE, NAME) \
+ case V8ClassIndex::TYPE: static_cast<NAME*>(domObj)->deref(); break;
+ SVG_OBJECT_TYPES(MakeCase) // This also includes SVGElementInstance.
+#undef MakeCase
+
+#define MakeCase(TYPE, NAME) \
+ case V8ClassIndex::TYPE: \
+ static_cast<V8SVGPODTypeWrapper<NAME>*>(domObj)->deref(); break;
+ SVG_POD_NATIVE_TYPES(MakeCase)
+#undef MakeCase
+#endif
+
+ default:
+ ASSERT(false);
+ }
+}
+
+static void derefDelayedObjects()
+{
+ WTF::MutexLocker locker(domThreadMapMutex);
+ ThreadSpecificDOMData::DelayedObjectMap& delayedObjectMap = (*threadSpecificDOMData).delayedObjectMap();
+ for (ThreadSpecificDOMData::DelayedObjectMap::iterator iter(delayedObjectMap.begin()); iter != delayedObjectMap.end(); ++iter) {
+ derefObject(iter->second, iter->first);
+ }
+ delayedObjectMap.clear();
+}
+
+static void derefDelayedObjectsInCurrentThread(void*)
+{
+ (*threadSpecificDOMData).setDelayedProcessingScheduled(false);
+ derefDelayedObjects();
+}
+
+template<typename T>
+static void removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap)
+{
+ for (typename WTF::HashMap<T*, v8::Object*>::iterator iter(domMap.impl().begin()); iter != domMap.impl().end(); ++iter) {
+ T* domObj = static_cast<T*>(iter->first);
+ v8::Persistent<v8::Object> obj(iter->second);
+
+ V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(obj));
+
+ // Deref the DOM object.
+ derefObject(type, domObj);
+
+ // Clear the JS wrapper.
+ obj.Dispose();
+ }
+ domMap.impl().clear();
+}
+
+static void removeAllDOMObjectsInCurrentThread()
+{
+ v8::Locker locker;
+ v8::HandleScope scope;
+
+ // Deref all objects in the delayed queue.
+ derefDelayedObjects();
+
+ // Remove all DOM nodes.
+ removeObjectsFromWrapperMap<Node>(getDOMNodeMap());
+
+ // Remove all DOM objects in the wrapper map.
+ removeObjectsFromWrapperMap<void>(getDOMObjectMap());
+
+ // Remove all active DOM objects in the wrapper map.
+ removeObjectsFromWrapperMap<void>(getActiveDOMObjectMap());
+
+#if ENABLE(SVG)
+ // Remove all SVG element instances in the wrapper map.
+ removeObjectsFromWrapperMap<SVGElementInstance>(getDOMSVGElementInstanceMap());
+
+ // Remove all SVG objects with context in the wrapper map.
+ removeObjectsFromWrapperMap<void>(getDOMSVGObjectWithContextMap());
+#endif
+}
+
+} // namespace WebCore
diff --git a/webkit/port/bindings/v8/V8DOMMap.h b/webkit/port/bindings/v8/V8DOMMap.h
new file mode 100644
index 0000000..835f064
--- /dev/null
+++ b/webkit/port/bindings/v8/V8DOMMap.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#ifndef V8DOMMap_h
+#define V8DOMMap_h
+
+#include "dom_wrapper_map.h"
+
+namespace WebCore {
+ // Callback when JS wrapper of active DOM object is dead.
+ void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> obj, void* domObj);
+
+ // A map from DOM node to its JS wrapper.
+ DOMWrapperMap<Node>& getDOMNodeMap();
+
+ // A map from a DOM object (non-node) to its JS wrapper. This map does not contain the DOM objects which can have pending activity (active dom objects).
+ DOMWrapperMap<void>& getDOMObjectMap();
+
+ // A map from a DOM object to its JS wrapper for DOM objects which can have pending activity.
+ DOMWrapperMap<void>& getActiveDOMObjectMap();
+
+#if ENABLE(SVG)
+ // A map for SVGElementInstances to its JS wrapper.
+ DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap();
+
+ // Map of SVG objects with contexts to V8 objects
+ DOMWrapperMap<void>& getDOMSVGObjectWithContextMap();
+#endif
+} // namespace WebCore
+
+#endif // V8DOMMap_h
diff --git a/webkit/port/bindings/v8/v8_proxy.cpp b/webkit/port/bindings/v8/v8_proxy.cpp
index ca00058..3f9e4da 100644
--- a/webkit/port/bindings/v8/v8_proxy.cpp
+++ b/webkit/port/bindings/v8/v8_proxy.cpp
@@ -36,7 +36,6 @@
#include <v8-debug.h>
#include "v8_proxy.h"
-#include "dom_wrapper_map.h"
#include "v8_index.h"
#include "v8_binding.h"
#include "v8_custom.h"
@@ -45,206 +44,12 @@
#include "V8DOMWindow.h"
#include "ChromiumBridge.h"
-
-#include "BarInfo.h"
-#include "CanvasGradient.h"
-#include "CanvasPattern.h"
-#include "CanvasPixelArray.h"
-#include "CanvasRenderingContext2D.h"
-#include "CanvasStyle.h"
-#include "CharacterData.h"
-#include "ClientRect.h"
-#include "ClientRectList.h"
-#include "Clipboard.h"
-#include "Console.h"
-#include "Counter.h"
-#include "CSSCharsetRule.h"
-#include "CSSFontFaceRule.h"
-#include "CSSImportRule.h"
-#include "CSSMediaRule.h"
-#include "CSSPageRule.h"
-#include "CSSRule.h"
-#include "CSSRuleList.h"
-#include "CSSValueList.h"
-#include "CSSStyleRule.h"
-#include "CSSStyleSheet.h"
-#include "CSSVariablesDeclaration.h"
-#include "CSSVariablesRule.h"
-#include "Database.h"
-#include "DocumentType.h"
-#include "DocumentFragment.h"
-#include "DOMCoreException.h"
-#include "DOMImplementation.h"
-#include "DOMParser.h"
-#include "DOMSelection.h"
-#include "DOMStringList.h"
-#include "DOMWindow.h"
-#include "Entity.h"
-#include "EventListener.h"
-#include "EventTarget.h"
-#include "Event.h"
-#include "EventException.h"
-#include "ExceptionCode.h"
-#include "File.h"
-#include "FileList.h"
-#include "Frame.h"
-#include "FrameLoader.h"
-#include "FrameTree.h"
-#include "History.h"
-#include "HTMLNames.h"
-#include "HTMLDocument.h"
-#include "HTMLElement.h"
-#include "HTMLImageElement.h"
-#include "HTMLInputElement.h"
-#include "HTMLSelectElement.h"
-#include "HTMLOptionsCollection.h"
-#include "ImageData.h"
-#include "InspectorController.h"
-#include "KeyboardEvent.h"
-#include "Location.h"
-#include "MediaError.h"
-#include "MediaList.h"
-#include "MediaPlayer.h"
-#include "MessageChannel.h"
-#include "MessageEvent.h"
-#include "MessagePort.h"
-#include "MimeTypeArray.h"
-#include "MouseEvent.h"
-#include "MutationEvent.h"
-#include "Navigator.h" // for MimeTypeArray
-#include "NodeFilter.h"
-#include "Notation.h"
-#include "NodeList.h"
-#include "NodeIterator.h"
-#include "OverflowEvent.h"
-#include "Page.h"
-#include "Plugin.h"
-#include "PluginArray.h"
-#include "ProcessingInstruction.h"
-#include "ProgressEvent.h"
-#include "Range.h"
-#include "RangeException.h"
-#include "Rect.h"
-#include "RGBColor.h"
-#include "Screen.h"
-#include "ScriptExecutionContext.h"
-#include "SecurityOrigin.h"
-#include "Settings.h"
-#include "SQLTransaction.h"
-#include "SQLResultSet.h"
-#include "SQLResultSetRowList.h"
-#include "StyleSheet.h"
-#include "StyleSheetList.h"
-#include "SVGColor.h"
-#include "SVGPaint.h"
-#include "TextEvent.h"
-#include "TextMetrics.h"
-#include "TimeRanges.h"
-#include "TreeWalker.h"
-#include "XSLTProcessor.h"
-#include "V8AbstractEventListener.h"
-#include "V8CustomEventListener.h"
-#include "V8DOMWindow.h"
-#include "V8HTMLElement.h"
-#include "V8LazyEventListener.h"
-#include "V8ObjectEventListener.h"
-#include "WebKitAnimationEvent.h"
-#include "WebKitCSSKeyframeRule.h"
-#include "WebKitCSSKeyframesRule.h"
-#include "WebKitCSSMatrix.h"
-#include "WebKitCSSTransformValue.h"
-#include "WebKitPoint.h"
-#include "WebKitTransitionEvent.h"
-#include "WheelEvent.h"
-#include "XMLHttpRequest.h"
-#include "XMLHttpRequestException.h"
-#include "XMLHttpRequestProgressEvent.h"
-#include "XMLHttpRequestUpload.h"
-#include "XMLSerializer.h"
-#include "XPathException.h"
-#include "XPathExpression.h"
-#include "XPathNSResolver.h"
-#include "XPathResult.h"
-
+#include "DOMObjectsInclude.h"
#include "ScriptController.h"
-#if ENABLE(SVG)
-#include "SVGAngle.h"
-#include "SVGAnimatedPoints.h"
-#include "SVGElement.h"
-#include "SVGElementInstance.h"
-#include "SVGElementInstanceList.h"
-#include "SVGException.h"
-#include "SVGLength.h"
-#include "SVGLengthList.h"
-#include "SVGNumberList.h"
-#include "SVGPathSeg.h"
-#include "SVGPathSegArc.h"
-#include "SVGPathSegClosePath.h"
-#include "SVGPathSegCurvetoCubic.h"
-#include "SVGPathSegCurvetoCubicSmooth.h"
-#include "SVGPathSegCurvetoQuadratic.h"
-#include "SVGPathSegCurvetoQuadraticSmooth.h"
-#include "SVGPathSegLineto.h"
-#include "SVGPathSegLinetoHorizontal.h"
-#include "SVGPathSegLinetoVertical.h"
-#include "SVGPathSegList.h"
-#include "SVGPathSegMoveto.h"
-#include "SVGPointList.h"
-#include "SVGPreserveAspectRatio.h"
-#include "SVGRenderingIntent.h"
-#include "SVGStringList.h"
-#include "SVGTransform.h"
-#include "SVGTransformList.h"
-#include "SVGUnitTypes.h"
-#include "SVGURIReference.h"
-#include "SVGZoomEvent.h"
-#include "V8SVGPODTypeWrapper.h"
-#endif // SVG
-
-#if ENABLE(WORKERS)
-#include "Worker.h"
-#include "WorkerContext.h"
-#include "WorkerLocation.h"
-#include "WorkerNavigator.h"
-#endif // WORKERS
-
-#if ENABLE(XPATH)
-#include "XPathEvaluator.h"
-#endif
-
-
namespace WebCore {
-
-// DOM binding algorithm:
-//
-// There are two kinds of DOM objects:
-// 1. DOM tree nodes, such as Document, HTMLElement, ...
-// there classes implements 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.
-
-
// Static utility context.
v8::Persistent<v8::Context> V8Proxy::m_utilityContext;
@@ -252,10 +57,6 @@ v8::Persistent<v8::Context> V8Proxy::m_utilityContext;
V8ExtensionList V8Proxy::m_extensions;
-// A helper class for undetectable document.all
-class UndetectableHTMLCollection : public HTMLCollection {
-};
-
#ifndef NDEBUG
// Keeps track of global handles created (not JS wrappers
// of DOM objects). Often these global handles are source
@@ -385,66 +186,14 @@ static void EnumerateDOMNodeMap(DOMNodeMap& node_map)
}
#endif // NDEBUG
-static void WeakDOMObjectCallback(v8::Persistent<v8::Value> obj, void* para);
-static void WeakActiveDOMObjectCallback(v8::Persistent<v8::Value> obj,
- void* para);
-static void WeakNodeCallback(v8::Persistent<v8::Value> obj, void* para);
-// A map from DOM node to its JS wrapper.
-static DOMWrapperMap<Node>& GetDOMNodeMap()
-{
- static DOMWrapperMap<Node> static_dom_node_map(&WeakNodeCallback);
- return static_dom_node_map;
-}
-
-
-// A map from a DOM object (non-node) to its JS wrapper. This map does not
-// contain the DOM objects which can have pending activity (active dom objects).
-DOMWrapperMap<void>& GetDOMObjectMap()
-{
- static DOMWrapperMap<void>
- static_dom_object_map(&WeakDOMObjectCallback);
- return static_dom_object_map;
-}
-
-
-// A map from a DOM object to its JS wrapper for DOM objects which
-// can have pending activity.
-static DOMWrapperMap<void>& GetActiveDOMObjectMap()
-{
- static DOMWrapperMap<void>
- static_active_dom_object_map(&WeakActiveDOMObjectCallback);
- return static_active_dom_object_map;
-}
-
#if ENABLE(SVG)
-static void WeakSVGElementInstanceCallback(v8::Persistent<v8::Value> obj,
- void* param);
-
-// A map for SVGElementInstances.
-static DOMWrapperMap<SVGElementInstance>& dom_svg_element_instance_map()
-{
- static DOMWrapperMap<SVGElementInstance>
- static_dom_svg_element_instance_map(&WeakSVGElementInstanceCallback);
- return static_dom_svg_element_instance_map;
-}
-
-static void WeakSVGElementInstanceCallback(v8::Persistent<v8::Value> obj,
- void* param)
-{
- SVGElementInstance* instance = static_cast<SVGElementInstance*>(param);
- ASSERT(dom_svg_element_instance_map().contains(instance));
-
- instance->deref();
- dom_svg_element_instance_map().forget(instance);
-}
-
v8::Handle<v8::Value> V8Proxy::SVGElementInstanceToV8Object(
SVGElementInstance* instance)
{
if (!instance)
return v8::Null();
- v8::Handle<v8::Object> existing_instance = dom_svg_element_instance_map().get(instance);
+ v8::Handle<v8::Object> existing_instance = getDOMSVGElementInstanceMap().get(instance);
if (!existing_instance.IsEmpty())
return existing_instance;
@@ -457,32 +206,12 @@ v8::Handle<v8::Value> V8Proxy::SVGElementInstanceToV8Object(
instance);
if (!result.IsEmpty()) {
// Only update the DOM SVG element map if the result is non-empty.
- dom_svg_element_instance_map().set(instance,
+ getDOMSVGElementInstanceMap().set(instance,
v8::Persistent<v8::Object>::New(result));
}
return result;
}
-
-// SVG non-node elements may have a reference to a context node which
-// should be notified when the element is change
-static void WeakSVGObjectWithContext(v8::Persistent<v8::Value> obj,
- void* dom_obj);
-
-// Map of SVG objects with contexts to V8 objects
-static DOMWrapperMap<void>& dom_svg_object_with_context_map() {
- static DOMWrapperMap<void>
- static_dom_svg_object_with_context_map(&WeakSVGObjectWithContext);
- return static_dom_svg_object_with_context_map;
-}
-
-// Map of SVG objects with contexts to their contexts
-static HashMap<void*, SVGElement*>& svg_object_to_context_map()
-{
- static HashMap<void*, SVGElement*> static_svg_object_to_context_map;
- return static_svg_object_to_context_map;
-}
-
v8::Handle<v8::Value> V8Proxy::SVGObjectWithContextToV8Object(
V8ClassIndex::V8WrapperType type, void* object)
{
@@ -490,7 +219,7 @@ v8::Handle<v8::Value> V8Proxy::SVGObjectWithContextToV8Object(
return v8::Null();
v8::Persistent<v8::Object> result =
- dom_svg_object_with_context_map().get(object);
+ getDOMSVGObjectWithContextMap().get(object);
if (!result.IsEmpty()) return result;
// Special case: SVGPathSegs need to be downcast to their real type
@@ -513,38 +242,16 @@ SVG_POD_NATIVE_TYPES(MAKE_CASE)
default:
ASSERT(false);
}
- dom_svg_object_with_context_map().set(object, result);
+ getDOMSVGObjectWithContextMap().set(object, result);
}
return result;
}
-static void WeakSVGObjectWithContext(v8::Persistent<v8::Value> obj,
- void* dom_obj)
-{
- v8::HandleScope handle_scope;
- ASSERT(dom_svg_object_with_context_map().contains(dom_obj));
- ASSERT(obj->IsObject());
-
- // Forget function removes object from the map and dispose the wrapper.
- dom_svg_object_with_context_map().forget(dom_obj);
-
- V8ClassIndex::V8WrapperType type =
- V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(obj));
-
- switch (type) {
-#define MAKE_CASE(TYPE, NAME) \
- case V8ClassIndex::TYPE: static_cast<NAME*>(dom_obj)->deref(); break;
-SVG_OBJECT_TYPES(MAKE_CASE)
-#undef MAKE_CASE
-#define MAKE_CASE(TYPE, NAME) \
- case V8ClassIndex::TYPE: \
- static_cast<V8SVGPODTypeWrapper<NAME>*>(dom_obj)->deref(); break;
-SVG_POD_NATIVE_TYPES(MAKE_CASE)
-#undef MAKE_CASE
- default:
- ASSERT(false);
- }
+// Map of SVG objects with contexts to their contexts
+static HashMap<void*, SVGElement*>& svg_object_to_context_map() {
+ static HashMap<void*, SVGElement*> static_svg_object_to_context_map;
+ return static_svg_object_to_context_map;
}
void V8Proxy::SetSVGContext(void* obj, SVGElement* context)
@@ -567,66 +274,8 @@ SVGElement* V8Proxy::GetSVGContext(void* obj)
{
return svg_object_to_context_map().get(obj);
}
-
#endif
-// Called when obj is near death (not reachable from JS roots)
-// It is time to remove the entry from the table and dispose
-// the handle.
-static void WeakDOMObjectCallback(v8::Persistent<v8::Value> obj,
- void* dom_obj) {
- v8::HandleScope scope;
- ASSERT(GetDOMObjectMap().contains(dom_obj));
- ASSERT(obj->IsObject());
-
- // Forget function removes object from the map and dispose the wrapper.
- GetDOMObjectMap().forget(dom_obj);
-
- V8ClassIndex::V8WrapperType type =
- V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(obj));
- switch (type) {
-#define MAKE_CASE(TYPE, NAME) \
- case V8ClassIndex::TYPE: static_cast<NAME*>(dom_obj)->deref(); break;
- DOM_OBJECT_TYPES(MAKE_CASE)
-#undef MAKE_CASE
- default:
- ASSERT(false);
- }
-}
-
-
-static void WeakActiveDOMObjectCallback(v8::Persistent<v8::Value> obj,
- void* dom_obj)
-{
- v8::HandleScope scope;
- ASSERT(GetActiveDOMObjectMap().contains(dom_obj));
- ASSERT(obj->IsObject());
-
- // Forget function removes object from the map and dispose the wrapper.
- GetActiveDOMObjectMap().forget(dom_obj);
-
- V8ClassIndex::V8WrapperType type =
- V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(obj));
- switch (type) {
-#define MAKE_CASE(TYPE, NAME) \
- case V8ClassIndex::TYPE: static_cast<NAME*>(dom_obj)->deref(); break;
- ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE)
-#undef MAKE_CASE
- default:
- ASSERT(false);
- }
-}
-
-static void WeakNodeCallback(v8::Persistent<v8::Value> obj, void* param)
-{
- Node* node = static_cast<Node*>(param);
- ASSERT(GetDOMNodeMap().contains(node));
-
- GetDOMNodeMap().forget(node);
- node->deref();
-}
-
-
// A map from a DOM node to its JS wrapper, the wrapper
// is kept as a strong reference to survive GCs.
static DOMObjectMap& gc_protected_map() {
@@ -641,11 +290,11 @@ void V8Proxy::GCProtect(void* dom_object)
return;
if (gc_protected_map().contains(dom_object))
return;
- if (!GetDOMObjectMap().contains(dom_object))
+ if (!getDOMObjectMap().contains(dom_object))
return;
// Create a new (strong) persistent handle for the object.
- v8::Persistent<v8::Object> wrapper = GetDOMObjectMap().get(dom_object);
+ v8::Persistent<v8::Object> wrapper = getDOMObjectMap().get(dom_object);
if (wrapper.IsEmpty()) return;
gc_protected_map().set(dom_object, *v8::Persistent<v8::Object>::New(wrapper));
@@ -672,12 +321,12 @@ static void GCPrologue()
v8::HandleScope scope;
#ifndef NDEBUG
- EnumerateDOMObjectMap(GetDOMObjectMap().impl());
+ EnumerateDOMObjectMap(getDOMObjectMap().impl());
#endif
// Run through all objects with possible pending activity making their
// wrappers non weak if there is pending activity.
- DOMObjectMap active_map = GetActiveDOMObjectMap().impl();
+ DOMObjectMap active_map = getActiveDOMObjectMap().impl();
for (DOMObjectMap::iterator it = active_map.begin(), end = active_map.end();
it != end; ++it) {
void* obj = it->first;
@@ -740,7 +389,7 @@ ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE)
typedef std::pair<uintptr_t, Node*> GrouperPair;
typedef Vector<GrouperPair> GrouperList;
- DOMNodeMap node_map = GetDOMNodeMap().impl();
+ DOMNodeMap node_map = getDOMNodeMap().impl();
GrouperList grouper;
grouper.reserveCapacity(node_map.size());
@@ -806,7 +455,7 @@ ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE)
group.reserveCapacity(next_key_index - i);
for (; i < next_key_index; ++i) {
v8::Persistent<v8::Value> wrapper =
- GetDOMNodeMap().get(grouper[i].second);
+ getDOMNodeMap().get(grouper[i].second);
if (!wrapper.IsEmpty())
group.append(wrapper);
}
@@ -825,7 +474,7 @@ static void GCEpilogue()
// Run through all objects with pending activity making their wrappers weak
// again.
- DOMObjectMap active_map = GetActiveDOMObjectMap().impl();
+ DOMObjectMap active_map = getActiveDOMObjectMap().impl();
for (DOMObjectMap::iterator it = active_map.begin(), end = active_map.end();
it != end; ++it) {
void* obj = it->first;
@@ -837,7 +486,7 @@ static void GCEpilogue()
NAME* impl = static_cast<NAME*>(obj); \
if (impl->hasPendingActivity()) { \
ASSERT(!wrapper.IsWeak()); \
- wrapper.MakeWeak(impl, &WeakActiveDOMObjectCallback); \
+ wrapper.MakeWeak(impl, &weakActiveDOMObjectCallback); \
} \
break; \
}
@@ -850,8 +499,8 @@ ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE)
#ifndef NDEBUG
// Check all survivals are weak.
- EnumerateDOMObjectMap(GetDOMObjectMap().impl());
- EnumerateDOMNodeMap(GetDOMNodeMap().impl());
+ EnumerateDOMObjectMap(getDOMObjectMap().impl());
+ EnumerateDOMNodeMap(getDOMNodeMap().impl());
EnumerateDOMObjectMap(gc_protected_map());
EnumerateGlobalHandles();
#undef USE_VAR
@@ -1113,8 +762,8 @@ void V8Proxy::DestroyGlobal()
bool V8Proxy::DOMObjectHasJSWrapper(void* obj) {
- return GetDOMObjectMap().contains(obj) ||
- GetActiveDOMObjectMap().contains(obj);
+ return getDOMObjectMap().contains(obj) ||
+ getActiveDOMObjectMap().contains(obj);
}
@@ -1132,7 +781,7 @@ ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE)
default: break;
}
#endif
- GetDOMObjectMap().set(obj, wrapper);
+ getDOMObjectMap().set(obj, wrapper);
}
// The caller must have increased obj's ref count.
@@ -1148,14 +797,14 @@ ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE)
#undef MAKE_CASE
}
#endif
- GetActiveDOMObjectMap().set(obj, wrapper);
+ getActiveDOMObjectMap().set(obj, wrapper);
}
// The caller must have increased node's ref count.
void V8Proxy::SetJSWrapperForDOMNode(Node* node, v8::Persistent<v8::Object> wrapper)
{
ASSERT(MaybeDOMWrapper(wrapper));
- GetDOMNodeMap().set(node, wrapper);
+ getDOMNodeMap().set(node, wrapper);
}
PassRefPtr<EventListener> V8Proxy::createInlineEventListener(
@@ -2632,8 +2281,8 @@ v8::Handle<v8::Value> V8Proxy::ToV8Object(V8ClassIndex::V8WrapperType type, void
// Non DOM node
v8::Persistent<v8::Object> result = is_active_dom_object ?
- GetActiveDOMObjectMap().get(imp) :
- GetDOMObjectMap().get(imp);
+ getActiveDOMObjectMap().get(imp) :
+ getDOMObjectMap().get(imp);
if (result.IsEmpty()) {
v8::Local<v8::Object> v8obj = InstantiateV8Object(type, type, imp);
if (!v8obj.IsEmpty()) {
@@ -3103,7 +2752,7 @@ v8::Handle<v8::Value> V8Proxy::EventToV8Object(Event* event)
if (!event)
return v8::Null();
- v8::Handle<v8::Object> wrapper = GetDOMObjectMap().get(event);
+ v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(event);
if (!wrapper.IsEmpty())
return wrapper;
@@ -3162,7 +2811,7 @@ v8::Handle<v8::Value> V8Proxy::NodeToV8Object(Node* node)
{
if (!node) return v8::Null();
- v8::Handle<v8::Object> wrapper = GetDOMNodeMap().get(node);
+ v8::Handle<v8::Object> wrapper = getDOMNodeMap().get(node);
if (!wrapper.IsEmpty())
return wrapper;
@@ -3308,7 +2957,7 @@ v8::Handle<v8::Value> V8Proxy::EventTargetToV8Object(EventTarget* target)
// XMLHttpRequest is created within its JS counterpart.
XMLHttpRequest* xhr = target->toXMLHttpRequest();
if (xhr) {
- v8::Handle<v8::Object> wrapper = GetActiveDOMObjectMap().get(xhr);
+ v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(xhr);
ASSERT(!wrapper.IsEmpty());
return wrapper;
}
@@ -3316,14 +2965,14 @@ v8::Handle<v8::Value> V8Proxy::EventTargetToV8Object(EventTarget* target)
// MessagePort is created within its JS counterpart
MessagePort* port = target->toMessagePort();
if (port) {
- v8::Handle<v8::Object> wrapper = GetActiveDOMObjectMap().get(port);
+ v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(port);
ASSERT(!wrapper.IsEmpty());
return wrapper;
}
XMLHttpRequestUpload* upload = target->toXMLHttpRequestUpload();
if (upload) {
- v8::Handle<v8::Object> wrapper = GetDOMObjectMap().get(upload);
+ v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(upload);
ASSERT(!wrapper.IsEmpty());
return wrapper;
}
@@ -3365,7 +3014,7 @@ v8::Handle<v8::Value> V8Proxy::StyleSheetToV8Object(StyleSheet* sheet)
{
if (!sheet) return v8::Null();
- v8::Handle<v8::Object> wrapper = GetDOMObjectMap().get(sheet);
+ v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(sheet);
if (!wrapper.IsEmpty())
return wrapper;
@@ -3397,7 +3046,7 @@ v8::Handle<v8::Value> V8Proxy::CSSValueToV8Object(CSSValue* value)
{
if (!value) return v8::Null();
- v8::Handle<v8::Object> wrapper = GetDOMObjectMap().get(value);
+ v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(value);
if (!wrapper.IsEmpty())
return wrapper;
@@ -3434,7 +3083,7 @@ v8::Handle<v8::Value> V8Proxy::CSSRuleToV8Object(CSSRule* rule)
{
if (!rule) return v8::Null();
- v8::Handle<v8::Object> wrapper = GetDOMObjectMap().get(rule);
+ v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(rule);
if (!wrapper.IsEmpty())
return wrapper;
diff --git a/webkit/port/bindings/v8/v8_proxy.h b/webkit/port/bindings/v8/v8_proxy.h
index e403751..017293e 100644
--- a/webkit/port/bindings/v8/v8_proxy.h
+++ b/webkit/port/bindings/v8/v8_proxy.h
@@ -6,7 +6,6 @@
#define V8_PROXY_H__
#include <v8.h>
-#include "dom_wrapper_map.h"
#include "v8_index.h"
#include "v8_custom.h"
#include "v8_utility.h"
@@ -16,6 +15,7 @@
#include "PlatformString.h" // for WebCore::String
#include "ScriptSourceCode.h" // for WebCore::ScriptSourceCode
#include "SecurityOrigin.h" // for WebCore::SecurityOrigin
+#include "V8DOMMap.h"
#include <wtf/Assertions.h>
#include <wtf/PassRefPtr.h> // so generated bindings don't have to
#include <wtf/Vector.h>
@@ -29,6 +29,9 @@
#define INC_STATS(name)
#endif
+// FIXME: Remove the following hack when we replace all references to GetDOMObjectMap.
+#define GetDOMObjectMap getDOMObjectMap
+
namespace WebCore {
class CSSStyleDeclaration;
@@ -144,8 +147,6 @@ void BatchConfigureConstants(v8::Handle<v8::FunctionTemplate> desc,
const BatchedConstant* consts,
size_t num_consts);
-DOMWrapperMap<void>& GetDOMObjectMap();
-
const int kMaxRecursionDepth = 20;
// Information about an extension that is registered for use with V8. If scheme
diff --git a/webkit/webkit.gyp b/webkit/webkit.gyp
index 76c84b5..77a431a 100644
--- a/webkit/webkit.gyp
+++ b/webkit/webkit.gyp
@@ -1056,6 +1056,7 @@
'extensions/v8/playback_extension.h',
'extensions/v8/profiler_extension.cc',
'extensions/v8/profiler_extension.h',
+ 'port/bindings/v8/DOMObjectsInclude.h',
'port/bindings/v8/JSDOMBinding.cpp',
'port/bindings/v8/JSDOMBinding.h',
'port/bindings/v8/JSXPathNSResolver.cpp',
@@ -1065,6 +1066,8 @@
'port/bindings/v8/ScriptController.cpp',
'port/bindings/v8/ScriptController.h',
'port/bindings/v8/V8CanvasPixelArrayCustom.cpp',
+ 'port/bindings/v8/V8DOMMap.cpp',
+ 'port/bindings/v8/V8DOMMap.h',
'port/bindings/v8/V8MessagePortCustom.cpp',
'port/bindings/v8/V8SVGPODTypeWrapper.h',
'port/bindings/v8/V8WorkerContextCustom.cpp',