Bug 1835710 - Cancel off-thread JIT compilation before changing nursery allocation...
[gecko.git] / dom / base / nsWrapperCache.cpp
blob317e580c6cb330cbfd9717c2945ee3ed9ba53c1f
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"
10 #include "js/Class.h"
11 #include "js/Proxy.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;
20 #ifdef DEBUG
21 /* static */
22 bool nsWrapperCache::HasJSObjectMovedOp(JSObject* aWrapper) {
23 return js::HasObjectMovedOp(aWrapper);
25 #endif
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);
60 #ifdef DEBUG
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 {
70 public:
71 explicit DebugWrapperTraversalCallback(JSObject* aWrapper)
72 : mFound(false), mWrapper(JS::GCCellPtr(aWrapper)) {
73 mFlags = WANT_ALL_TRACES;
76 NS_IMETHOD_(void)
77 DescribeRefCountedNode(nsrefcnt aRefCount, const char* aObjName) override {}
78 NS_IMETHOD_(void)
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) {
84 mFound = true;
87 NS_IMETHOD_(void) NoteXPCOMChild(nsISupports* aChild) override {}
88 NS_IMETHOD_(void)
89 NoteNativeChild(void* aChild,
90 nsCycleCollectionParticipant* aHelper) override {}
92 NS_IMETHOD_(void)
93 NoteWeakMapping(JSObject* aKey, nsISupports* aVal,
94 nsCycleCollectionParticipant* aValParticipant) override {}
96 NS_IMETHOD_(void) NoteNextEdgeName(const char* aName) override {}
98 bool mFound;
100 private:
101 JS::GCCellPtr mWrapper;
104 static void DebugWrapperTraceCallback(JS::GCCellPtr aPtr, const char* aName,
105 void* aClosure) {
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();
116 if (!wrapper) {
117 return;
120 // Temporarily make this a preserving wrapper so that TraceWrapper() traces
121 // it.
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);
146 #endif // DEBUG