nsWrapperCacheInlines.h (3362B)
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 #ifndef nsWrapperCacheInline_h___ 8 #define nsWrapperCacheInline_h___ 9 10 #include "js/RootingAPI.h" 11 #include "js/TracingAPI.h" 12 #include "nsWrapperCache.h" 13 14 inline JSObject* nsWrapperCache::GetWrapperPreserveColor() const { 15 JSObject* obj = GetWrapperMaybeDead(); 16 if (obj && js::gc::EdgeNeedsSweepUnbarriered(&obj)) { 17 // The object has been found to be dead and is in the process of being 18 // finalized, so don't let the caller see it. 19 // Don't clear the cache though: this happens when a new wrapper is created 20 // for this native or when the wrapper is finalized. 21 return nullptr; 22 } 23 MOZ_ASSERT(obj == mWrapper); 24 return obj; 25 } 26 27 inline JSObject* nsWrapperCache::GetWrapper() const { 28 JSObject* obj = GetWrapperPreserveColor(); 29 if (obj) { 30 JS::ExposeObjectToActiveJS(obj); 31 } 32 return obj; 33 } 34 35 inline bool nsWrapperCache::HasKnownLiveWrapper() const { 36 // If we have a wrapper and it's not gray in the GC-marking sense, that means 37 // that we can't be cycle-collected. That's because the wrapper is being kept 38 // alive by the JS engine (and not just due to being traced from some 39 // cycle-collectable thing), and the wrapper holds us alive, so we know we're 40 // not collectable. 41 JSObject* o = GetWrapperPreserveColor(); 42 return o && !JS::ObjectIsMarkedGray(o); 43 } 44 45 static void SearchGray(JS::GCCellPtr aGCThing, const char* aName, 46 void* aClosure) { 47 bool* hasGrayObjects = static_cast<bool*>(aClosure); 48 if (!*hasGrayObjects && aGCThing && JS::GCThingIsMarkedGray(aGCThing)) { 49 *hasGrayObjects = true; 50 } 51 } 52 53 inline bool nsWrapperCache::HasNothingToTrace(nsISupports* aThis) { 54 nsXPCOMCycleCollectionParticipant* participant = nullptr; 55 CallQueryInterface(aThis, &participant); 56 bool hasGrayObjects = false; 57 participant->Trace(aThis, TraceCallbackFunc(SearchGray), &hasGrayObjects); 58 return !hasGrayObjects; 59 } 60 61 inline bool nsWrapperCache::HasKnownLiveWrapperAndDoesNotNeedTracing( 62 nsISupports* aThis) { 63 return HasKnownLiveWrapper() && HasNothingToTrace(aThis); 64 } 65 66 inline void nsWrapperCache::MarkWrapperLive() { 67 // Just call GetWrapper and ignore the return value. It will do the 68 // gray-unmarking for us. 69 GetWrapper(); 70 } 71 72 template <typename T> 73 inline void nsWrapperCache::UpdateWrapperForNewGlobal(T* aScriptObjectHolder, 74 JSObject* aNewWrapper) { 75 // If the new wrapper is in a different zone we must ensure the 76 // DropJSObjects/HoldJSObjects are called to move the holder to the new zone. 77 78 bool preserving = PreservingWrapper(); 79 bool zoneChanged = 80 preserving && (JS::GetObjectZone(GetWrapperPreserveColor()) != 81 JS::GetObjectZone(aNewWrapper)); 82 83 if (zoneChanged) { 84 ReleaseWrapper(aScriptObjectHolder); 85 } else if (preserving) { 86 SetPreservingWrapper(false); 87 } 88 89 SetWrapper(aNewWrapper); 90 91 if (zoneChanged) { 92 PreserveWrapper(aScriptObjectHolder); 93 } else if (preserving) { 94 SetPreservingWrapper(true); 95 } 96 } 97 98 #endif /* nsWrapperCache_h___ */