From 6e69df6102d167344a74d720b5ef080cdf04a8d7 Mon Sep 17 00:00:00 2001 From: Jan Ziak <0xe2.0x9a.0x9b@gmail.com> Date: Tue, 19 Mar 2013 19:51:03 +0100 Subject: [PATCH] cmd/gc: support channel types in the garbage collector R=golang-dev, dvyukov, rsc CC=golang-dev https://golang.org/cl/7473044 --- src/cmd/gc/reflect.c | 11 ++++++++++- src/pkg/runtime/mgc0.c | 32 ++++++++++++++++++++++++++++---- src/pkg/runtime/mgc0.h | 1 + 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c index 026b5a12b5..8b546e2356 100644 --- a/src/cmd/gc/reflect.c +++ b/src/cmd/gc/reflect.c @@ -1082,7 +1082,6 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size) *off += t->width; break; - case TCHAN: case TUNSAFEPTR: case TFUNC: if(*off % widthptr != 0) @@ -1092,6 +1091,16 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size) *off += t->width; break; + // struct Hchan* + case TCHAN: + if(*off % widthptr != 0) + fatal("dgcsym1: invalid alignment, %T", t); + ot = duintptr(s, ot, GC_CHAN_PTR); + ot = duintptr(s, ot, *off); + ot = dsymptr(s, ot, dtypesym(t), 0); + *off += t->width; + break; + // struct Hmap* case TMAP: if(*off % widthptr != 0) diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c index 5a810c0788..39beed9f9e 100644 --- a/src/pkg/runtime/mgc0.c +++ b/src/pkg/runtime/mgc0.c @@ -566,7 +566,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; + uintptr *map_ret, mapkey_size, mapval_size, mapkey_ti, mapval_ti, *chan_ret; void *obj; Type *t; Slice *sliceptr; @@ -627,6 +627,7 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking) mapkey_ti = mapval_ti = 0; chan = nil; chantype = nil; + chan_ret = nil; goto next_block; @@ -692,7 +693,7 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking) mapval_kind = maptype->elem->kind; mapval_ti = (uintptr)maptype->elem->gc | PRECISE; - map_ret = 0; + map_ret = nil; pc = mapProg; } else { goto next_block; @@ -701,6 +702,7 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking) case TypeInfo_Chan: chan = (Hchan*)b; chantype = (ChanType*)t; + chan_ret = nil; pc = chanProg; break; default: @@ -941,7 +943,7 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking) } } } - if(map_ret == 0) + if(map_ret == nil) goto next_block; pc = map_ret; continue; @@ -957,6 +959,25 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking) flushobjbuf(objbuf, &objbufpos, &wp, &wbuf, &nobj); continue; + case GC_CHAN_PTR: + // Similar to GC_MAP_PTR + chan = *(Hchan**)(stack_top.b + pc[1]); + if(chan == nil) { + pc += 3; + continue; + } + if(markonly(chan)) { + chantype = (ChanType*)pc[2]; + if(!(chantype->elem->kind & KindNoPointers)) { + // Start chanProg. + chan_ret = pc+3; + pc = chanProg+1; + continue; + } + } + pc += 3; + continue; + case GC_CHAN: // There are no heap pointers in struct Hchan, // so we can ignore the leading sizeof(Hchan) bytes. @@ -975,7 +996,10 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking) flushobjbuf(objbuf, &objbufpos, &wp, &wbuf, &nobj); } } - goto next_block; + if(chan_ret == nil) + goto next_block; + pc = chan_ret; + continue; default: runtime·throw("scanblock: invalid GC instruction"); diff --git a/src/pkg/runtime/mgc0.h b/src/pkg/runtime/mgc0.h index 87b604a36d..18f3654b48 100644 --- a/src/pkg/runtime/mgc0.h +++ b/src/pkg/runtime/mgc0.h @@ -24,6 +24,7 @@ enum { GC_ARRAY_NEXT, // The next element of an array. Args: none GC_CALL, // Call a subroutine. Args: (off, objgcrel) GC_MAP_PTR, // Go map. Args: (off, MapType*) + GC_CHAN_PTR, // Go channel. Args: (off, ChanType*) GC_STRING, // Go string. Args: (off) GC_EFACE, // interface{}. Args: (off) GC_IFACE, // interface{...}. Args: (off) -- 2.48.1