helper_unsafe.go

  1// +build !safe
  2// +build !appengine
  3// +build go1.7
  4
  5// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
  6// Use of this source code is governed by a MIT license found in the LICENSE file.
  7
  8package codec
  9
 10import (
 11	"reflect"
 12	"sync/atomic"
 13	"time"
 14	"unsafe"
 15)
 16
 17// This file has unsafe variants of some helper methods.
 18// NOTE: See helper_not_unsafe.go for the usage information.
 19
 20// var zeroRTv [4]uintptr
 21
 22const safeMode = false
 23const unsafeFlagIndir = 1 << 7 // keep in sync with GO_ROOT/src/reflect/value.go
 24
 25type unsafeString struct {
 26	Data unsafe.Pointer
 27	Len  int
 28}
 29
 30type unsafeSlice struct {
 31	Data unsafe.Pointer
 32	Len  int
 33	Cap  int
 34}
 35
 36type unsafeIntf struct {
 37	typ  unsafe.Pointer
 38	word unsafe.Pointer
 39}
 40
 41type unsafeReflectValue struct {
 42	typ  unsafe.Pointer
 43	ptr  unsafe.Pointer
 44	flag uintptr
 45}
 46
 47func stringView(v []byte) string {
 48	if len(v) == 0 {
 49		return ""
 50	}
 51	bx := (*unsafeSlice)(unsafe.Pointer(&v))
 52	return *(*string)(unsafe.Pointer(&unsafeString{bx.Data, bx.Len}))
 53}
 54
 55func bytesView(v string) []byte {
 56	if len(v) == 0 {
 57		return zeroByteSlice
 58	}
 59	sx := (*unsafeString)(unsafe.Pointer(&v))
 60	return *(*[]byte)(unsafe.Pointer(&unsafeSlice{sx.Data, sx.Len, sx.Len}))
 61}
 62
 63func definitelyNil(v interface{}) bool {
 64	// There is no global way of checking if an interface is nil.
 65	// For true references (map, ptr, func, chan), you can just look
 66	// at the word of the interface. However, for slices, you have to dereference
 67	// the word, and get a pointer to the 3-word interface value.
 68	//
 69	// However, the following are cheap calls
 70	// - TypeOf(interface): cheap 2-line call.
 71	// - ValueOf(interface{}): expensive
 72	// - type.Kind: cheap call through an interface
 73	// - Value.Type(): cheap call
 74	//                 except it's a method value (e.g. r.Read, which implies that it is a Func)
 75
 76	return ((*unsafeIntf)(unsafe.Pointer(&v))).word == nil
 77}
 78
 79func rv2i(rv reflect.Value) interface{} {
 80	// TODO: consider a more generally-known optimization for reflect.Value ==> Interface
 81	//
 82	// Currently, we use this fragile method that taps into implememtation details from
 83	// the source go stdlib reflect/value.go, and trims the implementation.
 84
 85	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 86	// true references (map, func, chan, ptr - NOT slice) may be double-referenced as flagIndir
 87	var ptr unsafe.Pointer
 88	if refBitset.isset(byte(urv.flag&(1<<5-1))) && urv.flag&unsafeFlagIndir != 0 {
 89		ptr = *(*unsafe.Pointer)(urv.ptr)
 90	} else {
 91		ptr = urv.ptr
 92	}
 93	return *(*interface{})(unsafe.Pointer(&unsafeIntf{typ: urv.typ, word: ptr}))
 94}
 95
 96func rt2id(rt reflect.Type) uintptr {
 97	return uintptr(((*unsafeIntf)(unsafe.Pointer(&rt))).word)
 98}
 99
