diff --git a/src/reflect/type.go b/src/reflect/type.go index b5142ca6..126450de 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -318,7 +318,7 @@ func (t Type) Size() uintptr { case Slice: return unsafe.Sizeof(SliceHeader{}) case Interface: - return unsafe.Sizeof(interfaceHeader{}) + return unsafe.Sizeof(interface{}(nil)) case Array: return t.Elem().Size() * uintptr(t.Len()) case Struct: @@ -364,7 +364,7 @@ func (t Type) Align() int { case Slice: return int(unsafe.Alignof(SliceHeader{})) case Interface: - return int(unsafe.Alignof(interfaceHeader{})) + return int(unsafe.Alignof(interface{}(nil))) case Struct: numField := t.NumField() alignment := 1 diff --git a/src/reflect/value.go b/src/reflect/value.go index a2ed58aa..ad3b1fcb 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -35,20 +35,22 @@ func Indirect(v Value) Value { return v.Elem() } +//go:linkname composeInterface runtime.composeInterface +func composeInterface(Type, unsafe.Pointer) interface{} + +//go:linkname decomposeInterface runtime.decomposeInterface +func decomposeInterface(i interface{}) (Type, unsafe.Pointer) + func ValueOf(i interface{}) Value { - v := (*interfaceHeader)(unsafe.Pointer(&i)) + typecode, value := decomposeInterface(i) return Value{ - typecode: v.typecode, - value: v.value, + typecode: typecode, + value: value, flags: valueFlagExported, } } func (v Value) Interface() interface{} { - i := interfaceHeader{ - typecode: v.typecode, - value: v.value, - } if v.isIndirect() && v.Type().Size() <= unsafe.Sizeof(uintptr(0)) { // Value was indirect but must be put back directly in the interface // value. @@ -56,9 +58,9 @@ func (v Value) Interface() interface{} { for j := v.Type().Size(); j != 0; j-- { value = (value << 8) | uintptr(*(*uint8)(unsafe.Pointer(uintptr(v.value) + j - 1))) } - i.value = unsafe.Pointer(value) + v.value = unsafe.Pointer(value) } - return *(*interface{})(unsafe.Pointer(&i)) + return composeInterface(v.typecode, v.value) } func (v Value) Type() Type { @@ -94,8 +96,8 @@ func (v Value) IsNil() bool { if v.value == nil { return true } - itf := (*interfaceHeader)(v.value) - return itf.value == nil + _, val := decomposeInterface(*(*interface{})(v.value)) + return val == nil default: panic(&ValueError{"IsNil"}) } @@ -657,12 +659,6 @@ type funcHeader struct { Code unsafe.Pointer } -// This is the same thing as an interface{}. -type interfaceHeader struct { - typecode Type - value unsafe.Pointer -} - type SliceHeader struct { Data uintptr Len uintptr diff --git a/src/runtime/interface.go b/src/runtime/interface.go index 78cfba2c..d0fce58d 100644 --- a/src/runtime/interface.go +++ b/src/runtime/interface.go @@ -12,6 +12,16 @@ type _interface struct { value unsafe.Pointer } +//go:inline +func composeInterface(typecode uintptr, value unsafe.Pointer) _interface { + return _interface{typecode, value} +} + +//go:inline +func decomposeInterface(i _interface) (uintptr, unsafe.Pointer) { + return i.typecode, i.value +} + // Return true iff both interfaces are equal. func interfaceEqual(x, y _interface) bool { if x.typecode != y.typecode {