| Differences between
and this patch
- WebCore/ChangeLog +62 lines
Lines 1-3 WebCore/ChangeLog_sec1
1
2009-06-22  Adam Barth  <abarth@webkit.org>
2
3
        Reviewed by NOBODY (OOPS!).
4
5
        Refactor V8DOMMap to support isolated worlds.
6
7
        * bindings/v8/ScriptController.cpp:
8
        (WebCore::ScriptController::evaluateInNewWorld):
9
        * bindings/v8/ScriptController.h:
10
        * bindings/v8/V8DOMMap.cpp:
11
        (WebCore::DOMDataStore::InternalDOMWrapperMap::InternalDOMWrapperMap):
12
        (WebCore::DOMDataStore::allStores):
13
        (WebCore::DOMDataStore::allStoresMutex):
14
        (WebCore::DOMDataStore::domData):
15
        (WebCore::ScopedDOMDataStore::ScopedDOMDataStore):
16
        (WebCore::ScopedDOMDataStore::~ScopedDOMDataStore):
17
        (WebCore::StaticDOMDataStore::StaticDOMDataStore):
18
        (WebCore::):
19
        (WebCore::MainThreadDOMData::MainThreadDOMData):
20
        (WebCore::MainThreadDOMData::getStore):
21
        (WebCore::ChildThreadDOMData::ChildThreadDOMData):
22
        (WebCore::ChildThreadDOMData::getStore):
23
        (WebCore::DOMDataStore::DOMDataStore):
24
        (WebCore::DOMDataStore::~DOMDataStore):
25
        (WebCore::DOMDataStoreHandle::DOMDataStoreHandle):
26
        (WebCore::DOMDataStoreHandle::~DOMDataStoreHandle):
27
        (WebCore::::forget):
28
        (WebCore::getDOMNodeMap):
29
        (WebCore::getDOMObjectMap):
30
        (WebCore::getActiveDOMObjectMap):
31
        (WebCore::getDOMSVGElementInstanceMap):
32
        (WebCore::getDOMSVGObjectWithContextMap):
33
        (WebCore::DOMData::getCurrent):
34
        (WebCore::DOMData::handleWeakObject):
35
        (WebCore::DOMData::ensureDeref):
36
        (WebCore::weakDOMObjectCallback):
37
        (WebCore::weakActiveDOMObjectCallback):
38
        (WebCore::weakNodeCallback):
39
        (WebCore::weakSVGElementInstanceCallback):
40
        (WebCore::weakSVGObjectWithContextCallback):
41
        (WebCore::DOMData::derefObject):
42
        (WebCore::DOMData::derefDelayedObjects):
43
        (WebCore::DOMData::derefDelayedObjectsInCurrentThread):
44
        (WebCore::DOMData::removeObjectsFromWrapperMap):
45
        (WebCore::removeAllDOMObjectsInCurrentThreadHelper):
46
        (WebCore::visitDOMNodesInCurrentThread):
47
        (WebCore::visitDOMObjectsInCurrentThread):
48
        (WebCore::visitActiveDOMObjectsInCurrentThread):
49
        (WebCore::visitDOMSVGElementInstancesInCurrentThread):
50
        (WebCore::visitSVGObjectsInCurrentThread):
51
        * bindings/v8/V8DOMMap.h:
52
        (WebCore::DOMDataStoreHandle::getStore):
53
        * bindings/v8/V8IsolatedWorld.cpp: Added.
54
        (WebCore::getIsolatedWorldKey):
55
        (WebCore::contextWeakReferenceCallback):
56
        (WebCore::V8IsolatedWorld::evaluate):
57
        (WebCore::V8IsolatedWorld::V8IsolatedWorld):
58
        (WebCore::V8IsolatedWorld::~V8IsolatedWorld):
59
        (WebCore::V8IsolatedWorld::getEntered):
60
        * bindings/v8/V8IsolatedWorld.h: Added.
61
        (WebCore::V8IsolatedWorld::getDOMDataStore):
62
1
2009-06-21  Darin Adler  <darin@apple.com>
63
2009-06-21  Darin Adler  <darin@apple.com>
2
64
3
        Reviewed by Sam Weinig.
65
        Reviewed by Sam Weinig.
- WebCore/bindings/v8/ScriptController.cpp +5 lines
Lines 180-185 bool ScriptController::processingUserGes WebCore/bindings/v8/ScriptController.cpp_sec1
180
    return false;
180
    return false;
