mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: introduce unsafe.New and unsafe.NewArray
to provide functionality previously hacked in to
reflect and gob.
R=r
https://golang.org/cl/165076
This commit is contained in:
parent
a4a8224152
commit
33649bd278
7 changed files with 78 additions and 37 deletions
|
|
@ -86,5 +86,7 @@ char *unsafeimport =
|
||||||
"func unsafe.Typeof (i interface { }) (typ interface { })\n"
|
"func unsafe.Typeof (i interface { }) (typ interface { })\n"
|
||||||
"func unsafe.Reflect (i interface { }) (typ interface { }, addr unsafe.Pointer)\n"
|
"func unsafe.Reflect (i interface { }) (typ interface { }, addr unsafe.Pointer)\n"
|
||||||
"func unsafe.Unreflect (typ interface { }, addr unsafe.Pointer) (ret interface { })\n"
|
"func unsafe.Unreflect (typ interface { }, addr unsafe.Pointer) (ret interface { })\n"
|
||||||
|
"func unsafe.New (typ interface { }) (? unsafe.Pointer)\n"
|
||||||
|
"func unsafe.NewArray (typ interface { }, n int) (? unsafe.Pointer)\n"
|
||||||
"\n"
|
"\n"
|
||||||
"$$\n";
|
"$$\n";
|
||||||
|
|
|
||||||
|
|
@ -12,3 +12,5 @@ func Alignof(any) int
|
||||||
func Typeof(i interface{}) (typ interface{})
|
func Typeof(i interface{}) (typ interface{})
|
||||||
func Reflect(i interface{}) (typ interface{}, addr Pointer)
|
func Reflect(i interface{}) (typ interface{}, addr Pointer)
|
||||||
func Unreflect(typ interface{}, addr Pointer) (ret interface{})
|
func Unreflect(typ interface{}, addr Pointer) (ret interface{})
|
||||||
|
func New(typ interface{}) Pointer
|
||||||
|
func NewArray(typ interface{}, n int) Pointer
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"math";
|
"math";
|
||||||
"os";
|
"os";
|
||||||
"reflect";
|
"reflect";
|
||||||
|
"runtime";
|
||||||
"unsafe";
|
"unsafe";
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -361,10 +362,8 @@ func decodeStruct(engine *decEngine, rtyp *reflect.StructType, b *bytes.Buffer,
|
||||||
up = decIndirect(up, indir)
|
up = decIndirect(up, indir)
|
||||||
}
|
}
|
||||||
if *(*unsafe.Pointer)(up) == nil {
|
if *(*unsafe.Pointer)(up) == nil {
|
||||||
// Allocate object by making a slice of bytes and recording the
|
// Allocate object.
|
||||||
// address of the beginning of the array. TODO(rsc).
|
*(*unsafe.Pointer)(up) = unsafe.New((*runtime.StructType)(unsafe.Pointer(rtyp)))
|
||||||
b := make([]byte, rtyp.Size());
|
|
||||||
*(*unsafe.Pointer)(up) = unsafe.Pointer(&b[0]);
|
|
||||||
}
|
}
|
||||||
p = *(*uintptr)(up);
|
p = *(*uintptr)(up);
|
||||||
}
|
}
|
||||||
|
|
@ -437,10 +436,8 @@ func decodeArray(atyp *reflect.ArrayType, state *decodeState, p uintptr, elemOp
|
||||||
if indir > 0 {
|
if indir > 0 {
|
||||||
up := unsafe.Pointer(p);
|
up := unsafe.Pointer(p);
|
||||||
if *(*unsafe.Pointer)(up) == nil {
|
if *(*unsafe.Pointer)(up) == nil {
|
||||||
// Allocate the array by making a slice of bytes of the correct size
|
// Allocate object.
|
||||||
// and taking the address of the beginning of the array. TODO(rsc).
|
*(*unsafe.Pointer)(up) = unsafe.New(atyp)
|
||||||
b := make([]byte, atyp.Size());
|
|
||||||
*(**byte)(up) = &b[0];
|
|
||||||
}
|
}
|
||||||
p = *(*uintptr)(up);
|
p = *(*uintptr)(up);
|
||||||
}
|
}
|
||||||
|
|
@ -466,23 +463,22 @@ func ignoreArray(state *decodeState, elemOp decOp, length int) os.Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeSlice(atyp *reflect.SliceType, state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl os.ErrorString) os.Error {
|
func decodeSlice(atyp *reflect.SliceType, state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl os.ErrorString) os.Error {
|
||||||
length := uintptr(decodeUint(state));
|
n := int(uintptr(decodeUint(state)));
|
||||||
if indir > 0 {
|
if indir > 0 {
|
||||||
up := unsafe.Pointer(p);
|
up := unsafe.Pointer(p);
|
||||||
if *(*unsafe.Pointer)(up) == nil {
|
if *(*unsafe.Pointer)(up) == nil {
|
||||||
// Allocate the slice header.
|
// Allocate the slice header.
|
||||||
*(*unsafe.Pointer)(up) = unsafe.Pointer(new(reflect.SliceHeader))
|
*(*unsafe.Pointer)(up) = unsafe.Pointer(new([]unsafe.Pointer))
|
||||||
}
|
}
|
||||||
p = *(*uintptr)(up);
|
p = *(*uintptr)(up);
|
||||||
}
|
}
|
||||||
// Allocate storage for the slice elements, that is, the underlying array.
|
// Allocate storage for the slice elements, that is, the underlying array.
|
||||||
data := make([]byte, length*atyp.Elem().Size());
|
|
||||||
// Always write a header at p.
|
// Always write a header at p.
|
||||||
hdrp := (*reflect.SliceHeader)(unsafe.Pointer(p));
|
hdrp := (*reflect.SliceHeader)(unsafe.Pointer(p));
|
||||||
hdrp.Data = uintptr(unsafe.Pointer(&data[0]));
|
hdrp.Data = uintptr(unsafe.NewArray(atyp.Elem(), n));
|
||||||
hdrp.Len = int(length);
|
hdrp.Len = n;
|
||||||
hdrp.Cap = int(length);
|
hdrp.Cap = n;
|
||||||
return decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, int(length), elemIndir, ovfl);
|
return decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, n, elemIndir, ovfl);
|
||||||
}
|
}
|
||||||
|
|
||||||
func ignoreSlice(state *decodeState, elemOp decOp) os.Error {
|
func ignoreSlice(state *decodeState, elemOp decOp) os.Error {
|
||||||
|
|
|
||||||
|
|
@ -595,15 +595,11 @@ func (v *SliceValue) Elem(i int) Value {
|
||||||
// MakeSlice creates a new zero-initialized slice value
|
// MakeSlice creates a new zero-initialized slice value
|
||||||
// for the specified slice type, length, and capacity.
|
// for the specified slice type, length, and capacity.
|
||||||
func MakeSlice(typ *SliceType, len, cap int) *SliceValue {
|
func MakeSlice(typ *SliceType, len, cap int) *SliceValue {
|
||||||
s := new(SliceHeader);
|
s := &SliceHeader{
|
||||||
size := typ.Elem().Size() * uintptr(cap);
|
Data: uintptr(unsafe.NewArray(typ.Elem(), cap)),
|
||||||
if size == 0 {
|
Len: len,
|
||||||
size = 1
|
Cap: cap,
|
||||||
}
|
};
|
||||||
data := make([]uint8, size);
|
|
||||||
s.Data = uintptr(addr(&data[0]));
|
|
||||||
s.Len = len;
|
|
||||||
s.Cap = cap;
|
|
||||||
return newValue(typ, addr(s), true).(*SliceValue);
|
return newValue(typ, addr(s), true).(*SliceValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1270,13 +1266,8 @@ func newValue(typ Type, addr addr, canSet bool) Value {
|
||||||
|
|
||||||
// MakeZero returns a zero Value for the specified Type.
|
// MakeZero returns a zero Value for the specified Type.
|
||||||
func MakeZero(typ Type) Value {
|
func MakeZero(typ Type) Value {
|
||||||
// TODO: this will have to move into
|
if typ == nil {
|
||||||
// the runtime proper in order to play nicely
|
return nil
|
||||||
// with the garbage collector.
|
|
||||||
size := typ.Size();
|
|
||||||
if size == 0 {
|
|
||||||
size = 1
|
|
||||||
}
|
}
|
||||||
data := make([]uint8, size);
|
return newValue(typ, addr(unsafe.New(typ)), true);
|
||||||
return newValue(typ, addr(&data[0]), true);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
#include "type.h"
|
#include "type.h"
|
||||||
|
#include "malloc.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
printiface(Iface i)
|
printiface(Iface i)
|
||||||
|
|
@ -605,7 +606,7 @@ unsafe·Reflect(Eface e, Eface rettype, void *retaddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
unsafe·Unreflect(Iface typ, void *addr, Eface e)
|
unsafe·Unreflect(Eface typ, void *addr, Eface e)
|
||||||
{
|
{
|
||||||
// Reflect library has reinterpreted typ
|
// Reflect library has reinterpreted typ
|
||||||
// as its own kind of type structure.
|
// as its own kind of type structure.
|
||||||
|
|
@ -625,3 +626,41 @@ unsafe·Unreflect(Iface typ, void *addr, Eface e)
|
||||||
|
|
||||||
FLUSH(&e);
|
FLUSH(&e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
unsafe·New(Eface typ, void *ret)
|
||||||
|
{
|
||||||
|
Type *t;
|
||||||
|
|
||||||
|
// Reflect library has reinterpreted typ
|
||||||
|
// as its own kind of type structure.
|
||||||
|
// We know that the pointer to the original
|
||||||
|
// type structure sits before the data pointer.
|
||||||
|
t = (Type*)((Eface*)typ.data-1);
|
||||||
|
|
||||||
|
if(t->kind&KindNoPointers)
|
||||||
|
ret = mallocgc(t->size, RefNoPointers, 1);
|
||||||
|
else
|
||||||
|
ret = mal(t->size);
|
||||||
|
FLUSH(&ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
unsafe·NewArray(Eface typ, uint32 n, void *ret)
|
||||||
|
{
|
||||||
|
uint64 size;
|
||||||
|
Type *t;
|
||||||
|
|
||||||
|
// Reflect library has reinterpreted typ
|
||||||
|
// as its own kind of type structure.
|
||||||
|
// We know that the pointer to the original
|
||||||
|
// type structure sits before the data pointer.
|
||||||
|
t = (Type*)((Eface*)typ.data-1);
|
||||||
|
|
||||||
|
size = n*t->size;
|
||||||
|
if(t->kind&KindNoPointers)
|
||||||
|
ret = mallocgc(size, RefNoPointers, 1);
|
||||||
|
else
|
||||||
|
ret = mal(size);
|
||||||
|
FLUSH(&ret);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
static int32 debug = 0;
|
static int32 debug = 0;
|
||||||
|
|
||||||
|
// see also unsafe·NewArray
|
||||||
// makeslice(typ *Type, nel int, cap int) (ary []any);
|
// makeslice(typ *Type, nel int, cap int) (ary []any);
|
||||||
void
|
void
|
||||||
runtime·makeslice(SliceType *t, uint32 nel, uint32 cap, Slice ret)
|
runtime·makeslice(SliceType *t, uint32 nel, uint32 cap, Slice ret)
|
||||||
|
|
@ -21,9 +22,7 @@ runtime·makeslice(SliceType *t, uint32 nel, uint32 cap, Slice ret)
|
||||||
ret.len = nel;
|
ret.len = nel;
|
||||||
ret.cap = cap;
|
ret.cap = cap;
|
||||||
|
|
||||||
// TODO(rsc): Disabled because reflect and gob cast []byte
|
if((t->elem->kind&KindNoPointers))
|
||||||
// to data structures with pointers.
|
|
||||||
if(0 && (t->elem->kind&KindNoPointers))
|
|
||||||
ret.array = mallocgc(size, RefNoPointers, 1);
|
ret.array = mallocgc(size, RefNoPointers, 1);
|
||||||
else
|
else
|
||||||
ret.array = mal(size);
|
ret.array = mal(size);
|
||||||
|
|
|
||||||
|
|
@ -43,5 +43,17 @@ func Typeof(i interface{}) (typ interface{})
|
||||||
func Reflect(i interface{}) (typ interface{}, addr uintptr)
|
func Reflect(i interface{}) (typ interface{}, addr uintptr)
|
||||||
|
|
||||||
// Unreflect inverts Reflect: Given a type and a pointer, it returns an empty interface value
|
// Unreflect inverts Reflect: Given a type and a pointer, it returns an empty interface value
|
||||||
// with those contents.
|
// with those contents. The typ is assumed to contain a pointer to a runtime type;
|
||||||
|
// the type information in the interface{} is ignored, so that, for example, both
|
||||||
|
// *reflect.StructType and *runtime.StructType can be passed for typ.
|
||||||
func Unreflect(typ interface{}, addr uintptr) (ret interface{})
|
func Unreflect(typ interface{}, addr uintptr) (ret interface{})
|
||||||
|
|
||||||
|
// New allocates and returns a pointer to memory for a new value of the given type.
|
||||||
|
// The typ is assumed to hold a pointer to a runtime type.
|
||||||
|
// Callers should use reflect.MakeZero instead of invoking unsafe.New directly.
|
||||||
|
func New(typ interface{}) Pointer
|
||||||
|
|
||||||
|
// NewArray allocates and returns a pointer to an array of n elements of the given type.
|
||||||
|
// The typ is assumed to hold a pointer to a runtime type.
|
||||||
|
// Callers should use reflect.MakeSlice instead of invoking unsafe.NewArray directly.
|
||||||
|
func NewArray(typ interface{}, n int) Pointer
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue