mirror of
https://github.com/golang/go
synced 2024-11-14 20:20:30 -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{})
|
||||
}
|
||||
|
||||
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) {
|
||||
type T *uintptr
|
||||
tt := TypeOf(T(nil))
|
||||
|
@ -687,42 +687,14 @@ reflect·unsafe_Typeof(Eface e, Eface ret)
|
||||
void
|
||||
reflect·unsafe_New(Type *t, void *ret)
|
||||
{
|
||||
uint32 flag;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
ret = runtime·cnew(t);
|
||||
FLUSH(&ret);
|
||||
}
|
||||
|
||||
void
|
||||
reflect·unsafe_NewArray(Type *t, intgo n, void *ret)
|
||||
{
|
||||
uint64 size;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
ret = runtime·cnewarray(t, n);
|
||||
FLUSH(&ret);
|
||||
}
|
||||
|
||||
|
@ -717,9 +717,8 @@ runtime·new(Type *typ, uint8 *ret)
|
||||
ret = runtime·mallocgc(typ->size, flag, 1, 1);
|
||||
|
||||
if(UseSpanType && !flag) {
|
||||
if(false) {
|
||||
if(false)
|
||||
runtime·printf("new %S: %p\n", *typ->string, ret);
|
||||
}
|
||||
runtime·settype(ret, (uintptr)typ | TypeInfo_SingleObject);
|
||||
}
|
||||
}
|
||||
@ -727,36 +726,45 @@ runtime·new(Type *typ, uint8 *ret)
|
||||
FLUSH(&ret);
|
||||
}
|
||||
|
||||
// same as runtime·new, but callable from C
|
||||
void*
|
||||
runtime·cnew(Type *typ)
|
||||
static void*
|
||||
cnew(Type *typ, intgo n, int32 objtyp)
|
||||
{
|
||||
uint32 flag;
|
||||
void *ret;
|
||||
|
||||
if(raceenabled)
|
||||
m->racepc = runtime·getcallerpc(&typ);
|
||||
|
||||
if(typ->size == 0) {
|
||||
if((objtyp&(PtrSize-1)) != objtyp)
|
||||
runtime·throw("runtime: invalid objtyp");
|
||||
if(n < 0 || (typ->size > 0 && n > MaxMem/typ->size))
|
||||
runtime·panicstring("runtime: allocation size out of range");
|
||||
if(typ->size == 0 || n == 0) {
|
||||
// All 0-length allocations use this pointer.
|
||||
// The language does not require the allocations to
|
||||
// have distinct values.
|
||||
ret = (uint8*)&runtime·zerobase;
|
||||
} else {
|
||||
flag = typ->kind&KindNoPointers ? FlagNoPointers : 0;
|
||||
ret = runtime·mallocgc(typ->size, flag, 1, 1);
|
||||
|
||||
if(UseSpanType && !flag) {
|
||||
if(false) {
|
||||
runtime·printf("new %S: %p\n", *typ->string, ret);
|
||||
}
|
||||
runtime·settype(ret, (uintptr)typ | TypeInfo_SingleObject);
|
||||
}
|
||||
return &runtime·zerobase;
|
||||
}
|
||||
flag = typ->kind&KindNoPointers ? FlagNoPointers : 0;
|
||||
ret = runtime·mallocgc(typ->size*n, flag, 1, 1);
|
||||
if(UseSpanType && !flag) {
|
||||
if(false)
|
||||
runtime·printf("cnew [%D]%S: %p\n", (int64)n, *typ->string, ret);
|
||||
runtime·settype(ret, (uintptr)typ | objtyp);
|
||||
}
|
||||
|
||||
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() {
|
||||
runtime·gc(1);
|
||||
}
|
||||
|
@ -461,6 +461,7 @@ bool runtime·blockspecial(void*);
|
||||
void runtime·setblockspecial(void*, bool);
|
||||
void runtime·purgecachedstats(MCache*);
|
||||
void* runtime·cnew(Type*);
|
||||
void* runtime·cnewarray(Type*, intgo);
|
||||
|
||||
void runtime·settype(void*, uintptr);
|
||||
void runtime·settype_flush(M*, bool);
|
||||
|
@ -48,27 +48,9 @@ uintptr runtime·zerobase;
|
||||
static void
|
||||
makeslice1(SliceType *t, intgo len, intgo cap, Slice *ret)
|
||||
{
|
||||
uintptr size;
|
||||
|
||||
size = cap*t->elem->size;
|
||||
|
||||
ret->len = len;
|
||||
ret->cap = 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);
|
||||
}
|
||||
}
|
||||
ret->array = runtime·cnewarray(t->elem, cap);
|
||||
}
|
||||
|
||||
// appendslice(type *Type, x, y, []T) []T
|
||||
|
Loading…
Reference in New Issue
Block a user