181
}
181
}
182
182
183
void ScriptController::evaluateInNewWorld(const Vector<ScriptSourceCode>& sources)
184
{
185
    m_proxy->evaluateInNewWorld(sources);
186
}
187
183
void ScriptController::evaluateInNewContext(const Vector<ScriptSourceCode>& sources)
188
void ScriptController::evaluateInNewContext(const Vector<ScriptSourceCode>& sources)
184
{
189
{
185
    m_proxy->evaluateInNewContext(sources);
190
    m_proxy->evaluateInNewContext(sources);
- WebCore/bindings/v8/ScriptController.h +6 lines
Lines 65-70 namespace WebCore { WebCore/bindings/v8/ScriptController.h_sec1
65
        // as a string.
65
        // as a string.
66
        ScriptValue evaluate(const ScriptSourceCode&);
66
        ScriptValue evaluate(const ScriptSourceCode&);
67
67
68
        // Executes JavaScript in a new world associated with the web frame. The
69
        // script gets its own global scope, its own prototypes for intrinsic
70
        // JavaScript objects (String, Array, and so-on), and its own wrappers for
71
        // all DOM nodes and DOM constructors.
72
        void evaluateInNewWorld(const Vector<ScriptSourceCode>&);
73
68
        // Executes JavaScript in a new context associated with the web frame. The
74
        // Executes JavaScript in a new context associated with the web frame. The
69
        // script gets its own global scope and its own prototypes for intrinsic
75
        // script gets its own global scope and its own prototypes for intrinsic
70
        // JavaScript objects (String, Array, and so-on). It shares the wrappers for
76
        // JavaScript objects (String, Array, and so-on). It shares the wrappers for
- WebCore/bindings/v8/V8DOMMap.cpp -212 / +359 lines
Lines 34-39 WebCore/bindings/v8/V8DOMMap.cpp_sec1
34
#include "DOMObjectsInclude.h"
34
#include "DOMObjectsInclude.h"
35
35
36
#include <v8.h>
36
#include <v8.h>
37
37
#include <wtf/HashMap.h>
38
#include <wtf/HashMap.h>
38
#include <wtf/MainThread.h>
39
#include <wtf/MainThread.h>
39
#include <wtf/Noncopyable.h>
40
#include <wtf/Noncopyable.h>
Lines 42-47 WebCore/bindings/v8/V8DOMMap.cpp_sec2
42
#include <wtf/ThreadSpecific.h>
43
#include <wtf/ThreadSpecific.h>
43
#include <wtf/Vector.h>
44
#include <wtf/Vector.h>
44
45
46
#include "V8IsolatedWorld.h"
47
45
namespace WebCore {
48
namespace WebCore {
46
49
47
// DOM binding algorithm:
50
// DOM binding algorithm:
Lines 90-127 namespace WebCore { WebCore/bindings/v8/V8DOMMap.cpp_sec3
90
//    all objects in the delayed queue and the thread map and deref all of
93
//    all objects in the delayed queue and the thread map and deref all of
91
//    them.
94
//    them.
92
95
93
static void weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
94
static void weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
96
static void weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
95
97
static void weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
98
void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
96
#if ENABLE(SVG)
99
#if ENABLE(SVG)
97
static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
100
static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
98
99
// SVG non-node elements may have a reference to a context node which should be notified when the element is change.
101
// SVG non-node elements may have a reference to a context node which should be notified when the element is change.
100
static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
102
static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
101
#endif
103
#endif
102
104
103
// This is to ensure that we will deref DOM objects from the owning thread, not the GC thread.
105
class DOMData;
104
// The helper function will be scheduled by the GC thread to get called from the owning thread.
106
class DOMDataStore;
105
static void derefDelayedObjectsInCurrentThread(void*);
107
typedef WTF::Vector<DOMDataStore*> DOMDataList;
106
108
107
// A list of all ThreadSpecific DOM Data objects. Traversed during GC to find a thread-specific map that
109
// DOMDataStore
108
// contains the object - so we can schedule the object to be deleted on the thread which created it.
110
//
109
class ThreadSpecificDOMData;
111
// DOMDataStore is the backing store that holds the maps between DOM objects
110
typedef WTF::Vector<ThreadSpecificDOMData*> DOMDataList;
112
// and JavaScript objects.  In general, each thread can have multiple backing
111
static DOMDataList& domDataList()
113
// stores, one per isolated world.
112
{
114
//
113
    DEFINE_STATIC_LOCAL(DOMDataList, staticDOMDataList, ());
115
// This class doesn't manage the lifetime of the store.  The data store
114
    return staticDOMDataList;
116
// lifetime is managed by subclasses.
115
}
117
//
116
118
class DOMDataStore : Noncopyable {
117
// Mutex to protect against concurrent access of DOMDataList.
118
static WTF::Mutex& domDataListMutex()
119
{
120
    DEFINE_STATIC_LOCAL(WTF::Mutex, staticDOMDataListMutex, ());
121
    return staticDOMDataListMutex;
122
}
123
124
class ThreadSpecificDOMData : Noncopyable {
125
public:
119
public:
126
    enum DOMWrapperMapType {
120
    enum DOMWrapperMapType {
127
        DOMNodeMap,
121
        DOMNodeMap,
Lines 133-145 public: WebCore/bindings/v8/V8DOMMap.cpp_sec4
133
#endif
127
#endif
134
    };
128
    };
135
129
136
    typedef WTF::HashMap<void*, V8ClassIndex::V8WrapperType> DelayedObjectMap;
137
138
    template <class KeyType>
130
    template <class KeyType>
139
    class InternalDOMWrapperMap : public DOMWrapperMap<KeyType> {
131
    class InternalDOMWrapperMap : public DOMWrapperMap<KeyType> {
140
    public:
132
    public:
141
        InternalDOMWrapperMap(v8::WeakReferenceCallback callback)
133
        InternalDOMWrapperMap(DOMData* domData, v8::WeakReferenceCallback callback)
142
            : DOMWrapperMap<KeyType>(callback) { }
134
            : DOMWrapperMap<KeyType>(callback)
135
            , m_domData(domData) { }
143
136
144
        virtual void forget(KeyType*);
137
        virtual void forget(KeyType*);
145
138
Lines 147-175 public: WebCore/bindings/v8/V8DOMMap.cpp_sec5
147
        {
140
        {
148
            DOMWrapperMap<KeyType>::forget(object);
141
            DOMWrapperMap<KeyType>::forget(object);
149
        }
142
        }
143
144
    private:
145
        DOMData* m_domData;
150
    };
146
    };
151
147
152
    ThreadSpecificDOMData()
148
    // A list of all DOMDataStore objects.  Traversed during GC to find a thread-specific map that
153
        : m_domNodeMap(0)
149
    // contains the object - so we can schedule the object to be deleted on the thread which created it.
154
        , m_domObjectMap(0)
150
    static DOMDataList& allStores()
155
        , m_activeDomObjectMap(0)
156
#if ENABLE(SVG)
157
        , m_domSvgElementInstanceMap(0)
158
        , m_domSvgObjectWithContextMap(0)
159
#endif
160
        , m_delayedProcessingScheduled(false)
161
        , m_isMainThread(WTF::isMainThread())
162
    {
151
    {
163
        WTF::MutexLocker locker(domDataListMutex());
152
        DEFINE_STATIC_LOCAL(DOMDataList, staticDOMDataList, ());
164
        domDataList().append(this);
153
        return staticDOMDataList;
165
    }
154
    }
166
155
167
    virtual ~ThreadSpecificDOMData()
156
    // Mutex to protect against concurrent access of DOMDataList.
157
    static WTF::Mutex& allStoresMutex()
168
    {
158
    {
169
        WTF::MutexLocker locker(domDataListMutex());
159
        DEFINE_STATIC_LOCAL(WTF::Mutex, staticDOMDataListMutex, ());
170
        domDataList().remove(domDataList().find(this));
160
        return staticDOMDataListMutex;
171
    }
161
    }
172
162
163
    DOMDataStore(DOMData* domData);
164
    virtual ~DOMDataStore();
165
166
    DOMData* domData() const { return m_domData; }
167
173
    void* getDOMWrapperMap(DOMWrapperMapType type)
168
    void* getDOMWrapperMap(DOMWrapperMapType type)
174
    {
169
    {
175
        switch (type) {
170
        switch (type) {
Lines 199-209 public: WebCore/bindings/v8/V8DOMMap.cpp_sec6
199
    InternalDOMWrapperMap<void>& domSvgObjectWithContextMap() { return *m_domSvgObjectWithContextMap; }
194
    InternalDOMWrapperMap<void>& domSvgObjectWithContextMap() { return *m_domSvgObjectWithContextMap; }
200
#endif
195
#endif
201
196
202
    DelayedObjectMap& delayedObjectMap() { return m_delayedObjectMap; }
203
    bool delayedProcessingScheduled() const { return m_delayedProcessingScheduled; }
204
    void setDelayedProcessingScheduled(bool value) { m_delayedProcessingScheduled = value; }
205
    bool isMainThread() const { return m_isMainThread; }
206
207
protected:
197
protected:
208
    InternalDOMWrapperMap<Node>* m_domNodeMap;
198
    InternalDOMWrapperMap<Node>* m_domNodeMap;
209
    InternalDOMWrapperMap<void>* m_domObjectMap;
199
    InternalDOMWrapperMap<void>* m_domObjectMap;
Lines 213-244 protected: WebCore/bindings/v8/V8DOMMap.cpp_sec7
213
    InternalDOMWrapperMap<void>* m_domSvgObjectWithContextMap;
203
    InternalDOMWrapperMap<void>* m_domSvgObjectWithContextMap;
214
#endif
204
#endif
215
205
216
    // Stores all the DOM objects that are delayed to be processed when the owning thread gains control.
206
private:
217
    DelayedObjectMap m_delayedObjectMap;
207
    // A back-pointer to the DOMData to which we belong.
218
208
    DOMData* m_domData;
219
    // The flag to indicate if the task to do the delayed process has already been posted.
220
    bool m_delayedProcessingScheduled;
221
222
    bool m_isMainThread;
223
};
209
};
224
210
225
// This encapsulates thread-specific DOM data for non-main thread. All the maps in it are created dynamically.
211
// ScopedDOMDataStore
226
class NonMainThreadSpecificDOMData : public ThreadSpecificDOMData {
212
//
213
// ScopedDOMDataStore is a DOMDataStore that controls limits the lifetime of
214
// the store to the lifetime of the object itself.  In other words, when the
215
// ScopedDOMDataStore object is deallocated, the maps that belong to the store
216
// are deallocated as well.
217
//
218
class ScopedDOMDataStore : public DOMDataStore {
227
public:
219
public:
228
    NonMainThreadSpecificDOMData()
220
    ScopedDOMDataStore(DOMData* domData) : DOMDataStore(domData)
229
    {
221
    {
230
        m_domNodeMap = new InternalDOMWrapperMap<Node>(&weakNodeCallback);
222
        m_domNodeMap = new InternalDOMWrapperMap<Node>(domData, weakNodeCallback);
231
        m_domObjectMap = new InternalDOMWrapperMap<void>(weakDOMObjectCallback);
223
        m_domObjectMap = new InternalDOMWrapperMap<void>(domData, weakDOMObjectCallback);
232
        m_activeDomObjectMap = new InternalDOMWrapperMap<void>(weakActiveDOMObjectCallback);
224
        m_activeDomObjectMap = new InternalDOMWrapperMap<void>(domData, weakActiveDOMObjectCallback);
233
#if ENABLE(SVG)
225
#if ENABLE(SVG)
234
        m_domSvgElementInstanceMap = new InternalDOMWrapperMap<SVGElementInstance>(weakSVGElementInstanceCallback);
226
        m_domSvgElementInstanceMap = new InternalDOMWrapperMap<SVGElementInstance>(domData, weakSVGElementInstanceCallback);
235
        m_domSvgObjectWithContextMap = new InternalDOMWrapperMap<void>(weakSVGObjectWithContextCallback);
227
        m_domSvgObjectWithContextMap = new InternalDOMWrapperMap<void>(domData, weakSVGObjectWithContextCallback);
236
#endif
228
#endif
237
    }
229
    }
238
230
239
    // This is called when WTF thread is tearing down.
231
    // This can be called when WTF thread is tearing down.
240
    // We assume that all child threads running V8 instances are created by WTF.
232
    // We assume that all child threads running V8 instances are created by WTF.
241
    virtual ~NonMainThreadSpecificDOMData()
233
    virtual ~ScopedDOMDataStore()
242
    {
234
    {
243
        delete m_domNodeMap;
235
        delete m_domNodeMap;
244
        delete m_domObjectMap;
236
        delete m_domObjectMap;
Lines 250-267 public: WebCore/bindings/v8/V8DOMMap.cpp_sec8
250
    }
242
    }
251
};
243
};
252
244
253
// This encapsulates thread-specific DOM data for the main thread. All the maps in it are static.
245
// StaticDOMDataStore
254
// This is because we are unable to rely on WTF::ThreadSpecificThreadExit to do the cleanup since
246
//
255
// the place that tears down the main thread can not call any WTF functions.
247
// StaticDOMDataStore is a DOMDataStore that manages the lifetime of the store
256
class MainThreadSpecificDOMData : public ThreadSpecificDOMData {
248
// statically.  This encapsulates thread-specific DOM data for the main
249
// thread.  All the maps in it are static.  This is because we are unable to
250
// rely on WTF::ThreadSpecificThreadExit to do the cleanup since the place that
251
// tears down the main thread can not call any WTF functions.
252
class StaticDOMDataStore : public DOMDataStore {
257
public:
253
public:
258
    MainThreadSpecificDOMData()
254
    StaticDOMDataStore(DOMData* domData)
259
        : m_staticDomNodeMap(weakNodeCallback)
255
        : DOMDataStore(domData)
260
        , m_staticDomObjectMap(weakDOMObjectCallback)
256
        , m_staticDomNodeMap(domData, weakNodeCallback)
261
        , m_staticActiveDomObjectMap(weakActiveDOMObjectCallback)
257
        , m_staticDomObjectMap(domData, weakDOMObjectCallback)
258
        , m_staticActiveDomObjectMap(domData, weakActiveDOMObjectCallback)
262
#if ENABLE(SVG)
259
#if ENABLE(SVG)
263
        , m_staticDomSvgElementInstanceMap(weakSVGElementInstanceCallback)
260
        , m_staticDomSvgElementInstanceMap(domData, weakSVGElementInstanceCallback)
264
        , m_staticDomSvgObjectWithContextMap(weakSVGObjectWithContextCallback)
261
        , m_staticDomSvgObjectWithContextMap(domData, weakSVGObjectWithContextCallback)
265
#endif
262
#endif
266
    {
263
    {
267
        m_domNodeMap = &m_staticDomNodeMap;
264
        m_domNodeMap = &m_staticDomNodeMap;
Lines 281-378 private: WebCore/bindings/v8/V8DOMMap.cpp_sec9
281
    InternalDOMWrapperMap<void> m_staticDomSvgObjectWithContextMap;
278
    InternalDOMWrapperMap<void> m_staticDomSvgObjectWithContextMap;
282
};
279
};
283
280
284
DEFINE_STATIC_LOCAL(WTF::ThreadSpecific<NonMainThreadSpecificDOMData>, threadSpecificDOMData, ());
281
typedef WTF::Vector<DOMDataStore*> DOMDataStoreList;
285
282
286
template<typename T>
283
// DOMData
287
static void handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMWrapperMapType mapType, V8ClassIndex::V8WrapperType objectType, T*);
284
//
285
// DOMData represents the all the DOM wrappers for a given thread.  In
286
// particular, DOMData holds wrappers for all the isolated worlds in the
287
// thread.  The DOMData for the main thread and the DOMData for child threads
288
// use different subclasses.
289
//
290
class DOMData: Noncopyable {
291
public:
292
    DOMData()
293
        : m_delayedProcessingScheduled(false)
294
        , m_isMainThread(WTF::isMainThread())
295
        , m_owningThread(WTF::currentThread())
296
    {
297
    }
288
298
289
ThreadSpecificDOMData& getThreadSpecificDOMData()
299
    static DOMData* getCurrent();
290
{
300
    virtual DOMDataStore& getStore() = 0;
291
    if (WTF::isMainThread()) {
301
292
        DEFINE_STATIC_LOCAL(MainThreadSpecificDOMData, mainThreadSpecificDOMData, ());
302
    template<typename T>
293
        return mainThreadSpecificDOMData;
303
    static void handleWeakObject(DOMDataStore::DOMWrapperMapType mapType, v8::Handle<v8::Object> v8Object, T* domObject);
304
305
    void forgetDelayedObject(void* object) { m_delayedObjectMap.take(object); }
306
307
    // This is to ensure that we will deref DOM objects from the owning thread,
308
    // not the GC thread.  The helper function will be scheduled by the GC
309
    // thread to get called from the owning thread.
310
    static void derefDelayedObjectsInCurrentThread(void*);
311
    void derefDelayedObjects();
312
313
    template<typename T>
314
    static void removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap);
315
316
    ThreadIdentifier owningThread() const { return m_owningThread; }
317
318
private:
319
    typedef WTF::HashMap<void*, V8ClassIndex::V8WrapperType> DelayedObjectMap;
320
321
    void ensureDeref(V8ClassIndex::V8WrapperType type, void* domObject);
322
    static void derefObject(V8ClassIndex::V8WrapperType type, void* domObject);
323
324
    // Stores all the DOM objects that are delayed to be processed when the owning thread gains control.
325
    DelayedObjectMap m_delayedObjectMap;
326
327
    // The flag to indicate if the task to do the delayed process has already been posted.
328
    bool m_delayedProcessingScheduled;
329
330
    bool m_isMainThread;
331
    ThreadIdentifier m_owningThread;
332
};
333
334
class MainThreadDOMData : public DOMData {
335
public:
336
    MainThreadDOMData() : m_defaultStore(this) { }
337
338
    DOMDataStore& getStore()
339
    {
340
        ASSERT(WTF::isMainThread());
341
        V8IsolatedWorld* world = V8IsolatedWorld::getEntered();
342
        if (world)
343
            return *world->getDOMDataStore();
344
        return m_defaultStore;
345
    }
346
347
private:
348
    StaticDOMDataStore m_defaultStore;
349
    // Note: The DOMDataStores for isolated world are owned by the world object.
350
};
351
352
class ChildThreadDOMData : public DOMData {
353
public:
354
    ChildThreadDOMData() : m_defaultStore(this) { }
355
356
    DOMDataStore& getStore() {
357
        ASSERT(!WTF::isMainThread());
358
        // Currently, child threads have only one world.
359
        return m_defaultStore;
294
    }
360
    }
295
    return *threadSpecificDOMData;
361
362
private:
363
    ScopedDOMDataStore m_defaultStore;
364
};
365
366
DOMDataStore::DOMDataStore(DOMData* domData)
367
    : m_domNodeMap(0)
368
    , m_domObjectMap(0)
369
    , m_activeDomObjectMap(0)
370
#if ENABLE(SVG)
371
    , m_domSvgElementInstanceMap(0)
372
    , m_domSvgObjectWithContextMap(0)
373
#endif
374
    , m_domData(domData)
375
{
376
    WTF::MutexLocker locker(DOMDataStore::allStoresMutex());
377
    DOMDataStore::allStores().append(this);
378
}
379
380
DOMDataStore::~DOMDataStore()
381
{
382
    WTF::MutexLocker locker(DOMDataStore::allStoresMutex());
383
    DOMDataStore::allStores().remove(DOMDataStore::allStores().find(this));
384
}
385
386
DOMDataStoreHandle::DOMDataStoreHandle()
387
    : m_store(new ScopedDOMDataStore(DOMData::getCurrent()))
388
{
389
}
390
391
DOMDataStoreHandle::~DOMDataStoreHandle()
392
{
296
}
393
}
297
394
298
template <class KeyType>
395
template <class KeyType>
299
void ThreadSpecificDOMData::InternalDOMWrapperMap<KeyType>::forget(KeyType* object)
396
void DOMDataStore::InternalDOMWrapperMap<KeyType>::forget(KeyType* object)
300
{
397
{
301
    DOMWrapperMap<KeyType>::forget(object);
398
    DOMWrapperMap<KeyType>::forget(object);
302
399
    m_domData->forgetDelayedObject(object);
303
    ThreadSpecificDOMData::DelayedObjectMap& delayedObjectMap = getThreadSpecificDOMData().delayedObjectMap();
304
    delayedObjectMap.take(object);
305
}
400
}
306
401
307
DOMWrapperMap<Node>& getDOMNodeMap()
402
DOMWrapperMap<Node>& getDOMNodeMap()
308
{
403
{
309
    return getThreadSpecificDOMData().domNodeMap();
404
    return DOMData::getCurrent()->getStore().domNodeMap();
310
}
405
}
311
406
312
DOMWrapperMap<void>& getDOMObjectMap()
407
DOMWrapperMap<void>& getDOMObjectMap()
313
{
408
{
314
    return getThreadSpecificDOMData().domObjectMap();
409
    return DOMData::getCurrent()->getStore().domObjectMap();
315
}
410
}
316
411
317
DOMWrapperMap<void>& getActiveDOMObjectMap()
412
DOMWrapperMap<void>& getActiveDOMObjectMap()
318
{
413
{
319
    return getThreadSpecificDOMData().activeDomObjectMap();
414
    return DOMData::getCurrent()->getStore().activeDomObjectMap();
320
}
415
}
321
416
322
#if ENABLE(SVG)
417
#if ENABLE(SVG)
323
DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap()
324
{
325
    return getThreadSpecificDOMData().domSvgElementInstanceMap();
326
}
327
418
328
static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject)
419
DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap()
329
{
420
{
330
    SVGElementInstance* instance = static_cast<SVGElementInstance*>(domObject);
421
    return DOMData::getCurrent()->getStore().domSvgElementInstanceMap();
331
332
    ThreadSpecificDOMData::InternalDOMWrapperMap<SVGElementInstance>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<SVGElementInstance>&>(getDOMSVGElementInstanceMap());
333
    if (map.contains(instance)) {
334
        instance->deref();
335
        map.forgetOnly(instance);
336
    } else
337
        handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMSVGElementInstanceMap, V8ClassIndex::SVGELEMENTINSTANCE, instance);
338
}
422
}
339
423
340
// Map of SVG objects with contexts to V8 objects
424
// Map of SVG objects with contexts to V8 objects
341
DOMWrapperMap<void>& getDOMSVGObjectWithContextMap()
425
DOMWrapperMap<void>& getDOMSVGObjectWithContextMap()
342
{
426
{
343
    return getThreadSpecificDOMData().domSvgObjectWithContextMap();
427
    return DOMData::getCurrent()->getStore().domSvgObjectWithContextMap();
344
}
428
}
345
429
346
static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject)
430
#endif // ENABLE(SVG)
347
{
348
    v8::HandleScope scope;
349
    ASSERT(v8Object->IsObject());
350
351
    V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(v8Object));
352
353
    ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<void>&>(getDOMSVGObjectWithContextMap());
354
    if (map.contains(domObject)) {
355
        // The forget function removes object from the map and disposes the wrapper.
356
        map.forgetOnly(domObject);
357
431
358
        switch (type) {
432
// static
359
#define MakeCase(type, name)     \
433
DOMData* DOMData::getCurrent()
360
            case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break;
434
{
361
        SVG_OBJECT_TYPES(MakeCase)
435
    if (WTF::isMainThread()) {
362
#undef MakeCase
436
        DEFINE_STATIC_LOCAL(MainThreadDOMData, mainThreadDOMData, ());
363
#define MakeCase(type, name)     \
437
        return &mainThreadDOMData;
364
            case V8ClassIndex::type:    \
438
    }
365
                static_cast<V8SVGPODTypeWrapper<name>*>(domObject)->deref(); break;
439
    DEFINE_STATIC_LOCAL(WTF::ThreadSpecific<ChildThreadDOMData>, childThreadDOMData, ());
366
        SVG_POD_NATIVE_TYPES(MakeCase)
440
    return childThreadDOMData;
367
#undef MakeCase
368
        default:
369
            ASSERT_NOT_REACHED();
370
            break;
371
        }
372
    } else
373
        handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMSVGObjectWithContextMap, type, domObject);
374
}
441
}
375
#endif // ENABLE(SVG)
376
442
377
// Called when the dead object is not in GC thread's map. Go through all thread maps to find the one containing it.
443
// Called when the dead object is not in GC thread's map. Go through all thread maps to find the one containing it.
378
// 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.
444
// 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.
Lines 380-410 static void weakSVGObjectWithContextCall WebCore/bindings/v8/V8DOMMap.cpp_sec10
380
// * This can be called on any thread that has GC running.
446
// * This can be called on any thread that has GC running.
381
// * Only one V8 instance is running at a time due to V8::Locker. So we don't need to worry about concurrency.
447
// * Only one V8 instance is running at a time due to V8::Locker. So we don't need to worry about concurrency.
382
template<typename T>
448
template<typename T>
383
static void handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMWrapperMapType mapType, V8ClassIndex::V8WrapperType objectType, T* object)
449
// static
450
void DOMData::handleWeakObject(DOMDataStore::DOMWrapperMapType mapType, v8::Handle<v8::Object> v8Object, T* domObject)
384
{
451
{
385
    WTF::MutexLocker locker(domDataListMutex());
452
386
    DOMDataList& list = domDataList();
453
    WTF::MutexLocker locker(DOMDataStore::allStoresMutex());
454
    DOMDataList& list = DOMDataStore::allStores();
387
    for (size_t i = 0; i < list.size(); ++i) {
455
    for (size_t i = 0; i < list.size(); ++i) {
388
        ThreadSpecificDOMData* threadData = list[i];
456
        DOMDataStore* store = list[i];
457
458
        DOMDataStore::InternalDOMWrapperMap<T>* domMap = static_cast<DOMDataStore::InternalDOMWrapperMap<T>*>(store->getDOMWrapperMap(mapType));
389
459
390
        ThreadSpecificDOMData::InternalDOMWrapperMap<T>* domMap = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<T>*>(threadData->getDOMWrapperMap(mapType));
460
        v8::Handle<v8::Object> wrapper = domMap->get(domObject);
391
        if (domMap->contains(object)) {
461
        if (*wrapper == *v8Object) {
392
            // Clear the JS reference.
462
            // Clear the JS reference.
393
            domMap->forgetOnly(object);
463
            domMap->forgetOnly(domObject);
464
            store->domData()->ensureDeref(V8Proxy::GetDOMWrapperType(v8Object), domObject);
465
        }
466
    }
467
}
394
468
395
            // Push into the delayed queue.
469
void DOMData::ensureDeref(V8ClassIndex::V8WrapperType type, void* domObject)
396
            threadData->delayedObjectMap().set(object, objectType);
470
{
471
    if (m_owningThread == WTF::currentThread()) {
472
        // No need to delay the work.  We can deref right now.
473
        derefObject(type, domObject);
474
        return;
475
    }
397
476
398
            // Post a task to the owning thread in order to process the delayed queue.
477
    // We need to do the deref on the correct thread.
399
            // FIXME: 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.
478
    m_delayedObjectMap.set(domObject, type);
400
            if (!threadData->delayedProcessingScheduled()) {
401
                threadData->setDelayedProcessingScheduled(true);
402
                if (threadData->isMainThread())
403
                    WTF::callOnMainThread(&derefDelayedObjectsInCurrentThread, 0);
404
            }
405
479
406
            break;
480
    // Post a task to the owning thread in order to process the delayed queue.
407
        }
481
    // FIXME: 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.
482
    if (!m_delayedProcessingScheduled) {
483
        m_delayedProcessingScheduled = true;
484
        if (isMainThread())
485
            WTF::callOnMainThread(&derefDelayedObjectsInCurrentThread, 0);
408
    }
486
    }
409
}
487
}
410
488
Lines 414-478 static void weakDOMObjectCallback(v8::Pe WebCore/bindings/v8/V8DOMMap.cpp_sec11
414
{
492
{
415
    v8::HandleScope scope;
493
    v8::HandleScope scope;
416
    ASSERT(v8Object->IsObject());
494
    ASSERT(v8Object->IsObject());
417
495
    DOMData::handleWeakObject(DOMDataStore::DOMObjectMap, v8::Handle<v8::Object>::Cast(v8Object), domObject);
418
    V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(v8Object));
419
420
    ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<void>&>(getDOMObjectMap());
421
    if (map.contains(domObject)) {
422
        // The forget function removes object from the map and disposes the wrapper.
423
        map.forgetOnly(domObject);
424
425
        switch (type) {
426
#define MakeCase(type, name)   \
427
            case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break;
428
        DOM_OBJECT_TYPES(MakeCase)
429
#undef MakeCase
430
        default:
431
            ASSERT_NOT_REACHED();
432
            break;
433
        }
434
    } else
435
        handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMObjectMap, type, domObject);
436
}
496
}
437
497
438
void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject)
498
void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject)
439
{
499
{
440
    v8::HandleScope scope;
500
    v8::HandleScope scope;
441
    ASSERT(v8Object->IsObject());
501
    ASSERT(v8Object->IsObject());
502
    DOMData::handleWeakObject(DOMDataStore::ActiveDOMObjectMap, v8::Handle<v8::Object>::Cast(v8Object), domObject);
503
}
442
504
443
    V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(v8Object));
505
static void weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject)
506
{
507
    v8::HandleScope scope;
508
    ASSERT(v8Object->IsObject());
509
    DOMData::handleWeakObject<Node>(DOMDataStore::DOMNodeMap, v8::Handle<v8::Object>::Cast(v8Object), static_cast<Node*>(domObject));
510
}
444
511
445
    ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<void>&>(getActiveDOMObjectMap());
