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.
|
// table.
|
||||||
func readStringSidetable(table unsafe.Pointer, index uintptr) string {
|
func readStringSidetable(table unsafe.Pointer, index uintptr) string {
|
||||||
nameLen, namePtr := readVarint(unsafe.Pointer(uintptr(table) + index))
|
nameLen, namePtr := readVarint(unsafe.Pointer(uintptr(table) + index))
|
||||||
return *(*string)(unsafe.Pointer(&StringHeader{
|
return *(*string)(unsafe.Pointer(&stringHeader{
|
||||||
Data: uintptr(namePtr),
|
data: namePtr,
|
||||||
Len: nameLen,
|
len: nameLen,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,15 +24,15 @@ func Swapper(slice interface{}) func(i, j int) {
|
||||||
typ := v.typecode.Elem()
|
typ := v.typecode.Elem()
|
||||||
size := typ.Size()
|
size := typ.Size()
|
||||||
|
|
||||||
header := (*SliceHeader)(v.value)
|
header := (*sliceHeader)(v.value)
|
||||||
tmp := unsafe.Pointer(&make([]byte, size)[0])
|
tmp := unsafe.Pointer(&make([]byte, size)[0])
|
||||||
|
|
||||||
return func(i, j int) {
|
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")
|
panic("reflect: slice index out of range")
|
||||||
}
|
}
|
||||||
val1 := unsafe.Pointer(header.Data + uintptr(i)*size)
|
val1 := unsafe.Pointer(uintptr(header.data) + uintptr(i)*size)
|
||||||
val2 := unsafe.Pointer(header.Data + uintptr(j)*size)
|
val2 := unsafe.Pointer(uintptr(header.data) + uintptr(j)*size)
|
||||||
memcpy(tmp, val1, size)
|
memcpy(tmp, val1, size)
|
||||||
memcpy(val1, val2, size)
|
memcpy(val1, val2, size)
|
||||||
memcpy(val2, tmp, size)
|
memcpy(val2, tmp, size)
|
||||||
|
|
|
@ -114,8 +114,8 @@ func (v Value) IsNil() bool {
|
||||||
if v.value == nil {
|
if v.value == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
slice := (*SliceHeader)(v.value)
|
slice := (*sliceHeader)(v.value)
|
||||||
return slice.Data == 0
|
return slice.data == nil
|
||||||
case Interface:
|
case Interface:
|
||||||
if v.value == nil {
|
if v.value == nil {
|
||||||
return true
|
return true
|
||||||
|
@ -137,8 +137,8 @@ func (v Value) Pointer() uintptr {
|
||||||
}
|
}
|
||||||
return uintptr(v.value)
|
return uintptr(v.value)
|
||||||
case Slice:
|
case Slice:
|
||||||
slice := (*SliceHeader)(v.value)
|
slice := (*sliceHeader)(v.value)
|
||||||
return slice.Data
|
return uintptr(slice.data)
|
||||||
case Func:
|
case Func:
|
||||||
panic("unimplemented: (reflect.Value).Pointer()")
|
panic("unimplemented: (reflect.Value).Pointer()")
|
||||||
default: // not implemented: Func
|
default: // not implemented: Func
|
||||||
|
@ -345,9 +345,9 @@ func (v Value) Len() int {
|
||||||
case Map:
|
case Map:
|
||||||
return maplen(v.value)
|
return maplen(v.value)
|
||||||
case Slice:
|
case Slice:
|
||||||
return int((*SliceHeader)(v.value).Len)
|
return int((*sliceHeader)(v.value).len)
|
||||||
case String:
|
case String:
|
||||||
return int((*StringHeader)(v.value).Len)
|
return int((*stringHeader)(v.value).len)
|
||||||
default:
|
default:
|
||||||
panic(&ValueError{"Len"})
|
panic(&ValueError{"Len"})
|
||||||
}
|
}
|
||||||
|
@ -365,7 +365,7 @@ func (v Value) Cap() int {
|
||||||
case Chan:
|
case Chan:
|
||||||
return chancap(v.value)
|
return chancap(v.value)
|
||||||
case Slice:
|
case Slice:
|
||||||
return int((*SliceHeader)(v.value).Cap)
|
return int((*sliceHeader)(v.value).cap)
|
||||||
default:
|
default:
|
||||||
panic(&ValueError{"Cap"})
|
panic(&ValueError{"Cap"})
|
||||||
}
|
}
|
||||||
|
@ -462,28 +462,28 @@ func (v Value) Index(i int) Value {
|
||||||
switch v.Kind() {
|
switch v.Kind() {
|
||||||
case Slice:
|
case Slice:
|
||||||
// Extract an element from the slice.
|
// Extract an element from the slice.
|
||||||
slice := *(*SliceHeader)(v.value)
|
slice := *(*sliceHeader)(v.value)
|
||||||
if uint(i) >= uint(slice.Len) {
|
if uint(i) >= uint(slice.len) {
|
||||||
panic("reflect: slice index out of range")
|
panic("reflect: slice index out of range")
|
||||||
}
|
}
|
||||||
elem := Value{
|
elem := Value{
|
||||||
typecode: v.typecode.elem(),
|
typecode: v.typecode.elem(),
|
||||||
flags: v.flags | valueFlagIndirect,
|
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)
|
elem.value = unsafe.Pointer(addr)
|
||||||
return elem
|
return elem
|
||||||
case String:
|
case String:
|
||||||
// Extract a character from a string.
|
// Extract a character from a string.
|
||||||
// A string is never stored directly in the interface, but always as a
|
// A string is never stored directly in the interface, but always as a
|
||||||
// pointer to the string value.
|
// pointer to the string value.
|
||||||
s := *(*StringHeader)(v.value)
|
s := *(*stringHeader)(v.value)
|
||||||
if uint(i) >= uint(s.Len) {
|
if uint(i) >= uint(s.len) {
|
||||||
panic("reflect: string index out of range")
|
panic("reflect: string index out of range")
|
||||||
}
|
}
|
||||||
return Value{
|
return Value{
|
||||||
typecode: Uint8.basicType(),
|
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:
|
case Array:
|
||||||
// Extract an element from the array.
|
// Extract an element from the array.
|
||||||
|
@ -745,11 +745,26 @@ type SliceHeader struct {
|
||||||
Cap uintptr
|
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 {
|
type StringHeader struct {
|
||||||
Data uintptr
|
Data uintptr
|
||||||
Len 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 {
|
type ValueError struct {
|
||||||
Method string
|
Method string
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче