Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "nsWrapperCacheInlines.h"
8 :
9 : #include "js/Class.h"
10 : #include "js/Proxy.h"
11 : #include "mozilla/CycleCollectedJSRuntime.h"
12 : #include "mozilla/HoldDropJSObjects.h"
13 : #include "nsCycleCollectionTraversalCallback.h"
14 : #include "nsCycleCollector.h"
15 :
16 : using namespace mozilla;
17 : using namespace mozilla::dom;
18 :
19 : #ifdef DEBUG
20 : /* static */ bool
21 2598 : nsWrapperCache::HasJSObjectMovedOp(JSObject* aWrapper)
22 : {
23 2598 : return js::HasObjectMovedOp(aWrapper);
24 : }
25 : #endif
26 :
27 : void
28 259 : nsWrapperCache::HoldJSObjects(void* aScriptObjectHolder,
29 : nsScriptObjectTracer* aTracer)
30 : {
31 259 : cyclecollector::HoldJSObjectsImpl(aScriptObjectHolder, aTracer);
32 259 : if (mWrapper && !JS::ObjectIsTenured(mWrapper)) {
33 0 : CycleCollectedJSRuntime::Get()->NurseryWrapperPreserved(mWrapper);
34 : }
35 259 : }
36 :
37 : void
38 2656 : nsWrapperCache::SetWrapperJSObject(JSObject* aWrapper)
39 : {
40 2656 : mWrapper = aWrapper;
41 2656 : UnsetWrapperFlags(kWrapperFlagsMask & ~WRAPPER_IS_NOT_DOM_BINDING);
42 :
43 2656 : if (aWrapper && !JS::ObjectIsTenured(aWrapper)) {
44 77 : CycleCollectedJSRuntime::Get()->NurseryWrapperAdded(this);
45 : }
46 2656 : }
47 :
48 : void
49 47 : nsWrapperCache::ReleaseWrapper(void* aScriptObjectHolder)
50 : {
51 47 : if (PreservingWrapper()) {
52 0 : SetPreservingWrapper(false);
53 0 : cyclecollector::DropJSObjectsImpl(aScriptObjectHolder);
54 : }
55 47 : }
56 :
57 : #ifdef DEBUG
58 :
59 : class DebugWrapperTraversalCallback : public nsCycleCollectionTraversalCallback
60 : {
61 : public:
62 2572 : explicit DebugWrapperTraversalCallback(JSObject* aWrapper)
63 2572 : : mFound(false)
64 2572 : , mWrapper(JS::GCCellPtr(aWrapper))
65 : {
66 2572 : mFlags = WANT_ALL_TRACES;
67 2572 : }
68 :
69 2572 : NS_IMETHOD_(void) DescribeRefCountedNode(nsrefcnt aRefCount,
70 : const char* aObjName)
71 : {
72 2572 : }
73 0 : NS_IMETHOD_(void) DescribeGCedNode(bool aIsMarked,
74 : const char* aObjName,
75 : uint64_t aCompartmentAddress)
76 : {
77 0 : }
78 :
79 5184 : NS_IMETHOD_(void) NoteJSChild(const JS::GCCellPtr& aChild)
80 : {
81 5184 : if (aChild == mWrapper) {
82 5144 : mFound = true;
83 : }
84 5184 : }
85 9877 : NS_IMETHOD_(void) NoteXPCOMChild(nsISupports* aChild)
86 : {
87 9877 : }
88 1071 : NS_IMETHOD_(void) NoteNativeChild(void* aChild,
89 : nsCycleCollectionParticipant* aHelper)
90 : {
91 1071 : }
92 :
93 0 : NS_IMETHOD_(void) NoteNextEdgeName(const char* aName)
94 : {
95 0 : }
96 :
97 : bool mFound;
98 :
99 : private:
100 : JS::GCCellPtr mWrapper;
101 : };
102 :
103 : static void
104 2592 : DebugWrapperTraceCallback(JS::GCCellPtr aPtr, const char* aName, void* aClosure)
105 : {
106 : DebugWrapperTraversalCallback* callback =
107 2592 : static_cast<DebugWrapperTraversalCallback*>(aClosure);
108 2592 : if (aPtr.is<JSObject>()) {
109 2592 : callback->NoteJSChild(aPtr);
110 : }
111 2592 : }
112 :
113 : void
114 2572 : nsWrapperCache::CheckCCWrapperTraversal(void* aScriptObjectHolder,
115 : nsScriptObjectTracer* aTracer)
116 : {
117 2572 : JSObject* wrapper = GetWrapper();
118 2572 : if (!wrapper) {
119 0 : return;
120 : }
121 :
122 2572 : DebugWrapperTraversalCallback callback(wrapper);
123 :
124 : // The CC traversal machinery cannot trigger GC; however, the analysis cannot
125 : // see through the COM layer, so we use a suppression to help it.
126 5144 : JS::AutoSuppressGCAnalysis suppress;
127 :
128 2572 : aTracer->TraverseNativeAndJS(aScriptObjectHolder, callback);
129 2572 : MOZ_ASSERT(callback.mFound,
130 : "Cycle collection participant didn't traverse to preserved "
131 : "wrapper! This will probably crash.");
132 :
133 2572 : callback.mFound = false;
134 : aTracer->Trace(aScriptObjectHolder,
135 2572 : TraceCallbackFunc(DebugWrapperTraceCallback), &callback);
136 2572 : MOZ_ASSERT(callback.mFound,
137 : "Cycle collection participant didn't trace preserved wrapper! "
138 : "This will probably crash.");
139 : }
140 :
141 : #endif // DEBUG
|