512
#if ENABLE(SVG)
446
    if (map.contains(domObject)) {
447
        // The forget function removes object from the map and disposes the wrapper.
448
        map.forgetOnly(domObject);
449
513
450
        switch (type) {
514
static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject)
451
#define MakeCase(type, name)   \
515
{
452
            case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break;
516
    v8::HandleScope scope;
453
        ACTIVE_DOM_OBJECT_TYPES(MakeCase)
517
    ASSERT(v8Object->IsObject());
454
#undef MakeCase
518
    DOMData::handleWeakObject(DOMDataStore::DOMSVGElementInstanceMap, v8::Handle<v8::Object>::Cast(v8Object), static_cast<SVGElementInstance*>(domObject));
455
        default:
456
            ASSERT_NOT_REACHED();
457
            break;
458
        }
459
    } else
460
        handleWeakObjectInOwningThread(ThreadSpecificDOMData::ActiveDOMObjectMap, type, domObject);
461
}
519
}
462
520
463
static void weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject)
521
static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject)
464
{
522
{
465
    Node* node = static_cast<Node*>(domObject);
523
    v8::HandleScope scope;
466
524
    ASSERT(v8Object->IsObject());
467
    ThreadSpecificDOMData::InternalDOMWrapperMap<Node>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<Node>&>(getDOMNodeMap());
525
    DOMData::handleWeakObject(DOMDataStore::DOMSVGObjectWithContextMap, v8::Handle<v8::Object>::Cast(v8Object), domObject);
468
    if (map.contains(node)) {
469
        map.forgetOnly(node);
470
        node->deref();
471
    } else
472
        handleWeakObjectInOwningThread<Node>(ThreadSpecificDOMData::DOMNodeMap, V8ClassIndex::NODE, node);
473
}
526
}
474
527
475
static void derefObject(V8ClassIndex::V8WrapperType type, void* domObject)
528
#endif  // ENABLE(SVG)
529
530
// static
531
void DOMData::derefObject(V8ClassIndex::V8WrapperType type, void* domObject)
476
{
532
{
477
    switch (type) {
533
    switch (type) {
478
    case V8ClassIndex::NODE:
534
    case V8ClassIndex::NODE:
Lines 503-528 static void derefObject(V8ClassIndex::V8 WebCore/bindings/v8/V8DOMMap.cpp_sec12
503
    }
559
    }
504
}
560
}
505
561
506
static void derefDelayedObjects()
562
void DOMData::derefDelayedObjects()
507
{
563
{
508
    WTF::MutexLocker locker(domDataListMutex());
564
    WTF::MutexLocker locker(DOMDataStore::allStoresMutex());
509
565
510
    getThreadSpecificDOMData().setDelayedProcessingScheduled(false);
566
    m_delayedProcessingScheduled = false;
511
567
512
    ThreadSpecificDOMData::DelayedObjectMap& delayedObjectMap = getThreadSpecificDOMData().delayedObjectMap();
568
    for (DelayedObjectMap::iterator iter(m_delayedObjectMap.begin()); iter != m_delayedObjectMap.end(); ++iter)
513
    for (ThreadSpecificDOMData::DelayedObjectMap::iterator iter(delayedObjectMap.begin()); iter != delayedObjectMap.end(); ++iter) {
514
        derefObject(iter->second, iter->first);
569
        derefObject(iter->second, iter->first);
515
    }
570
516
    delayedObjectMap.clear();
571
    m_delayedObjectMap.clear();
517
}
572
}
518
573
519
static void derefDelayedObjectsInCurrentThread(void*)
574
// static
575
void DOMData::derefDelayedObjectsInCurrentThread(void*)
520
{
576
{
521
    derefDelayedObjects();
577
    getCurrent()->derefDelayedObjects();
522
}
578
}
523
579
580
// static
524
template<typename T>
581
template<typename T>
525
static void removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap)
582
void DOMData::removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap)
526
{
583
{
527
    for (typename WTF::HashMap<T*, v8::Object*>::iterator iter(domMap.impl().begin()); iter != domMap.impl().end(); ++iter) {
584
    for (typename WTF::HashMap<T*, v8::Object*>::iterator iter(domMap.impl().begin()); iter != domMap.impl().end(); ++iter) {
528
        T* domObject = static_cast<T*>(iter->first);
585
        T* domObject = static_cast<T*>(iter->first);
Lines 544-566 static void removeAllDOMObjectsInCurrent WebCore/bindings/v8/V8DOMMap.cpp_sec13
544
    v8::HandleScope scope;
601
    v8::HandleScope scope;
545
602
546
    // Deref all objects in the delayed queue.
603
    // Deref all objects in the delayed queue.
547
    derefDelayedObjects();
604
    DOMData::getCurrent()->derefDelayedObjects();
548
605
549
    // Remove all DOM nodes.
606
    // Remove all DOM nodes.
550
    removeObjectsFromWrapperMap<Node>(getDOMNodeMap());
607
    DOMData::removeObjectsFromWrapperMap<Node>(getDOMNodeMap());
551
608
552
    // Remove all DOM objects in the wrapper map.
609
    // Remove all DOM objects in the wrapper map.
553
    removeObjectsFromWrapperMap<void>(getDOMObjectMap());
610
    DOMData::removeObjectsFromWrapperMap<void>(getDOMObjectMap());
554
611
555
    // Remove all active DOM objects in the wrapper map.
612
    // Remove all active DOM objects in the wrapper map.
556
    removeObjectsFromWrapperMap<void>(getActiveDOMObjectMap());
613
    DOMData::removeObjectsFromWrapperMap<void>(getActiveDOMObjectMap());
557
614
558
#if ENABLE(SVG)
615
#if ENABLE(SVG)
559
    // Remove all SVG element instances in the wrapper map.
616
    // Remove all SVG element instances in the wrapper map.
560
    removeObjectsFromWrapperMap<SVGElementInstance>(getDOMSVGElementInstanceMap());
617
    DOMData::removeObjectsFromWrapperMap<SVGElementInstance>(getDOMSVGElementInstanceMap());
561
618
562
    // Remove all SVG objects with context in the wrapper map.
619
    // Remove all SVG objects with context in the wrapper map.
563
    removeObjectsFromWrapperMap<void>(getDOMSVGObjectWithContextMap());
620
    DOMData::removeObjectsFromWrapperMap<void>(getDOMSVGObjectWithContextMap());
564
#endif
621
#endif
565
}
622
}
566
623
Lines 574-577 void removeAllDOMObjectsInCurrentThread( WebCore/bindings/v8/V8DOMMap.cpp_sec14
574
        removeAllDOMObjectsInCurrentThreadHelper();
631
        removeAllDOMObjectsInCurrentThreadHelper();
575
}
632
}
576
633
634
635
void visitDOMNodesInCurrentThread(DOMWrapperMap<Node>::Visitor* visitor)
636
{
637
    v8::HandleScope scope;
638
639
    WTF::MutexLocker locker(DOMDataStore::allStoresMutex());
640
    DOMDataList& list = DOMDataStore::allStores();
641
    for (size_t i = 0; i < list.size(); ++i) {
642
        DOMDataStore* store = list[i];
643
        if (!store->domData()->owningThread() == WTF::currentThread())
644
            continue;
645
646
        HashMap<Node*, v8::Object*>& map = store->domNodeMap().impl();
647
        for (HashMap<Node*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it)
648
            visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second));
649
    }
