Index: gcc/go/gofrontend/MERGE =================================================================== --- gcc/go/gofrontend/MERGE (revision 257415) +++ gcc/go/gofrontend/MERGE (working copy) @@ -1,4 +1,4 @@ -02f11a2d5cf0db2c2675c13d92bb69529f2175dd +5fe998e4a18cc1dbbd4869be5c8202bda55adb33 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. Index: gcc/go/gofrontend/types.cc =================================================================== --- gcc/go/gofrontend/types.cc (revision 257415) +++ gcc/go/gofrontend/types.cc (working copy) @@ -9096,6 +9096,8 @@ Interface_type::get_backend_empty_interf return empty_interface_type; } +Interface_type::Bmethods_map Interface_type::bmethods_map; + // Return a pointer to the backend representation of the method table. Btype* @@ -9104,6 +9106,21 @@ Interface_type::get_backend_methods(Gogo if (this->bmethods_ != NULL && !this->bmethods_is_placeholder_) return this->bmethods_; + std::pair val; + val.first = this; + val.second.btype = NULL; + val.second.is_placeholder = false; + std::pair ins = + Interface_type::bmethods_map.insert(val); + if (!ins.second + && ins.first->second.btype != NULL + && !ins.first->second.is_placeholder) + { + this->bmethods_ = ins.first->second.btype; + this->bmethods_is_placeholder_ = false; + return this->bmethods_; + } + Location loc = this->location(); std::vector @@ -9160,10 +9177,14 @@ Interface_type::get_backend_methods(Gogo Btype* st = gogo->backend()->struct_type(mfields); Btype* ret = gogo->backend()->pointer_type(st); - if (this->bmethods_ != NULL && this->bmethods_is_placeholder_) - gogo->backend()->set_placeholder_pointer_type(this->bmethods_, ret); + if (ins.first->second.btype != NULL + && ins.first->second.is_placeholder) + gogo->backend()->set_placeholder_pointer_type(ins.first->second.btype, + ret); this->bmethods_ = ret; + ins.first->second.btype = ret; this->bmethods_is_placeholder_ = false; + ins.first->second.is_placeholder = false; return ret; } @@ -9174,10 +9195,25 @@ Interface_type::get_backend_methods_plac { if (this->bmethods_ == NULL) { + std::pair val; + val.first = this; + val.second.btype = NULL; + val.second.is_placeholder = false; + std::pair ins = + Interface_type::bmethods_map.insert(val); + if (!ins.second && ins.first->second.btype != NULL) + { + this->bmethods_ = ins.first->second.btype; + this->bmethods_is_placeholder_ = ins.first->second.is_placeholder; + return this->bmethods_; + } + Location loc = this->location(); - this->bmethods_ = gogo->backend()->placeholder_pointer_type("", loc, - false); + Btype* bt = gogo->backend()->placeholder_pointer_type("", loc, false); + this->bmethods_ = bt; + ins.first->second.btype = bt; this->bmethods_is_placeholder_ = true; + ins.first->second.is_placeholder = true; } return this->bmethods_; } Index: gcc/go/gofrontend/types.h =================================================================== --- gcc/go/gofrontend/types.h (revision 257415) +++ gcc/go/gofrontend/types.h (working copy) @@ -3185,6 +3185,20 @@ class Interface_type : public Type bool assume_identical(const Interface_type*, const Interface_type*) const; + struct Bmethods_map_entry + { + Btype *btype; + bool is_placeholder; + }; + + // A mapping from Interface_type to the backend type of its bmethods_, + // used to ensure that the backend representation of identical types + // is identical. + typedef Unordered_map_hash(const Interface_type*, Bmethods_map_entry, + Type_hash_identical, Type_identical) Bmethods_map; + + static Bmethods_map bmethods_map; + // The list of methods associated with the interface from the // parser. This will be NULL for the empty interface. This may // include unnamed interface types.