]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: introduce unsafe.New and unsafe.NewArray
authorRuss Cox <rsc@golang.org>
Mon, 7 Dec 2009 23:51:58 +0000 (15:51 -0800)
committerRuss Cox <rsc@golang.org>
Mon, 7 Dec 2009 23:51:58 +0000 (15:51 -0800)
    to provide functionality previously hacked in to
    reflect and gob.

R=r
https://golang.org/cl/165076

src/cmd/gc/builtin.c.boot
src/cmd/gc/unsafe.go
src/pkg/gob/decode.go
src/pkg/reflect/value.go
src/pkg/runtime/iface.c
src/pkg/runtime/slice.c
src/pkg/unsafe/unsafe.go

index 98c2b8a7ba634376eaa3dabdb50a0ae49a8faac6..4324c890faebb8702c56d412e91f0e25b4c624a0 100644 (file)
@@ -86,5 +86,7 @@ char *unsafeimport =
        "func unsafe.Typeof (i interface { }) (typ interface { })\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.New (typ interface { }) (? unsafe.Pointer)\n"
+       "func unsafe.NewArray (typ interface { }, n int) (? unsafe.Pointer)\n"
        "\n"
        "$$\n";
index 0511262072ab7412d711a7b7f183e079f07eab74..00fae062e5008c141980314fb4d1d56a9b9030eb 100644 (file)
@@ -12,3 +12,5 @@ func Alignof(any) int
 func Typeof(i interface{}) (typ interface{})
 func Reflect(i interface{}) (typ interface{}, addr Pointer)
 func Unreflect(typ interface{}, addr Pointer) (ret interface{})
+func New(typ interface{}) Pointer
+func NewArray(typ interface{}, n int) Pointer
index 3cf1233539ac8a827ced0aee4f01387d453344e6..a3294ac50ba2026ee345fd8823be6967e96cc01b 100644 (file)
@@ -13,6 +13,7 @@ import (
        "math";
        "os";
        "reflect";
+       "runtime";
        "unsafe";
 )
 
@@ -361,10 +362,8 @@ func decodeStruct(engine *decEngine, rtyp *reflect.StructType, b *bytes.Buffer,
                        up = decIndirect(up, indir)
                }
                if *(*unsafe.Pointer)(up) == nil {
-                       // Allocate object by making a slice of bytes and recording the
-                       // address of the beginning of the array. TODO(rsc).
-                       b := make([]byte, rtyp.Size());
-                       *(*unsafe.Pointer)(up) = unsafe.Pointer(&b[0]);
+                       // Allocate object.
+                       *(*unsafe.Pointer)(up) = unsafe.New((*runtime.StructType)(unsafe.Pointer(rtyp)))
                }
                p = *(*uintptr)(up);
        }
