reflect: use SliceHeader and StringHeader variant for internal use
These variants uses an unsafe.Pointer instead of uintptr so that the pointer/non-pointer fields match those of real slices and strings. This may be necessary in the future once we switch to a precise garbage collector.
Этот коммит содержится в:
родитель
711889bc3f
коммит
c8742e2b96
3 изменённых файлов: 35 добавлений и 20 удалений
|
@ -25,9 +25,9 @@ var arrayTypesSidetable byte
|
|||
// table.
|
||||
func readStringSidetable(table unsafe.Pointer, index uintptr) string {
|
||||
nameLen, namePtr := readVarint(unsafe.Pointer(uintptr(table) + index))
|
||||
return *(*string)(unsafe.Pointer(&StringHeader{
|
||||
Data: uintptr(namePtr),
|
||||
Len: nameLen,
|
||||
return *(*string)(unsafe.Pointer(&stringHeader{
|
||||
data: namePtr,
|
||||
len: nameLen,
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
|
@ -24,15 +24,15 @@ func Swapper(slice interface{}) func(i, j int) {
|
|||
typ := v.typecode.Elem()
|
||||
size := typ.Size()
|
||||
|
||||
header := (*SliceHeader)(v.value)
|
||||
header := (*sliceHeader)(v.value)
|
||||
tmp := unsafe.Pointer(&make([]byte, size)[0])
|
||||
|
||||
return func(i, j int) {
|
||||
if uint(i) >= uint(header.Len) || uint(j) >= uint(header.Len) {
|
||||
if uint(i) >= uint(header.len) || uint(j) >= uint(header.len) {
|
||||
panic("reflect: slice index out of range")
|
||||
}
|
||||
val1 := unsafe.Pointer(header.Data + uintptr(i)*size)
|
||||
val2 := unsafe.Pointer(header.Data + uintptr(j)*size)
|
||||
val1 := unsafe.Pointer(uintptr(header.data) + uintptr(i)*size)
|
||||
val2 := unsafe.Pointer(uintptr(header.data) + uintptr(j)*size)
|
||||
memcpy(tmp, val1, size)
|
||||
memcpy(val1, val2, size)
|
||||
memcpy(val2, tmp, size)
|
||||
|
|
|
@ -114,8 +114,8 @@ func (v Value) IsNil() bool {
|
|||
if v.value == nil {
|
||||
return true
|
||||
}
|
||||
slice := (*SliceHeader)(v.value)
|
||||
return slice.Data == 0
|
||||
slice := (*sliceHeader)(v.value)
|
||||
return slice.data == nil
|
||||
case Interface:
|
||||
if v.value == nil {
|
||||
return true
|
||||
|
@ -137,8 +137,8 @@ func (v Value) Pointer() uintptr {
|
|||
}
|
||||
return uintptr(v.value)
|
||||
case Slice:
|
||||
slice := (*SliceHeader)(v.value)
|
||||
return slice.Data
|
||||
slice := (*sliceHeader)(v.value)
|
||||
return uintptr(slice.data)
|
||||
case Func:
|
||||
panic("unimplemented: (reflect.Value).Pointer()")
|
||||
default: // not implemented: Func
|
||||
|
@ -345,9 +345,9 @@ func (v Value) Len() int {
|
|||
case Map:
|
||||
return maplen(v.value)
|
||||
case Slice:
|
||||
return int((*SliceHeader)(v.value).Len)
|
||||
return int((*sliceHeader)(v.value).len)
|
||||
case String:
|
||||
return int((*StringHeader)(v.value).Len)
|
||||
return int((*stringHeader)(v.value).len)
|
||||
default:
|
||||
panic(&ValueError{"Len"})
|
||||
}
|
||||
|
@ -365,7 +365,7 @@ func (v Value) Cap() int {
|
|||
case Chan:
|
||||
return chancap(v.value)
|
||||
case Slice:
|
||||
return int((*SliceHeader)(v.value).Cap)
|
||||
return int((*sliceHeader)(v.value).cap)
|
||||
default:
|
||||
panic(&ValueError{"Cap"})
|
||||
}
|
||||
|
@ -462,28 +462,28 @@ func (v Value) Index(i int) Value {
|
|||
switch v.Kind() {
|
||||
case Slice:
|
||||
// Extract an element from the slice.
|
||||
slice := *(*SliceHeader)(v.value)
|
||||
if uint(i) >= uint(slice.Len) {
|
||||
slice := *(*sliceHeader)(v.value)
|
||||
if uint(i) >= uint(slice.len) {
|
||||
panic("reflect: slice index out of range")
|
||||
}
|
||||
elem := Value{
|
||||
typecode: v.typecode.elem(),
|
||||
flags: v.flags | valueFlagIndirect,
|
||||
}
|
||||
addr := uintptr(slice.Data) + elem.typecode.Size()*uintptr(i) // pointer to new value
|
||||
addr := uintptr(slice.data) + elem.typecode.Size()*uintptr(i) // pointer to new value
|
||||
elem.value = unsafe.Pointer(addr)
|
||||
return elem
|
||||
case String:
|
||||
// Extract a character from a string.
|
||||
// A string is never stored directly in the interface, but always as a
|
||||
// pointer to the string value.
|
||||
s := *(*StringHeader)(v.value)
|
||||
if uint(i) >= uint(s.Len) {
|
||||
s := *(*stringHeader)(v.value)
|
||||
if uint(i) >= uint(s.len) {
|
||||
panic("reflect: string index out of range")
|
||||
}
|
||||
return Value{
|
||||
typecode: Uint8.basicType(),
|
||||
value: unsafe.Pointer(uintptr(*(*uint8)(unsafe.Pointer(s.Data + uintptr(i))))),
|
||||
value: unsafe.Pointer(uintptr(*(*uint8)(unsafe.Pointer(uintptr(s.data) + uintptr(i))))),
|
||||
}
|
||||
case Array:
|
||||
// Extract an element from the array.
|
||||
|
@ -745,11 +745,26 @@ type SliceHeader struct {
|
|||
Cap uintptr
|
||||
}
|
||||
|
||||
// Slice header that matches the underlying structure. Used for when we switch
|
||||
// to a precise GC, which needs to know exactly where pointers live.
|
||||
type sliceHeader struct {
|
||||
data unsafe.Pointer
|
||||
len uintptr
|
||||
cap uintptr
|
||||
}
|
||||
|
||||
type StringHeader struct {
|
||||
Data uintptr
|
||||
Len uintptr
|
||||
}
|
||||
|
||||
// Like sliceHeader, this type is used internally to make sure pointer and
|
||||
// non-pointer fields match those of actual strings.
|
||||
type stringHeader struct {
|
||||
data unsafe.Pointer
|
||||
len uintptr
|
||||
}
|
||||
|
||||
type ValueError struct {
|
||||
Method string
|
||||
}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче