]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: make unsafe use of SliceHeader gc-friendly
authorRuss Cox <rsc@golang.org>
Tue, 18 Oct 2011 14:03:37 +0000 (10:03 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 18 Oct 2011 14:03:37 +0000 (10:03 -0400)
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

src/cmd/gc/reflect.c
src/pkg/reflect/value.go
src/pkg/runtime/gc_test.go

index 4ce16957929aadf31008a6dac53ac7d97a1bd067..ca7d08e511a756bc9c633435759247d4b936f8f4 100644 (file)
@@ -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:
index 056704f79726d6c98491c02fd9e7f8b29e70cdec..9ddbee0e2e1d4fef9d44de8cb3d42ace504d4d25 100644 (file)
@@ -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.
index c299ba20e7aaf1ea4b294a87aa1476546909a3ea..fad60a368041c7b457791f68b7345a595326e928 100644 (file)
@@ -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")
-       }
-}