[vm/compiler] Fix for flaky crash in CallSpecializer::ReplaceWithInstanceOf

There were rare crashes

../../runtime/vm/compiler/call_specializer.cc: 1393: error: expected: call->MatchesCoreName(Symbols::_simpleInstanceOf())
version=2.3.0-edge.796ebc6069bde3a59475a9b45075f49e50b0cc34 (Thu May 9 09:38:28 2019 -0700) on "linux_x64"
thread=82540, isolate=vm-service(0x558748c5d200)
  pc 0x000055874635dd6c fp 0x00007fa94dd3bf30 dart::Profiler::DumpStackTrace(void*)
  pc 0x0000558745f90332 fp 0x00007fa94dd3c010 dart::Assert::Fail(char const*, ...)
  pc 0x000055874653909b fp 0x00007fa94dd3c0a0 dart::CallSpecializer::ReplaceWithInstanceOf(dart::InstanceCallInstr*)
  pc 0x0000558746496ed6 fp 0x00007fa94dd3c0f0 dart::FlowGraphVisitor::VisitBlocks()

when running

tools/test.py --repeat 5000 -n dartkb-mixed-linux-debug-x64 language_2/null_test

at the rate ~1-3 crashes per 30,000 test cases.

The problem is that in function

bool InstanceCallInstr::MatchesCoreName(const String& name) {
  return function_name().raw() == Library::PrivateCoreLibName(name).raw();
}

'function_name().raw()' is evaluated before PrivateCoreLibName(name) is called
and saved in a temporary (register). PrivateCoreLibName may trigger GC and
relocate objects. In such case, 'PrivateCoreLibName(name).raw()' results in a
moved object, which is compared to a stale object address.

This CL fixes InstanceCallInstr::MatchesCoreName and other similar places
by introducing Library::IsPrivateCoreLibName, which is also a little bit more
efficient as it avoids extra symbol table lookup.

Change-Id: I4dc91c586b0c595a3e85d6da13b98fc2248fb8fd
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/102120
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Aart Bik <ajcbik@google.com>
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 05d3029..635c4be 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -4260,7 +4260,7 @@
 }
 
 bool InstanceCallInstr::MatchesCoreName(const String& name) {
-  return function_name().raw() == Library::PrivateCoreLibName(name).raw();
+  return Library::IsPrivateCoreLibName(function_name(), name);
 }
 
 RawFunction* InstanceCallInstr::ResolveForReceiverClass(
diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
index 0a6df8f..61f37dfe 100644
--- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
@@ -820,13 +820,12 @@
     intptr_t argument_count = arg_desc.Count();
     ASSERT(argument_count <= 2);
     checked_argument_count = argument_count;
-  } else if (name.raw() ==
-             Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()).raw()) {
+  } else if (Library::IsPrivateCoreLibName(name,
+                                           Symbols::_simpleInstanceOf())) {
     ASSERT(arg_desc.Count() == 2);
     checked_argument_count = 2;
     token_kind = Token::kIS;
-  } else if (name.raw() ==
-             Library::PrivateCoreLibName(Symbols::_instanceOf()).raw()) {
+  } else if (Library::IsPrivateCoreLibName(name, Symbols::_instanceOf())) {
     token_kind = Token::kIS;
   }
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 7fc9316..c427228 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -11377,6 +11377,15 @@
   return private_name;
 }
 
+bool Library::IsPrivateCoreLibName(const String& name, const String& member) {
+  Zone* zone = Thread::Current()->zone();
+  const auto& core_lib = Library::Handle(zone, Library::CoreLibrary());
+  const auto& private_key = String::Handle(zone, core_lib.private_key());
+
+  ASSERT(core_lib.IsPrivate(member));
+  return name.EqualsConcat(member, private_key);
+}
+
 RawClass* Library::LookupCoreClass(const String& class_name) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index ab8e168..fbf47ae 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -4031,8 +4031,13 @@
 #endif  // defined(DART_NO_SNAPSHOT).
 
   static bool IsPrivate(const String& name);
+
   // Construct the full name of a corelib member.
   static const String& PrivateCoreLibName(const String& member);
+
+  // Returns true if [name] matches full name of corelib [member].
+  static bool IsPrivateCoreLibName(const String& name, const String& member);
+
   // Lookup class in the core lib which also contains various VM
   // helper methods and classes. Allow look up of private classes.
   static RawClass* LookupCoreClass(const String& class_name);