[vm, gc] Avoid race between unregistering pages with LSAN and exit.

After the Page is unregistered, the only reference to its VirtualMemory is in memory not traced by LSAN. If exit happens here before the VirtualMemory is deleted or put into the global cache, it appears to be leaked.

TEST=lsan
Bug: https://github.com/dart-lang/sdk/issues/51560
Change-Id: I973e09bb19910d9cdcc3af6c8c9a188f095df36a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/297040
Reviewed-by: Alexander Aprelev <aam@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
diff --git a/runtime/vm/heap/page.cc b/runtime/vm/heap/page.cc
index 3af1136..9bd7595 100644
--- a/runtime/vm/heap/page.cc
+++ b/runtime/vm/heap/page.cc
@@ -136,9 +136,12 @@
 
   free(card_table_);
 
+  // Load before unregistering with LSAN, or LSAN will temporarily think it has
+  // been leaked.
+  VirtualMemory* memory = memory_;
+
   LSAN_UNREGISTER_ROOT_REGION(this, sizeof(*this));
 
-  VirtualMemory* memory = memory_;
   if (CanUseCache(flags_)) {
     ASSERT(memory->size() == kPageSize);
     MutexLocker ml(page_cache_mutex);