1
0
mirror of https://github.com/golang/go synced 2024-11-20 00:04:43 -07:00

cmd/gc: support channel types in the garbage collector

R=golang-dev, dvyukov, rsc
CC=golang-dev
https://golang.org/cl/7473044
This commit is contained in:
Jan Ziak 2013-03-19 19:51:03 +01:00
parent d8714ca49f
commit 6e69df6102
3 changed files with 39 additions and 5 deletions

View File

@ -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)

View File

@ -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");

View File

@ -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)