diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc index 4b946311145..06994edce99 100644 --- a/runtime/vm/compiler/aot/precompiler.cc +++ b/runtime/vm/compiler/aot/precompiler.cc @@ -3087,6 +3087,16 @@ void Precompiler::DiscardCodeObjects() { } 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 243d246f5e4..cf44656abb5 100644 --- a/runtime/vm/compiler/aot/precompiler.h +++ b/runtime/vm/compiler/aot/precompiler.h @@ -199,11 +199,15 @@ class ProgramElementKeyValueTrait { 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()); }