mirror of
https://github.com/golang/go
synced 2024-11-23 18:40:03 -07:00
internal/unsafeheader: consolidate stringHeader and sliceHeader declarations into an internal package
The new package "internal/unsafeheader" depends only on "unsafe", and provides declarations equivalent to reflect.StringHeader and reflect.SliceHeader but with Data fields of the proper unsafe.Pointer type (instead of uintptr). Unlike the types it replaces, the "internal/unsafeheader" package has a regression test to ensure that its header types remain equivalent to the declarations provided by the "reflect" package. Since "internal/unsafeheader" has almost no dependencies, it can be used in other low-level packages such as "syscall" and "reflect". This change is based on the corresponding x/sys change in CL 231177. Fixes #37805 Updates #19367 Change-Id: I7a6d93ef8dd6e235bcab94e7c47270aad047af31 Reviewed-on: https://go-review.googlesource.com/c/go/+/231223 Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
4c78d54fdd
commit
da382a3978
1
src/cmd/dist/buildtool.go
vendored
1
src/cmd/dist/buildtool.go
vendored
@ -97,6 +97,7 @@ var bootstrapDirs = []string{
|
||||
"debug/pe",
|
||||
"internal/goversion",
|
||||
"internal/race",
|
||||
"internal/unsafeheader",
|
||||
"internal/xcoff",
|
||||
"math/big",
|
||||
"math/bits",
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"internal/unsafeheader"
|
||||
"io"
|
||||
"unsafe"
|
||||
)
|
||||
@ -502,16 +503,15 @@ func (r *Reader) StringAt(off uint32, len uint32) string {
|
||||
}
|
||||
|
||||
func toString(b []byte) string {
|
||||
type stringHeader struct {
|
||||
str unsafe.Pointer
|
||||
len int
|
||||
}
|
||||
|
||||
if len(b) == 0 {
|
||||
return ""
|
||||
}
|
||||
ss := stringHeader{str: unsafe.Pointer(&b[0]), len: len(b)}
|
||||
s := *(*string)(unsafe.Pointer(&ss))
|
||||
|
||||
var s string
|
||||
hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
|
||||
hdr.Data = unsafe.Pointer(&b[0])
|
||||
hdr.Len = len(b)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"cmd/internal/sys"
|
||||
"cmd/oldlink/internal/sym"
|
||||
"fmt"
|
||||
"internal/unsafeheader"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
@ -595,17 +596,16 @@ func (r *objReader) readData() []byte {
|
||||
return p
|
||||
}
|
||||
|
||||
type stringHeader struct {
|
||||
str unsafe.Pointer
|
||||
len int
|
||||
}
|
||||
|
||||
func mkROString(rodata []byte) string {
|
||||
if len(rodata) == 0 {
|
||||
return ""
|
||||
}
|
||||
ss := stringHeader{str: unsafe.Pointer(&rodata[0]), len: len(rodata)}
|
||||
s := *(*string)(unsafe.Pointer(&ss))
|
||||
|
||||
var s string
|
||||
hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
|
||||
hdr.Data = unsafe.Pointer(&rodata[0])
|
||||
hdr.Len = len(rodata)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,8 @@ var pkgDeps = map[string][]string{
|
||||
"unsafe": {},
|
||||
"internal/cpu": {},
|
||||
"internal/bytealg": {"unsafe", "internal/cpu"},
|
||||
"internal/reflectlite": {"runtime", "unsafe"},
|
||||
"internal/reflectlite": {"runtime", "unsafe", "internal/unsafeheader"},
|
||||
"internal/unsafeheader": {"unsafe"},
|
||||
|
||||
"L0": {
|
||||
"errors",
|
||||
@ -119,7 +120,7 @@ var pkgDeps = map[string][]string{
|
||||
"image/color": {"L2"}, // interfaces
|
||||
"image/color/palette": {"L2", "image/color"},
|
||||
"internal/fmtsort": {"reflect", "sort"},
|
||||
"reflect": {"L2"},
|
||||
"reflect": {"L2", "internal/unsafeheader"},
|
||||
"sort": {"internal/reflectlite"},
|
||||
|
||||
"L3": {
|
||||
@ -147,7 +148,7 @@ var pkgDeps = map[string][]string{
|
||||
// End of linear dependency definitions.
|
||||
|
||||
// Operating system access.
|
||||
"syscall": {"L0", "internal/oserror", "internal/race", "internal/syscall/windows/sysdll", "syscall/js", "unicode/utf16"},
|
||||
"syscall": {"L0", "internal/oserror", "internal/race", "internal/syscall/windows/sysdll", "internal/unsafeheader", "syscall/js", "unicode/utf16"},
|
||||
"syscall/js": {"L0"},
|
||||
"internal/oserror": {"L0"},
|
||||
"internal/syscall/unix": {"L0", "syscall"},
|
||||
|
@ -4,7 +4,10 @@
|
||||
|
||||
package reflectlite
|
||||
|
||||
import "unsafe"
|
||||
import (
|
||||
"internal/unsafeheader"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Swapper returns a function that swaps the elements in the provided
|
||||
// slice.
|
||||
@ -58,7 +61,7 @@ func Swapper(slice interface{}) func(i, j int) {
|
||||
}
|
||||
}
|
||||
|
||||
s := (*sliceHeader)(v.ptr)
|
||||
s := (*unsafeheader.Slice)(v.ptr)
|
||||
tmp := unsafe_New(typ) // swap scratch space
|
||||
|
||||
return func(i, j int) {
|
||||
|
@ -7,6 +7,7 @@
|
||||
package reflectlite
|
||||
|
||||
import (
|
||||
"internal/unsafeheader"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@ -338,7 +339,7 @@ func (n name) name() (s string) {
|
||||
}
|
||||
b := (*[4]byte)(unsafe.Pointer(n.bytes))
|
||||
|
||||
hdr := (*stringHeader)(unsafe.Pointer(&s))
|
||||
hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
|
||||
hdr.Data = unsafe.Pointer(&b[3])
|
||||
hdr.Len = int(b[1])<<8 | int(b[2])
|
||||
return s
|
||||
@ -350,7 +351,7 @@ func (n name) tag() (s string) {
|
||||
return ""
|
||||
}
|
||||
nl := n.nameLen()
|
||||
hdr := (*stringHeader)(unsafe.Pointer(&s))
|
||||
hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
|
||||
hdr.Data = unsafe.Pointer(n.data(3+nl+2, "non-empty string"))
|
||||
hdr.Len = tl
|
||||
return s
|
||||
|
@ -5,6 +5,7 @@
|
||||
package reflectlite
|
||||
|
||||
import (
|
||||
"internal/unsafeheader"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
@ -335,10 +336,10 @@ func (v Value) Len() int {
|
||||
return maplen(v.pointer())
|
||||
case Slice:
|
||||
// Slice is bigger than a word; assume flagIndir.
|
||||
return (*sliceHeader)(v.ptr).Len
|
||||
return (*unsafeheader.Slice)(v.ptr).Len
|
||||
case String:
|
||||
// String is bigger than a word; assume flagIndir.
|
||||
return (*stringHeader)(v.ptr).Len
|
||||
return (*unsafeheader.String)(v.ptr).Len
|
||||
}
|
||||
panic(&ValueError{"reflect.Value.Len", v.kind()})
|
||||
}
|
||||
@ -379,19 +380,6 @@ func (v Value) Type() Type {
|
||||
return v.typ
|
||||
}
|
||||
|
||||
// stringHeader is a safe version of StringHeader used within this package.
|
||||
type stringHeader struct {
|
||||
Data unsafe.Pointer
|
||||
Len int
|
||||
}
|
||||
|
||||
// sliceHeader is a safe version of SliceHeader used within this package.
|
||||
type sliceHeader struct {
|
||||
Data unsafe.Pointer
|
||||
Len int
|
||||
Cap int
|
||||
}
|
||||
|
||||
/*
|
||||
* constructors
|
||||
*/
|
||||
|
37
src/internal/unsafeheader/unsafeheader.go
Normal file
37
src/internal/unsafeheader/unsafeheader.go
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package unsafeheader contains header declarations for the Go runtime's slice
|
||||
// and string implementations.
|
||||
//
|
||||
// This package allows packages that cannot import "reflect" to use types that
|
||||
// are tested to be equivalent to reflect.SliceHeader and reflect.StringHeader.
|
||||
package unsafeheader
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Slice is the runtime representation of a slice.
|
||||
// It cannot be used safely or portably and its representation may
|
||||
// change in a later release.
|
||||
//
|
||||
// Unlike reflect.SliceHeader, its Data field is sufficient to guarantee the
|
||||
// data it references will not be garbage collected.
|
||||
type Slice struct {
|
||||
Data unsafe.Pointer
|
||||
Len int
|
||||
Cap int
|
||||
}
|
||||
|
||||
// String is the runtime representation of a string.
|
||||
// It cannot be used safely or portably and its representation may
|
||||
// change in a later release.
|
||||
//
|
||||
// Unlike reflect.SliceHeader, its Data field is sufficient to guarantee the
|
||||
// data it references will not be garbage collected.
|
||||
type String struct {
|
||||
Data unsafe.Pointer
|
||||
Len int
|
||||
}
|
100
src/internal/unsafeheader/unsafeheader_test.go
Normal file
100
src/internal/unsafeheader/unsafeheader_test.go
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package unsafeheader_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"internal/unsafeheader"
|
||||
"reflect"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// TestTypeMatchesReflectType ensures that the name and layout of the
|
||||
// unsafeheader types matches the corresponding Header types in the reflect
|
||||
// package.
|
||||
func TestTypeMatchesReflectType(t *testing.T) {
|
||||
t.Run("Slice", func(t *testing.T) {
|
||||
testHeaderMatchesReflect(t, unsafeheader.Slice{}, reflect.SliceHeader{})
|
||||
})
|
||||
|
||||
t.Run("String", func(t *testing.T) {
|
||||
testHeaderMatchesReflect(t, unsafeheader.String{}, reflect.StringHeader{})
|
||||
})
|
||||
}
|
||||
|
||||
func testHeaderMatchesReflect(t *testing.T, header, reflectHeader interface{}) {
|
||||
h := reflect.TypeOf(header)
|
||||
rh := reflect.TypeOf(reflectHeader)
|
||||
|
||||
for i := 0; i < h.NumField(); i++ {
|
||||
f := h.Field(i)
|
||||
rf, ok := rh.FieldByName(f.Name)
|
||||
if !ok {
|
||||
t.Errorf("Field %d of %v is named %s, but no such field exists in %v", i, h, f.Name, rh)
|
||||
continue
|
||||
}
|
||||
if !typeCompatible(f.Type, rf.Type) {
|
||||
t.Errorf("%v.%s has type %v, but %v.%s has type %v", h, f.Name, f.Type, rh, rf.Name, rf.Type)
|
||||
}
|
||||
if f.Offset != rf.Offset {
|
||||
t.Errorf("%v.%s has offset %d, but %v.%s has offset %d", h, f.Name, f.Offset, rh, rf.Name, rf.Offset)
|
||||
}
|
||||
}
|
||||
|
||||
if h.NumField() != rh.NumField() {
|
||||
t.Errorf("%v has %d fields, but %v has %d", h, h.NumField(), rh, rh.NumField())
|
||||
}
|
||||
if h.Align() != rh.Align() {
|
||||
t.Errorf("%v has alignment %d, but %v has alignment %d", h, h.Align(), rh, rh.Align())
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
unsafePointerType = reflect.TypeOf(unsafe.Pointer(nil))
|
||||
uintptrType = reflect.TypeOf(uintptr(0))
|
||||
)
|
||||
|
||||
func typeCompatible(t, rt reflect.Type) bool {
|
||||
return t == rt || (t == unsafePointerType && rt == uintptrType)
|
||||
}
|
||||
|
||||
// TestWriteThroughHeader ensures that the headers in the unsafeheader package
|
||||
// can successfully mutate variables of the corresponding built-in types.
|
||||
//
|
||||
// This test is expected to fail under -race (which implicitly enables
|
||||
// -d=checkptr) if the runtime views the header types as incompatible with the
|
||||
// underlying built-in types.
|
||||
func TestWriteThroughHeader(t *testing.T) {
|
||||
t.Run("Slice", func(t *testing.T) {
|
||||
s := []byte("Hello, checkptr!")[:5]
|
||||
|
||||
var alias []byte
|
||||
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&alias))
|
||||
hdr.Data = unsafe.Pointer(&s[0])
|
||||
hdr.Cap = cap(s)
|
||||
hdr.Len = len(s)
|
||||
|
||||
if !bytes.Equal(alias, s) {
|
||||
t.Errorf("alias of %T(%q) constructed via Slice = %T(%q)", s, s, alias, alias)
|
||||
}
|
||||
if cap(alias) != cap(s) {
|
||||
t.Errorf("alias of %T with cap %d has cap %d", s, cap(s), cap(alias))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("String", func(t *testing.T) {
|
||||
s := "Hello, checkptr!"
|
||||
|
||||
var alias string
|
||||
hdr := (*unsafeheader.String)(unsafe.Pointer(&alias))
|
||||
hdr.Data = (*unsafeheader.String)(unsafe.Pointer(&s)).Data
|
||||
hdr.Len = len(s)
|
||||
|
||||
if alias != s {
|
||||
t.Errorf("alias of %q constructed via String = %q", s, alias)
|
||||
}
|
||||
})
|
||||
}
|
@ -4,7 +4,10 @@
|
||||
|
||||
package reflect
|
||||
|
||||
import "unsafe"
|
||||
import (
|
||||
"internal/unsafeheader"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Swapper returns a function that swaps the elements in the provided
|
||||
// slice.
|
||||
@ -58,7 +61,7 @@ func Swapper(slice interface{}) func(i, j int) {
|
||||
}
|
||||
}
|
||||
|
||||
s := (*sliceHeader)(v.ptr)
|
||||
s := (*unsafeheader.Slice)(v.ptr)
|
||||
tmp := unsafe_New(typ) // swap scratch space
|
||||
|
||||
return func(i, j int) {
|
||||
|
@ -16,6 +16,7 @@
|
||||
package reflect
|
||||
|
||||
import (
|
||||
"internal/unsafeheader"
|
||||
"strconv"
|
||||
"sync"
|
||||
"unicode"
|
||||
@ -490,7 +491,7 @@ func (n name) name() (s string) {
|
||||
}
|
||||
b := (*[4]byte)(unsafe.Pointer(n.bytes))
|
||||
|
||||
hdr := (*stringHeader)(unsafe.Pointer(&s))
|
||||
hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
|
||||
hdr.Data = unsafe.Pointer(&b[3])
|
||||
hdr.Len = int(b[1])<<8 | int(b[2])
|
||||
return s
|
||||
@ -502,7 +503,7 @@ func (n name) tag() (s string) {
|
||||
return ""
|
||||
}
|
||||
nl := n.nameLen()
|
||||
hdr := (*stringHeader)(unsafe.Pointer(&s))
|
||||
hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
|
||||
hdr.Data = unsafe.Pointer(n.data(3+nl+2, "non-empty string"))
|
||||
hdr.Len = tl
|
||||
return s
|
||||
|
@ -5,6 +5,7 @@
|
||||
package reflect
|
||||
|
||||
import (
|
||||
"internal/unsafeheader"
|
||||
"math"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
@ -766,7 +767,7 @@ func (v Value) Cap() int {
|
||||
return chancap(v.pointer())
|
||||
case Slice:
|
||||
// Slice is always bigger than a word; assume flagIndir.
|
||||
return (*sliceHeader)(v.ptr).Cap
|
||||
return (*unsafeheader.Slice)(v.ptr).Cap
|
||||
}
|
||||
panic(&ValueError{"reflect.Value.Cap", v.kind()})
|
||||
}
|
||||
@ -945,7 +946,7 @@ func (v Value) Index(i int) Value {
|
||||
case Slice:
|
||||
// Element flag same as Elem of Ptr.
|
||||
// Addressable, indirect, possibly read-only.
|
||||
s := (*sliceHeader)(v.ptr)
|
||||
s := (*unsafeheader.Slice)(v.ptr)
|
||||
if uint(i) >= uint(s.Len) {
|
||||
panic("reflect: slice index out of range")
|
||||
}
|
||||
@ -956,7 +957,7 @@ func (v Value) Index(i int) Value {
|
||||
return Value{typ, val, fl}
|
||||
|
||||
case String:
|
||||
s := (*stringHeader)(v.ptr)
|
||||
s := (*unsafeheader.String)(v.ptr)
|
||||
if uint(i) >= uint(s.Len) {
|
||||
panic("reflect: string index out of range")
|
||||
}
|
||||
@ -1143,10 +1144,10 @@ func (v Value) Len() int {
|
||||
return maplen(v.pointer())
|
||||
case Slice:
|
||||
// Slice is bigger than a word; assume flagIndir.
|
||||
return (*sliceHeader)(v.ptr).Len
|
||||
return (*unsafeheader.Slice)(v.ptr).Len
|
||||
case String:
|
||||
// String is bigger than a word; assume flagIndir.
|
||||
return (*stringHeader)(v.ptr).Len
|
||||
return (*unsafeheader.String)(v.ptr).Len
|
||||
}
|
||||
panic(&ValueError{"reflect.Value.Len", v.kind()})
|
||||
}
|
||||
@ -1632,7 +1633,7 @@ func (v Value) SetInt(x int64) {
|
||||
func (v Value) SetLen(n int) {
|
||||
v.mustBeAssignable()
|
||||
v.mustBe(Slice)
|
||||
s := (*sliceHeader)(v.ptr)
|
||||
s := (*unsafeheader.Slice)(v.ptr)
|
||||
if uint(n) > uint(s.Cap) {
|
||||
panic("reflect: slice length out of range in SetLen")
|
||||
}
|
||||
@ -1645,7 +1646,7 @@ func (v Value) SetLen(n int) {
|
||||
func (v Value) SetCap(n int) {
|
||||
v.mustBeAssignable()
|
||||
v.mustBe(Slice)
|
||||
s := (*sliceHeader)(v.ptr)
|
||||
s := (*unsafeheader.Slice)(v.ptr)
|
||||
if n < s.Len || n > s.Cap {
|
||||
panic("reflect: slice capacity out of range in SetCap")
|
||||
}
|
||||
@ -1747,18 +1748,18 @@ func (v Value) Slice(i, j int) Value {
|
||||
|
||||
case Slice:
|
||||
typ = (*sliceType)(unsafe.Pointer(v.typ))
|
||||
s := (*sliceHeader)(v.ptr)
|
||||
s := (*unsafeheader.Slice)(v.ptr)
|
||||
base = s.Data
|
||||
cap = s.Cap
|
||||
|
||||
case String:
|
||||
s := (*stringHeader)(v.ptr)
|
||||
s := (*unsafeheader.String)(v.ptr)
|
||||
if i < 0 || j < i || j > s.Len {
|
||||
panic("reflect.Value.Slice: string slice index out of bounds")
|
||||
}
|
||||
var t stringHeader
|
||||
var t unsafeheader.String
|
||||
if i < s.Len {
|
||||
t = stringHeader{arrayAt(s.Data, i, 1, "i < s.Len"), j - i}
|
||||
t = unsafeheader.String{Data: arrayAt(s.Data, i, 1, "i < s.Len"), Len: j - i}
|
||||
}
|
||||
return Value{v.typ, unsafe.Pointer(&t), v.flag}
|
||||
}
|
||||
@ -1770,8 +1771,8 @@ func (v Value) Slice(i, j int) Value {
|
||||
// Declare slice so that gc can see the base pointer in it.
|
||||
var x []unsafe.Pointer
|
||||
|
||||
// Reinterpret as *sliceHeader to edit.
|
||||
s := (*sliceHeader)(unsafe.Pointer(&x))
|
||||
// Reinterpret as *unsafeheader.Slice to edit.
|
||||
s := (*unsafeheader.Slice)(unsafe.Pointer(&x))
|
||||
s.Len = j - i
|
||||
s.Cap = cap - i
|
||||
if cap-i > 0 {
|
||||
@ -1809,7 +1810,7 @@ func (v Value) Slice3(i, j, k int) Value {
|
||||
|
||||
case Slice:
|
||||
typ = (*sliceType)(unsafe.Pointer(v.typ))
|
||||
s := (*sliceHeader)(v.ptr)
|
||||
s := (*unsafeheader.Slice)(v.ptr)
|
||||
base = s.Data
|
||||
cap = s.Cap
|
||||
}
|
||||
@ -1822,8 +1823,8 @@ func (v Value) Slice3(i, j, k int) Value {
|
||||
// can see the base pointer in it.
|
||||
var x []unsafe.Pointer
|
||||
|
||||
// Reinterpret as *sliceHeader to edit.
|
||||
s := (*sliceHeader)(unsafe.Pointer(&x))
|
||||
// Reinterpret as *unsafeheader.Slice to edit.
|
||||
s := (*unsafeheader.Slice)(unsafe.Pointer(&x))
|
||||
s.Len = j - i
|
||||
s.Cap = k - i
|
||||
if k-i > 0 {
|
||||
@ -1960,12 +1961,6 @@ type StringHeader struct {
|
||||
Len int
|
||||
}
|
||||
|
||||
// stringHeader is a safe version of StringHeader used within this package.
|
||||
type stringHeader struct {
|
||||
Data unsafe.Pointer
|
||||
Len int
|
||||
}
|
||||
|
||||
// SliceHeader is the runtime representation of a slice.
|
||||
// It cannot be used safely or portably and its representation may
|
||||
// change in a later release.
|
||||
@ -1978,13 +1973,6 @@ type SliceHeader struct {
|
||||
Cap int
|
||||
}
|
||||
|
||||
// sliceHeader is a safe version of SliceHeader used within this package.
|
||||
type sliceHeader struct {
|
||||
Data unsafe.Pointer
|
||||
Len int
|
||||
Cap int
|
||||
}
|
||||
|
||||
func typesMustMatch(what string, t1, t2 Type) {
|
||||
if t1 != t2 {
|
||||
panic(what + ": " + t1.String() + " != " + t2.String())
|
||||
@ -2085,22 +2073,22 @@ func Copy(dst, src Value) int {
|
||||
typesMustMatch("reflect.Copy", de, se)
|
||||
}
|
||||
|
||||
var ds, ss sliceHeader
|
||||
var ds, ss unsafeheader.Slice
|
||||
if dk == Array {
|
||||
ds.Data = dst.ptr
|
||||
ds.Len = dst.Len()
|
||||
ds.Cap = ds.Len
|
||||
} else {
|
||||
ds = *(*sliceHeader)(dst.ptr)
|
||||
ds = *(*unsafeheader.Slice)(dst.ptr)
|
||||
}
|
||||
if sk == Array {
|
||||
ss.Data = src.ptr
|
||||
ss.Len = src.Len()
|
||||
ss.Cap = ss.Len
|
||||
} else if sk == Slice {
|
||||
ss = *(*sliceHeader)(src.ptr)
|
||||
ss = *(*unsafeheader.Slice)(src.ptr)
|
||||
} else {
|
||||
sh := *(*stringHeader)(src.ptr)
|
||||
sh := *(*unsafeheader.String)(src.ptr)
|
||||
ss.Data = sh.Data
|
||||
ss.Len = sh.Len
|
||||
ss.Cap = sh.Len
|
||||
@ -2288,7 +2276,7 @@ func MakeSlice(typ Type, len, cap int) Value {
|
||||
panic("reflect.MakeSlice: len > cap")
|
||||
}
|
||||
|
||||
s := sliceHeader{unsafe_NewArray(typ.Elem().(*rtype), cap), len, cap}
|
||||
s := unsafeheader.Slice{Data: unsafe_NewArray(typ.Elem().(*rtype), cap), Len: len, Cap: cap}
|
||||
return Value{typ.(*rtype), unsafe.Pointer(&s), flagIndir | flag(Slice)}
|
||||
}
|
||||
|
||||
@ -2805,7 +2793,7 @@ func typedmemclrpartial(t *rtype, ptr unsafe.Pointer, off, size uintptr)
|
||||
// typedslicecopy copies a slice of elemType values from src to dst,
|
||||
// returning the number of elements copied.
|
||||
//go:noescape
|
||||
func typedslicecopy(elemType *rtype, dst, src sliceHeader) int
|
||||
func typedslicecopy(elemType *rtype, dst, src unsafeheader.Slice) int
|
||||
|
||||
//go:noescape
|
||||
func typehash(t *rtype, p unsafe.Pointer, h uintptr) uintptr
|
||||
|
@ -9,6 +9,7 @@ package syscall
|
||||
import (
|
||||
"internal/oserror"
|
||||
"internal/race"
|
||||
"internal/unsafeheader"
|
||||
"runtime"
|
||||
"sync"
|
||||
"unsafe"
|
||||
@ -60,15 +61,12 @@ func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (d
|
||||
return nil, errno
|
||||
}
|
||||
|
||||
// Slice memory layout
|
||||
var sl = struct {
|
||||
addr uintptr
|
||||
len int
|
||||
cap int
|
||||
}{addr, length, length}
|
||||
|
||||
// Use unsafe to turn sl into a []byte.
|
||||
b := *(*[]byte)(unsafe.Pointer(&sl))
|
||||
// Use unsafe to turn addr into a []byte.
|
||||
var b []byte
|
||||
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&b))
|
||||
hdr.Data = unsafe.Pointer(addr)
|
||||
hdr.Cap = length
|
||||
hdr.Len = length
|
||||
|
||||
// Register mapping in m and return it.
|
||||
p := &b[cap(b)-1]
|
||||
|
Loading…
Reference in New Issue
Block a user