650
}
651
652
void visitDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor* visitor)
653
{
654
    v8::HandleScope scope;
655
656
    WTF::MutexLocker locker(DOMDataStore::allStoresMutex());
657
    DOMDataList& list = DOMDataStore::allStores();
658
    for (size_t i = 0; i < list.size(); ++i) {
659
        DOMDataStore* store = list[i];
660
        if (!store->domData()->owningThread() == WTF::currentThread())
661
            continue;
662
663
        HashMap<void*, v8::Object*> & map = store->domObjectMap().impl();
664
        for (HashMap<void*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it)
665
            visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second));
666
    }
667
}
668
669
void visitActiveDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor* visitor)
670
{
671
    v8::HandleScope scope;
672
673
    WTF::MutexLocker locker(DOMDataStore::allStoresMutex());
674
    DOMDataList& list = DOMDataStore::allStores();
675
    for (size_t i = 0; i < list.size(); ++i) {
676
        DOMDataStore* store = list[i];
677
        if (!store->domData()->owningThread() == WTF::currentThread())
678
            continue;
679
680
        HashMap<void*, v8::Object*>& map = store->activeDomObjectMap().impl();
681
        for (HashMap<void*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it)
682
            visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second));
683
    }
684
}
685
686
#if ENABLE(SVG)
687
688
void visitDOMSVGElementInstancesInCurrentThread(DOMWrapperMap<SVGElementInstance>::Visitor* visitor)
689
{
690
    v8::HandleScope scope;
691
692
    WTF::MutexLocker locker(DOMDataStore::allStoresMutex());
693
    DOMDataList& list = DOMDataStore::allStores();
694
    for (size_t i = 0; i < list.size(); ++i) {
695
        DOMDataStore* store = list[i];
696
        if (!store->domData()->owningThread() == WTF::currentThread())
697
            continue;
698
699
        HashMap<SVGElementInstance*, v8::Object*> & map = store->domSvgElementInstanceMap().impl();
700
        for (HashMap<SVGElementInstance*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it)
701
            visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second));
