mirror of
https://github.com/golang/go
synced 2024-11-14 22:40:40 -07:00
[release-branch.go1.1] runtime: introduce cnewarray() to simplify allocation of typed arrays
««« CL 9648044 / 139919984600 runtime: introduce cnewarray() to simplify allocation of typed arrays R=golang-dev, dsymonds CC=golang-dev https://golang.org/cl/9648044 »»» R=dsymonds, dvyukov, dave CC=golang-dev https://golang.org/cl/9780050
This commit is contained in:
parent
ea3b4c9321
commit
09879160e5
@ -3032,6 +3032,25 @@ func TestSliceOf(t *testing.T) {
|
|||||||
checkSameType(t, Zero(SliceOf(TypeOf(T1(1)))).Interface(), []T1{})
|
checkSameType(t, Zero(SliceOf(TypeOf(T1(1)))).Interface(), []T1{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSliceOverflow(t *testing.T) {
|
||||||
|
// check that MakeSlice panics when size of slice overflows uint
|
||||||
|
const S = 1e6
|
||||||
|
s := uint(S)
|
||||||
|
l := (1<<(unsafe.Sizeof((*byte)(nil))*8)-1)/s + 1
|
||||||
|
if l*s >= s {
|
||||||
|
t.Fatal("slice size does not overflow")
|
||||||
|
}
|
||||||
|
var x [S]byte
|
||||||
|
st := SliceOf(TypeOf(x))
|
||||||
|
defer func() {
|
||||||
|
err := recover()
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("slice overflow does not panic")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
MakeSlice(st, int(l), int(l))
|
||||||
|
}
|
||||||
|
|
||||||
func TestSliceOfGC(t *testing.T) {
|
func TestSliceOfGC(t *testing.T) {
|
||||||
type T *uintptr
|
type T *uintptr
|
||||||
tt := TypeOf(T(nil))
|
tt := TypeOf(T(nil))
|
||||||
|
@ -687,42 +687,14 @@ reflect·unsafe_Typeof(Eface e, Eface ret)
|
|||||||
void
|
void
|
||||||
reflect·unsafe_New(Type *t, void *ret)
|
reflect·unsafe_New(Type *t, void *ret)
|
||||||
{
|
{
|
||||||
uint32 flag;
|
ret = runtime·cnew(t);
|
||||||
|
|
||||||
flag = t->kind&KindNoPointers ? FlagNoPointers : 0;
|
|
||||||
ret = runtime·mallocgc(t->size, flag, 1, 1);
|
|
||||||
|
|
||||||
if(UseSpanType && !flag) {
|
|
||||||
if(false) {
|
|
||||||
runtime·printf("unsafe_New %S: %p\n", *t->string, ret);
|
|
||||||
}
|
|
||||||
runtime·settype(ret, (uintptr)t | TypeInfo_SingleObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
FLUSH(&ret);
|
FLUSH(&ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
reflect·unsafe_NewArray(Type *t, intgo n, void *ret)
|
reflect·unsafe_NewArray(Type *t, intgo n, void *ret)
|
||||||
{
|
{
|
||||||
uint64 size;
|
ret = runtime·cnewarray(t, n);
|
||||||
|
|
||||||
size = n*t->size;
|
|
||||||
if(size == 0)
|
|
||||||
ret = (byte*)&runtime·zerobase;
|
|
||||||
else if(t->kind&KindNoPointers)
|
|
||||||
ret = runtime·mallocgc(size, FlagNoPointers, 1, 1);
|
|
||||||
else {
|
|
||||||
ret = runtime·mallocgc(size, 0, 1, 1);
|
|
||||||
|
|
||||||
if(UseSpanType) {
|
|
||||||
if(false) {
|
|
||||||
runtime·printf("unsafe_NewArray [%D]%S: %p\n", (int64)n, *t->string, ret);
|
|
||||||
}
|
|
||||||
runtime·settype(ret, (uintptr)t | TypeInfo_Array);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FLUSH(&ret);
|
FLUSH(&ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -717,9 +717,8 @@ runtime·new(Type *typ, uint8 *ret)
|
|||||||
ret = runtime·mallocgc(typ->size, flag, 1, 1);
|
ret = runtime·mallocgc(typ->size, flag, 1, 1);
|
||||||
|
|
||||||
if(UseSpanType && !flag) {
|
if(UseSpanType && !flag) {
|
||||||
if(false) {
|
if(false)
|
||||||
runtime·printf("new %S: %p\n", *typ->string, ret);
|
runtime·printf("new %S: %p\n", *typ->string, ret);
|
||||||
}
|
|
||||||
runtime·settype(ret, (uintptr)typ | TypeInfo_SingleObject);
|
runtime·settype(ret, (uintptr)typ | TypeInfo_SingleObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -727,36 +726,45 @@ runtime·new(Type *typ, uint8 *ret)
|
|||||||
FLUSH(&ret);
|
FLUSH(&ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// same as runtime·new, but callable from C
|
static void*
|
||||||
void*
|
cnew(Type *typ, intgo n, int32 objtyp)
|
||||||
runtime·cnew(Type *typ)
|
|
||||||
{
|
{
|
||||||
uint32 flag;
|
uint32 flag;
|
||||||
void *ret;
|
void *ret;
|
||||||
|
|
||||||
if(raceenabled)
|
if((objtyp&(PtrSize-1)) != objtyp)
|
||||||
m->racepc = runtime·getcallerpc(&typ);
|
runtime·throw("runtime: invalid objtyp");
|
||||||
|
if(n < 0 || (typ->size > 0 && n > MaxMem/typ->size))
|
||||||
if(typ->size == 0) {
|
runtime·panicstring("runtime: allocation size out of range");
|
||||||
|
if(typ->size == 0 || n == 0) {
|
||||||
// All 0-length allocations use this pointer.
|
// All 0-length allocations use this pointer.
|
||||||
// The language does not require the allocations to
|
// The language does not require the allocations to
|
||||||
// have distinct values.
|
// have distinct values.
|
||||||
ret = (uint8*)&runtime·zerobase;
|
return &runtime·zerobase;
|
||||||
} else {
|
}
|
||||||
flag = typ->kind&KindNoPointers ? FlagNoPointers : 0;
|
flag = typ->kind&KindNoPointers ? FlagNoPointers : 0;
|
||||||
ret = runtime·mallocgc(typ->size, flag, 1, 1);
|
ret = runtime·mallocgc(typ->size*n, flag, 1, 1);
|
||||||
|
if(UseSpanType && !flag) {
|
||||||
if(UseSpanType && !flag) {
|
if(false)
|
||||||
if(false) {
|
runtime·printf("cnew [%D]%S: %p\n", (int64)n, *typ->string, ret);
|
||||||
runtime·printf("new %S: %p\n", *typ->string, ret);
|
runtime·settype(ret, (uintptr)typ | objtyp);
|
||||||
}
|
|
||||||
runtime·settype(ret, (uintptr)typ | TypeInfo_SingleObject);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// same as runtime·new, but callable from C
|
||||||
|
void*
|
||||||
|
runtime·cnew(Type *typ)
|
||||||
|
{
|
||||||
|
return cnew(typ, 1, TypeInfo_SingleObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
runtime·cnewarray(Type *typ, intgo n)
|
||||||
|
{
|
||||||
|
return cnew(typ, n, TypeInfo_Array);
|
||||||
|
}
|
||||||
|
|
||||||
func GC() {
|
func GC() {
|
||||||
runtime·gc(1);
|
runtime·gc(1);
|
||||||
}
|
}
|
||||||
|
@ -461,6 +461,7 @@ bool runtime·blockspecial(void*);
|
|||||||
void runtime·setblockspecial(void*, bool);
|
void runtime·setblockspecial(void*, bool);
|
||||||
void runtime·purgecachedstats(MCache*);
|
void runtime·purgecachedstats(MCache*);
|
||||||
void* runtime·cnew(Type*);
|
void* runtime·cnew(Type*);
|
||||||
|
void* runtime·cnewarray(Type*, intgo);
|
||||||
|
|
||||||
void runtime·settype(void*, uintptr);
|
void runtime·settype(void*, uintptr);
|
||||||
void runtime·settype_flush(M*, bool);
|
void runtime·settype_flush(M*, bool);
|
||||||
|
@ -48,27 +48,9 @@ uintptr runtime·zerobase;
|
|||||||
static void
|
static void
|
||||||
makeslice1(SliceType *t, intgo len, intgo cap, Slice *ret)
|
makeslice1(SliceType *t, intgo len, intgo cap, Slice *ret)
|
||||||
{
|
{
|
||||||
uintptr size;
|
|
||||||
|
|
||||||
size = cap*t->elem->size;
|
|
||||||
|
|
||||||
ret->len = len;
|
ret->len = len;
|
||||||
ret->cap = cap;
|
ret->cap = cap;
|
||||||
|
ret->array = runtime·cnewarray(t->elem, cap);
|
||||||
if(size == 0)
|
|
||||||
ret->array = (byte*)&runtime·zerobase;
|
|
||||||
else if((t->elem->kind&KindNoPointers))
|
|
||||||
ret->array = runtime·mallocgc(size, FlagNoPointers, 1, 1);
|
|
||||||
else {
|
|
||||||
ret->array = runtime·mallocgc(size, 0, 1, 1);
|
|
||||||
|
|
||||||
if(UseSpanType) {
|
|
||||||
if(false) {
|
|
||||||
runtime·printf("new slice [%D]%S: %p\n", (int64)cap, *t->elem->string, ret->array);
|
|
||||||
}
|
|
||||||
runtime·settype(ret->array, (uintptr)t->elem | TypeInfo_Array);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// appendslice(type *Type, x, y, []T) []T
|
// appendslice(type *Type, x, y, []T) []T
|
||||||
|
Loading…
Reference in New Issue
Block a user