@@ -437,10 +436,8 @@ func decodeArray(atyp *reflect.ArrayType, state *decodeState, p uintptr, elemOp
        if indir > 0 {
                up := unsafe.Pointer(p);
                if *(*unsafe.Pointer)(up) == nil {
-                       // Allocate the array by making a slice of bytes of the correct size
-                       // and taking the address of the beginning of the array. TODO(rsc).
-                       b := make([]byte, atyp.Size());
-                       *(**byte)(up) = &b[0];
+                       // Allocate object.
+                       *(*unsafe.Pointer)(up) = unsafe.New(atyp)
                }
                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 {
-       length := uintptr(decodeUint(state));
+       n := int(uintptr(decodeUint(state)));
        if indir > 0 {
                up := unsafe.Pointer(p);
                if *(*unsafe.Pointer)(up) == nil {
                        // Allocate the slice header.
-                       *(*unsafe.Pointer)(up) = unsafe.Pointer(new(reflect.SliceHeader))
+                       *(*unsafe.Pointer)(up) = unsafe.Pointer(new([]unsafe.Pointer))
                }
                p = *(*uintptr)(up);
        }
        // Allocate storage for the slice elements, that is, the underlying array.
-       data := make([]byte, length*atyp.Elem().Size());
        // Always write a header at p.
        hdrp := (*reflect.SliceHeader)(unsafe.Pointer(p));
-       hdrp.Data = uintptr(unsafe.Pointer(&data[0]));
-       hdrp.Len = int(length);
-       hdrp.Cap = int(length);
-       return decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, int(length), elemIndir, ovfl);
+       hdrp.Data = uintptr(unsafe.NewArray(atyp.Elem(), n));
+       hdrp.Len = n;
+       hdrp.Cap = n;
+       return decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, n, elemIndir, ovfl);
 }
 
 func ignoreSlice(state *decodeState, elemOp decOp) os.Error {
index c71f4dd693fafda26244f1cdc4d538865543c779..34393f953d241bbc74bf2d8f6240298157a3b03c 100644 (file)
@@ -595,15 +595,11 @@ func (v *SliceValue) Elem(i int) Value {
 // MakeSlice creates a new zero-initialized slice value
 // for the specified slice type, length, and capacity.
 func MakeSlice(typ *SliceType, len, cap int) *SliceValue {
-       s := new(SliceHeader);
-       size := typ.Elem().Size() * uintptr(cap);
-       if size == 0 {
-               size = 1
-       }
-       data := make([]uint8, size);
-       s.Data = uintptr(addr(&data[0]));
-       s.Len = len;
-       s.Cap = cap;
+       s := &SliceHeader{
+               Data: uintptr(unsafe.NewArray(typ.Elem(), cap)),
+               Len: len,
+               Cap: cap,
+       };
        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.
 func MakeZero(typ Type) Value {
-       // TODO: this will have to move into
-       // the runtime proper in order to play nicely
-       // with the garbage collector.
-       size := typ.Size();
-       if size == 0 {
-               size = 1
-       }
-       data := make([]uint8, size);
-       return newValue(typ, addr(&data[0]), true);
+       if typ == nil {
+               return nil
+       }
+       return newValue(typ, addr(unsafe.New(typ)), true);
 }
index a48f504c29e4c0a8daeb30ce669dd6ad8fc45a7d..4a961ceae0b95ed690dac8f3d1e073d411076205 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "runtime.h"
 #include "type.h"
+#include "malloc.h"
 
 static void
 printiface(Iface i)
@@ -605,7 +606,7 @@ unsafe·Reflect(Eface e, Eface rettype, void *retaddr)
 }
 
 void
-unsafe·Unreflect(Iface typ, void *addr, Eface e)
+unsafe·Unreflect(Eface typ, void *addr, Eface e)
 {
        // Reflect library has reinterpreted typ
        // as its own kind of type structure.
@@ -625,3 +626,41 @@ unsafe·Unreflect(Iface typ, void *addr, Eface 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);
+}
index 1d7a56e7ba8ef5568ec795664e8c233a83d2d336..4d5840c21c731146f8908ef5265b37c89c74deda 100644 (file)
@@ -8,6 +8,7 @@
 
 static int32   debug   = 0;
 
+// see also unsafe·NewArray
 // makeslice(typ *Type, nel int, cap int) (ary []any);
 void
 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.cap = cap;
 
-       // TODO(rsc): Disabled because reflect and gob cast []byte
-       // to data structures with pointers.
-       if(0 && (t->elem->kind&KindNoPointers))
+       if((t->elem->kind&KindNoPointers))
                ret.array = mallocgc(size, RefNoPointers, 1);
        else
                ret.array = mal(size);
index d55aa2446deeee4b12186ac74a36149e718cf139..fc583fe95b37045dbe3d8d498eb2bb838a1a2081 100644 (file)
@@ -43,5 +43,17 @@ func Typeof(i interface{}) (typ interface{})
 func Reflect(i interface{}) (typ interface{}, addr uintptr)
 
 // 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{})
+
+// 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