Allow aliasing in GrProxyProvider::processInvalidUniqueKey

Rearranges the code to support the case "&key == &proxy->fUniqueKey".
Removes the redundant GrUniqueKey parameter from
GrProxyProvider::removeUniqueKeyFromProxy (we can just get the key
from the proxy itself). Adds a passthru for "processInvalidUniqueKey"
to GrOnFlushResourceProvier.

Bug: skia:8462
Change-Id: I0c1e1f2c6ff15a9976f8475c19fd8a33a363193c
Reviewed-on: https://skia-review.googlesource.com/c/180048
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/GrBitmapTextureMaker.cpp b/src/gpu/GrBitmapTextureMaker.cpp
index 224af01..291d6b1 100644
--- a/src/gpu/GrBitmapTextureMaker.cpp
+++ b/src/gpu/GrBitmapTextureMaker.cpp
@@ -83,7 +83,8 @@
                 // mipmapped version. The texture backing the unmipped version will remain in the
                 // resource cache until the last texture proxy referencing it is deleted at which
                 // time it too will be deleted or recycled.
-                proxyProvider->removeUniqueKeyFromProxy(fOriginalKey, proxy.get());
+                SkASSERT(proxy->getUniqueKey() == fOriginalKey);
+                proxyProvider->removeUniqueKeyFromProxy(proxy.get());
                 proxyProvider->assignUniqueKeyToProxy(fOriginalKey, mippedProxy.get());
                 GrInstallBitmapUniqueKeyInvalidator(fOriginalKey, proxyProvider->contextUniqueID(),
                                                     fBitmap.pixelRef());
diff --git a/src/gpu/GrOnFlushResourceProvider.cpp b/src/gpu/GrOnFlushResourceProvider.cpp
index 2555c81..aadd353 100644
--- a/src/gpu/GrOnFlushResourceProvider.cpp
+++ b/src/gpu/GrOnFlushResourceProvider.cpp
@@ -44,10 +44,15 @@
     return proxyProvider->assignUniqueKeyToProxy(key, proxy);
 }
 
-void GrOnFlushResourceProvider::removeUniqueKeyFromProxy(const GrUniqueKey& key,
-                                                         GrTextureProxy* proxy) {
+void GrOnFlushResourceProvider::removeUniqueKeyFromProxy(GrTextureProxy* proxy) {
     auto proxyProvider = fDrawingMgr->getContext()->contextPriv().proxyProvider();
-    proxyProvider->removeUniqueKeyFromProxy(key, proxy);
+    proxyProvider->removeUniqueKeyFromProxy(proxy);
+}
+
+void GrOnFlushResourceProvider::processInvalidUniqueKey(const GrUniqueKey& key) {
+    auto proxyProvider = fDrawingMgr->getContext()->contextPriv().proxyProvider();
+    proxyProvider->processInvalidUniqueKey(key, nullptr,
+                                           GrProxyProvider::InvalidateGPUResource::kYes);
 }
 
 sk_sp<GrTextureProxy> GrOnFlushResourceProvider::findOrCreateProxyByUniqueKey(
diff --git a/src/gpu/GrOnFlushResourceProvider.h b/src/gpu/GrOnFlushResourceProvider.h
index 9ff2384..9cbcddc 100644
--- a/src/gpu/GrOnFlushResourceProvider.h
+++ b/src/gpu/GrOnFlushResourceProvider.h
@@ -77,9 +77,10 @@
                                                          sk_sp<SkColorSpace>,
                                                          const SkSurfaceProps*);
 
-    // Proxy unique key management. See GrProxyProvider.
+    // Proxy unique key management. See GrProxyProvider.h.
     bool assignUniqueKeyToProxy(const GrUniqueKey&, GrTextureProxy*);
-    void removeUniqueKeyFromProxy(const GrUniqueKey&, GrTextureProxy*);
+    void removeUniqueKeyFromProxy(GrTextureProxy*);
+    void processInvalidUniqueKey(const GrUniqueKey&);
     sk_sp<GrTextureProxy> findOrCreateProxyByUniqueKey(const GrUniqueKey&, GrSurfaceOrigin);
 
     bool instatiateProxy(GrSurfaceProxy*);
diff --git a/src/gpu/GrProxyProvider.cpp b/src/gpu/GrProxyProvider.cpp
index 0a45d60..657d607 100644
--- a/src/gpu/GrProxyProvider.cpp
+++ b/src/gpu/GrProxyProvider.cpp
@@ -104,13 +104,16 @@
     fUniquelyKeyedProxies.add(proxy);
 }
 
