diff options
Diffstat (limited to '')
-rw-r--r-- | dom/base/nsWrapperCacheInlines.h | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/dom/base/nsWrapperCacheInlines.h b/dom/base/nsWrapperCacheInlines.h new file mode 100644 index 0000000000..efd0e9a7f5 --- /dev/null +++ b/dom/base/nsWrapperCacheInlines.h @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsWrapperCacheInline_h___ +#define nsWrapperCacheInline_h___ + +#include "nsWrapperCache.h" +#include "js/RootingAPI.h" +#include "js/TracingAPI.h" + +inline JSObject* nsWrapperCache::GetWrapperPreserveColor() const { + JSObject* obj = GetWrapperMaybeDead(); + if (obj && js::gc::EdgeNeedsSweepUnbarriered(&obj)) { + // The object has been found to be dead and is in the process of being + // finalized, so don't let the caller see it. + // Don't clear the cache though: this happens when a new wrapper is created + // for this native or when the wrapper is finalized. + return nullptr; + } + MOZ_ASSERT(obj == mWrapper); + return obj; +} + +inline JSObject* nsWrapperCache::GetWrapper() const { + JSObject* obj = GetWrapperPreserveColor(); + if (obj) { + JS::ExposeObjectToActiveJS(obj); + } + return obj; +} + +inline bool nsWrapperCache::HasKnownLiveWrapper() const { + // If we have a wrapper and it's not gray in the GC-marking sense, that means + // that we can't be cycle-collected. That's because the wrapper is being kept + // alive by the JS engine (and not just due to being traced from some + // cycle-collectable thing), and the wrapper holds us alive, so we know we're + // not collectable. + JSObject* o = GetWrapperPreserveColor(); + return o && !JS::ObjectIsMarkedGray(o); +} + +static void SearchGray(JS::GCCellPtr aGCThing, const char* aName, + void* aClosure) { + bool* hasGrayObjects = static_cast<bool*>(aClosure); + if (!*hasGrayObjects && aGCThing && JS::GCThingIsMarkedGray(aGCThing)) { + *hasGrayObjects = true; + } +} + +inline bool nsWrapperCache::HasNothingToTrace(nsISupports* aThis) { + nsXPCOMCycleCollectionParticipant* participant = nullptr; + CallQueryInterface(aThis, &participant); + bool hasGrayObjects = false; + participant->Trace(aThis, TraceCallbackFunc(SearchGray), &hasGrayObjects); + return !hasGrayObjects; +} + +inline bool nsWrapperCache::HasKnownLiveWrapperAndDoesNotNeedTracing( + nsISupports* aThis) { + return HasKnownLiveWrapper() && HasNothingToTrace(aThis); +} + +inline void nsWrapperCache::MarkWrapperLive() { + // Just call GetWrapper and ignore the return value. It will do the + // gray-unmarking for us. + GetWrapper(); +} + +template <typename T> +inline void nsWrapperCache::UpdateWrapperForNewGlobal(T* aScriptObjectHolder, + JSObject* aNewWrapper) { + // If the new wrapper is in a different zone we must ensure the + // DropJSObjects/HoldJSObjects are called to move the holder to the new zone. + + bool preserving = PreservingWrapper(); + bool zoneChanged = + preserving && (JS::GetObjectZone(GetWrapperPreserveColor()) != + JS::GetObjectZone(aNewWrapper)); + + if (zoneChanged) { + ReleaseWrapper(aScriptObjectHolder); + } else if (preserving) { + SetPreservingWrapper(false); + } + + SetWrapper(aNewWrapper); + + if (zoneChanged) { + PreserveWrapper(aScriptObjectHolder); + } else if (preserving) { + SetPreservingWrapper(true); + } +} + +#endif /* nsWrapperCache_h___ */ |