702
    }
703
}
704
705
void visitSVGObjectsInCurrentThread(DOMWrapperMap<void>::Visitor* visitor)
706
{
707
    v8::HandleScope scope;
708
709
    WTF::MutexLocker locker(DOMDataStore::allStoresMutex());
710
    DOMDataList& list = DOMDataStore::allStores();
711
    for (size_t i = 0; i < list.size(); ++i) {
712
        DOMDataStore* store = list[i];
713
        if (!store->domData()->owningThread() == WTF::currentThread())
714
            continue;
715
716
        HashMap<void*, v8::Object*>& map = store->domSvgObjectWithContextMap().impl();
717
        for (HashMap<void*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it)
718
            visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second));
719
    }
720
}
721
722
#endif
723
577
} // namespace WebCore
724
} // namespace WebCore
- WebCore/bindings/v8/V8DOMMap.h -1 / +26 lines
Lines 32-37 WebCore/bindings/v8/V8DOMMap.h_sec1
32
#define V8DOMMap_h
32
#define V8DOMMap_h
33
33
34
#include <wtf/HashMap.h>
34
#include <wtf/HashMap.h>
35
#include <wtf/OwnPtr.h>
35
#include <v8.h>
36
#include <v8.h>
36
37
37
namespace WebCore {
38
namespace WebCore {
Lines 89-98 namespace WebCore { WebCore/bindings/v8/V8DOMMap.h_sec2
89
        v8::WeakReferenceCallback m_weakReferenceCallback;
90
        v8::WeakReferenceCallback m_weakReferenceCallback;
90
    };
91
    };
91
92
92
93
    template <class KeyType> class DOMWrapperMap : public WeakReferenceMap<KeyType, v8::Object> {
93
    template <class KeyType> class DOMWrapperMap : public WeakReferenceMap<KeyType, v8::Object> {
94
    public:
94
    public:
95
        DOMWrapperMap(v8::WeakReferenceCallback callback) : WeakReferenceMap<KeyType, v8::Object>(callback) { }
95
        DOMWrapperMap(v8::WeakReferenceCallback callback) : WeakReferenceMap<KeyType, v8::Object>(callback) { }
96
97
        class Visitor {
98
        public:
99
          virtual void visitDOMWrapper(KeyType* key, v8::Persistent<v8::Object> object) = 0;
100
        };
101
    };
102
103
    // An opaque class that represents a set of DOM wrappers.
104
    class DOMDataStore;
105
106
    // A utility class to manage the lifetime of set of DOM wrappers.
107
    class DOMDataStoreHandle {
108
    public:
109
        DOMDataStoreHandle();
110
        ~DOMDataStoreHandle();
111
112
        DOMDataStore* getStore() const { return m_store.get(); }
113
114
    private:
115
        OwnPtr<DOMDataStore> m_store;
96
    };
116
    };
97
117
98
    // Callback when JS wrapper of active DOM object is dead.
118
    // Callback when JS wrapper of active DOM object is dead.
Lines 100-111 namespace WebCore { WebCore/bindings/v8/V8DOMMap.h_sec3
100
120
101
    // A map from DOM node to its JS wrapper.
121
    // A map from DOM node to its JS wrapper.
102
    DOMWrapperMap<Node>& getDOMNodeMap();
122
    DOMWrapperMap<Node>& getDOMNodeMap();
123
    void visitDOMNodesInCurrentThread(DOMWrapperMap<Node>::Visitor*);
103
124
104
    // 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).
125
    // 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).
105
    DOMWrapperMap<void>& getDOMObjectMap();
126
    DOMWrapperMap<void>& getDOMObjectMap();
127
    void visitDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor*);
106
128
107
    // A map from a DOM object to its JS wrapper for DOM objects which can have pending activity.
129
    // A map from a DOM object to its JS wrapper for DOM objects which can have pending activity.
108
    DOMWrapperMap<void>& getActiveDOMObjectMap();
130
    DOMWrapperMap<void>& getActiveDOMObjectMap();
131
    void visitActiveDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor*);
