Commit abc516e4 authored by Carl Shapiro's avatar Carl Shapiro

cmd/cc, cmd/gc, runtime: Uniquely encode iface and eface pointers in the pointer map.

Prior to this change, pointer maps encoded the disposition of
a word using a single bit.  A zero signaled a non-pointer
value and a one signaled a pointer value.  Interface values,
which are a effectively a union type, were conservatively
labeled as a pointer.

This change widens the logical element size of the pointer map
to two bits per word.  As before, zero signals a non-pointer
value and one signals a pointer value.  Additionally, a two
signals an iface pointer and a three signals an eface pointer.

Following other changes to the runtime, values two and three
will allow a type information to drive interpretation of the
subsequent word so only those interface values containing a
pointer value will be scanned.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/12689046
parent 556b337e
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#include "gc.h" #include "gc.h"
#include "../../pkg/runtime/funcdata.h" #include "../../pkg/runtime/funcdata.h"
enum { BitsPerPointer = 2 };
static void dumpgcargs(Type *fn, Sym *sym); static void dumpgcargs(Type *fn, Sym *sym);
int int
...@@ -674,7 +676,7 @@ walktype1(Type *t, int32 offset, Bvec *bv) ...@@ -674,7 +676,7 @@ walktype1(Type *t, int32 offset, Bvec *bv)
// pointer types // pointer types
if((offset + t->offset) % ewidth[TIND] != 0) if((offset + t->offset) % ewidth[TIND] != 0)
yyerror("unaligned pointer"); yyerror("unaligned pointer");
bvset(bv, (offset + t->offset) / ewidth[TIND]); bvset(bv, ((offset + t->offset) / ewidth[TIND])*BitsPerPointer);
break; break;
case TSTRUCT: case TSTRUCT:
...@@ -701,6 +703,7 @@ dumpgcargs(Type *fn, Sym *sym) ...@@ -701,6 +703,7 @@ dumpgcargs(Type *fn, Sym *sym)
Bvec *bv; Bvec *bv;
Type *t; Type *t;
int32 i; int32 i;
int32 argbytes;
int32 symoffset, argoffset; int32 symoffset, argoffset;
if(hasdotdotdot()) { if(hasdotdotdot()) {
...@@ -709,7 +712,8 @@ dumpgcargs(Type *fn, Sym *sym) ...@@ -709,7 +712,8 @@ dumpgcargs(Type *fn, Sym *sym)
gextern(sym, nodconst(0), 0, 4); // nptrs=0 gextern(sym, nodconst(0), 0, 4); // nptrs=0
symoffset = 4; symoffset = 4;
} else { } else {
bv = bvalloc((argsize() + ewidth[TIND] - 1) / ewidth[TIND]); argbytes = (argsize() + ewidth[TIND] - 1);
bv = bvalloc((argbytes / ewidth[TIND]) * BitsPerPointer);
argoffset = align(0, fn->link, Aarg0, nil); argoffset = align(0, fn->link, Aarg0, nil);
if(argoffset > 0) { if(argoffset > 0) {
// The C calling convention returns structs by // The C calling convention returns structs by
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include "opt.h" #include "opt.h"
#include "../../pkg/runtime/funcdata.h" #include "../../pkg/runtime/funcdata.h"
enum { BitsPerPointer = 2 };
static void allocauto(Prog* p); static void allocauto(Prog* p);
static void dumpgcargs(Node*, Sym*); static void dumpgcargs(Node*, Sym*);
static void dumpgclocals(Node*, Sym*); static void dumpgclocals(Node*, Sym*);
...@@ -227,7 +229,7 @@ walktype1(Type *t, vlong *xoffset, Bvec *bv) ...@@ -227,7 +229,7 @@ walktype1(Type *t, vlong *xoffset, Bvec *bv)
case TMAP: case TMAP:
if(*xoffset % widthptr != 0) if(*xoffset % widthptr != 0)
fatal("walktype1: invalid alignment, %T", t); fatal("walktype1: invalid alignment, %T", t);
bvset(bv, *xoffset / widthptr); bvset(bv, (*xoffset / widthptr) * BitsPerPointer);
*xoffset += t->width; *xoffset += t->width;
break; break;
...@@ -235,7 +237,7 @@ walktype1(Type *t, vlong *xoffset, Bvec *bv) ...@@ -235,7 +237,7 @@ walktype1(Type *t, vlong *xoffset, Bvec *bv)
// struct { byte *str; intgo len; } // struct { byte *str; intgo len; }
if(*xoffset % widthptr != 0) if(*xoffset % widthptr != 0)
fatal("walktype1: invalid alignment, %T", t); fatal("walktype1: invalid alignment, %T", t);
bvset(bv, *xoffset / widthptr); bvset(bv, (*xoffset / widthptr) * BitsPerPointer);
*xoffset += t->width; *xoffset += t->width;
break; break;
...@@ -245,8 +247,10 @@ walktype1(Type *t, vlong *xoffset, Bvec *bv) ...@@ -245,8 +247,10 @@ walktype1(Type *t, vlong *xoffset, Bvec *bv)
// struct { Type* type; union { void* ptr, uintptr val } data; } // struct { Type* type; union { void* ptr, uintptr val } data; }
if(*xoffset % widthptr != 0) if(*xoffset % widthptr != 0)
fatal("walktype1: invalid alignment, %T", t); fatal("walktype1: invalid alignment, %T", t);
bvset(bv, *xoffset / widthptr); bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 1);
bvset(bv, (*xoffset + widthptr) / widthptr); if(isnilinter(t))
bvset(bv, ((*xoffset / widthptr) * BitsPerPointer));
bvset(bv, ((*xoffset + widthptr) / widthptr) * BitsPerPointer);
*xoffset += t->width; *xoffset += t->width;
break; break;
...@@ -259,7 +263,7 @@ walktype1(Type *t, vlong *xoffset, Bvec *bv) ...@@ -259,7 +263,7 @@ walktype1(Type *t, vlong *xoffset, Bvec *bv)
// struct { byte* array; uintgo len; uintgo cap; } // struct { byte* array; uintgo len; uintgo cap; }
if(*xoffset % widthptr != 0) if(*xoffset % widthptr != 0)
fatal("walktype1: invalid TARRAY alignment, %T", t); fatal("walktype1: invalid TARRAY alignment, %T", t);
bvset(bv, *xoffset / widthptr); bvset(bv, (*xoffset / widthptr) * BitsPerPointer);
*xoffset += t->width; *xoffset += t->width;
} else if(!haspointers(t->type)) } else if(!haspointers(t->type))
*xoffset += t->width; *xoffset += t->width;
...@@ -309,7 +313,7 @@ dumpgcargs(Node *fn, Sym *sym) ...@@ -309,7 +313,7 @@ dumpgcargs(Node *fn, Sym *sym)
thistype = getthisx(fn->type); thistype = getthisx(fn->type);
inargtype = getinargx(fn->type); inargtype = getinargx(fn->type);
outargtype = getoutargx(fn->type); outargtype = getoutargx(fn->type);
bv = bvalloc(fn->type->argwid / widthptr); bv = bvalloc((fn->type->argwid / widthptr) * BitsPerPointer);
if(thistype != nil) if(thistype != nil)
walktype(thistype, bv); walktype(thistype, bv);
if(inargtype != nil) if(inargtype != nil)
...@@ -336,7 +340,7 @@ dumpgclocals(Node* fn, Sym *sym) ...@@ -336,7 +340,7 @@ dumpgclocals(Node* fn, Sym *sym)
int32 i; int32 i;
int off; int off;
bv = bvalloc(stkptrsize / widthptr); bv = bvalloc((stkptrsize / widthptr) * BitsPerPointer);
for(ll = fn->dcl; ll != nil; ll = ll->next) { for(ll = fn->dcl; ll != nil; ll = ll->next) {
node = ll->n; node = ll->n;
if(node->class == PAUTO && node->op == ONAME) { if(node->class == PAUTO && node->op == ONAME) {
......
...@@ -33,6 +33,9 @@ enum { ...@@ -33,6 +33,9 @@ enum {
PRECISE = 1, PRECISE = 1,
LOOP = 2, LOOP = 2,
PC_BITS = PRECISE | LOOP, PC_BITS = PRECISE | LOOP,
// Pointer map
BitsPerPointer = 2,
}; };
// Bits in per-word bitmap. // Bits in per-word bitmap.
...@@ -1409,10 +1412,11 @@ scanbitvector(byte *scanp, BitVector *bv) ...@@ -1409,10 +1412,11 @@ scanbitvector(byte *scanp, BitVector *bv)
i = remptrs; i = remptrs;
else else
i = 32; i = 32;
i /= BitsPerPointer;
for(; i > 0; i--) { for(; i > 0; i--) {
if(w & 1) if(w & 3)
addroot((Obj){scanp, PtrSize, 0}); addroot((Obj){scanp, PtrSize, 0});
w >>= 1; w >>= BitsPerPointer;
scanp += PtrSize; scanp += PtrSize;
} }
} }
...@@ -1444,7 +1448,7 @@ addframeroots(Stkframe *frame, void*) ...@@ -1444,7 +1448,7 @@ addframeroots(Stkframe *frame, void*)
} else if(locals->n > 0) { } else if(locals->n > 0) {
// Locals bitmap information, scan just the // Locals bitmap information, scan just the
// pointers in locals. // pointers in locals.
size = locals->n*PtrSize; size = (locals->n*PtrSize) / BitsPerPointer;
scanbitvector(frame->varp - size, locals); scanbitvector(frame->varp - size, locals);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment