[vm] Get script of closure from owner as parent function may contain wrong script

When a mixin class is created, there might be anonymous closures copied over to the other script.
Previously the script of closure function is the script of its parent function, which is not true in that case.
The solution is to create a patch class as the owner if parent function has a different script object. Return script of owner when query for script of closure function.

Bug: https://github.com/dart-lang/sdk/issues/34841
Change-Id: I53065cbf13f2d0dc8da320993fd3cd425e5c9714
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/102226
Commit-Queue: Zichang Guo <zichangguo@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
diff --git a/runtime/observatory/tests/service/regress_34841_lib.dart b/runtime/observatory/tests/service/regress_34841_lib.dart
index 304f6f5..60eb3e4 100644
--- a/runtime/observatory/tests/service/regress_34841_lib.dart
+++ b/runtime/observatory/tests/service/regress_34841_lib.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 class Foo {
+  String baz() => StackTrace.current.toString();
   final String foo = () {
     return StackTrace.current.toString();
   }();
diff --git a/runtime/observatory/tests/service/regress_34841_test.dart b/runtime/observatory/tests/service/regress_34841_test.dart
index 69acbad..c53a9e9 100644
--- a/runtime/observatory/tests/service/regress_34841_test.dart
+++ b/runtime/observatory/tests/service/regress_34841_test.dart
@@ -19,6 +19,7 @@
 void testFunction() {
   Bar bar = new Bar();
   print(bar.foo);
+  print(bar.baz());
   debugger();
 }
 
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index b0f294f..706d2e6 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -175,7 +175,11 @@
 
   Fragment instructions;
   instructions += LoadLocal(parsed_function()->receiver_var());
+  // All closures created inside BuildExpression will have
+  // field.RawOwner() as its owner.
+  closure_owner_ = field.RawOwner();
   instructions += BuildExpression();
+  closure_owner_ = Object::null();
   instructions += flow_graph_builder_->StoreInstanceFieldGuarded(field, true);
   return instructions;
 }
@@ -4902,8 +4906,14 @@
         name = &Symbols::AnonymousClosure();
       }
       // NOTE: This is not TokenPosition in the general sense!
-      function = Function::NewClosureFunction(
-          *name, parsed_function()->function(), position);
+      if (!closure_owner_.IsNull()) {
+        function = Function::NewClosureFunctionWithKind(
+            RawFunction::kClosureFunction, *name, parsed_function()->function(),
+            position, closure_owner_);
+      } else {
+        function = Function::NewClosureFunction(
+            *name, parsed_function()->function(), position);
+      }
 
       function.set_is_debuggable(function_node_helper.dart_async_marker_ ==
                                  FunctionNodeHelper::kSync);
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index edf29ea..2006924 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -43,7 +43,8 @@
         direct_call_metadata_helper_(this),
         inferred_type_metadata_helper_(this),
         procedure_attributes_metadata_helper_(this),
-        call_site_attributes_metadata_helper_(this, &type_translator_) {}
+        call_site_attributes_metadata_helper_(this, &type_translator_),
+        closure_owner_(Object::Handle(flow_graph_builder->zone_)) {}
 
   virtual ~StreamingFlowGraphBuilder() {}
 
@@ -358,6 +359,7 @@
   InferredTypeMetadataHelper inferred_type_metadata_helper_;
   ProcedureAttributesMetadataHelper procedure_attributes_metadata_helper_;
   CallSiteAttributesMetadataHelper call_site_attributes_metadata_helper_;
+  Object& closure_owner_;
 
   friend class KernelLoader;
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index c427228..d2e8a61 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -7277,20 +7277,19 @@
 RawFunction* Function::NewClosureFunctionWithKind(RawFunction::Kind kind,
                                                   const String& name,
                                                   const Function& parent,
-                                                  TokenPosition token_pos) {
+                                                  TokenPosition token_pos,
+                                                  const Object& owner) {
   ASSERT((kind == RawFunction::kClosureFunction) ||
          (kind == RawFunction::kImplicitClosureFunction));
   ASSERT(!parent.IsNull());
-  // Use the owner defining the parent function and not the class containing it.
-  const Object& parent_owner = Object::Handle(parent.raw_ptr()->owner_);
-  ASSERT(!parent_owner.IsNull());
+  ASSERT(!owner.IsNull());
   const Function& result = Function::Handle(
       Function::New(name, kind,
                     /* is_static = */ parent.is_static(),
                     /* is_const = */ false,
                     /* is_abstract = */ false,
                     /* is_external = */ false,
-                    /* is_native = */ false, parent_owner, token_pos));
+                    /* is_native = */ false, owner, token_pos));
   result.set_parent_function(parent);
   return result.raw();
 }
@@ -7298,15 +7297,19 @@
 RawFunction* Function::NewClosureFunction(const String& name,
                                           const Function& parent,
                                           TokenPosition token_pos) {
+  // Use the owner defining the parent function and not the class containing it.
+  const Object& parent_owner = Object::Handle(parent.RawOwner());
   return NewClosureFunctionWithKind(RawFunction::kClosureFunction, name, parent,
-                                    token_pos);
+                                    token_pos, parent_owner);
 }
 
 RawFunction* Function::NewImplicitClosureFunction(const String& name,
                                                   const Function& parent,
                                                   TokenPosition token_pos) {
+  // Use the owner defining the parent function and not the class containing it.
+  const Object& parent_owner = Object::Handle(parent.RawOwner());
   return NewClosureFunctionWithKind(RawFunction::kImplicitClosureFunction, name,
-                                    parent, token_pos);
+                                    parent, token_pos, parent_owner);
 }
 
 RawFunction* Function::NewSignatureFunction(const Object& owner,
@@ -7717,19 +7720,19 @@
       return script.raw();
     }
   }
+  const Object& obj = Object::Handle(raw_ptr()->owner_);
+  if (obj.IsPatchClass()) {
+    return PatchClass::Cast(obj).script();
+  }
   if (IsClosureFunction()) {
     return Function::Handle(parent_function()).script();
   }
-  const Object& obj = Object::Handle(raw_ptr()->owner_);
   if (obj.IsNull()) {
     ASSERT(IsSignatureFunction());
     return Script::null();
   }
-  if (obj.IsClass()) {
-    return Class::Cast(obj).script();
-  }
-  ASSERT(obj.IsPatchClass());
-  return PatchClass::Cast(obj).script();
+  ASSERT(obj.IsClass());
+  return Class::Cast(obj).script();
 }
 
 RawExternalTypedData* Function::KernelData() const {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 540a7ac..2b04c83 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2762,7 +2762,8 @@
   static RawFunction* NewClosureFunctionWithKind(RawFunction::Kind kind,
                                                  const String& name,
                                                  const Function& parent,
-                                                 TokenPosition token_pos);
+                                                 TokenPosition token_pos,
+                                                 const Object& owner);
 
   // Allocates a new Function object representing a closure function.
   static RawFunction* NewClosureFunction(const String& name,