109
132
110
    // This should be called to remove all DOM objects associated with the current thread when it is tearing down.
133
    // This should be called to remove all DOM objects associated with the current thread when it is tearing down.
111
    void removeAllDOMObjectsInCurrentThread();
134
    void removeAllDOMObjectsInCurrentThread();
Lines 113-121 namespace WebCore { WebCore/bindings/v8/V8DOMMap.h_sec4
113
#if ENABLE(SVG)
136
#if ENABLE(SVG)
114
    // A map for SVGElementInstances to its JS wrapper.
137
    // A map for SVGElementInstances to its JS wrapper.
115
    DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap();
138
    DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap();
139
    void visitSVGElementInstancesInCurrentThread(DOMWrapperMap<SVGElementInstance>::Visitor*);
116
140
117
    // Map of SVG objects with contexts to V8 objects.
141
    // Map of SVG objects with contexts to V8 objects.
118
    DOMWrapperMap<void>& getDOMSVGObjectWithContextMap();
142
    DOMWrapperMap<void>& getDOMSVGObjectWithContextMap();
143
    void visitDOMSVGObjectsInCurrentThread(DOMWrapperMap<void>::Visitor*);
119
#endif
144
#endif
120
} // namespace WebCore
145
} // namespace WebCore
121
146
- WebCore/bindings/v8/V8IsolatedWorld.cpp +133 lines
Line 0 WebCore/bindings/v8/V8IsolatedWorld.cpp_sec1
1
/*
2
 * Copyright (C) 2009 Google 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 are
6
 * met:
7
 *
8
 *     * Redistributions of source code must retain the above copyright
9
 * notice, this list of conditions and the following disclaimer.
10
 *     * Redistributions in binary form must reproduce the above
11
 * copyright notice, this list of conditions and the following disclaimer
12
 * in the documentation and/or other materials provided with the
13
 * distribution.
14
 *     * Neither the name of Google Inc. nor the names of its
15
 * contributors may be used to endorse or promote products derived from
16
 * this software without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
 */
