This patch does two related things.  First, it fixes the hash code in
the type descript for a named type so that it matches the hash code the
compiler will use internally.  Second, it fixes the hash code in the new
type structure created by reflect.PtrTo to match the hash code which the
compiler will generate for that type.  Also it changes PtrTo to
canonicalize the type.  A change to the reflect test is included; I've
already committed that change in the upstream sources.  Bootstrapped and
ran Go testsuite on x86_64-unknown-linux-gnu.  Committed to mainline.

Ian

diff -r a935765ae010 go/types.cc
--- a/go/types.cc	Thu Feb 02 17:05:05 2012 -0800
+++ b/go/types.cc	Fri Feb 03 17:18:52 2012 -0800
@@ -1658,7 +1658,12 @@
 
   ++p;
   go_assert(p->is_field_name("hash"));
-  mpz_set_ui(iv, this->hash_for_method(gogo));
+  unsigned int h;
+  if (name != NULL)
+    h = name->hash_for_method(gogo);
+  else
+    h = this->hash_for_method(gogo);
+  mpz_set_ui(iv, h);
   vals->push_back(Expression::make_integer(&iv, p->type(), bloc));
 
   ++p;
diff -r a935765ae010 libgo/go/reflect/all_test.go
--- a/libgo/go/reflect/all_test.go	Thu Feb 02 17:05:05 2012 -0800
+++ b/libgo/go/reflect/all_test.go	Fri Feb 03 17:18:52 2012 -0800
@@ -1528,6 +1528,18 @@
 	if p.X != 4 {
 		t.Errorf("Addr.Elem.Set valued to set value in top value")
 	}
+
+	// Verify that taking the address of a type gives us a pointer
+	// which we can convert back using the usual interface
+	// notation.
+	var s struct {
+		B *bool
+	}
+	ps := ValueOf(&s).Elem().Field(0).Addr().Interface()
+	*(ps.(**bool)) = new(bool)
+	if s.B == nil {
+		t.Errorf("Addr.Interface direct assignment failed")
+	}
 }
 
 /* gccgo does do allocations here.
diff -r a935765ae010 libgo/go/reflect/type.go
--- a/libgo/go/reflect/type.go	Thu Feb 02 17:05:05 2012 -0800
+++ b/libgo/go/reflect/type.go	Fri Feb 03 17:18:52 2012 -0800
@@ -999,6 +999,17 @@
 		return &p.commonType
 	}
 
+	s := "*" + *ct.string
+
+	canonicalTypeLock.RLock()
+	r, ok := canonicalType[s]
+	canonicalTypeLock.RUnlock()
+	if ok {
+		ptrMap.m[ct] = (*ptrType)(unsafe.Pointer(r.(*commonType)))
+		ptrMap.Unlock()
+		return r.(*commonType)
+	}
+
 	rp := new(runtime.PtrType)
 
 	// initialize p using *byte's ptrType as a prototype.
@@ -1008,7 +1019,6 @@
 	bp := (*ptrType)(unsafe.Pointer(unsafe.Typeof((*byte)(nil)).(*runtime.PtrType)))
 	*p = *bp
 
-	s := "*" + *ct.string
 	p.string = &s
 
 	// For the type structures linked into the binary, the
@@ -1016,12 +1026,16 @@
 	// Create a good hash for the new string by using
 	// the FNV-1 hash's mixing function to combine the
 	// old hash and the new "*".
-	p.hash = ct.hash*16777619 ^ '*'
+	// p.hash = ct.hash*16777619 ^ '*'
+	// This is the gccgo version.
+	p.hash = (ct.hash << 4) + 9
 
 	p.uncommonType = nil
 	p.ptrToThis = nil
 	p.elem = (*runtime.Type)(unsafe.Pointer(ct))
 
+	p = canonicalize(p).(*ptrType)
+
 	ptrMap.m[ct] = p
 	ptrMap.Unlock()
 	return &p.commonType

Reply via email to