compiler: improve type caching for interface types
authorIan Lance Taylor <ian@gcc.gnu.org>
Wed, 3 Aug 2016 20:01:09 +0000 (20:01 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Wed, 3 Aug 2016 20:01:09 +0000 (20:01 +0000)
    Add a cached to Interface_info_expression::do_type() so as to reuse
    previously created interface types. This change reduces gccgo peak heap
    usage when compiling the "fmt" package from around 16mb to around 10mb.

    Fixes golang/go#16334

    Reviewed-on: https://go-review.googlesource.com/24890

From-SVN: r239095

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/expressions.cc

index 5009c891e8aed16d76aa2093125154db22f3a669..1d833281f1dc36d741bbb67d09d742d33aa204e9 100644 (file)
@@ -1,4 +1,4 @@
-7d6c53910e52b7db2a77c1c1c3bc2c170283a1fa
+0fb416a7bed076bdfef168480789bb2994a58de3
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index ff2893f960c154f840a86b53b7c7b6a574849579..71a84c76b1dfcbf927bf6ea4560aa0e8bca50bfe 100644 (file)
@@ -14114,16 +14114,27 @@ Interface_info_expression::do_type()
     {
     case INTERFACE_INFO_METHODS:
       {
+        typedef Unordered_map(Interface_type*, Type*) Hashtable;
+        static Hashtable result_types;
+
+        Interface_type* itype = this->iface_->type()->interface_type();
+
+        Hashtable::const_iterator p = result_types.find(itype);
+        if (p != result_types.end())
+          return p->second;
+
         Type* pdt = Type::make_type_descriptor_ptr_type();
-        if (this->iface_->type()->interface_type()->is_empty())
-          return pdt;
+        if (itype->is_empty())
+          {
+            result_types[itype] = pdt;
+            return pdt;
+          }
 
         Location loc = this->location();
         Struct_field_list* sfl = new Struct_field_list();
         sfl->push_back(
             Struct_field(Typed_identifier("__type_descriptor", pdt, loc)));
 
-        Interface_type* itype = this->iface_->type()->interface_type();
         for (Typed_identifier_list::const_iterator p = itype->methods()->begin();
              p != itype->methods()->end();
              ++p)
@@ -14156,7 +14167,9 @@ Interface_info_expression::do_type()
             sfl->push_back(Struct_field(Typed_identifier(fname, mft, loc)));
           }
 
-        return Type::make_pointer_type(Type::make_struct_type(sfl, loc));
+        Pointer_type *pt = Type::make_pointer_type(Type::make_struct_type(sfl, loc));
+        result_types[itype] = pt;
+        return pt;
       }
     case INTERFACE_INFO_OBJECT:
       return Type::make_pointer_type(Type::make_void_type());