-void GrProxyProvider::removeUniqueKeyFromProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
+void GrProxyProvider::removeUniqueKeyFromProxy(GrTextureProxy* proxy) {
     ASSERT_SINGLE_OWNER
-    if (this->isAbandoned() || !proxy) {
+    SkASSERT(proxy);
+    SkASSERT(proxy->getUniqueKey().isValid());
+
+    if (this->isAbandoned()) {
         return;
     }
 
-    this->processInvalidUniqueKey(key, proxy, GrProxyProvider::InvalidateGPUResource::kYes);
+    this->processInvalidUniqueKey(proxy->getUniqueKey(), proxy, InvalidateGPUResource::kYes);
 }
 
 sk_sp<GrTextureProxy> GrProxyProvider::findProxyByUniqueKey(const GrUniqueKey& key,
@@ -684,37 +687,35 @@
 
 void GrProxyProvider::processInvalidUniqueKey(const GrUniqueKey& key, GrTextureProxy* proxy,
                                               InvalidateGPUResource invalidateGPUResource) {
+    SkASSERT(key.isValid());
+
     if (!proxy) {
         proxy = fUniquelyKeyedProxies.find(key);
     }
+    SkASSERT(!proxy || proxy->getUniqueKey() == key);
+
+    // Locate the corresponding GrGpuResource (if it needs to be invalidated) before clearing the
+    // proxy's unique key. We must do it in this order because 'key' may alias the proxy's key.
+    sk_sp<GrGpuResource> invalidGpuResource;
+    if (InvalidateGPUResource::kYes == invalidateGPUResource) {
+        if (proxy && proxy->isInstantiated()) {
+            invalidGpuResource = sk_ref_sp(proxy->peekSurface());
+        }
+        if (!invalidGpuResource && fResourceProvider) {
+            invalidGpuResource = fResourceProvider->findByUniqueKey<GrGpuResource>(key);
+        }
+        SkASSERT(!invalidGpuResource || invalidGpuResource->getUniqueKey() == key);
+    }
 
     // Note: this method is called for the whole variety of GrGpuResources so often 'key'
     // will not be in 'fUniquelyKeyedProxies'.
     if (proxy) {
-        SkASSERT(proxy->getUniqueKey().isValid());
-        SkASSERT(proxy->getUniqueKey() == key);
-
         fUniquelyKeyedProxies.remove(key);
         proxy->cacheAccess().clearUniqueKey();
     }
 
-    if (InvalidateGPUResource::kNo == invalidateGPUResource) {
-        return;
-    }
-
-    if (proxy && proxy->isInstantiated()) {
-        GrSurface* surface = proxy->peekSurface();
-        if (surface) {
-            surface->resourcePriv().removeUniqueKey();
-            return;
-        }
-    }
-
-    if (fResourceProvider) {
-        sk_sp<GrGpuResource> resource = fResourceProvider->findByUniqueKey<GrGpuResource>(key);
-        if (resource) {
-            resource->resourcePriv().removeUniqueKey();
-        }
+    if (invalidGpuResource) {
+        invalidGpuResource->resourcePriv().removeUniqueKey();
     }
 }
 
@@ -732,8 +733,7 @@
     for (UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies); !iter.done(); ++iter) {
         GrTextureProxy& tmp = *iter;
 
-        this->processInvalidUniqueKey(tmp.getUniqueKey(), &tmp,
-                                      GrProxyProvider::InvalidateGPUResource::kNo);
+        this->processInvalidUniqueKey(tmp.getUniqueKey(), &tmp, InvalidateGPUResource::kNo);
     }
     SkASSERT(!fUniquelyKeyedProxies.count());
 }
diff --git a/src/gpu/GrProxyProvider.h b/src/gpu/GrProxyProvider.h
index dd5cfb0..8e8c2e0 100644
--- a/src/gpu/GrProxyProvider.h
+++ b/src/gpu/GrProxyProvider.h
@@ -47,7 +47,7 @@
      * Removes a unique key from a proxy. If the proxy has already been instantiated, it will
      * also remove the unique key from the target GrSurface.
      */
-    void removeUniqueKeyFromProxy(const GrUniqueKey&, GrTextureProxy*);
+    void removeUniqueKeyFromProxy(GrTextureProxy*);
 
     /*
      * Finds a proxy by unique key.
@@ -207,8 +207,7 @@
      * (in which case we don't want it cluttering up the hash table) or the client has indicated
      * that it will never refer to the unique key again.
      */
-    void processInvalidUniqueKey(const GrUniqueKey&, GrTextureProxy*,
-                                 InvalidateGPUResource invalidateGPUResource);
+    void processInvalidUniqueKey(const GrUniqueKey&, GrTextureProxy*, InvalidateGPUResource);
 
     uint32_t contextUniqueID() const { return fContextUniqueID; }
     const GrCaps* caps() const { return fCaps.get(); }
diff --git a/src/gpu/GrTextureAdjuster.cpp b/src/gpu/GrTextureAdjuster.cpp
index 8bbcd52..2b8f44c 100644
--- a/src/gpu/GrTextureAdjuster.cpp
+++ b/src/gpu/GrTextureAdjuster.cpp
@@ -62,7 +62,8 @@
                 // If we had a cachedProxy, that means there already is a proxy in the cache which
                 // matches the key, but it does not have mip levels and we require them. Thus we
                 // must remove the unique key from that proxy.
-                proxyProvider->removeUniqueKeyFromProxy(key, cachedCopy.get());
+                SkASSERT(cachedCopy->getUniqueKey() == key);
+                proxyProvider->removeUniqueKeyFromProxy(cachedCopy.get());
             }
             proxyProvider->assignUniqueKeyToProxy(key, copy.get());
             this->didCacheCopy(key, proxyProvider->contextUniqueID());
