Home | History | Annotate | Download | only in runtime
      1 // Copyright 2014 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package runtime
      6 
      7 import (
      8 	"runtime/internal/atomic"
      9 	"runtime/internal/sys"
     10 	"unsafe"
     11 )
     12 
     13 const itabInitSize = 512
     14 
     15 var (
     16 	itabLock      mutex                               // lock for accessing itab table
     17 	itabTable     = &itabTableInit                    // pointer to current table
     18 	itabTableInit = itabTableType{size: itabInitSize} // starter table
     19 )
     20 
     21 //Note: change the formula in the mallocgc call in itabAdd if you change these fields.
     22 type itabTableType struct {
     23 	size    uintptr             // length of entries array. Always a power of 2.
     24 	count   uintptr             // current number of filled entries.
     25 	entries [itabInitSize]*itab // really [size] large
     26 }
     27 
     28 func itabHashFunc(inter *interfacetype, typ *_type) uintptr {
     29 	// compiler has provided some good hash codes for us.
     30 	return uintptr(inter.typ.hash ^ typ.hash)
     31 }
     32 
     33 func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
     34 	if len(inter.mhdr) == 0 {
     35 		throw("internal error - misuse of itab")
     36 	}
     37 
     38 	// easy case
     39 	if typ.tflag&tflagUncommon == 0 {
     40 		if canfail {
     41 			return nil
     42 		}
     43 		name := inter.typ.nameOff(inter.mhdr[0].name)
     44 		panic(&TypeAssertionError{"", typ.string(), inter.typ.string(), name.name()})
     45 	}
     46 
     47 	var m *itab
     48 
     49 	// First, look in the existing table to see if we can find the itab we need.
     50 	// This is by far the most common case, so do it without locks.
     51 	// Use atomic to ensure we see any previous writes done by the thread
     52 	// that updates the itabTable field (with atomic.Storep in itabAdd).
     53 	t := (*itabTableType)(atomic.Loadp(unsafe.Pointer(&itabTable)))
     54 	if m = t.find(inter, typ); m != nil {
     55 		goto finish
     56 	}
     57 
     58 	// Not found.  Grab the lock and try again.
     59 	lock(&itabLock)
     60 	if m = itabTable.find(inter, typ); m != nil {
     61 		unlock(&itabLock)
     62 		goto finish
     63 	}
     64 
     65 	// Entry doesn't exist yet. Make a new entry & add it.
     66 	m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.mhdr)-1)*sys.PtrSize, 0, &memstats.other_sys))
     67 	m.inter = inter
     68 	m._type = typ
     69 	m.init()
     70 	itabAdd(m)
     71 	unlock(&itabLock)
     72 finish:
     73 	if m.fun[0] != 0 {
     74 		return m
     75 	}
     76 	if canfail {
     77 		return nil
     78 	}
     79 	// this can only happen if the conversion
     80 	// was already done once using the , ok form
     81 	// and we have a cached negative result.
     82 	// The cached result doesn't record which
     83 	// interface function was missing, so initialize
     84 	// the itab again to get the missing function name.
     85 	panic(&TypeAssertionError{concreteString: typ.string(), assertedString: inter.typ.string(), missingMethod: m.init()})
     86 }
     87 
     88 // find finds the given interface/type pair in t.
     89 // Returns nil if the given interface/type pair isn't present.
     90 func (t *itabTableType) find(inter *interfacetype, typ *_type) *itab {
     91 	// Implemented using quadratic probing.
     92 	// Probe sequence is h(i) = h0 + i*(i+1)/2 mod 2^k.
     93 	// We're guaranteed to hit all table entries using this probe sequence.
     94 	mask := t.size - 1
     95 	h := itabHashFunc(inter, typ) & mask
     96 	for i := uintptr(1); ; i++ {
     97 		p := (**itab)(add(unsafe.Pointer(&t.entries), h*sys.PtrSize))
     98 		// Use atomic read here so if we see m != nil, we also see
     99 		// the initializations of the fields of m.
    100 		// m := *p
    101 		m := (*itab)(atomic.Loadp(unsafe.Pointer(p)))
    102 		if m == nil {
    103 			return nil
    104 		}
    105 		if m.inter == inter && m._type == typ {
    106 			return m
    107 		}
    108 		h += i
    109 		h &= mask
    110 	}
    111 }
    112 
    113 // itabAdd adds the given itab to the itab hash table.
    114 // itabLock must be held.
    115 func itabAdd(m *itab) {
    116 	t := itabTable
    117 	if t.count >= 3*(t.size/4) { // 75% load factor
    118 		// Grow hash table.
    119 		// t2 = new(itabTableType) + some additional entries
    120 		// We lie and tell malloc we want pointer-free memory because
    121 		// all the pointed-to values are not in the heap.
    122 		t2 := (*itabTableType)(mallocgc((2+2*t.size)*sys.PtrSize, nil, true))
    123 		t2.size = t.size * 2
    124 
    125 		// Copy over entries.
    126 		// Note: while copying, other threads may look for an itab and
    127 		// fail to find it. That's ok, they will then try to get the itab lock
    128 		// and as a consequence wait until this copying is complete.
    129 		iterate_itabs(t2.add)
    130 		if t2.count != t.count {
    131 			throw("mismatched count during itab table copy")
    132 		}
    133 		// Publish new hash table. Use an atomic write: see comment in getitab.
    134 		atomicstorep(unsafe.Pointer(&itabTable), unsafe.Pointer(t2))
    135 		// Adopt the new table as our own.
    136 		t = itabTable
    137 		// Note: the old table can be GC'ed here.
    138 	}
    139 	t.add(m)
    140 }
    141 
    142 // add adds the given itab to itab table t.
    143 // itabLock must be held.
    144 func (t *itabTableType) add(m *itab) {
    145 	// See comment in find about the probe sequence.
    146 	// Insert new itab in the first empty spot in the probe sequence.
    147 	mask := t.size - 1
    148 	h := itabHashFunc(m.inter, m._type) & mask
    149 	for i := uintptr(1); ; i++ {
    150 		p := (**itab)(add(unsafe.Pointer(&t.entries), h*sys.PtrSize))
    151 		m2 := *p
    152 		if m2 == m {
    153 			// A given itab may be used in more than one module
    154 			// and thanks to the way global symbol resolution works, the
    155 			// pointed-to itab may already have been inserted into the
    156 			// global 'hash'.
    157 			return
    158 		}
    159 		if m2 == nil {
    160 			// Use atomic write here so if a reader sees m, it also
    161 			// sees the correctly initialized fields of m.
    162 			// NoWB is ok because m is not in heap memory.
    163 			// *p = m
    164 			atomic.StorepNoWB(unsafe.Pointer(p), unsafe.Pointer(m))
    165 			t.count++
    166 			return
    167 		}
    168 		h += i
    169 		h &= mask
    170 	}
    171 }
    172 
    173 // init fills in the m.fun array with all the code pointers for
    174 // the m.inter/m._type pair. If the type does not implement the interface,
    175 // it sets m.fun[0] to 0 and returns the name of an interface function that is missing.
    176 // It is ok to call this multiple times on the same m, even concurrently.
    177 func (m *itab) init() string {
    178 	inter := m.inter
    179 	typ := m._type
    180 	x := typ.uncommon()
    181 
    182 	// both inter and typ have method sorted by name,
    183 	// and interface names are unique,
    184 	// so can iterate over both in lock step;
    185 	// the loop is O(ni+nt) not O(ni*nt).
    186 	ni := len(inter.mhdr)
    187 	nt := int(x.mcount)
    188 	xmhdr := (*[1 << 16]method)(add(unsafe.Pointer(x), uintptr(x.moff)))[:nt:nt]
    189 	j := 0
    190 imethods:
    191 	for k := 0; k < ni; k++ {
    192 		i := &inter.mhdr[k]
    193 		itype := inter.typ.typeOff(i.ityp)
    194 		name := inter.typ.nameOff(i.name)
    195 		iname := name.name()
    196 		ipkg := name.pkgPath()
    197 		if ipkg == "" {
    198 			ipkg = inter.pkgpath.name()
    199 		}
    200 		for ; j < nt; j++ {
    201 			t := &xmhdr[j]
    202 			tname := typ.nameOff(t.name)
    203 			if typ.typeOff(t.mtyp) == itype && tname.name() == iname {
    204 				pkgPath := tname.pkgPath()
    205 				if pkgPath == "" {
    206 					pkgPath = typ.nameOff(x.pkgpath).name()
    207 				}
    208 				if tname.isExported() || pkgPath == ipkg {
    209 					if m != nil {
    210 						ifn := typ.textOff(t.ifn)
    211 						*(*unsafe.Pointer)(add(unsafe.Pointer(&m.fun[0]), uintptr(k)*sys.PtrSize)) = ifn
    212 					}
    213 					continue imethods
    214 				}
    215 			}
    216 		}
    217 		// didn't find method
    218 		m.fun[0] = 0
    219 		return iname
    220 	}
    221 	m.hash = typ.hash
    222 	return ""
    223 }
    224 
    225 func itabsinit() {
    226 	lock(&itabLock)
    227 	for _, md := range activeModules() {
    228 		for _, i := range md.itablinks {
    229 			itabAdd(i)
    230 		}
    231 	}
    232 	unlock(&itabLock)
    233 }
    234 
    235 // panicdottypeE is called when doing an e.(T) conversion and the conversion fails.
    236 // have = the dynamic type we have.
    237 // want = the static type we're trying to convert to.
    238 // iface = the static type we're converting from.
    239 func panicdottypeE(have, want, iface *_type) {
    240 	haveString := ""
    241 	if have != nil {
    242 		haveString = have.string()
    243 	}
    244 	panic(&TypeAssertionError{iface.string(), haveString, want.string(), ""})
    245 }
    246 
    247 // panicdottypeI is called when doing an i.(T) conversion and the conversion fails.
    248 // Same args as panicdottypeE, but "have" is the dynamic itab we have.
    249 func panicdottypeI(have *itab, want, iface *_type) {
    250 	var t *_type
    251 	if have != nil {
    252 		t = have._type
    253 	}
    254 	panicdottypeE(t, want, iface)
    255 }
    256 
    257 // panicnildottype is called when doing a i.(T) conversion and the interface i is nil.
    258 // want = the static type we're trying to convert to.
    259 func panicnildottype(want *_type) {
    260 	panic(&TypeAssertionError{"", "", want.string(), ""})
    261 	// TODO: Add the static type we're converting from as well.
    262 	// It might generate a better error message.
    263 	// Just to match other nil conversion errors, we don't for now.
    264 }
    265 
    266 // The conv and assert functions below do very similar things.
    267 // The convXXX functions are guaranteed by the compiler to succeed.
    268 // The assertXXX functions may fail (either panicking or returning false,
    269 // depending on whether they are 1-result or 2-result).
    270 // The convXXX functions succeed on a nil input, whereas the assertXXX
    271 // functions fail on a nil input.
    272 
    273 func convT2E(t *_type, elem unsafe.Pointer) (e eface) {
    274 	if raceenabled {
    275 		raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2E))
    276 	}
    277 	if msanenabled {
    278 		msanread(elem, t.size)
    279 	}
    280 	x := mallocgc(t.size, t, true)
    281 	// TODO: We allocate a zeroed object only to overwrite it with actual data.
    282 	// Figure out how to avoid zeroing. Also below in convT2Eslice, convT2I, convT2Islice.
    283 	typedmemmove(t, x, elem)
    284 	e._type = t
    285 	e.data = x
    286 	return
    287 }
    288 
    289 func convT2E16(t *_type, elem unsafe.Pointer) (e eface) {
    290 	if raceenabled {
    291 		raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2E16))
    292 	}
    293 	if msanenabled {
    294 		msanread(elem, t.size)
    295 	}
    296 	var x unsafe.Pointer
    297 	if *(*uint16)(elem) == 0 {
    298 		x = unsafe.Pointer(&zeroVal[0])
    299 	} else {
    300 		x = mallocgc(2, t, false)
    301 		*(*uint16)(x) = *(*uint16)(elem)
    302 	}
    303 	e._type = t
    304 	e.data = x
    305 	return
    306 }
    307 
    308 func convT2E32(t *_type, elem unsafe.Pointer) (e eface) {
    309 	if raceenabled {
    310 		raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2E32))
    311 	}
    312 	if msanenabled {
    313 		msanread(elem, t.size)
    314 	}
    315 	var x unsafe.Pointer
    316 	if *(*uint32)(elem) == 0 {
    317 		x = unsafe.Pointer(&zeroVal[0])
    318 	} else {
    319 		x = mallocgc(4, t, false)
    320 		*(*uint32)(x) = *(*uint32)(elem)
    321 	}
    322 	e._type = t
    323 	e.data = x
    324 	return
    325 }
    326 
    327 func convT2E64(t *_type, elem unsafe.Pointer) (e eface) {
    328 	if raceenabled {
    329 		raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2E64))
    330 	}
    331 	if msanenabled {
    332 		msanread(elem, t.size)
    333 	}
    334 	var x unsafe.Pointer
    335 	if *(*uint64)(elem) == 0 {
    336 		x = unsafe.Pointer(&zeroVal[0])
    337 	} else {
    338 		x = mallocgc(8, t, false)
    339 		*(*uint64)(x) = *(*uint64)(elem)
    340 	}
    341 	e._type = t
    342 	e.data = x
    343 	return
    344 }
    345 
    346 func convT2Estring(t *_type, elem unsafe.Pointer) (e eface) {
    347 	if raceenabled {
    348 		raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2Estring))
    349 	}
    350 	if msanenabled {
    351 		msanread(elem, t.size)
    352 	}
    353 	var x unsafe.Pointer
    354 	if *(*string)(elem) == "" {
    355 		x = unsafe.Pointer(&zeroVal[0])
    356 	} else {
    357 		x = mallocgc(t.size, t, true)
    358 		*(*string)(x) = *(*string)(elem)
    359 	}
    360 	e._type = t
    361 	e.data = x
    362 	return
    363 }
    364 
    365 func convT2Eslice(t *_type, elem unsafe.Pointer) (e eface) {
    366 	if raceenabled {
    367 		raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2Eslice))
    368 	}
    369 	if msanenabled {
    370 		msanread(elem, t.size)
    371 	}
    372 	var x unsafe.Pointer
    373 	if v := *(*slice)(elem); uintptr(v.array) == 0 {
    374 		x = unsafe.Pointer(&zeroVal[0])
    375 	} else {
    376 		x = mallocgc(t.size, t, true)
    377 		*(*slice)(x) = *(*slice)(elem)
    378 	}
    379 	e._type = t
    380 	e.data = x
    381 	return
    382 }
    383 
    384 func convT2Enoptr(t *_type, elem unsafe.Pointer) (e eface) {
    385 	if raceenabled {
    386 		raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2Enoptr))
    387 	}
    388 	if msanenabled {
    389 		msanread(elem, t.size)
    390 	}
    391 	x := mallocgc(t.size, t, false)
    392 	memmove(x, elem, t.size)
    393 	e._type = t
    394 	e.data = x
    395 	return
    396 }
    397 
    398 func convT2I(tab *itab, elem unsafe.Pointer) (i iface) {
    399 	t := tab._type
    400 	if raceenabled {
    401 		raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2I))
    402 	}
    403 	if msanenabled {
    404 		msanread(elem, t.size)
    405 	}
    406 	x := mallocgc(t.size, t, true)
    407 	typedmemmove(t, x, elem)
    408 	i.tab = tab
    409 	i.data = x
    410 	return
    411 }
    412 
    413 func convT2I16(tab *itab, elem unsafe.Pointer) (i iface) {
    414 	t := tab._type
    415 	if raceenabled {
    416 		raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2I16))
    417 	}
    418 	if msanenabled {
    419 		msanread(elem, t.size)
    420 	}
    421 	var x unsafe.Pointer
    422 	if *(*uint16)(elem) == 0 {
    423 		x = unsafe.Pointer(&zeroVal[0])
    424 	} else {
    425 		x = mallocgc(2, t, false)
    426 		*(*uint16)(x) = *(*uint16)(elem)
    427 	}
    428 	i.tab = tab
    429 	i.data = x
    430 	return
    431 }
    432 
    433 func convT2I32(tab *itab, elem unsafe.Pointer) (i iface) {
    434 	t := tab._type
    435 	if raceenabled {
    436 		raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2I32))
    437 	}
    438 	if msanenabled {
    439 		msanread(elem, t.size)
    440 	}
    441 	var x unsafe.Pointer
    442 	if *(*uint32)(elem) == 0 {
    443 		x = unsafe.Pointer(&zeroVal[0])
    444 	} else {
    445 		x = mallocgc(4, t, false)
    446 		*(*uint32)(x) = *(*uint32)(elem)
    447 	}
    448 	i.tab = tab
    449 	i.data = x
    450 	return
    451 }
    452 
    453 func convT2I64(tab *itab, elem unsafe.Pointer) (i iface) {
    454 	t := tab._type
    455 	if raceenabled {
    456 		raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2I64))
    457 	}
    458 	if msanenabled {
    459 		msanread(elem, t.size)
    460 	}
    461 	var x unsafe.Pointer
    462 	if *(*uint64)(elem) == 0 {
    463 		x = unsafe.Pointer(&zeroVal[0])
    464 	} else {
    465 		x = mallocgc(8, t, false)
    466 		*(*uint64)(x) = *(*uint64)(elem)
    467 	}
    468 	i.tab = tab
    469 	i.data = x
    470 	return
    471 }
    472 
    473 func convT2Istring(tab *itab, elem unsafe.Pointer) (i iface) {
    474 	t := tab._type
    475 	if raceenabled {
    476 		raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2Istring))
    477 	}
    478 	if msanenabled {
    479 		msanread(elem, t.size)
    480 	}
    481 	var x unsafe.Pointer
    482 	if *(*string)(elem) == "" {
    483 		x = unsafe.Pointer(&zeroVal[0])
    484 	} else {
    485 		x = mallocgc(t.size, t, true)
    486 		*(*string)(x) = *(*string)(elem)
    487 	}
    488 	i.tab = tab
    489 	i.data = x
    490 	return
    491 }
    492 
    493 func convT2Islice(tab *itab, elem unsafe.Pointer) (i iface) {
    494 	t := tab._type
    495 	if raceenabled {
    496 		raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2Islice))
    497 	}
    498 	if msanenabled {
    499 		msanread(elem, t.size)
    500 	}
    501 	var x unsafe.Pointer
    502 	if v := *(*slice)(elem); uintptr(v.array) == 0 {
    503 		x = unsafe.Pointer(&zeroVal[0])
    504 	} else {
    505 		x = mallocgc(t.size, t, true)
    506 		*(*slice)(x) = *(*slice)(elem)
    507 	}
    508 	i.tab = tab
    509 	i.data = x
    510 	return
    511 }
    512 
    513 func convT2Inoptr(tab *itab, elem unsafe.Pointer) (i iface) {
    514 	t := tab._type
    515 	if raceenabled {
    516 		raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2Inoptr))
    517 	}
    518 	if msanenabled {
    519 		msanread(elem, t.size)
    520 	}
    521 	x := mallocgc(t.size, t, false)
    522 	memmove(x, elem, t.size)
    523 	i.tab = tab
    524 	i.data = x
    525 	return
    526 }
    527 
    528 func convI2I(inter *interfacetype, i iface) (r iface) {
    529 	tab := i.tab
    530 	if tab == nil {
    531 		return
    532 	}
    533 	if tab.inter == inter {
    534 		r.tab = tab
    535 		r.data = i.data
    536 		return
    537 	}
    538 	r.tab = getitab(inter, tab._type, false)
    539 	r.data = i.data
    540 	return
    541 }
    542 
    543 func assertI2I(inter *interfacetype, i iface) (r iface) {
    544 	tab := i.tab
    545 	if tab == nil {
    546 		// explicit conversions require non-nil interface value.
    547 		panic(&TypeAssertionError{"", "", inter.typ.string(), ""})
    548 	}
    549 	if tab.inter == inter {
    550 		r.tab = tab
    551 		r.data = i.data
    552 		return
    553 	}
    554 	r.tab = getitab(inter, tab._type, false)
    555 	r.data = i.data
    556 	return
    557 }
    558 
    559 func assertI2I2(inter *interfacetype, i iface) (r iface, b bool) {
    560 	tab := i.tab
    561 	if tab == nil {
    562 		return
    563 	}
    564 	if tab.inter != inter {
    565 		tab = getitab(inter, tab._type, true)
    566 		if tab == nil {
    567 			return
    568 		}
    569 	}
    570 	r.tab = tab
    571 	r.data = i.data
    572 	b = true
    573 	return
    574 }
    575 
    576 func assertE2I(inter *interfacetype, e eface) (r iface) {
    577 	t := e._type
    578 	if t == nil {
    579 		// explicit conversions require non-nil interface value.
    580 		panic(&TypeAssertionError{"", "", inter.typ.string(), ""})
    581 	}
    582 	r.tab = getitab(inter, t, false)
    583 	r.data = e.data
    584 	return
    585 }
    586 
    587 func assertE2I2(inter *interfacetype, e eface) (r iface, b bool) {
    588 	t := e._type
    589 	if t == nil {
    590 		return
    591 	}
    592 	tab := getitab(inter, t, true)
    593 	if tab == nil {
    594 		return
    595 	}
    596 	r.tab = tab
    597 	r.data = e.data
    598 	b = true
    599 	return
    600 }
    601 
    602 //go:linkname reflect_ifaceE2I reflect.ifaceE2I
    603 func reflect_ifaceE2I(inter *interfacetype, e eface, dst *iface) {
    604 	*dst = assertE2I(inter, e)
    605 }
    606 
    607 func iterate_itabs(fn func(*itab)) {
    608 	// Note: only runs during stop the world or with itabLock held,
    609 	// so no other locks/atomics needed.
    610 	t := itabTable
    611 	for i := uintptr(0); i < t.size; i++ {
    612 		m := *(**itab)(add(unsafe.Pointer(&t.entries), i*sys.PtrSize))
    613 		if m != nil {
    614 			fn(m)
    615 		}
    616 	}
    617 }
    618 
    619 // staticbytes is used to avoid convT2E for byte-sized values.
    620 var staticbytes = [...]byte{
    621 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    622 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    623 	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
    624 	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
    625 	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
    626 	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
    627 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
    628 	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
    629 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
    630 	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
    631 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
    632 	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
    633 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
    634 	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
    635 	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
    636 	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
    637 	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
    638 	0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
    639 	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
    640 	0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
    641 	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
    642 	0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
    643 	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
    644 	0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
    645 	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
    646 	0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
    647 	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
    648 	0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
    649 	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
    650 	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
    651 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
    652 	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
    653 }
    654