diff options
| author | Russ Cox <rsc@golang.org> | 2010-10-27 17:56:32 -0700 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2010-10-27 17:56:32 -0700 |
| commit | d8b5d039cd1bec151cc325973ff32bd34ebb0456 (patch) | |
| tree | e16c56c9e4593224ebe7442c1332af7297c97c8f /src/pkg/runtime | |
| parent | b803a255fcad3fcc2f0c1d40f7d262b7989f1117 (diff) | |
| download | go-d8b5d039cd1bec151cc325973ff32bd34ebb0456.tar.xz | |
gc: implement append
R=ken2
CC=golang-dev
https://golang.org/cl/2757042
Diffstat (limited to 'src/pkg/runtime')
| -rw-r--r-- | src/pkg/runtime/slice.c | 86 |
1 files changed, 75 insertions, 11 deletions
diff --git a/src/pkg/runtime/slice.c b/src/pkg/runtime/slice.c index d0ba4ede3f..5884cfcef7 100644 --- a/src/pkg/runtime/slice.c +++ b/src/pkg/runtime/slice.c @@ -8,37 +8,101 @@ static int32 debug = 0; +static void makeslice(SliceType*, int32, int32, Slice*); + void ·slicecopy(Slice to, Slice fm, uintptr width, int32 ret); + // see also unsafe·NewArray // makeslice(typ *Type, len, cap int64) (ary []any); void ·makeslice(SliceType *t, int64 len, int64 cap, Slice ret) { - uintptr size; - if(len < 0 || (int32)len != len) panicstring("makeslice: len out of range"); if(cap < len || (int32)cap != cap || cap > ((uintptr)-1) / t->elem->size) panicstring("makeslice: cap out of range"); + makeslice(t, len, cap, &ret); + + if(debug) { + printf("makeslice(%S, %D, %D); ret=", + *t->string, len, cap); + ·printslice(ret); + } +} + +static void +makeslice(SliceType *t, int32 len, int32 cap, Slice *ret) +{ + uintptr size; + size = cap*t->elem->size; - ret.len = len; - ret.cap = cap; + ret->len = len; + ret->cap = cap; if((t->elem->kind&KindNoPointers)) - ret.array = mallocgc(size, RefNoPointers, 1, 1); + ret->array = mallocgc(size, RefNoPointers, 1, 1); else - ret.array = mal(size); + ret->array = mal(size); +} - FLUSH(&ret); +static void appendslice(SliceType*, Slice, Slice, Slice*); - if(debug) { - printf("makeslice(%S, %D, %D); ret=", - *t->string, len, cap); - ·printslice(ret); +// append(type *Type, n int, old []T, ...,) []T +#pragma textflag 7 +void +·append(SliceType *t, int32 n, Slice old, ...) +{ + Slice sl; + Slice *ret; + + sl.len = n; + sl.array = (byte*)(&old+1); + ret = (Slice*)(sl.array + ((t->elem->size*n+sizeof(uintptr)-1) & ~(sizeof(uintptr)-1))); + appendslice(t, old, sl, ret); +} + +// appendslice(type *Type, x, y, []T) []T +void +·appendslice(SliceType *t, Slice x, Slice y, Slice ret) +{ + appendslice(t, x, y, &ret); +} + +static void +appendslice(SliceType *t, Slice x, Slice y, Slice *ret) +{ + Slice newx; + int32 m; + uintptr w; + + if(x.len+y.len < x.len) + throw("append: slice overflow"); + + w = t->elem->size; + if(x.len+y.len > x.cap) { + m = x.cap; + if(m == 0) + m = y.len; + else { + do { + if(x.len < 1024) + m += m; + else + m += m/4; + } while(m < x.len+y.len); + } + makeslice(t, x.len, m, &newx); + memmove(newx.array, x.array, x.len*w); + x = newx; } + memmove(x.array+x.len*w, y.array, y.len*w); + x.len += y.len; + *ret = x; } + + // sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any); void ·sliceslice(Slice old, uint64 lb, uint64 hb, uint64 width, Slice ret) |
