[vm/aot] Fix ProgramElementKeyValueTrait::Hash.

It was returning library's index which is an unstable
value. This instability could cause `Precompiler::HasApiUse`
to stop returning `true` after `Precompiler::DropLibraries` even
if library was added to the `api_uses_` set. This in turn could cause
`Precompiler::PruneDictionaries` to drop library entries it should
not have dropped.

TEST=added assertion that verifies stability of the set

Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try
Change-Id: I0685bd75562f83e2b9d8b3a03fa410ba218df2ea
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/275241
Reviewed-by: Tess Strickland <sstrickl@google.com>
Auto-Submit: Slava Egorov <vegorov@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 4b94631..06994ed 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -3087,6 +3087,16 @@
 }
 
 void Precompiler::PruneDictionaries() {
+#if defined(DEBUG)
+  // Verify that api_uses_ is stable: any entry in it can be found. This
+  // check serves to catch bugs when ProgramElementSet::Hash is accidentally
+  // defined using unstable values.
+  ProgramElementSet::Iterator it = api_uses_.GetIterator();
+  while (auto entry = it.Next()) {
+    ASSERT(api_uses_.HasKey(*entry));
+  }
+#endif
+
   // PRODUCT-only: pruning interferes with various uses of the service protocol,
   // including heap analysis tools.
 #if defined(PRODUCT)
diff --git a/runtime/vm/compiler/aot/precompiler.h b/runtime/vm/compiler/aot/precompiler.h
index 243d246..cf44656 100644
--- a/runtime/vm/compiler/aot/precompiler.h
+++ b/runtime/vm/compiler/aot/precompiler.h
@@ -199,11 +199,15 @@
     if (key->IsFunction()) {
       return Function::Cast(*key).Hash();
     } else if (key->IsField()) {
-      return Field::Cast(*key).kernel_offset();
+      return Utils::WordHash(Field::Cast(*key).kernel_offset());
     } else if (key->IsClass()) {
-      return Class::Cast(*key).kernel_offset();
+      return Utils::WordHash(Class::Cast(*key).kernel_offset());
     } else if (key->IsLibrary()) {
-      return Library::Cast(*key).index();
+      // This must not use library's index or url hash because both
+      // of these might change during precompilation: urls are changed
+      // by |Precompiler::Obfuscate| and library index is changed by
+      // |Precompiler::DropLibraries|.
+      return Utils::WordHash(Library::Cast(*key).kernel_offset());
     }
     FATAL("Unexpected type: %s\n", key->ToCString());
   }