summaryrefslogtreecommitdiff
path: root/src/cmd/gc/reflect.c
diff options
context:
space:
mode:
authorMichael Stapelberg <stapelberg@debian.org>2013-12-03 09:43:15 +0100
committerMichael Stapelberg <stapelberg@debian.org>2013-12-03 09:43:15 +0100
commit64d2a7c8945ba05af859901f5e248f1befdd8621 (patch)
tree013fcb7e9e3296ecdda876012252c36bd6bcb063 /src/cmd/gc/reflect.c
parentb901efe83e212f0c34c769c079e41373da12d723 (diff)
downloadgolang-64d2a7c8945ba05af859901f5e248f1befdd8621.tar.gz
Imported Upstream version 1.2upstream/1.2
Diffstat (limited to 'src/cmd/gc/reflect.c')
-rw-r--r--src/cmd/gc/reflect.c201
1 files changed, 172 insertions, 29 deletions
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index fc182b03e..0a8aa8d7a 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -101,6 +101,138 @@ lsort(Sig *l, int(*f)(Sig*, Sig*))
return l;
}
+// Builds a type respresenting a Bucket structure for
+// the given map type. This type is not visible to users -
+// we include only enough information to generate a correct GC
+// program for it.
+// Make sure this stays in sync with ../../pkg/runtime/hashmap.c!
+enum {
+ BUCKETSIZE = 8,
+ MAXKEYSIZE = 128,
+ MAXVALSIZE = 128,
+};
+
+static Type*
+mapbucket(Type *t)
+{
+ Type *keytype, *valtype;
+ Type *bucket;
+ Type *overflowfield, *keysfield, *valuesfield;
+ int32 offset;
+
+ if(t->bucket != T)
+ return t->bucket;
+
+ keytype = t->down;
+ valtype = t->type;
+ if(keytype->width > MAXKEYSIZE)
+ keytype = ptrto(keytype);
+ if(valtype->width > MAXVALSIZE)
+ valtype = ptrto(valtype);
+
+ bucket = typ(TSTRUCT);
+ bucket->noalg = 1;
+
+ // The first field is: uint8 topbits[BUCKETSIZE].
+ // We don't need to encode it as GC doesn't care about it.
+ offset = BUCKETSIZE * 1;
+
+ overflowfield = typ(TFIELD);
+ overflowfield->type = ptrto(bucket);
+ overflowfield->width = offset; // "width" is offset in structure
+ overflowfield->sym = mal(sizeof(Sym)); // not important but needs to be set to give this type a name
+ overflowfield->sym->name = "overflow";
+ offset += widthptr;
+
+ keysfield = typ(TFIELD);
+ keysfield->type = typ(TARRAY);
+ keysfield->type->type = keytype;
+ keysfield->type->bound = BUCKETSIZE;
+ keysfield->type->width = BUCKETSIZE * keytype->width;
+ keysfield->width = offset;
+ keysfield->sym = mal(sizeof(Sym));
+ keysfield->sym->name = "keys";
+ offset += BUCKETSIZE * keytype->width;
+
+ valuesfield = typ(TFIELD);
+ valuesfield->type = typ(TARRAY);
+ valuesfield->type->type = valtype;
+ valuesfield->type->bound = BUCKETSIZE;
+ valuesfield->type->width = BUCKETSIZE * valtype->width;
+ valuesfield->width = offset;
+ valuesfield->sym = mal(sizeof(Sym));
+ valuesfield->sym->name = "values";
+ offset += BUCKETSIZE * valtype->width;
+
+ // link up fields
+ bucket->type = overflowfield;
+ overflowfield->down = keysfield;
+ keysfield->down = valuesfield;
+ valuesfield->down = T;
+
+ bucket->width = offset;
+ bucket->local = t->local;
+ t->bucket = bucket;
+ return bucket;
+}
+
+// Builds a type respresenting a Hmap structure for
+// the given map type. This type is not visible to users -
+// we include only enough information to generate a correct GC
+// program for it.
+// Make sure this stays in sync with ../../pkg/runtime/hashmap.c!
+static Type*
+hmap(Type *t)
+{
+ Type *h, *bucket;
+ Type *bucketsfield, *oldbucketsfield;
+ int32 offset;
+
+ if(t->hmap != T)
+ return t->hmap;
+
+ bucket = mapbucket(t);
+ h = typ(TSTRUCT);
+ h->noalg = 1;
+
+ offset = widthint; // count
+ offset += 4; // flags
+ offset += 4; // hash0
+ offset += 1; // B
+ offset += 1; // keysize
+ offset += 1; // valuesize
+ offset = (offset + 1) / 2 * 2;
+ offset += 2; // bucketsize
+ offset = (offset + widthptr - 1) / widthptr * widthptr;
+
+ bucketsfield = typ(TFIELD);
+ bucketsfield->type = ptrto(bucket);
+ bucketsfield->width = offset;
+ bucketsfield->sym = mal(sizeof(Sym));
+ bucketsfield->sym->name = "buckets";
+ offset += widthptr;
+
+ oldbucketsfield = typ(TFIELD);
+ oldbucketsfield->type = ptrto(bucket);
+ oldbucketsfield->width = offset;
+ oldbucketsfield->sym = mal(sizeof(Sym));
+ oldbucketsfield->sym->name = "oldbuckets";
+ offset += widthptr;
+
+ offset += widthptr; // nevacuate (last field in Hmap)
+
+ // link up fields
+ h->type = bucketsfield;
+ bucketsfield->down = oldbucketsfield;
+ oldbucketsfield->down = T;
+
+ h->width = offset;
+ h->local = t->local;
+ t->hmap = h;
+ h->hmap = t;
+ return h;
+}
+
/*
* f is method type, with receiver.
* return function type, receiver as first argument (or not).
@@ -208,16 +340,8 @@ methods(Type *t)
if(!(a->isym->flags & SymSiggen)) {
a->isym->flags |= SymSiggen;
if(!eqtype(this, it) || this->width < types[tptr]->width) {
- // Is okay to call genwrapper here always,
- // but we can generate more efficient code
- // using genembedtramp if all that is necessary
- // is a pointer adjustment and a JMP.
compiling_wrappers = 1;
- if(isptr[it->etype] && isptr[this->etype]
- && f->embedded && !isifacemethod(f->type))
- genembedtramp(it, f, a->isym, 1);
- else
- genwrapper(it, f, a->isym, 1);
+ genwrapper(it, f, a->isym, 1);
compiling_wrappers = 0;
}
}
@@ -226,11 +350,7 @@ methods(Type *t)
a->tsym->flags |= SymSiggen;
if(!eqtype(this, t)) {
compiling_wrappers = 1;
- if(isptr[t->etype] && isptr[this->etype]
- && f->embedded && !isifacemethod(f->type))
- genembedtramp(t, f, a->tsym, 0);
- else
- genwrapper(t, f, a->tsym, 0);
+ genwrapper(t, f, a->tsym, 0);
compiling_wrappers = 0;
}
}
@@ -277,8 +397,8 @@ imethods(Type *t)
last = a;
// Compiler can only refer to wrappers for
- // named interface types.
- if(t->sym == S)
+ // named interface types and non-blank methods.
+ if(t->sym == S || isblanksym(method))
continue;
// NOTE(rsc): Perhaps an oversight that
@@ -471,6 +591,10 @@ int
haspointers(Type *t)
{
Type *t1;
+ int ret;
+
+ if(t->haspointers != 0)
+ return t->haspointers - 1;
switch(t->etype) {
case TINT:
@@ -486,17 +610,27 @@ haspointers(Type *t)
case TUINTPTR:
case TFLOAT32:
case TFLOAT64:
+ case TCOMPLEX64:
+ case TCOMPLEX128:
case TBOOL:
- return 0;
+ ret = 0;
+ break;
case TARRAY:
- if(t->bound < 0) // slice
- return 1;
- return haspointers(t->type);
+ if(t->bound < 0) { // slice
+ ret = 1;
+ break;
+ }
+ ret = haspointers(t->type);
+ break;
case TSTRUCT:
- for(t1=t->type; t1!=T; t1=t1->down)
- if(haspointers(t1->type))
- return 1;
- return 0;
+ ret = 0;
+ for(t1=t->type; t1!=T; t1=t1->down) {
+ if(haspointers(t1->type)) {
+ ret = 1;
+ break;
+ }
+ }
+ break;
case TSTRING:
case TPTR32:
case TPTR64:
@@ -506,8 +640,12 @@ haspointers(Type *t)
case TMAP:
case TFUNC:
default:
- return 1;
+ ret = 1;
+ break;
}
+
+ t->haspointers = 1+ret;
+ return ret;
}
/*
@@ -709,7 +847,7 @@ static Sym*
dtypesym(Type *t)
{
int ot, xt, n, isddd, dupok;
- Sym *s, *s1, *s2, *slink;
+ Sym *s, *s1, *s2, *s3, *s4, *slink;
Sig *a, *m;
Type *t1, *tbase, *t2;
@@ -849,10 +987,14 @@ ok:
// ../../pkg/runtime/type.go:/MapType
s1 = dtypesym(t->down);
s2 = dtypesym(t->type);
+ s3 = dtypesym(mapbucket(t));
+ s4 = dtypesym(hmap(t));
ot = dcommontype(s, ot, t);
xt = ot - 2*widthptr;
ot = dsymptr(s, ot, s1, 0);
ot = dsymptr(s, ot, s2, 0);
+ ot = dsymptr(s, ot, s3, 0);
+ ot = dsymptr(s, ot, s4, 0);
break;
case TPTR32:
@@ -1026,7 +1168,8 @@ dalgsym(Type *t)
}
static int
-gcinline(Type *t) {
+gcinline(Type *t)
+{
switch(t->etype) {
case TARRAY:
if(t->bound == 1)
@@ -1111,9 +1254,9 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
// 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);
+ ot = duintptr(s, ot, GC_PTR);
ot = duintptr(s, ot, *off);
- ot = dsymptr(s, ot, dtypesym(t), 0);
+ ot = dsymptr(s, ot, dgcsym(hmap(t)), 0);
*off += t->width;
break;