diff options
Diffstat (limited to 'src/cmd/gc/reflect.c')
-rw-r--r-- | src/cmd/gc/reflect.c | 46 |
1 files changed, 42 insertions, 4 deletions
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c index b8eb79938..fc182b03e 100644 --- a/src/cmd/gc/reflect.c +++ b/src/cmd/gc/reflect.c @@ -1026,13 +1026,29 @@ dalgsym(Type *t) } static int +gcinline(Type *t) { + switch(t->etype) { + case TARRAY: + if(t->bound == 1) + return 1; + if(t->width <= 4*widthptr) + return 1; + break; + } + return 0; +} + +static int dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size) { Type *t1; - vlong o, off2, fieldoffset; + vlong o, off2, fieldoffset, i; if(t->align > 0 && (*off % t->align) != 0) fatal("dgcsym1: invalid initial alignment, %T", t); + + if(t->width == BADWIDTH) + dowidth(t); switch(t->etype) { case TINT8: @@ -1056,6 +1072,7 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size) case TPTR32: case TPTR64: + // NOTE: Any changes here need to be made to reflect.PtrTo as well. if(*off % widthptr != 0) fatal("dgcsym1: invalid alignment, %T", t); if(!haspointers(t->type) || t->type->etype == TUINT8) { @@ -1069,7 +1086,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) @@ -1079,8 +1095,20 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size) *off += t->width; break; + // struct Hchan* + case TCHAN: + // NOTE: Any changes here need to be made to reflect.ChanOf as well. + 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: + // NOTE: Any changes here need to be made to reflect.MapOf as well. if(*off % widthptr != 0) fatal("dgcsym1: invalid alignment, %T", t); ot = duintptr(s, ot, GC_MAP_PTR); @@ -1116,7 +1144,10 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size) case TARRAY: if(t->bound < -1) fatal("dgcsym1: invalid bound, %T", t); + if(t->type->width == BADWIDTH) + dowidth(t->type); if(isslice(t)) { + // NOTE: Any changes here need to be made to reflect.SliceOf as well. // struct { byte* array; uint32 len; uint32 cap; } if(*off % widthptr != 0) fatal("dgcsym1: invalid alignment, %T", t); @@ -1130,10 +1161,14 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size) } *off += t->width; } else { + // NOTE: Any changes here need to be made to reflect.ArrayOf as well, + // at least once ArrayOf's gc info is implemented and ArrayOf is exported. + // struct { byte* array; uint32 len; uint32 cap; } if(t->bound < 1 || !haspointers(t->type)) { *off += t->width; - } else if(t->bound == 1) { - ot = dgcsym1(s, ot, t->type, off, stack_size); // recursive call of dgcsym1 + } else if(gcinline(t)) { + for(i=0; i<t->bound; i++) + ot = dgcsym1(s, ot, t->type, off, stack_size); // recursive call of dgcsym1 } else { if(stack_size < GC_STACK_CAPACITY) { ot = duintptr(s, ot, GC_ARRAY_START); // a stack push during GC @@ -1184,6 +1219,9 @@ dgcsym(Type *t) return s; s->flags |= SymGcgen; + if(t->width == BADWIDTH) + dowidth(t); + ot = 0; off = 0; ot = duintptr(s, ot, t->width); |