Commit 5782f411 authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

runtime: introduce cnewarray() to simplify allocation of typed arrays

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/9648044
parent e017e0cb
...@@ -3032,6 +3032,25 @@ func TestSliceOf(t *testing.T) { ...@@ -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) ...@@ -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);
} }
......
...@@ -729,9 +729,8 @@ runtime·new(Type *typ, uint8 *ret) ...@@ -729,9 +729,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);
} }
} }
...@@ -739,36 +738,45 @@ runtime·new(Type *typ, uint8 *ret) ...@@ -739,36 +738,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);
} }
......
...@@ -458,6 +458,7 @@ bool runtime·blockspecial(void*); ...@@ -458,6 +458,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);
......
...@@ -51,27 +51,9 @@ uintptr runtime·zerobase; ...@@ -51,27 +51,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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment