forked from mirrors/gecko-dev
		
	 7cf55278e0
			
		
	
	
		7cf55278e0
		
	
	
	
	
		
			
			So that we can update the holders table correctly we will need to remove the wrapper from its original vector and add it to the one associated with the new zone. I tried to make SetPreservingWrapper private but there's still a use in layout/style/Rule.cpp that I couldn't see an obvious fix for. Differential Revision: https://phabricator.services.mozilla.com/D68521
		
			
				
	
	
		
			129 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			129 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- 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/. */
 | |
| 
 | |
| #include "nsWrapperCacheInlines.h"
 | |
| 
 | |
| #include "js/Class.h"
 | |
| #include "js/Proxy.h"
 | |
| #include "mozilla/CycleCollectedJSRuntime.h"
 | |
| #include "mozilla/HoldDropJSObjects.h"
 | |
| #include "nsCycleCollectionTraversalCallback.h"
 | |
| #include "nsCycleCollector.h"
 | |
| 
 | |
| using namespace mozilla;
 | |
| using namespace mozilla::dom;
 | |
| 
 | |
| #ifdef DEBUG
 | |
| /* static */
 | |
| bool nsWrapperCache::HasJSObjectMovedOp(JSObject* aWrapper) {
 | |
|   return js::HasObjectMovedOp(aWrapper);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| void nsWrapperCache::HoldJSObjects(void* aScriptObjectHolder,
 | |
|                                    nsScriptObjectTracer* aTracer,
 | |
|                                    JS::Zone* aWrapperZone) {
 | |
|   cyclecollector::HoldJSObjectsImpl(aScriptObjectHolder, aTracer, aWrapperZone);
 | |
|   if (mWrapper && !JS::ObjectIsTenured(mWrapper)) {
 | |
|     CycleCollectedJSRuntime::Get()->NurseryWrapperPreserved(mWrapper);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void nsWrapperCache::SetWrapperJSObject(JSObject* aWrapper) {
 | |
|   mWrapper = aWrapper;
 | |
|   UnsetWrapperFlags(kWrapperFlagsMask);
 | |
| 
 | |
|   if (aWrapper && !JS::ObjectIsTenured(aWrapper)) {
 | |
|     CycleCollectedJSRuntime::Get()->NurseryWrapperAdded(this);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void nsWrapperCache::ReleaseWrapper(void* aScriptObjectHolder) {
 | |
|   // If the behavior here changes in a substantive way, you may need
 | |
|   // to update css::Rule::UnlinkDeclarationWrapper as well.
 | |
|   if (PreservingWrapper()) {
 | |
|     SetPreservingWrapper(false);
 | |
|     cyclecollector::DropJSObjectsImpl(aScriptObjectHolder);
 | |
|   }
 | |
| }
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 
 | |
| class DebugWrapperTraversalCallback
 | |
|     : public nsCycleCollectionTraversalCallback {
 | |
|  public:
 | |
|   explicit DebugWrapperTraversalCallback(JSObject* aWrapper)
 | |
|       : mFound(false), mWrapper(JS::GCCellPtr(aWrapper)) {
 | |
|     mFlags = WANT_ALL_TRACES;
 | |
|   }
 | |
| 
 | |
|   NS_IMETHOD_(void)
 | |
|   DescribeRefCountedNode(nsrefcnt aRefCount, const char* aObjName) override {}
 | |
|   NS_IMETHOD_(void)
 | |
|   DescribeGCedNode(bool aIsMarked, const char* aObjName,
 | |
|                    uint64_t aCompartmentAddress) override {}
 | |
| 
 | |
|   NS_IMETHOD_(void) NoteJSChild(const JS::GCCellPtr& aChild) override {
 | |
|     if (aChild == mWrapper) {
 | |
|       mFound = true;
 | |
|     }
 | |
|   }
 | |
|   NS_IMETHOD_(void) NoteXPCOMChild(nsISupports* aChild) override {}
 | |
|   NS_IMETHOD_(void)
 | |
|   NoteNativeChild(void* aChild,
 | |
|                   nsCycleCollectionParticipant* aHelper) override {}
 | |
| 
 | |
|   NS_IMETHOD_(void) NoteNextEdgeName(const char* aName) override {}
 | |
| 
 | |
|   bool mFound;
 | |
| 
 | |
|  private:
 | |
|   JS::GCCellPtr mWrapper;
 | |
| };
 | |
| 
 | |
| static void DebugWrapperTraceCallback(JS::GCCellPtr aPtr, const char* aName,
 | |
|                                       void* aClosure) {
 | |
|   DebugWrapperTraversalCallback* callback =
 | |
|       static_cast<DebugWrapperTraversalCallback*>(aClosure);
 | |
|   if (aPtr.is<JSObject>()) {
 | |
|     callback->NoteJSChild(aPtr);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void nsWrapperCache::CheckCCWrapperTraversal(void* aScriptObjectHolder,
 | |
|                                              nsScriptObjectTracer* aTracer) {
 | |
|   JSObject* wrapper = GetWrapperPreserveColor();
 | |
|   if (!wrapper) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // Temporarily make this a preserving wrapper so that TraceWrapper() traces
 | |
|   // it.
 | |
|   bool wasPreservingWrapper = PreservingWrapper();
 | |
|   SetPreservingWrapper(true);
 | |
| 
 | |
|   DebugWrapperTraversalCallback callback(wrapper);
 | |
| 
 | |
|   // The CC traversal machinery cannot trigger GC; however, the analysis cannot
 | |
|   // see through the COM layer, so we use a suppression to help it.
 | |
|   JS::AutoSuppressGCAnalysis suppress;
 | |
| 
 | |
|   aTracer->TraverseNativeAndJS(aScriptObjectHolder, callback);
 | |
|   MOZ_ASSERT(callback.mFound,
 | |
|              "Cycle collection participant didn't traverse to preserved "
 | |
|              "wrapper! This will probably crash.");
 | |
| 
 | |
|   callback.mFound = false;
 | |
|   aTracer->Trace(aScriptObjectHolder,
 | |
|                  TraceCallbackFunc(DebugWrapperTraceCallback), &callback);
 | |
|   MOZ_ASSERT(callback.mFound,
 | |
|              "Cycle collection participant didn't trace preserved wrapper! "
 | |
|              "This will probably crash.");
 | |
| 
 | |
|   SetPreservingWrapper(wasPreservingWrapper);
 | |
| }
 | |
| 
 | |
| #endif  // DEBUG
 |