30
31
#include "config.h"
32
33
#include "V8IsolatedWorld.h"
34
35
#include <v8.h>
36
37
#include "V8DOMWindow.h"
38
#include "Frame.h"
39
#include "HashMap.h"
40
#include "ScriptController.h"
41
42
namespace WebCore {
43
44
// We cache a pointer to the V8IsolatedWorld as a hidden property on the
45
// context's global object.  This constant is the name of our hidden property.
46
//
47
// FIXME: We should centralize our list of V8 hidden proprety names to ensure
48
// we don't have name collisions.
49
//
50
static char kIsolatedWorldKey[] = "IsolatedWorld";
51
52
static v8::Handle<v8::String> getIsolatedWorldKey()
53
{
54
    static v8::Persistent<v8::String>* key;
55
    if (!key)
56
        key = new v8::Persistent<v8::String>(v8::Persistent<v8::String>::New(v8::String::NewSymbol(kIsolatedWorldKey)));
57
    return *key;
58
}
59
60
static int g_isolatedWorldCount = 0;
61
62
static void contextWeakReferenceCallback(v8::Persistent<v8::Value> object, void* isolated_world)
63
{
64
    // Our context is going away.  Time to clean up the world.
65
    V8IsolatedWorld* world = static_cast<V8IsolatedWorld*>(isolated_world);
66
    delete world;
67
}
68
69
void V8IsolatedWorld::evaluate(const Vector<ScriptSourceCode>& sources, V8Proxy* proxy)
70
{
71
    v8::HandleScope scope;
72
    v8::Persistent<v8::Context> context = proxy->createNewContext(v8::Handle<v8::Object>());
73
74
    // Run code in the new context.
75
    v8::Context::Scope context_scope(context);
76
77
    // The lifetime of this object is controlled by the V8 GC.
78
    // We need to create the world before touching DOM wrappers.
79
    V8IsolatedWorld* world = new V8IsolatedWorld(context);
80
81
    proxy->installDOMWindow(context, proxy->frame()->domWindow());
82
    for (size_t i = 0; i < sources.size(); ++i)
83
        proxy->evaluate(sources[i], 0);
84
85
    // Using the default security token means that the canAccess is always
86
    // called, which is slow.
87
    // TODO(aa): Use tokens where possible. This will mean keeping track of all
88
    // created contexts so that they can all be updated when the document domain
89
    // changes.
90
    // TODO(abarth): Move this statement above proxy->evaluate?  It seems like
91
    //               we should set up the token before running the script.
92
    context->UseDefaultSecurityToken();
93
94
    context.Dispose();
95
    // WARNING!  This might well delete |world|.
96
}
97
98
V8IsolatedWorld::V8IsolatedWorld(v8::Handle<v8::Context> context)
99
    : m_context(context)
100
{
101
    ++g_isolatedWorldCount;
102
    m_context.MakeWeak(this, &contextWeakReferenceCallback);
103
    m_context->Global()->SetHiddenValue(getIsolatedWorldKey(), v8::External::Wrap(this));
104
}
105
106
V8IsolatedWorld::~V8IsolatedWorld()
107
{
108
    --g_isolatedWorldCount;
109
}
110
111
V8IsolatedWorld* V8IsolatedWorld::getEntered()
112
{
113
    if (g_isolatedWorldCount == 0) {
114
        // This is a temporary performance optimization.   Essentially,
115
        // GetHiddenValue is too slow for this code path.  We need to get the
116
        // V8 team to add a real property to v8::Context for isolated worlds.
117
        // Until then, we optimize the common case of not having any isolated
118
        // worlds at all.
119
        return NULL;
120
    }
121
122
    if (!v8::Context::InContext())
123
        return NULL;
124
    v8::HandleScope scope;
125
126
    v8::Local<v8::Value> world = v8::Context::GetEntered()->Global()->GetHiddenValue(getIsolatedWorldKey());
127
    if (world.IsEmpty())
128
        return NULL;
129
130
    return static_cast<V8IsolatedWorld*>(v8::External::Unwrap(world));
131
}
132
133
} // namespace WebCore
- WebCore/bindings/v8/V8IsolatedWorld.h +96 lines
Line 0 WebCore/bindings/v8/V8IsolatedWorld.h_sec1
1
/*
2
 * Copyright (C) 2009 Google 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 are
6
 * met:
7
 *
8
 *     * Redistributions of source code must retain the above copyright
9
 * notice, this list of conditions and the following disclaimer.
10
 *     * Redistributions in binary form must reproduce the above
11
 * copyright notice, this list of conditions and the following disclaimer
12
 * in the documentation and/or other materials provided with the
13
 * distribution.
14
 *     * Neither the name of Google Inc. nor the names of its
15
 * contributors may be used to endorse or promote products derived from
16
 * this software without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
 */
