public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Ian Lance Taylor <iant@golang.org>
To: gcc-patches <gcc-patches@gcc.gnu.org>,
		"gofrontend-dev@googlegroups.com"
	<gofrontend-dev@googlegroups.com>
Subject: Go patch committed: Propagate escape info from closures to enclosed variables
Date: Wed, 29 Apr 2015 22:29:00 -0000	[thread overview]
Message-ID: <CAOyqgcV9+8jHdPy2NTO55RAc4Jm3BB6VE4B=FXdX6Fn0eQ1qEg@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 239 bytes --]

This patch from Chris Manghane fixes the Go frontend to propagate
escape information from closures to the enclosed variables to which
they refer.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu.  Committed to mainline.

Ian

[-- Attachment #2: foo.txt --]
[-- Type: text/plain, Size: 3099 bytes --]

diff -r 0010ef165479 go/escape.cc
--- a/go/escape.cc	Wed Apr 29 14:28:30 2015 -0700
+++ b/go/escape.cc	Wed Apr 29 15:07:47 2015 -0700
@@ -1276,8 +1276,22 @@
       Node* m = worklist.front();
       worklist.pop_front();
 
-      for (std::set<Node*>::iterator n = m->edges().begin();
-	   n != m->edges().end();
+      std::set<Node*> reachable = m->edges();
+      if (m->object()->is_function()
+	  && m->object()->func_value()->needs_closure())
+	{
+	  // If a closure escapes everything it closes over also escapes.
+	  Function* closure = m->object()->func_value();
+	  for (size_t i = 0; i < closure->closure_field_count(); i++)
+	    {
+	      Named_object* enclosed = closure->enclosing_var(i);
+	      Node* enclosed_node = this->lookup_connection_node(enclosed);
+	      go_assert(enclosed_node != NULL);
+	      reachable.insert(enclosed_node);
+	    }
+	}
+      for (std::set<Node*>::iterator n = reachable.begin();
+	   n != reachable.end();
 	   ++n)
 	{
 	  // If an object can be reached from a node with ESCAPE_GLOBAL,
@@ -1296,7 +1310,7 @@
        p != this->named_connection_nodes_.end();
        ++p)
     {
-      if (p->second->connection_node()->escape_state() == Node::ESCAPE_ARG)
+      if (p->second->connection_node()->escape_state() < Node::ESCAPE_NONE)
 	worklist.push_back(p->second);
     }
 
@@ -1305,15 +1319,30 @@
       Node* m = worklist.front();
       worklist.pop_front();
 
-      for (std::set<Node*>::iterator n = m->edges().begin();
-	   n != m->edges().end();
+      std::set<Node*> reachable = m->edges();
+      if (m->object()->is_function()
+	  && m->object()->func_value()->needs_closure())
+	{
+	  // If a closure escapes everything it closes over also escapes.
+	  Function* closure = m->object()->func_value();
+	  for (size_t i = 0; i < closure->closure_field_count(); i++)
+	    {
+	      Named_object* enclosed = closure->enclosing_var(i);
+	      Node* enclosed_node = this->lookup_connection_node(enclosed);
+	      go_assert(enclosed_node != NULL);
+	      reachable.insert(enclosed_node);
+	    }
+	}
+      for (std::set<Node*>::iterator n = reachable.begin();
+	   n != reachable.end();
 	   ++n)
 	{
 	  // If an object can be reached from a node with ESCAPE_ARG,
 	  // it is ESCAPE_ARG or ESCAPE_GLOBAL.
-	  if ((*n)->connection_node()->escape_state() > Node::ESCAPE_ARG)
+	  Node::Escapement_lattice e = m->connection_node()->escape_state();
+	  if ((*n)->connection_node()->escape_state() > e)
 	    {
-	      (*n)->connection_node()->set_escape_state(Node::ESCAPE_ARG);
+	      (*n)->connection_node()->set_escape_state(e);
 	      worklist.push_back(*n);
 	    }
 	}
diff -r 0010ef165479 go/gogo.h
--- a/go/gogo.h	Wed Apr 29 14:28:30 2015 -0700
+++ b/go/gogo.h	Wed Apr 29 15:07:47 2015 -0700
@@ -1042,6 +1042,11 @@
     this->is_unnamed_type_stub_method_ = true;
   }
 
+  // Return the amount of enclosed variables in this closure.
+  size_t
+  closure_field_count() const
+  { return this->closure_fields_.size(); }
+
   // Add a new field to the closure variable.
   void
   add_closure_field(Named_object* var, Location loc)

                 reply	other threads:[~2015-04-29 22:14 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAOyqgcV9+8jHdPy2NTO55RAc4Jm3BB6VE4B=FXdX6Fn0eQ1qEg@mail.gmail.com' \
    --to=iant@golang.org \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=gofrontend-dev@googlegroups.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).