[vm,dyn_modules] Handle bytecode in LookupHeapObjectCode.

TEST=pkg/vm_service/test/code
     pkg/vm_service/test/fetch_all_types

Cq-Include-Trybots: luci.dart.try:vm-dyn-linux-debug-x64-try,vm-aot-dyn-linux-debug-x64-try,vm-aot-dyn-linux-product-x64-try,vm-dyn-mac-debug-arm64-try
Change-Id: I4e630911ec836ddcad2cadd338bc59be50827316
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/449801
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 9be7318..9d9f4b7 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -19529,6 +19529,39 @@
   return zone->PrintToString("[Bytecode] %s", function_name);
 }
 
+BytecodePtr Bytecode::FindBytecode(uword pc) {
+#if defined(DART_DYNAMIC_MODULES)
+  class SlowFindBytecodeVisitor : public ObjectVisitor {
+   public:
+    explicit SlowFindBytecodeVisitor(uword pc)
+        : pc_(pc), result_(Bytecode::null()) {}
+
+    void VisitObject(ObjectPtr obj) {
+      if (!obj->IsBytecode()) return;
+      BytecodePtr bytecode = static_cast<BytecodePtr>(obj);
+      if (PayloadStartOf(bytecode) != pc_) return;
+      ASSERT(result_ == Bytecode::null());
+      result_ = bytecode;
+    }
+
+    BytecodePtr result() const { return result_; }
+
+   private:
+    uword pc_;
+    BytecodePtr result_;
+  };
+
+  HeapIterationScope iteration(Thread::Current());
+  SlowFindBytecodeVisitor visitor(pc);
+  iteration.IterateVMIsolateObjects(&visitor);
+  iteration.IterateOldObjectsNoImagePages(&visitor);
+  return visitor.result();
+#else
+  UNREACHABLE();
+  return Bytecode::null();
+#endif
+}
+
 void Bytecode::set_binary(const TypedDataBase& binary) const {
   ASSERT(binary.IsNull() || binary.IsExternalOrExternalView());
   untag()->set_binary(binary.ptr());
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 35a80a1..f0b221e 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -7522,7 +7522,10 @@
  public:
   uword instructions() const { return untag()->instructions_; }
 
-  uword PayloadStart() const { return instructions(); }
+  static uword PayloadStartOf(BytecodePtr ptr) {
+    return ptr->untag()->instructions_;
+  }
+  uword PayloadStart() const { return PayloadStartOf(ptr()); }
   intptr_t Size() const { return untag()->instructions_size_; }
 
   ObjectPoolPtr object_pool() const { return untag()->object_pool(); }
@@ -7628,6 +7631,8 @@
   const char* QualifiedName() const;
   const char* FullyQualifiedName() const;
 
+  static BytecodePtr FindBytecode(uword pc);
+
  private:
   void set_instructions(uword instructions) const {
     StoreNonPointer(&untag()->instructions_, instructions);
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 8a819d6..f7c9ff4 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -2194,6 +2194,12 @@
   if (!code.IsNull()) {
     return code.ptr();
   }
+#if defined(DART_DYNAMIC_MODULES)
+  const auto& bytecode = Bytecode::Handle(Bytecode::FindBytecode(pc));
+  if (!bytecode.IsNull()) {
+    return bytecode.ptr();
+  }
+#endif
 
   // Not found.
   return Object::sentinel().ptr();