github.com/s1s1ty/go@v0.0.0-20180207192209-104445e3140f/src/runtime/iface.go (about)

     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  }