diff --git a/src/gpu/GrTextureMaker.cpp b/src/gpu/GrTextureMaker.cpp
index 9f4651f..fa4d986 100644
--- a/src/gpu/GrTextureMaker.cpp
+++ b/src/gpu/GrTextureMaker.cpp
@@ -94,7 +94,8 @@
             // If we had a cachedProxy, that means there already is a proxy in the cache which
             // matches the key, but it does not have mip levels and we require them. Thus we must
             // remove the unique key from that proxy.
-            proxyProvider->removeUniqueKeyFromProxy(copyKey, cachedProxy.get());
+            SkASSERT(cachedProxy->getUniqueKey() == copyKey);
+            proxyProvider->removeUniqueKeyFromProxy(cachedProxy.get());
         }
         proxyProvider->assignUniqueKeyToProxy(copyKey, result.get());
         this->didCacheCopy(copyKey, proxyProvider->contextUniqueID());
diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
index 77f5a02..293d8c2 100644
--- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
+++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
@@ -202,7 +202,8 @@
         if (stashedAtlasProxy) {
             // Instantiate the proxy so we can clear the underlying texture's unique key.
             onFlushRP->instatiateProxy(stashedAtlasProxy.get());
-            onFlushRP->removeUniqueKeyFromProxy(fStashedAtlasKey, stashedAtlasProxy.get());
+            SkASSERT(fStashedAtlasKey == stashedAtlasProxy->getUniqueKey());
+            onFlushRP->removeUniqueKeyFromProxy(stashedAtlasProxy.get());
         } else {
             fStashedAtlasKey.reset();  // Indicate there is no stashed atlas to copy from.
         }
diff --git a/src/image/SkImage_Lazy.cpp b/src/image/SkImage_Lazy.cpp
index fef4bf4..a1557e1 100644
--- a/src/image/SkImage_Lazy.cpp
+++ b/src/image/SkImage_Lazy.cpp
@@ -323,7 +323,8 @@
             // If we had an originalProxy with a valid key, that means there already is a proxy in
             // the cache which matches the key, but it does not have mip levels and we require them.
             // Thus we must remove the unique key from that proxy.
-            proxyProvider->removeUniqueKeyFromProxy(key, originalProxy);
+            SkASSERT(originalProxy->getUniqueKey() == key);
+            proxyProvider->removeUniqueKeyFromProxy(originalProxy);
         }
         proxyProvider->assignUniqueKeyToProxy(key, proxy);
     }