summaryrefslogtreecommitdiff
path: root/src/pkg/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime')
-rw-r--r--src/pkg/runtime/gc_test.go52
-rw-r--r--src/pkg/runtime/iface.c32
-rw-r--r--src/pkg/runtime/malloc.goc50
-rw-r--r--src/pkg/runtime/malloc.h1
-rw-r--r--src/pkg/runtime/mgc0.c14
-rw-r--r--src/pkg/runtime/proc.c1
-rw-r--r--src/pkg/runtime/slice.c20
7 files changed, 95 insertions, 75 deletions
diff --git a/src/pkg/runtime/gc_test.go b/src/pkg/runtime/gc_test.go
index 26fc77de1..a3c731ccb 100644
--- a/src/pkg/runtime/gc_test.go
+++ b/src/pkg/runtime/gc_test.go
@@ -97,3 +97,55 @@ func TestGcHashmapIndirection(t *testing.T) {
m[a] = T{}
}
}
+
+func TestGcArraySlice(t *testing.T) {
+ type X struct {
+ buf [1]byte
+ nextbuf []byte
+ next *X
+ }
+ var head *X
+ for i := 0; i < 10; i++ {
+ p := &X{}
+ p.buf[0] = 42
+ p.next = head
+ if head != nil {
+ p.nextbuf = head.buf[:]
+ }
+ head = p
+ runtime.GC()
+ }
+ for p := head; p != nil; p = p.next {
+ if p.buf[0] != 42 {
+ t.Fatal("corrupted heap")
+ }
+ }
+}
+
+func TestGcRescan(t *testing.T) {
+ type X struct {
+ c chan error
+ nextx *X
+ }
+ type Y struct {
+ X
+ nexty *Y
+ p *int
+ }
+ var head *Y
+ for i := 0; i < 10; i++ {
+ p := &Y{}
+ p.c = make(chan error)
+ p.nextx = &head.X
+ p.nexty = head
+ p.p = new(int)
+ *p.p = 42
+ head = p
+ runtime.GC()
+ }
+ for p := head; p != nil; p = p.nexty {
+ if *p.p != 42 {
+ t.Fatal("corrupted heap")
+ }
+ }
+}
diff --git a/src/pkg/runtime/iface.c b/src/pkg/runtime/iface.c
index 370edffb8..5973d6d03 100644
--- a/src/pkg/runtime/iface.c
+++ b/src/pkg/runtime/iface.c
@@ -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);
}
diff --git a/src/pkg/runtime/malloc.goc b/src/pkg/runtime/malloc.goc
index f1d25a793..ef755f25c 100644
--- a/src/pkg/runtime/malloc.goc
+++ b/src/pkg/runtime/malloc.goc
@@ -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);
}
diff --git a/src/pkg/runtime/malloc.h b/src/pkg/runtime/malloc.h
index 52b76d557..7bbc1b2b3 100644
--- a/src/pkg/runtime/malloc.h
+++ b/src/pkg/runtime/malloc.h
@@ -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);
diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c
index f9dbdbb4a..c83f1892c 100644
--- a/src/pkg/runtime/mgc0.c
+++ b/src/pkg/runtime/mgc0.c
@@ -623,7 +623,7 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
byte *b, *arena_start, *arena_used;
uintptr n, i, end_b, elemsize, size, ti, objti, count, type;
uintptr *pc, precise_type, nominal_size;
- uintptr *map_ret, mapkey_size, mapval_size, mapkey_ti, mapval_ti, *chan_ret;
+ uintptr *map_ret, mapkey_size, mapval_size, mapkey_ti, mapval_ti, *chan_ret, chancap;
void *obj;
Type *t;
Slice *sliceptr;
@@ -799,7 +799,11 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
sliceptr = (Slice*)(stack_top.b + pc[1]);
if(sliceptr->cap != 0) {
obj = sliceptr->array;
- objti = pc[2] | PRECISE | LOOP;
+ // Can't use slice element type for scanning,
+ // because if it points to an array embedded
+ // in the beginning of a struct,
+ // we will scan the whole struct as the slice.
+ // So just obtain type info from heap.
}
pc += 3;
break;
@@ -1058,13 +1062,13 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
if(!(chantype->elem->kind & KindNoPointers)) {
// Channel's buffer follows Hchan immediately in memory.
// Size of buffer (cap(c)) is second int in the chan struct.
- n = ((uintgo*)chan)[1];
- if(n > 0) {
+ chancap = ((uintgo*)chan)[1];
+ if(chancap > 0) {
// TODO(atom): split into two chunks so that only the
// in-use part of the circular buffer is scanned.
// (Channel routines zero the unused part, so the current
// code does not lead to leaks, it's just a little inefficient.)
- *objbufpos++ = (Obj){(byte*)chan+runtime·Hchansize, n*chantype->elem->size,
+ *objbufpos++ = (Obj){(byte*)chan+runtime·Hchansize, chancap*chantype->elem->size,
(uintptr)chantype->elem->gc | PRECISE | LOOP};
if(objbufpos == objbuf_end)
flushobjbuf(objbuf, &objbufpos, &wp, &wbuf, &nobj);
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index 018a453d6..31876b62a 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -1232,6 +1232,7 @@ static void
goexit0(G *gp)
{
gp->status = Gdead;
+ gp->fnstart = nil;
gp->m = nil;
gp->lockedm = nil;
m->curg = nil;
diff --git a/src/pkg/runtime/slice.c b/src/pkg/runtime/slice.c
index 354c54c86..dd92a59a9 100644
--- a/src/pkg/runtime/slice.c
+++ b/src/pkg/runtime/slice.c
@@ -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