summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/slice.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/slice.c')
-rw-r--r--src/pkg/runtime/slice.c65
1 files changed, 45 insertions, 20 deletions
diff --git a/src/pkg/runtime/slice.c b/src/pkg/runtime/slice.c
index 70534279b..e5726c93b 100644
--- a/src/pkg/runtime/slice.c
+++ b/src/pkg/runtime/slice.c
@@ -3,6 +3,7 @@
// license that can be found in the LICENSE file.
#include "runtime.h"
+#include "arch_GOARCH.h"
#include "type.h"
#include "malloc.h"
@@ -10,8 +11,7 @@ static int32 debug = 0;
static void makeslice1(SliceType*, int32, int32, Slice*);
static void growslice1(SliceType*, Slice, int32, Slice *);
-static void appendslice1(SliceType*, Slice, Slice, Slice*);
- void runtime·slicecopy(Slice to, Slice fm, uintptr width, int32 ret);
+ void runtime·copy(Slice to, Slice fm, uintptr width, int32 ret);
// see also unsafe·NewArray
// makeslice(typ *Type, len, cap int64) (ary []any);
@@ -28,13 +28,18 @@ runtime·makeslice(SliceType *t, int64 len, int64 cap, Slice ret)
if(debug) {
runtime·printf("makeslice(%S, %D, %D); ret=",
*t->string, len, cap);
- runtime·printslice(ret);
+ runtime·printslice(ret);
}
}
+// Dummy word to use as base pointer for make([]T, 0).
+// Since you cannot take the address of such a slice,
+// you can't tell that they all have the same base pointer.
+static uintptr zerobase;
+
static void
makeslice1(SliceType *t, int32 len, int32 cap, Slice *ret)
-{
+{
uintptr size;
size = cap*t->elem->size;
@@ -42,7 +47,9 @@ makeslice1(SliceType *t, int32 len, int32 cap, Slice *ret)
ret->len = len;
ret->cap = cap;
- if((t->elem->kind&KindNoPointers))
+ if(cap == 0)
+ ret->array = (byte*)&zerobase;
+ else if((t->elem->kind&KindNoPointers))
ret->array = runtime·mallocgc(size, FlagNoPointers, 1, 1);
else
ret->array = runtime·mal(size);
@@ -52,14 +59,31 @@ makeslice1(SliceType *t, int32 len, int32 cap, Slice *ret)
void
runtime·appendslice(SliceType *t, Slice x, Slice y, Slice ret)
{
- appendslice1(t, x, y, &ret);
+ int32 m;
+ uintptr w;
+
+ m = x.len+y.len;
+
+ if(m < x.len)
+ runtime·throw("append: slice overflow");
+
+ if(m > x.cap)
+ growslice1(t, x, m, &ret);
+ else
+ ret = x;
+
+ w = t->elem->size;
+ runtime·memmove(ret.array + ret.len*w, y.array, y.len*w);
+ ret.len += y.len;
+ FLUSH(&ret);
}
-static void
-appendslice1(SliceType *t, Slice x, Slice y, Slice *ret)
+
+// appendstr([]byte, string) []byte
+void
+runtime·appendstr(SliceType *t, Slice x, String y, Slice ret)
{
int32 m;
- uintptr w;
m = x.len+y.len;
@@ -67,15 +91,16 @@ appendslice1(SliceType *t, Slice x, Slice y, Slice *ret)
runtime·throw("append: slice overflow");
if(m > x.cap)
- growslice1(t, x, m, ret);
+ growslice1(t, x, m, &ret);
else
- *ret = x;
+ ret = x;
- w = t->elem->size;
- runtime·memmove(ret->array + ret->len*w, y.array, y.len*w);
- ret->len += y.len;
+ runtime·memmove(ret.array + ret.len, y.str, y.len);
+ ret.len += y.len;
+ FLUSH(&ret);
}
+
// growslice(type *Type, x, []T, n int64) []T
void
runtime·growslice(SliceType *t, Slice old, int64 n, Slice ret)
@@ -96,9 +121,9 @@ runtime·growslice(SliceType *t, Slice old, int64 n, Slice ret)
if(debug) {
runtime·printf("growslice(%S,", *t->string);
- runtime·printslice(old);
+ runtime·printslice(old);
runtime·printf(", new cap=%D) =", cap);
- runtime·printslice(ret);
+ runtime·printslice(ret);
}
}
@@ -265,9 +290,9 @@ runtime·slicearray(byte* old, uint64 nel, uint64 lb, uint64 hb, uint64 width, S
}
}
-// slicecopy(to any, fr any, wid uint32) int
+// copy(to any, fr any, wid uint32) int
void
-runtime·slicecopy(Slice to, Slice fm, uintptr width, int32 ret)
+runtime·copy(Slice to, Slice fm, uintptr width, int32 ret)
{
if(fm.len == 0 || to.len == 0 || width == 0) {
ret = 0;
@@ -307,11 +332,11 @@ runtime·slicestringcopy(Slice to, String fm, int32 ret)
ret = 0;
goto out;
}
-
+
ret = fm.len;
if(to.len < ret)
ret = to.len;
-
+
runtime·memmove(to.array, fm.str, ret);
out: