1 package runtime
2 3 // This file implements Go interfaces.
4 //
5 // Interfaces are represented as a pair of {typecode, value}, where value can be
6 // anything (including non-pointers).
7 8 import "unsafe"
9 10 type _interface struct {
11 typecode unsafe.Pointer
12 value unsafe.Pointer
13 }
14 15 //go:inline
16 func composeInterface(typecode, value unsafe.Pointer) _interface {
17 return _interface{typecode, value}
18 }
19 20 //go:inline
21 func decomposeInterface(i _interface) (unsafe.Pointer, unsafe.Pointer) {
22 return i.typecode, i.value
23 }
24 25 // Return true iff both interfaces are equal.
26 func interfaceEqual(x, y interface{}) bool {
27 xi := (*_interface)(unsafe.Pointer(&x))
28 yi := (*_interface)(unsafe.Pointer(&y))
29 return rawValueEqual(xi.typecode, xi.value, yi.typecode, yi.value)
30 }
31 32 // rawValueEqual compares two values by their raw type codes and value pointers.
33 // xt/yt are type code pointers; xv/yv are interface value slots (small values
34 // packed directly, large values as pointers to data).
35 func rawValueEqual(xt, xv, yt, yv unsafe.Pointer) bool {
36 if xt == nil || yt == nil {
37 return xt == yt
38 }
39 if xt != yt {
40 return false
41 }
42 43 t := (*rawType)(xt)
44 45 // Convert interface value representation to direct data pointer.
46 // Small values (fit in a pointer) are stored directly in the value slot.
47 // Large values are stored as a pointer to the data.
48 xp, yp := xv, yv
49 if t.size() <= unsafe.Sizeof(uintptr(0)) {
50 xp = unsafe.Pointer(&xv)
51 yp = unsafe.Pointer(&yv)
52 }
53 54 return rawPtrEqual(t, xp, yp)
55 }
56 57 // rawPtrEqual compares two values where xp and yp always point directly to the
58 // value data. Used for recursive comparison of struct fields and array elements
59 // where we already have direct pointers (no interface packing).
60 func rawPtrEqual(t *rawType, xp, yp unsafe.Pointer) bool {
61 k := t.kind()
62 63 switch k {
64 case Bool:
65 return *(*bool)(xp) == *(*bool)(yp)
66 case Int:
67 return *(*int)(xp) == *(*int)(yp)
68 case Int8:
69 return *(*int8)(xp) == *(*int8)(yp)
70 case Int16:
71 return *(*int16)(xp) == *(*int16)(yp)
72 case Int32:
73 return *(*int32)(xp) == *(*int32)(yp)
74 case Int64:
75 return *(*int64)(xp) == *(*int64)(yp)
76 case Uint:
77 return *(*uint)(xp) == *(*uint)(yp)
78 case Uint8:
79 return *(*uint8)(xp) == *(*uint8)(yp)
80 case Uint16:
81 return *(*uint16)(xp) == *(*uint16)(yp)
82 case Uint32:
83 return *(*uint32)(xp) == *(*uint32)(yp)
84 case Uint64:
85 return *(*uint64)(xp) == *(*uint64)(yp)
86 case Uintptr:
87 return *(*uintptr)(xp) == *(*uintptr)(yp)
88 case Float32:
89 return *(*float32)(xp) == *(*float32)(yp)
90 case Float64:
91 return *(*float64)(xp) == *(*float64)(yp)
92 case Complex64:
93 return *(*complex64)(xp) == *(*complex64)(yp)
94 case Complex128:
95 return *(*complex128)(xp) == *(*complex128)(yp)
96 case kindBytes:
97 xs := *(*_string)(xp)
98 ys := *(*_string)(yp)
99 if xs.length != ys.length {
100 return false
101 }
102 return memequal(unsafe.Pointer(xs.ptr), unsafe.Pointer(ys.ptr), xs.length)
103 case kindChan, kindPointer, kindUnsafePointer:
104 return *(*uintptr)(xp) == *(*uintptr)(yp)
105 case kindArray:
106 elemType := t.elem()
107 elemSize := elemType.size()
108 length := t.arrayLen()
109 for i := 0; i < length; i++ {
110 ex := unsafe.Add(xp, uintptr(i)*elemSize)
111 ey := unsafe.Add(yp, uintptr(i)*elemSize)
112 if !rawPtrEqual(elemType, ex, ey) {
113 return false
114 }
115 }
116 return true
117 case kindStruct:
118 nf := t.numField()
119 for i := 0; i < nf; i++ {
120 ft := t.structFieldType(i)
121 off := t.structFieldOffset(i)
122 fx := unsafe.Add(xp, off)
123 fy := unsafe.Add(yp, off)
124 if !rawPtrEqual(ft, fx, fy) {
125 return false
126 }
127 }
128 return true
129 case kindInterface:
130 xi := (*_interface)(xp)
131 yi := (*_interface)(yp)
132 return rawValueEqual(xi.typecode, xi.value, yi.typecode, yi.value)
133 default:
134 runtimePanic("comparing un-comparable type")
135 return false
136 }
137 }
138 139 // interfaceTypeAssert is called when a type assert without comma-ok still
140 // returns false.
141 func interfaceTypeAssert(ok bool) {
142 if !ok {
143 runtimePanic("type assert failed")
144 }
145 }
146 147 // The following declarations are only used during IR construction. They are
148 // lowered to inline IR in the interface lowering pass.
149 // See compiler/interface-lowering.go for details.
150 151 type structField struct {
152 typecode unsafe.Pointer // type of this struct field
153 data *uint8 // pointer to byte array containing name, tag, varint-encoded offset, and some flags
154 }
155 156 // Pseudo function call used during a type assert. It is used during interface
157 // lowering, to assign the lowest type numbers to the types with the most type
158 // asserts. Also, it is replaced with const false if this type assert can never
159 // happen.
160 func typeAssert(actualType unsafe.Pointer, assertedType *uint8) bool
161