diff options
author | Michael Stapelberg <stapelberg@debian.org> | 2013-12-03 09:43:15 +0100 |
---|---|---|
committer | Michael Stapelberg <stapelberg@debian.org> | 2013-12-03 09:43:15 +0100 |
commit | 64d2a7c8945ba05af859901f5e248f1befdd8621 (patch) | |
tree | 013fcb7e9e3296ecdda876012252c36bd6bcb063 /src/cmd/gc/reflect.c | |
parent | b901efe83e212f0c34c769c079e41373da12d723 (diff) | |
download | golang-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.c | 201 |
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; |