]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: support channel types in the garbage collector
authorJan Ziak <0xe2.0x9a.0x9b@gmail.com>
Tue, 19 Mar 2013 18:51:03 +0000 (19:51 +0100)
committerJan Ziak <0xe2.0x9a.0x9b@gmail.com>
Tue, 19 Mar 2013 18:51:03 +0000 (19:51 +0100)
R=golang-dev, dvyukov, rsc
CC=golang-dev
https://golang.org/cl/7473044

src/cmd/gc/reflect.c
src/pkg/runtime/mgc0.c
src/pkg/runtime/mgc0.h

index 026b5a12b52ba6974771df3c07495ed0a21f5dd6..8b546e2356ecf0c0b6656ad89d78d7c8a0a4c9d9 100644 (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)
index 5a810c0788b68bbde59eb5abd870cdb821e9ce90..39beed9f9e8eb773875f52570cc42aaf3e3f8287 100644 (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");
index 87b604a36d9b166ef57b24157ecda387fb82fa89..18f3654b48ddbebe14bf54337fd88155b7b341bf 100644 (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)