mirror of
https://github.com/golang/go
synced 2024-11-20 10:14:43 -07:00
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
This commit is contained in:
parent
313c8224d5
commit
4e7aac5413
@ -516,6 +516,7 @@ haspointers(Type *t)
|
|||||||
case TUINT32:
|
case TUINT32:
|
||||||
case TINT64:
|
case TINT64:
|
||||||
case TUINT64:
|
case TUINT64:
|
||||||
|
case TUINTPTR:
|
||||||
case TFLOAT32:
|
case TFLOAT32:
|
||||||
case TFLOAT64:
|
case TFLOAT64:
|
||||||
case TBOOL:
|
case TBOOL:
|
||||||
@ -533,7 +534,6 @@ haspointers(Type *t)
|
|||||||
case TPTR32:
|
case TPTR32:
|
||||||
case TPTR64:
|
case TPTR64:
|
||||||
case TUNSAFEPTR:
|
case TUNSAFEPTR:
|
||||||
case TUINTPTR:
|
|
||||||
case TINTER:
|
case TINTER:
|
||||||
case TCHAN:
|
case TCHAN:
|
||||||
case TMAP:
|
case TMAP:
|
||||||
|
@ -1424,11 +1424,17 @@ func (v Value) Slice(beg, end int) Value {
|
|||||||
typ = iv.typ.toType()
|
typ = iv.typ.toType()
|
||||||
base = (*SliceHeader)(iv.addr).Data
|
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.Data = base + uintptr(beg)*typ.Elem().Size()
|
||||||
s.Len = end - beg
|
s.Len = end - beg
|
||||||
s.Cap = cap - beg
|
s.Cap = end - beg
|
||||||
return valueFromAddr(iv.flag&flagRO, typ, unsafe.Pointer(s))
|
|
||||||
|
return valueFromAddr(iv.flag&flagRO, typ, unsafe.Pointer(&x))
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the string v's underlying value, as a string.
|
// 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 {
|
if typ.Kind() != Slice {
|
||||||
panic("reflect: MakeSlice of non-slice type")
|
panic("reflect: MakeSlice of non-slice type")
|
||||||
}
|
}
|
||||||
s := &SliceHeader{
|
|
||||||
Data: uintptr(unsafe.NewArray(typ.Elem(), cap)),
|
// Declare slice so that gc can see the base pointer in it.
|
||||||
Len: len,
|
var x []byte
|
||||||
Cap: cap,
|
|
||||||
}
|
// Reinterpret as *SliceHeader to edit.
|
||||||
return valueFromAddr(0, typ, unsafe.Pointer(s))
|
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.
|
// MakeChan creates a new channel with the specified type and buffer size.
|
||||||
|
@ -3,7 +3,6 @@ package runtime_test
|
|||||||
import (
|
import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"unsafe"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGcSys(t *testing.T) {
|
func TestGcSys(t *testing.T) {
|
||||||
@ -23,73 +22,3 @@ func TestGcSys(t *testing.T) {
|
|||||||
func workthegc() []byte {
|
func workthegc() []byte {
|
||||||
return make([]byte, 1029)
|
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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user