30
31
#ifndef V8IsolatedWorld_h
32
#define V8IsolatedWorld_h
33
34
#include <v8.h>
35
36
#include "v8_index.h"
37
#include "v8_utility.h"
38
#include "V8DOMMap.h"
39
#include "ScriptSourceCode.h"  // for WebCore::ScriptSourceCode
40
41
namespace WebCore {
42
43
    class V8Proxy;
44
45
    // V8IsolatedWorld
46
    //
47
    // V8IsolatedWorld represents a isolated execution environment for
48
    // JavaScript.  Each isolated world executes in parallel with the main
49
    // JavaScript world.  An isolated world has access to the same DOM data
50
    // structures as the main world but none of the JavaScript pointers.
51
    //
52
    // It is an error to ever share a JavaScript pointer between two isolated
53
    // worlds or between an isolated world and the main world.  Because
54
    // isolated worlds have access to the DOM, they need their own DOM wrappers
55
    // to avoid having pointers to the main world's DOM wrappers (which are
56
    // JavaScript objects).
57
    //
58
    class V8IsolatedWorld {
59
    public:
60
        ~V8IsolatedWorld();
61
62
        // Evaluate JavaScript in a new isolated world.  The script has access
63
        // to the DOM of the document associated with |proxy|.
64
        static void evaluate(const Vector<ScriptSourceCode>& sources, V8Proxy* proxy);
65
66
        // Returns the isolated world associated with
67
        // v8::Context::GetEntered().  Because worlds are isolated, the entire
68
        // JavaScript call stack should be from the same isolated world.
69
        // Returns NULL if the entered context is from the main world.
70
        //
71
        // FIXME: Consider edge cases with DOM mutation events that might
72
        // violate this invariant.
73
        //
74
        static V8IsolatedWorld* getEntered();
75
76
        DOMDataStore* getDOMDataStore() const { return m_domDataStore.getStore(); }
77
78
    private:
79
        // The lifetime of an isolated world is managed by the V8 garbage
80
        // collector.  In particular, the object created by this constructor is
81
        // freed when |context| is garbage collected.
82
        explicit V8IsolatedWorld(v8::Handle<v8::Context> context);
83
84
        // The v8::Context for the isolated world.  This object is keep on the
85
        // heap as long as |m_context| has not been garbage collected.
86
        v8::Persistent<v8::Context> m_context;
87
88
        // The backing store for the isolated world's DOM wrappers.  This class
89
        // doesn't have visibility into the wrappers.  This handle simply helps
90
        // manage their lifetime.
91
        DOMDataStoreHandle m_domDataStore;
92
    };
93
94
} // namespace WebCore
95
96
#endif // V8IsolatedWorld_h

Return to Bug 26366