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/. */
7 #include "nsWrapperCacheInlines.h"
9 #include "jsfriendapi.h"
12 #include "mozilla/CycleCollectedJSRuntime.h"
13 #include "mozilla/HoldDropJSObjects.h"
14 #include "nsCycleCollectionTraversalCallback.h"
15 #include "nsCycleCollector.h"
17 using namespace mozilla
;
18 using namespace mozilla::dom
;
22 bool nsWrapperCache::HasJSObjectMovedOp(JSObject
* aWrapper
) {
23 return js::HasObjectMovedOp(aWrapper
);
27 void nsWrapperCache::HoldJSObjects(void* aScriptObjectHolder
,
28 nsScriptObjectTracer
* aTracer
,
29 JS::Zone
* aWrapperZone
) {
30 cyclecollector::HoldJSObjectsImpl(aScriptObjectHolder
, aTracer
, aWrapperZone
);
31 if (mWrapper
&& !JS::ObjectIsTenured(mWrapper
)) {
32 JS::HeapObjectPostWriteBarrier(&mWrapper
, nullptr, mWrapper
);
36 static inline bool IsNurseryWrapper(JSObject
* aWrapper
) {
37 return aWrapper
&& !JS::ObjectIsTenured(aWrapper
);
40 void nsWrapperCache::SetWrapperJSObject(JSObject
* aNewWrapper
) {
41 JSObject
* oldWrapper
= mWrapper
;
42 mWrapper
= aNewWrapper
;
43 UnsetWrapperFlags(kWrapperFlagsMask
);
45 if (IsNurseryWrapper(aNewWrapper
) && !IsNurseryWrapper(oldWrapper
)) {
46 CycleCollectedJSRuntime::Get()->NurseryWrapperAdded(this);
50 void nsWrapperCache::ReleaseWrapper(void* aScriptObjectHolder
) {
51 // If the behavior here changes in a substantive way, you may need
52 // to update css::Rule::UnlinkDeclarationWrapper as well.
53 if (PreservingWrapper()) {
54 SetPreservingWrapper(false);
55 cyclecollector::DropJSObjectsImpl(aScriptObjectHolder
);
56 JS::HeapObjectPostWriteBarrier(&mWrapper
, mWrapper
, nullptr);
62 void nsWrapperCache::AssertUpdatedWrapperZone(const JSObject
* aNewObject
,
63 const JSObject
* aOldObject
) {
64 MOZ_ASSERT(js::GetObjectZoneFromAnyThread(aNewObject
) ==
65 js::GetObjectZoneFromAnyThread(aOldObject
));
68 class DebugWrapperTraversalCallback
69 : public nsCycleCollectionTraversalCallback
{
71 explicit DebugWrapperTraversalCallback(JSObject
* aWrapper
)
72 : mFound(false), mWrapper(JS::GCCellPtr(aWrapper
)) {
73 mFlags
= WANT_ALL_TRACES
;
77 DescribeRefCountedNode(nsrefcnt aRefCount
, const char* aObjName
) override
{}
79 DescribeGCedNode(bool aIsMarked
, const char* aObjName
,
80 uint64_t aCompartmentAddress
) override
{}
82 NS_IMETHOD_(void) NoteJSChild(JS::GCCellPtr aChild
) override
{
83 if (aChild
== mWrapper
) {
87 NS_IMETHOD_(void) NoteXPCOMChild(nsISupports
* aChild
) override
{}
89 NoteNativeChild(void* aChild
,
90 nsCycleCollectionParticipant
* aHelper
) override
{}
93 NoteWeakMapping(JSObject
* aKey
, nsISupports
* aVal
,
94 nsCycleCollectionParticipant
* aValParticipant
) override
{}
96 NS_IMETHOD_(void) NoteNextEdgeName(const char* aName
) override
{}
101 JS::GCCellPtr mWrapper
;
104 static void DebugWrapperTraceCallback(JS::GCCellPtr aPtr
, const char* aName
,
106 DebugWrapperTraversalCallback
* callback
=
107 static_cast<DebugWrapperTraversalCallback
*>(aClosure
);
108 if (aPtr
.is
<JSObject
>()) {
109 callback
->NoteJSChild(aPtr
);
113 void nsWrapperCache::CheckCCWrapperTraversal(void* aScriptObjectHolder
,
114 nsScriptObjectTracer
* aTracer
) {
115 JSObject
* wrapper
= GetWrapperPreserveColor();
120 // Temporarily make this a preserving wrapper so that TraceWrapper() traces
122 bool wasPreservingWrapper
= PreservingWrapper();
123 SetPreservingWrapper(true);
125 DebugWrapperTraversalCallback
callback(wrapper
);
127 // The CC traversal machinery cannot trigger GC; however, the analysis cannot
128 // see through the COM layer, so we use a suppression to help it.
129 JS::AutoSuppressGCAnalysis suppress
;
131 aTracer
->TraverseNativeAndJS(aScriptObjectHolder
, callback
);
132 MOZ_ASSERT(callback
.mFound
,
133 "Cycle collection participant didn't traverse to preserved "
134 "wrapper! This will probably crash.");
136 callback
.mFound
= false;
137 aTracer
->Trace(aScriptObjectHolder
,
138 TraceCallbackFunc(DebugWrapperTraceCallback
), &callback
);
139 MOZ_ASSERT(callback
.mFound
,
140 "Cycle collection participant didn't trace preserved wrapper! "
141 "This will probably crash.");
143 SetPreservingWrapper(wasPreservingWrapper
);