cmd/compile, runtime: new static name encoding

Create a byte encoding designed for static Go names.

It is intended to be a compact representation of a name
and optional tag data that can be turned into a Go string
without allocating, and describes whether or not it is
exported without unicode table.

The encoding is described in reflect/type.go:

// The first byte is a bit field containing:
//
//	1<<0 the name is exported
//	1<<1 tag data follows the name
//	1<<2 pkgPath *string follow the name and tag
//
// The next two bytes are the data length:
//
//	 l := uint16(data[1])<<8 | uint16(data[2])
//
// Bytes [3:3+l] are the string data.
//
// If tag data follows then bytes 3+l and 3+l+1 are the tag length,
// with the data following.
//
// If the import path follows, then ptrSize bytes at the end of
// the data form a *string. The import path is only set for concrete
// methods that are defined in a different package than their type.

Shrinks binary sizes:

	cmd/go: 164KB (1.6%)
	jujud:  1.0MB (1.5%)

For #6853.

Change-Id: I46b6591015b17936a443c9efb5009de8dfe8b609
Reviewed-on: https://go-review.googlesource.com/20968
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
David Crawshaw 2016-03-21 13:21:55 -04:00
parent 0a82ed5d7c
commit 24ce64d1a9
6 changed files with 387 additions and 138 deletions

View file

@ -6,7 +6,10 @@
package runtime
import "unsafe"
import (
"runtime/internal/sys"
"unsafe"
)
// tflag is documented in ../reflect/type.go.
type tflag uint8
@ -152,11 +155,10 @@ func (t *functype) dotdotdot() bool {
}
type method struct {
name *string
pkgpath *string
mtyp *_type
ifn unsafe.Pointer
tfn unsafe.Pointer
name name
mtyp *_type
ifn unsafe.Pointer
tfn unsafe.Pointer
}
type uncommontype struct {
@ -165,14 +167,14 @@ type uncommontype struct {
}
type imethod struct {
name *string
pkgpath *string
_type *_type
name name
_type *_type
}
type interfacetype struct {
typ _type
mhdr []imethod
typ _type
pkgpath *string
mhdr []imethod
}
type maptype struct {
@ -220,14 +222,62 @@ type ptrtype struct {
}
type structfield struct {
name *string
pkgpath *string
typ *_type
tag *string
offset uintptr
name name
typ *_type
offset uintptr
}
type structtype struct {
typ _type
fields []structfield
typ _type
pkgPath *string
fields []structfield
}
// name is an encoded type name with optional extra data.
// See reflect/type.go for details.
type name struct {
bytes *byte
}
func (n *name) data(off int) *byte {
return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off)))
}
func (n *name) isExported() bool {
return (*n.bytes)&(1<<0) != 0
}
func (n *name) nameLen() int {
return int(uint16(*n.data(1))<<8 | uint16(*n.data(2)))
}
func (n *name) tagLen() int {
if *n.data(0)&(1<<1) == 0 {
return 0
}
off := 3 + n.nameLen()
return int(uint16(*n.data(off))<<8 | uint16(*n.data(off + 1)))
}
func (n *name) name() (s string) {
nl := n.nameLen()
if nl == 0 {
return ""
}
hdr := (*stringStruct)(unsafe.Pointer(&s))
hdr.str = unsafe.Pointer(n.data(3))
hdr.len = nl
return s
}
func (n *name) pkgPath() *string {
if *n.data(0)&(1<<2) == 0 {
return nil
}
off := 3 + n.nameLen()
if tl := n.tagLen(); tl > 0 {
off += 2 + tl
}
off = int(round(uintptr(off), sys.PtrSize))
return *(**string)(unsafe.Pointer(n.data(off)))
}