100func rv2rtid(rv reflect.Value) uintptr {
101	return uintptr((*unsafeReflectValue)(unsafe.Pointer(&rv)).typ)
102}
103
104func i2rtid(i interface{}) uintptr {
105	return uintptr(((*unsafeIntf)(unsafe.Pointer(&i))).typ)
106}
107
108// --------------------------
109
110func isEmptyValue(v reflect.Value, tinfos *TypeInfos, deref, checkStruct bool) bool {
111	urv := (*unsafeReflectValue)(unsafe.Pointer(&v))
112	if urv.flag == 0 {
113		return true
114	}
115	switch v.Kind() {
116	case reflect.Invalid:
117		return true
118	case reflect.String:
119		return (*unsafeString)(urv.ptr).Len == 0
120	case reflect.Slice:
121		return (*unsafeSlice)(urv.ptr).Len == 0
122	case reflect.Bool:
123		return !*(*bool)(urv.ptr)
124	case reflect.Int:
125		return *(*int)(urv.ptr) == 0
126	case reflect.Int8:
127		return *(*int8)(urv.ptr) == 0
128	case reflect.Int16:
129		return *(*int16)(urv.ptr) == 0
130	case reflect.Int32:
131		return *(*int32)(urv.ptr) == 0
132	case reflect.Int64:
133		return *(*int64)(urv.ptr) == 0
134	case reflect.Uint:
135		return *(*uint)(urv.ptr) == 0
136	case reflect.Uint8:
137		return *(*uint8)(urv.ptr) == 0
138	case reflect.Uint16:
139		return *(*uint16)(urv.ptr) == 0
140	case reflect.Uint32:
141		return *(*uint32)(urv.ptr) == 0
142	case reflect.Uint64:
143		return *(*uint64)(urv.ptr) == 0
144	case reflect.Uintptr:
145		return *(*uintptr)(urv.ptr) == 0
146	case reflect.Float32:
147		return *(*float32)(urv.ptr) == 0
148	case reflect.Float64:
149		return *(*float64)(urv.ptr) == 0
150	case reflect.Interface:
151		isnil := urv.ptr == nil || *(*unsafe.Pointer)(urv.ptr) == nil
152		if deref {
153			if isnil {
154				return true
155			}
156			return isEmptyValue(v.Elem(), tinfos, deref, checkStruct)
157		}
158		return isnil
159	case reflect.Ptr:
160		// isnil := urv.ptr == nil (not sufficient, as a pointer value encodes the type)
161		isnil := urv.ptr == nil || *(*unsafe.Pointer)(urv.ptr) == nil
162		if deref {
163			if isnil {
164				return true
165			}
166			return isEmptyValue(v.Elem(), tinfos, deref, checkStruct)
167		}
168		return isnil
169	case reflect.Struct:
170		return isEmptyStruct(v, tinfos, deref, checkStruct)
171	case reflect.Map, reflect.Array, reflect.Chan:
172		return v.Len() == 0
173	}
174	return false
175}
176
177// --------------------------
178
179// atomicTypeInfoSlice contains length and pointer to the array for a slice.
180// It is expected to be 2 words.
181//
182// Previously, we atomically loaded and stored the length and array pointer separately,
183// which could lead to some races.
184// We now just atomically store and load the pointer to the value directly.
185
186type atomicTypeInfoSlice struct { // expected to be 2 words
187	l int            // length of the data array (must be first in struct, for 64-bit alignment necessary for 386)
188	v unsafe.Pointer // data array - Pointer (not uintptr) to maintain GC reference
189}
190
191func (x *atomicTypeInfoSlice) load() []rtid2ti {
192	xp := unsafe.Pointer(x)
193	x2 := *(*atomicTypeInfoSlice)(atomic.LoadPointer(&xp))
194	if x2.l == 0 {
195		return nil
196	}
197	return *(*[]rtid2ti)(unsafe.Pointer(&unsafeSlice{Data: x2.v, Len: x2.l, Cap: x2.l}))
198}
199
200func (x *atomicTypeInfoSlice) store(p []rtid2ti) {
201	s := (*unsafeSlice)(unsafe.Pointer(&p))
202	xp := unsafe.Pointer(x)
203	atomic.StorePointer(&xp, unsafe.Pointer(&atomicTypeInfoSlice{l: s.Len, v: s.Data}))
204}
205
206// --------------------------
207func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
208	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
209	*(*[]byte)(urv.ptr) = d.rawBytes()
210}
211
212func (d *Decoder) kString(f *codecFnInfo, rv reflect.Value) {
213	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
214	*(*string)(urv.ptr) = d.d.DecodeString()
215}
216
217func (d *Decoder) kBool(f *codecFnInfo, rv reflect.Value) {
218	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
219	*(*bool)(urv.ptr) = d.d.DecodeBool()
220}
221
222func (d *Decoder) kTime(f *codecFnInfo, rv reflect.Value) {
223	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
224	*(*time.Time)(urv.ptr) = d.d.DecodeTime()
225}
226
227func (d *Decoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
228	fv := d.d.DecodeFloat64()
229	if chkOvf.Float32(fv) {
230		d.errorf("float32 overflow: %v", fv)
231	}
232	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
233	*(*float32)(urv.ptr) = float32(fv)
234}
235
236func (d *Decoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
237	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
238	*(*float64)(urv.ptr) = d.d.DecodeFloat64()
239}
240
241func (d *Decoder) kInt(f *codecFnInfo, rv reflect.Value) {
242	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
243	*(*int)(urv.ptr) = int(chkOvf.IntV(d.d.DecodeInt64(), intBitsize))
244}
245
246func (d *Decoder) kInt8(f *codecFnInfo, rv reflect.Value) {
247	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
248	*(*int8)(urv.ptr) = int8(chkOvf.IntV(d.d.DecodeInt64(), 8))
249}
250
251func (d *Decoder) kInt16(f *codecFnInfo, rv reflect.Value) {
252	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
253	*(*int16)(urv.ptr) = int16(chkOvf.IntV(d.d.DecodeInt64(), 16))
254}
255
256func (d *Decoder) kInt32(f *codecFnInfo, rv reflect.Value) {
257	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
258	*(*int32)(urv.ptr) = int32(chkOvf.IntV(d.d.DecodeInt64(), 32))
259}
260
261func (d *Decoder) kInt64(f *codecFnInfo, rv reflect.Value) {
262	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
263	*(*int64)(urv.ptr) = d.d.DecodeInt64()
264}
265
266func (d *Decoder) kUint(f *codecFnInfo, rv reflect.Value) {
267	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
268	*(*uint)(urv.ptr) = uint(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
269}
270
271func (d *Decoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
272	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
273	*(*uintptr)(urv.ptr) = uintptr(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
274}
275
276func (d *Decoder) kUint8(f *codecFnInfo, rv reflect.Value) {
277	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
278	*(*uint8)(urv.ptr) = uint8(chkOvf.UintV(d.d.DecodeUint64(), 8))
279}
280
281func (d *Decoder) kUint16(f *codecFnInfo, rv reflect.Value) {
282	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
283	*(*uint16)(urv.ptr) = uint16(chkOvf.UintV(d.d.DecodeUint64(), 16))
284}
285
286func (d *Decoder) kUint32(f *codecFnInfo, rv reflect.Value) {
287	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
288	*(*uint32)(urv.ptr) = uint32(chkOvf.UintV(d.d.DecodeUint64(), 32))
289}
290
291func (d *Decoder) kUint64(f *codecFnInfo, rv reflect.Value) {
292	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
293	*(*uint64)(urv.ptr) = d.d.DecodeUint64()
294}
295
296// ------------
297
298func (e *Encoder) kBool(f *codecFnInfo, rv reflect.Value) {
299	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
300	e.e.EncodeBool(*(*bool)(v.ptr))
301}
302
303func (e *Encoder) kTime(f *codecFnInfo, rv reflect.Value) {
304	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
305	e.e.EncodeTime(*(*time.Time)(v.ptr))
306}
307
308func (e *Encoder) kString(f *codecFnInfo, rv reflect.Value) {
309	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
310	e.e.EncodeString(cUTF8, *(*string)(v.ptr))
311}
312
313func (e *Encoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
314	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
315	e.e.EncodeFloat64(*(*float64)(v.ptr))
316}
317
318func (e *Encoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
319	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
320	e.e.EncodeFloat32(*(*float32)(v.ptr))
321}
322
323func (e *Encoder) kInt(f *codecFnInfo, rv reflect.Value) {
324	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
325	e.e.EncodeInt(int64(*(*int)(v.ptr)))
326}
327
328func (e *Encoder) kInt8(f *codecFnInfo, rv reflect.Value) {
329	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
330	e.e.EncodeInt(int64(*(*int8)(v.ptr)))
331}
332
333func (e *Encoder) kInt16(f *codecFnInfo, rv reflect.Value) {
334	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
335	e.e.EncodeInt(int64(*(*int16)(v.ptr)))
336}
337
338func (e *Encoder) kInt32(f *codecFnInfo, rv reflect.Value) {
339	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
340	e.e.EncodeInt(int64(*(*int32)(v.ptr)))
341}
342
343func (e *Encoder) kInt64(f *codecFnInfo, rv reflect.Value) {
344	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
345	e.e.EncodeInt(int64(*(*int64)(v.ptr)))
346}
347
348func (e *Encoder) kUint(f *codecFnInfo, rv reflect.Value) {
349	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
350	e.e.EncodeUint(uint64(*(*uint)(v.ptr)))
351}
352
353func (e *Encoder) kUint8(f *codecFnInfo, rv reflect.Value) {
354	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
355	e.e.EncodeUint(uint64(*(*uint8)(v.ptr)))
356}
357
358func (e *Encoder) kUint16(f *codecFnInfo, rv reflect.Value) {
359	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
360	e.e.EncodeUint(uint64(*(*uint16)(v.ptr)))
361}
362
363func (e *Encoder) kUint32(f *codecFnInfo, rv reflect.Value) {
364	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
365	e.e.EncodeUint(uint64(*(*uint32)(v.ptr)))
366}
367
368func (e *Encoder) kUint64(f *codecFnInfo, rv reflect.Value) {
369	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
370	e.e.EncodeUint(uint64(*(*uint64)(v.ptr)))
371}
372
373func (e *Encoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
374	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
375	e.e.EncodeUint(uint64(*(*uintptr)(v.ptr)))
376}
377
378// ------------
379
380// func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
381// 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
382// 	// if urv.flag&unsafeFlagIndir != 0 {
383// 	// 	urv.ptr = *(*unsafe.Pointer)(urv.ptr)
384// 	// }
385// 	*(*[]byte)(urv.ptr) = d.rawBytes()
386// }
387
388// func rv0t(rt reflect.Type) reflect.Value {
389// 	ut := (*unsafeIntf)(unsafe.Pointer(&rt))
390// 	// we need to determine whether ifaceIndir, and then whether to just pass 0 as the ptr
391// 	uv := unsafeReflectValue{ut.word, &zeroRTv, flag(rt.Kind())}
392// 	return *(*reflect.Value)(unsafe.Pointer(&uv})
393// }
394
395// func rv2i(rv reflect.Value) interface{} {
396// 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
397// 	// true references (map, func, chan, ptr - NOT slice) may be double-referenced as flagIndir
398// 	var ptr unsafe.Pointer
399// 	// kk := reflect.Kind(urv.flag & (1<<5 - 1))
400// 	// if (kk == reflect.Map || kk == reflect.Ptr || kk == reflect.Chan || kk == reflect.Func) && urv.flag&unsafeFlagIndir != 0 {
401// 	if refBitset.isset(byte(urv.flag&(1<<5-1))) && urv.flag&unsafeFlagIndir != 0 {
402// 		ptr = *(*unsafe.Pointer)(urv.ptr)
403// 	} else {
404// 		ptr = urv.ptr
405// 	}
406// 	return *(*interface{})(unsafe.Pointer(&unsafeIntf{typ: urv.typ, word: ptr}))
407// 	// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
408// 	// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
409// }
410
411// func definitelyNil(v interface{}) bool {
412// 	var ui *unsafeIntf = (*unsafeIntf)(unsafe.Pointer(&v))
413// 	if ui.word == nil {
414// 		return true
415// 	}
416// 	var tk = reflect.TypeOf(v).Kind()
417// 	return (tk == reflect.Interface || tk == reflect.Slice) && *(*unsafe.Pointer)(ui.word) == nil
418// 	fmt.Printf(">>>> definitely nil: isnil: %v, TYPE: \t%T, word: %v, *word: %v, type: %v, nil: %v\n",
419// 	v == nil, v, word, *((*unsafe.Pointer)(word)), ui.typ, nil)
420// }
421
422// func keepAlive4BytesView(v string) {
423// 	runtime.KeepAlive(v)
424// }
425
426// func keepAlive4StringView(v []byte) {
427// 	runtime.KeepAlive(v)
428// }
429
430// func rt2id(rt reflect.Type) uintptr {
431// 	return uintptr(((*unsafeIntf)(unsafe.Pointer(&rt))).word)
432// 	// var i interface{} = rt
433// 	// // ui := (*unsafeIntf)(unsafe.Pointer(&i))
434// 	// return ((*unsafeIntf)(unsafe.Pointer(&i))).word
435// }
436
437// func rv2i(rv reflect.Value) interface{} {
438// 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
439// 	// non-reference type: already indir
440// 	// reference type: depend on flagIndir property ('cos maybe was double-referenced)
441// 	// const (unsafeRvFlagKindMask    = 1<<5 - 1 , unsafeRvFlagIndir       = 1 << 7 )
442// 	// rvk := reflect.Kind(urv.flag & (1<<5 - 1))
443// 	// if (rvk == reflect.Chan ||
444// 	// 	rvk == reflect.Func ||
445// 	// 	rvk == reflect.Interface ||
446// 	// 	rvk == reflect.Map ||
447// 	// 	rvk == reflect.Ptr ||
448// 	// 	rvk == reflect.UnsafePointer) && urv.flag&(1<<8) != 0 {
449// 	// 	fmt.Printf(">>>>> ---- double indirect reference: %v, %v\n", rvk, rv.Type())
450// 	// 	return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
451// 	// }
452// 	if urv.flag&(1<<5-1) == uintptr(reflect.Map) && urv.flag&(1<<7) != 0 {
453// 		// fmt.Printf(">>>>> ---- double indirect reference: %v, %v\n", rvk, rv.Type())
454// 		return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
455// 	}
456// 	// fmt.Printf(">>>>> ++++ direct reference: %v, %v\n", rvk, rv.Type())
457// 	return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
458// }
459
460// const (
461// 	unsafeRvFlagKindMask    = 1<<5 - 1
462// 	unsafeRvKindDirectIface = 1 << 5
463// 	unsafeRvFlagIndir       = 1 << 7
464// 	unsafeRvFlagAddr        = 1 << 8
465// 	unsafeRvFlagMethod      = 1 << 9
466
467// 	_USE_RV_INTERFACE bool = false
468// 	_UNSAFE_RV_DEBUG       = true
469// )
470
471// type unsafeRtype struct {
472// 	_    [2]uintptr
473// 	_    uint32
474// 	_    uint8
475// 	_    uint8
476// 	_    uint8
477// 	kind uint8
478// 	_    [2]uintptr
479// 	_    int32
480// }
481
482// func _rv2i(rv reflect.Value) interface{} {
483// 	// Note: From use,
484// 	//   - it's never an interface
485// 	//   - the only calls here are for ifaceIndir types.
486// 	//     (though that conditional is wrong)
487// 	//     To know for sure, we need the value of t.kind (which is not exposed).
488// 	//
489// 	// Need to validate the path: type is indirect ==> only value is indirect ==> default (value is direct)
490// 	//    - Type indirect, Value indirect: ==> numbers, boolean, slice, struct, array, string
491// 	//    - Type Direct,   Value indirect: ==> map???
492// 	//    - Type Direct,   Value direct:   ==> pointers, unsafe.Pointer, func, chan, map
493// 	//
494// 	// TRANSLATES TO:
495// 	//    if typeIndirect { } else if valueIndirect { } else { }
496// 	//
497// 	// Since we don't deal with funcs, then "flagNethod" is unset, and can be ignored.
498
499// 	if _USE_RV_INTERFACE {
500// 		return rv.Interface()
501// 	}
502// 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
503
504// 	// if urv.flag&unsafeRvFlagMethod != 0 || urv.flag&unsafeRvFlagKindMask == uintptr(reflect.Interface) {
505// 	// 	println("***** IS flag method or interface: delegating to rv.Interface()")
506// 	// 	return rv.Interface()
507// 	// }
508
509// 	// if urv.flag&unsafeRvFlagKindMask == uintptr(reflect.Interface) {
510// 	// 	println("***** IS Interface: delegate to rv.Interface")
511// 	// 	return rv.Interface()
512// 	// }
513// 	// if urv.flag&unsafeRvFlagKindMask&unsafeRvKindDirectIface == 0 {
514// 	// 	if urv.flag&unsafeRvFlagAddr == 0 {
515// 	// 		println("***** IS ifaceIndir typ")
516// 	// 		// ui := unsafeIntf{word: urv.ptr, typ: urv.typ}
517// 	// 		// return *(*interface{})(unsafe.Pointer(&ui))
518// 	// 		// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
519// 	// 	}
520// 	// } else if urv.flag&unsafeRvFlagIndir != 0 {
521// 	// 	println("***** IS flagindir")
522// 	// 	// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
523// 	// } else {
524// 	// 	println("***** NOT flagindir")
525// 	// 	return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
526// 	// }
527// 	// println("***** default: delegate to rv.Interface")
528
529// 	urt := (*unsafeRtype)(unsafe.Pointer(urv.typ))
530// 	if _UNSAFE_RV_DEBUG {
531// 		fmt.Printf(">>>> start: %v: ", rv.Type())
532// 		fmt.Printf("%v - %v\n", *urv, *urt)
533// 	}
534// 	if urt.kind&unsafeRvKindDirectIface == 0 {
535// 		if _UNSAFE_RV_DEBUG {
536// 			fmt.Printf("**** +ifaceIndir type: %v\n", rv.Type())
537// 		}
538// 		// println("***** IS ifaceIndir typ")
539// 		// if true || urv.flag&unsafeRvFlagAddr == 0 {
540// 		// 	// println("    ***** IS NOT addr")
541// 		return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
542// 		// }
543// 	} else if urv.flag&unsafeRvFlagIndir != 0 {
544// 		if _UNSAFE_RV_DEBUG {
545// 			fmt.Printf("**** +flagIndir type: %v\n", rv.Type())
546// 		}
547// 		// println("***** IS flagindir")
548// 		return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
549// 	} else {
550// 		if _UNSAFE_RV_DEBUG {
551// 			fmt.Printf("**** -flagIndir type: %v\n", rv.Type())
552// 		}
553// 		// println("***** NOT flagindir")
554// 		return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
555// 	}
556// 	// println("***** default: delegating to rv.Interface()")
557// 	// return rv.Interface()
558// }
559
560// var staticM0 = make(map[string]uint64)
561// var staticI0 = (int32)(-5)
562
563// func staticRv2iTest() {
564// 	i0 := (int32)(-5)
565// 	m0 := make(map[string]uint16)
566// 	m0["1"] = 1
567// 	for _, i := range []interface{}{
568// 		(int)(7),
569// 		(uint)(8),
570// 		(int16)(-9),
571// 		(uint16)(19),
572// 		(uintptr)(77),
573// 		(bool)(true),
574// 		float32(-32.7),
575// 		float64(64.9),
576// 		complex(float32(19), 5),
577// 		complex(float64(-32), 7),
578// 		[4]uint64{1, 2, 3, 4},
579// 		(chan<- int)(nil), // chan,
580// 		rv2i,              // func
581// 		io.Writer(ioutil.Discard),
582// 		make(map[string]uint),
583// 		(map[string]uint)(nil),
584// 		staticM0,
585// 		m0,
586// 		&m0,
587// 		i0,
588// 		&i0,
589// 		&staticI0,
590// 		&staticM0,
591// 		[]uint32{6, 7, 8},
592// 		"abc",
593// 		Raw{},
594// 		RawExt{},
595// 		&Raw{},
596// 		&RawExt{},
597// 		unsafe.Pointer(&i0),
598// 	} {
599// 		i2 := rv2i(reflect.ValueOf(i))
600// 		eq := reflect.DeepEqual(i, i2)
601// 		fmt.Printf(">>>> %v == %v? %v\n", i, i2, eq)
602// 	}
603// 	// os.Exit(0)
604// }
605
606// func init() {
607// 	staticRv2iTest()
608// }
609
610// func rv2i(rv reflect.Value) interface{} {
611// 	if _USE_RV_INTERFACE || rv.Kind() == reflect.Interface || rv.CanAddr() {
612// 		return rv.Interface()
613// 	}
614// 	// var i interface{}
615// 	// ui := (*unsafeIntf)(unsafe.Pointer(&i))
616// 	var ui unsafeIntf
617// 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
618// 	// fmt.Printf("urv: flag: %b, typ: %b, ptr: %b\n", urv.flag, uintptr(urv.typ), uintptr(urv.ptr))
619// 	if (urv.flag&unsafeRvFlagKindMask)&unsafeRvKindDirectIface == 0 {
620// 		if urv.flag&unsafeRvFlagAddr != 0 {
621// 			println("***** indirect and addressable! Needs typed move - delegate to rv.Interface()")
622// 			return rv.Interface()
623// 		}
624// 		println("****** indirect type/kind")
625// 		ui.word = urv.ptr
626// 	} else if urv.flag&unsafeRvFlagIndir != 0 {
627// 		println("****** unsafe rv flag indir")
628// 		ui.word = *(*unsafe.Pointer)(urv.ptr)
629// 	} else {
630// 		println("****** default: assign prt to word directly")
631// 		ui.word = urv.ptr
632// 	}
633// 	// ui.word = urv.ptr
634// 	ui.typ = urv.typ
635// 	// fmt.Printf("(pointers) ui.typ: %p, word: %p\n", ui.typ, ui.word)
636// 	// fmt.Printf("(binary)   ui.typ: %b, word: %b\n", uintptr(ui.typ), uintptr(ui.word))
637// 	return *(*interface{})(unsafe.Pointer(&ui))
638// 	// return i
639// }