aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2011-10-18 10:03:37 -0400
committerRuss Cox <rsc@golang.org>2011-10-18 10:03:37 -0400
commit4e7aac54137bb77a0b821b1cf24dcc3f42588a7d (patch)
treeffa32c689766b521cc3cabaeab0c1e13fe205982
parent313c8224d5e16fe554252aeaa11365e33c35b87b (diff)
downloadgo-4e7aac54137bb77a0b821b1cf24dcc3f42588a7d.tar.gz
go-4e7aac54137bb77a0b821b1cf24dcc3f42588a7d.zip
reflect: make unsafe use of SliceHeader gc-friendly
Revert workaround in compiler and revert test for compiler workaround. Tested that the 386 build continues to fail if the gc change is made without the reflect change. R=golang-dev, bradfitz CC=golang-dev https://golang.org/cl/5312041
-rw-r--r--src/cmd/gc/reflect.c2
-rw-r--r--src/pkg/reflect/value.go29
-rw-r--r--src/pkg/runtime/gc_test.go71
3 files changed, 21 insertions, 81 deletions
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index 4ce1695792..ca7d08e511 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -516,6 +516,7 @@ haspointers(Type *t)
case TUINT32:
case TINT64:
case TUINT64:
+ case TUINTPTR:
case TFLOAT32:
case TFLOAT64:
case TBOOL:
@@ -533,7 +534,6 @@ haspointers(Type *t)
case TPTR32:
case TPTR64:
case TUNSAFEPTR:
- case TUINTPTR:
case TINTER:
case TCHAN:
case TMAP:
diff --git a/src/pkg/reflect/value.go b/src/pkg/reflect/value.go
index 056704f797..9ddbee0e2e 100644
--- a/src/pkg/reflect/value.go
+++ b/src/pkg/reflect/value.go
@@ -1424,11 +1424,17 @@ func (v Value) Slice(beg, end int) Value {
typ = iv.typ.toType()
base = (*SliceHeader)(iv.addr).Data
}
- s := new(SliceHeader)
+
+ // Declare slice so that gc can see the base pointer in it.
+ var x []byte
+
+ // Reinterpret as *SliceHeader to edit.
+ s := (*SliceHeader)(unsafe.Pointer(&x))
s.Data = base + uintptr(beg)*typ.Elem().Size()
s.Len = end - beg
- s.Cap = cap - beg
- return valueFromAddr(iv.flag&flagRO, typ, unsafe.Pointer(s))
+ s.Cap = end - beg
+
+ return valueFromAddr(iv.flag&flagRO, typ, unsafe.Pointer(&x))
}
// String returns the string v's underlying value, as a string.
@@ -1654,12 +1660,17 @@ func MakeSlice(typ Type, len, cap int) Value {
if typ.Kind() != Slice {
panic("reflect: MakeSlice of non-slice type")
}
- s := &SliceHeader{
- Data: uintptr(unsafe.NewArray(typ.Elem(), cap)),
- Len: len,
- Cap: cap,
- }
- return valueFromAddr(0, typ, unsafe.Pointer(s))
+
+ // Declare slice so that gc can see the base pointer in it.
+ var x []byte
+
+ // Reinterpret as *SliceHeader to edit.
+ s := (*SliceHeader)(unsafe.Pointer(&x))
+ s.Data = uintptr(unsafe.NewArray(typ.Elem(), cap))
+ s.Len = len
+ s.Cap = cap
+
+ return valueFromAddr(0, typ, unsafe.Pointer(&x))
}
// MakeChan creates a new channel with the specified type and buffer size.
diff --git a/src/pkg/runtime/gc_test.go b/src/pkg/runtime/gc_test.go
index c299ba20e7..fad60a3680 100644
--- a/src/pkg/runtime/gc_test.go
+++ b/src/pkg/runtime/gc_test.go
@@ -3,7 +3,6 @@ package runtime_test
import (
"runtime"
"testing"
- "unsafe"
)
func TestGcSys(t *testing.T) {
@@ -23,73 +22,3 @@ func TestGcSys(t *testing.T) {
func workthegc() []byte {
return make([]byte, 1029)
}
-
-func TestGcUintptr(t *testing.T) {
- p1 := unsafe.Pointer(new(int))
- *(*int)(unsafe.Pointer(p1)) = 42
- p2 := uintptr(unsafe.Pointer(new(int)))
- *(*int)(unsafe.Pointer(p2)) = 42
- var a1 [1]unsafe.Pointer
- a1[0] = unsafe.Pointer(new(int))
- *(*int)(unsafe.Pointer(a1[0])) = 42
- var a2 [1]uintptr
- a2[0] = uintptr(unsafe.Pointer(new(int)))
- *(*int)(unsafe.Pointer(a2[0])) = 42
- s1 := make([]unsafe.Pointer, 1)
- s1[0] = unsafe.Pointer(new(int))
- *(*int)(unsafe.Pointer(s1[0])) = 42
- s2 := make([]uintptr, 1)
- s2[0] = uintptr(unsafe.Pointer(new(int)))
- *(*int)(unsafe.Pointer(s2[0])) = 42
- m1 := make(map[int]unsafe.Pointer)
- m1[0] = unsafe.Pointer(new(int))
- *(*int)(unsafe.Pointer(m1[0])) = 42
- m2 := make(map[int]uintptr)
- m2[0] = uintptr(unsafe.Pointer(new(int)))
- *(*int)(unsafe.Pointer(m2[0])) = 42
- c1 := make(chan unsafe.Pointer, 1)
- func() {
- p := new(int)
- *p = 42
- c1 <- unsafe.Pointer(p)
- }()
- c2 := make(chan uintptr, 1)
- func() {
- p := new(int)
- *p = 42
- c2 <- uintptr(unsafe.Pointer(p))
- }()
-
- runtime.GC()
-
- if p, _ := runtime.Lookup((*byte)(unsafe.Pointer(p1))); p == nil || *(*int)(unsafe.Pointer(p)) != 42 {
- t.Fatalf("p1 is freed")
- }
- if p, _ := runtime.Lookup((*byte)(unsafe.Pointer(p2))); p == nil || *(*int)(unsafe.Pointer(p)) != 42 {
- t.Fatalf("p2 is freed")
- }
- if p, _ := runtime.Lookup((*byte)(unsafe.Pointer(a1[0]))); p == nil || *(*int)(unsafe.Pointer(p)) != 42 {
- t.Fatalf("a1[0] is freed")
- }
- if p, _ := runtime.Lookup((*byte)(unsafe.Pointer(a2[0]))); p == nil || *(*int)(unsafe.Pointer(p)) != 42 {
- t.Fatalf("a2[0] is freed")
- }
- if p, _ := runtime.Lookup((*byte)(unsafe.Pointer(s1[0]))); p == nil || *(*int)(unsafe.Pointer(p)) != 42 {
- t.Fatalf("s1[0] is freed")
- }
- if p, _ := runtime.Lookup((*byte)(unsafe.Pointer(s2[0]))); p == nil || *(*int)(unsafe.Pointer(p)) != 42 {
- t.Fatalf("s2[0] is freed")
- }
- if p, _ := runtime.Lookup((*byte)(unsafe.Pointer(m1[0]))); p == nil || *(*int)(unsafe.Pointer(p)) != 42 {
- t.Fatalf("m1[0] is freed")
- }
- if p, _ := runtime.Lookup((*byte)(unsafe.Pointer(m2[0]))); p == nil || *(*int)(unsafe.Pointer(p)) != 42 {
- t.Fatalf("m2[0] is freed")
- }
- if p, _ := runtime.Lookup((*byte)(unsafe.Pointer(<-c1))); p == nil || *(*int)(unsafe.Pointer(p)) != 42 {
- t.Fatalf("<-c1 is freed")
- }
- if p, _ := runtime.Lookup((*byte)(unsafe.Pointer(<-c2))); p == nil || *(*int)(unsafe.Pointer(p)) != 42 {
- t.Fatalf("<-c2 is freed")
- }
-}