aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime/slice.c
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2010-10-27 17:56:32 -0700
committerRuss Cox <rsc@golang.org>2010-10-27 17:56:32 -0700
commitd8b5d039cd1bec151cc325973ff32bd34ebb0456 (patch)
treee16c56c9e4593224ebe7442c1332af7297c97c8f /src/pkg/runtime/slice.c
parentb803a255fcad3fcc2f0c1d40f7d262b7989f1117 (diff)
downloadgo-d8b5d039cd1bec151cc325973ff32bd34ebb0456.tar.xz
gc: implement append
R=ken2 CC=golang-dev https://golang.org/cl/2757042
Diffstat (limited to 'src/pkg/runtime/slice.c')
-rw-r--r--src/pkg/runtime/slice.c86
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)