aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorJan Ziak <0xe2.0x9a.0x9b@gmail.com>2012-09-12 12:08:27 -0400
committerRuss Cox <rsc@golang.org>2012-09-12 12:08:27 -0400
commitd09afc2efb50eeb3a1e55cbe05f42307ca0369b1 (patch)
tree00b356133f01f2be1f2bbbfd6486bf4aeee077ce /src/cmd
parent792518c65618599853e1f9da3c23d4ba7d2cce9f (diff)
downloadgo-d09afc2efb50eeb3a1e55cbe05f42307ca0369b1.tar.xz
gc: generate garbage collection info for types
R=rsc, nigeltao, minux.ma CC=golang-dev https://golang.org/cl/6290043
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/gc/go.h1
-rw-r--r--src/cmd/gc/reflect.c178
2 files changed, 178 insertions, 1 deletions
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 4a8d191dc7..5ce9fb9e94 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -347,6 +347,7 @@ enum
SymExported = 1<<2, // already written out by export
SymUniq = 1<<3,
SymSiggen = 1<<4,
+ SymGcgen = 1<<5,
};
struct Sym
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index 7496b71bf2..9dbf1ec596 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -5,6 +5,7 @@
#include <u.h>
#include <libc.h>
#include "go.h"
+#include "../../pkg/runtime/mgc0.h"
/*
* runtime interface and reflection data structures
@@ -14,6 +15,7 @@ static NodeList* signatlist;
static Sym* dtypesym(Type*);
static Sym* weaktypesym(Type*);
static Sym* dalgsym(Type*);
+static Sym* dgcsym(Type*);
static int
sigcmp(Sig *a, Sig *b)
@@ -586,7 +588,7 @@ dcommontype(Sym *s, int ot, Type *t)
ot = dsymptr(s, ot, algarray, alg*sizeofAlg);
else
ot = dsymptr(s, ot, algsym, 0);
- ot = duintptr(s, ot, 0); // gc
+ ot = dsymptr(s, ot, dgcsym(t), 0); // gc
p = smprint("%-uT", t);
//print("dcommontype: %s\n", p);
ot = dgostringptr(s, ot, p); // string
@@ -970,3 +972,177 @@ dalgsym(Type *t)
return s;
}
+static int
+dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
+{
+ Type *t1;
+ vlong o, off2, fieldoffset;
+
+ if(t->align > 0 && (*off % t->align) != 0)
+ fatal("dgcsym1: invalid initial alignment, %T", t);
+
+ switch(t->etype) {
+ case TINT8:
+ case TUINT8:
+ case TINT16:
+ case TUINT16:
+ case TINT32:
+ case TUINT32:
+ case TINT64:
+ case TUINT64:
+ case TINT:
+ case TUINT:
+ case TUINTPTR:
+ case TBOOL:
+ case TFLOAT32:
+ case TFLOAT64:
+ case TCOMPLEX64:
+ case TCOMPLEX128:
+ *off += t->width;
+ break;
+
+ case TPTR32:
+ case TPTR64:
+ if(*off % widthptr != 0)
+ fatal("dgcsym1: invalid alignment, %T", t);
+ if(!haspointers(t->type) || t->type->etype == TUINT8) {
+ ot = duintptr(s, ot, GC_APTR);
+ ot = duintptr(s, ot, *off);
+ } else {
+ ot = duintptr(s, ot, GC_PTR);
+ ot = duintptr(s, ot, *off);
+ ot = dsymptr(s, ot, dgcsym(t->type), 0);
+ }
+ *off += t->width;
+ break;
+
+ case TCHAN:
+ case TUNSAFEPTR:
+ case TFUNC:
+ if(*off % widthptr != 0)
+ fatal("dgcsym1: invalid alignment, %T", t);
+ ot = duintptr(s, ot, GC_APTR);
+ ot = duintptr(s, ot, *off);
+ *off += t->width;
+ break;
+
+ // struct Hmap*
+ case TMAP:
+ if(*off % widthptr != 0)
+ fatal("dgcsym1: invalid alignment, %T", t);
+ ot = duintptr(s, ot, GC_MAP_PTR);
+ ot = duintptr(s, ot, *off);
+ ot = dsymptr(s, ot, dtypesym(t), 0);
+ *off += t->width;
+ break;
+
+ // struct { byte *str; int32 len; }
+ case TSTRING:
+ if(*off % widthptr != 0)
+ fatal("dgcsym1: invalid alignment, %T", t);
+ ot = duintptr(s, ot, GC_STRING);
+ ot = duintptr(s, ot, *off);
+ *off += t->width;
+ break;
+
+ // struct { Itab* tab; void* data; }
+ // struct { Type* type; void* data; } // When isnilinter(t)==true
+ case TINTER:
+ if(*off % widthptr != 0)
+ fatal("dgcsym1: invalid alignment, %T", t);
+ if(isnilinter(t)) {
+ ot = duintptr(s, ot, GC_EFACE);
+ ot = duintptr(s, ot, *off);
+ } else {
+ ot = duintptr(s, ot, GC_IFACE);
+ ot = duintptr(s, ot, *off);
+ }
+ *off += t->width;
+ break;
+
+ case TARRAY:
+ if(t->bound < -1)
+ fatal("dgcsym1: invalid bound, %T", t);
+ if(isslice(t)) {
+ // struct { byte* array; uint32 len; uint32 cap; }
+ if(*off % widthptr != 0)
+ fatal("dgcsym1: invalid alignment, %T", t);
+ if(t->type->width != 0) {
+ ot = duintptr(s, ot, GC_SLICE);
+ ot = duintptr(s, ot, *off);
+ ot = dsymptr(s, ot, dgcsym(t->type), 0);
+ } else {
+ ot = duintptr(s, ot, GC_APTR);
+ ot = duintptr(s, ot, *off);
+ }
+ *off += t->width;
+ } else {
+ 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(stack_size < GC_STACK_CAPACITY) {
+ ot = duintptr(s, ot, GC_ARRAY_START); // a stack push during GC
+ ot = duintptr(s, ot, *off);
+ ot = duintptr(s, ot, t->bound);
+ ot = duintptr(s, ot, t->type->width);
+ off2 = 0;
+ ot = dgcsym1(s, ot, t->type, &off2, stack_size+1); // recursive call of dgcsym1
+ ot = duintptr(s, ot, GC_ARRAY_NEXT); // a stack pop during GC
+ } else {
+ ot = duintptr(s, ot, GC_REGION);
+ ot = duintptr(s, ot, *off);
+ ot = duintptr(s, ot, t->width);
+ ot = dsymptr(s, ot, dgcsym(t), 0);
+ }
+ *off += t->width;
+ }
+ }
+ break;
+
+ case TSTRUCT:
+ o = 0;
+ for(t1=t->type; t1!=T; t1=t1->down) {
+ fieldoffset = t1->width;
+ *off += fieldoffset - o;
+ ot = dgcsym1(s, ot, t1->type, off, stack_size); // recursive call of dgcsym1
+ o = fieldoffset + t1->type->width;
+ }
+ *off += t->width - o;
+ break;
+
+ default:
+ fatal("dgcsym1: unexpected type %T", t);
+ }
+
+ return ot;
+}
+
+static Sym*
+dgcsym(Type *t)
+{
+ int ot;
+ vlong off;
+ Sym *s;
+
+ s = typesymprefix(".gc", t);
+ if(s->flags & SymGcgen)
+ return s;
+ s->flags |= SymGcgen;
+
+ ot = 0;
+ off = 0;
+ ot = duintptr(s, ot, t->width);
+ ot = dgcsym1(s, ot, t, &off, 0);
+ ot = duintptr(s, ot, GC_END);
+ ggloblsym(s, ot, 1, 1);
+
+ if(t->align > 0)
+ off = rnd(off, t->align);
+ if(off != t->width)
+ fatal("dgcsym: off=%lld, size=%lld, type %T", off, t->width, t);
+
+ return s;
+}
+