Commit 6dbaa206 authored by Russ Cox's avatar Russ Cox

runtime: replace runtime·rnd function with ROUND macro

It's sad to introduce a new macro, but rnd shows up consistently
in profiles, and the function call overwhelms the two arithmetic
instructions it performs.

R=r
CC=golang-dev
https://golang.org/cl/6260051
parent 90d59c58
...@@ -19,7 +19,7 @@ static int ...@@ -19,7 +19,7 @@ static int
sigcmp(Sig *a, Sig *b) sigcmp(Sig *a, Sig *b)
{ {
int i; int i;
i = strcmp(a->name, b->name); i = strcmp(a->name, b->name);
if(i != 0) if(i != 0)
return i; return i;
...@@ -262,12 +262,12 @@ imethods(Type *t) ...@@ -262,12 +262,12 @@ imethods(Type *t)
else else
last->link = a; last->link = a;
last = a; last = a;
// Compiler can only refer to wrappers for // Compiler can only refer to wrappers for
// named interface types. // named interface types.
if(t->sym == S) if(t->sym == S)
continue; continue;
// NOTE(rsc): Perhaps an oversight that // NOTE(rsc): Perhaps an oversight that
// IfaceType.Method is not in the reflect data. // IfaceType.Method is not in the reflect data.
// Generate the method body, so that compiled // Generate the method body, so that compiled
...@@ -287,7 +287,7 @@ dimportpath(Pkg *p) ...@@ -287,7 +287,7 @@ dimportpath(Pkg *p)
static Pkg *gopkg; static Pkg *gopkg;
char *nam; char *nam;
Node *n; Node *n;
if(p->pathsym != S) if(p->pathsym != S)
return; return;
...@@ -303,7 +303,7 @@ dimportpath(Pkg *p) ...@@ -303,7 +303,7 @@ dimportpath(Pkg *p)
n->class = PEXTERN; n->class = PEXTERN;
n->xoffset = 0; n->xoffset = 0;
p->pathsym = n->sym; p->pathsym = n->sym;
gdatastring(n, p->path); gdatastring(n, p->path);
ggloblsym(n->sym, types[TSTRING]->width, 1); ggloblsym(n->sym, types[TSTRING]->width, 1);
} }
...@@ -319,7 +319,7 @@ dgopkgpath(Sym *s, int ot, Pkg *pkg) ...@@ -319,7 +319,7 @@ dgopkgpath(Sym *s, int ot, Pkg *pkg)
// that imports this one directly defines the symbol. // that imports this one directly defines the symbol.
if(pkg == localpkg) { if(pkg == localpkg) {
static Sym *ns; static Sym *ns;
if(ns == nil) if(ns == nil)
ns = pkglookup("importpath.\"\".", mkpkg(strlit("go"))); ns = pkglookup("importpath.\"\".", mkpkg(strlit("go")));
return dsymptr(s, ot, ns, 0); return dsymptr(s, ot, ns, 0);
...@@ -343,7 +343,7 @@ dextratype(Sym *sym, int off, Type *t, int ptroff) ...@@ -343,7 +343,7 @@ dextratype(Sym *sym, int off, Type *t, int ptroff)
m = methods(t); m = methods(t);
if(t->sym == nil && m == nil) if(t->sym == nil && m == nil)
return off; return off;
// fill in *extraType pointer in header // fill in *extraType pointer in header
dsymptr(sym, ptroff, sym, off); dsymptr(sym, ptroff, sym, off);
...@@ -419,7 +419,7 @@ enum { ...@@ -419,7 +419,7 @@ enum {
KindString, KindString,
KindStruct, KindStruct,
KindUnsafePointer, KindUnsafePointer,
KindNoPointers = 1<<7, KindNoPointers = 1<<7,
}; };
...@@ -559,8 +559,16 @@ dcommontype(Sym *s, int ot, Type *t) ...@@ -559,8 +559,16 @@ dcommontype(Sym *s, int ot, Type *t)
ot = duintptr(s, ot, t->width); ot = duintptr(s, ot, t->width);
ot = duint32(s, ot, typehash(t)); ot = duint32(s, ot, typehash(t));
ot = duint8(s, ot, 0); // unused ot = duint8(s, ot, 0); // unused
// runtime (and common sense) expects alignment to be a power of two.
i = t->align;
if(i == 0)
i = 1;
if((i&(i-1)) != 0)
fatal("invalid alignment %d for %T", t->align, t);
ot = duint8(s, ot, t->align); // align ot = duint8(s, ot, t->align); // align
ot = duint8(s, ot, t->align); // fieldAlign ot = duint8(s, ot, t->align); // fieldAlign
i = kinds[t->etype]; i = kinds[t->etype];
if(t->etype == TARRAY && t->bound < 0) if(t->etype == TARRAY && t->bound < 0)
i = KindSlice; i = KindSlice;
...@@ -575,7 +583,7 @@ dcommontype(Sym *s, int ot, Type *t) ...@@ -575,7 +583,7 @@ dcommontype(Sym *s, int ot, Type *t)
//print("dcommontype: %s\n", p); //print("dcommontype: %s\n", p);
ot = dgostringptr(s, ot, p); // string ot = dgostringptr(s, ot, p); // string
free(p); free(p);
// skip pointer to extraType, // skip pointer to extraType,
// which follows the rest of this type structure. // which follows the rest of this type structure.
// caller will fill in if needed. // caller will fill in if needed.
...@@ -678,7 +686,7 @@ dtypesym(Type *t) ...@@ -678,7 +686,7 @@ dtypesym(Type *t)
tbase = t->type; tbase = t->type;
dupok = tbase->sym == S; dupok = tbase->sym == S;
if(compiling_runtime && if(compiling_runtime &&
(tbase == types[tbase->etype] || (tbase == types[tbase->etype] ||
tbase == bytetype || tbase == bytetype ||
tbase == runetype || tbase == runetype ||
...@@ -897,10 +905,10 @@ dumptypestructs(void) ...@@ -897,10 +905,10 @@ dumptypestructs(void)
// emit type structs for error and func(error) string. // emit type structs for error and func(error) string.
// The latter is the type of an auto-generated wrapper. // The latter is the type of an auto-generated wrapper.
dtypesym(ptrto(errortype)); dtypesym(ptrto(errortype));
dtypesym(functype(nil, dtypesym(functype(nil,
list1(nod(ODCLFIELD, N, typenod(errortype))), list1(nod(ODCLFIELD, N, typenod(errortype))),
list1(nod(ODCLFIELD, N, typenod(types[TSTRING]))))); list1(nod(ODCLFIELD, N, typenod(types[TSTRING])))));
// add paths for runtime and main, which 6l imports implicitly. // add paths for runtime and main, which 6l imports implicitly.
dimportpath(runtimepkg); dimportpath(runtimepkg);
dimportpath(mkpkg(strlit("main"))); dimportpath(mkpkg(strlit("main")));
......
...@@ -86,7 +86,7 @@ runtime·makechan_c(ChanType *t, int64 hint) ...@@ -86,7 +86,7 @@ runtime·makechan_c(ChanType *t, int64 hint)
Hchan *c; Hchan *c;
int32 n; int32 n;
Type *elem; Type *elem;
elem = t->elem; elem = t->elem;
if(hint < 0 || (int32)hint != hint || (elem->size > 0 && hint > ((uintptr)-1) / elem->size)) if(hint < 0 || (int32)hint != hint || (elem->size > 0 && hint > ((uintptr)-1) / elem->size))
...@@ -180,7 +180,7 @@ runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres) ...@@ -180,7 +180,7 @@ runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
sg = dequeue(&c->recvq); sg = dequeue(&c->recvq);
if(sg != nil) { if(sg != nil) {
runtime·unlock(c); runtime·unlock(c);
gp = sg->g; gp = sg->g;
gp->param = sg; gp->param = sg;
if(sg->elem != nil) if(sg->elem != nil)
...@@ -446,7 +446,7 @@ runtime·selectnbsend(ChanType *t, Hchan *c, ...) ...@@ -446,7 +446,7 @@ runtime·selectnbsend(ChanType *t, Hchan *c, ...)
byte *ae, *ap; byte *ae, *ap;
ae = (byte*)(&c + 1); ae = (byte*)(&c + 1);
ap = ae + runtime·rnd(t->elem->size, Structrnd); ap = ae + ROUND(t->elem->size, Structrnd);
runtime·chansend(t, c, ae, ap); runtime·chansend(t, c, ae, ap);
} }
...@@ -474,7 +474,7 @@ void ...@@ -474,7 +474,7 @@ void
runtime·selectnbrecv(ChanType *t, byte *v, Hchan *c, bool selected) runtime·selectnbrecv(ChanType *t, byte *v, Hchan *c, bool selected)
{ {
runtime·chanrecv(t, c, v, &selected, nil); runtime·chanrecv(t, c, v, &selected, nil);
} }
// func selectnbrecv2(elem *any, ok *bool, c chan any) bool // func selectnbrecv2(elem *any, ok *bool, c chan any) bool
// //
...@@ -500,7 +500,7 @@ void ...@@ -500,7 +500,7 @@ void
runtime·selectnbrecv2(ChanType *t, byte *v, bool *received, Hchan *c, bool selected) runtime·selectnbrecv2(ChanType *t, byte *v, bool *received, Hchan *c, bool selected)
{ {
runtime·chanrecv(t, c, v, &selected, received); runtime·chanrecv(t, c, v, &selected, received);
} }
// For reflect: // For reflect:
// func chansend(c chan, val iword, nb bool) (selected bool) // func chansend(c chan, val iword, nb bool) (selected bool)
...@@ -514,7 +514,7 @@ reflect·chansend(ChanType *t, Hchan *c, uintptr val, bool nb, uintptr selected) ...@@ -514,7 +514,7 @@ reflect·chansend(ChanType *t, Hchan *c, uintptr val, bool nb, uintptr selected)
{ {
bool *sp; bool *sp;
byte *vp; byte *vp;
if(nb) { if(nb) {
selected = false; selected = false;
sp = (bool*)&selected; sp = (bool*)&selected;
...@@ -571,7 +571,7 @@ runtime·newselect(int32 size, ...) ...@@ -571,7 +571,7 @@ runtime·newselect(int32 size, ...)
int32 o; int32 o;
Select **selp; Select **selp;
o = runtime·rnd(sizeof(size), Structrnd); o = ROUND(sizeof(size), Structrnd);
selp = (Select**)((byte*)&size + o); selp = (Select**)((byte*)&size + o);
newselect(size, selp); newselect(size, selp);
} }
...@@ -619,7 +619,7 @@ runtime·selectsend(Select *sel, Hchan *c, void *elem, bool selected) ...@@ -619,7 +619,7 @@ runtime·selectsend(Select *sel, Hchan *c, void *elem, bool selected)
// nil cases do not compete // nil cases do not compete
if(c == nil) if(c == nil)
return; return;
selectsend(sel, c, runtime·getcallerpc(&sel), elem, (byte*)&selected - (byte*)&sel); selectsend(sel, c, runtime·getcallerpc(&sel), elem, (byte*)&selected - (byte*)&sel);
} }
...@@ -628,7 +628,7 @@ selectsend(Select *sel, Hchan *c, void *pc, void *elem, int32 so) ...@@ -628,7 +628,7 @@ selectsend(Select *sel, Hchan *c, void *pc, void *elem, int32 so)
{ {
int32 i; int32 i;
Scase *cas; Scase *cas;
i = sel->ncase; i = sel->ncase;
if(i >= sel->tcase) if(i >= sel->tcase)
runtime·throw("selectsend: too many cases"); runtime·throw("selectsend: too many cases");
...@@ -899,7 +899,7 @@ loop: ...@@ -899,7 +899,7 @@ loop:
case CaseRecv: case CaseRecv:
enqueue(&c->recvq, sg); enqueue(&c->recvq, sg);
break; break;
case CaseSend: case CaseSend:
enqueue(&c->sendq, sg); enqueue(&c->sendq, sg);
break; break;
......
...@@ -115,7 +115,7 @@ hash_init (Hmap *h, int32 datasize, int64 hint) ...@@ -115,7 +115,7 @@ hash_init (Hmap *h, int32 datasize, int64 hint)
if(datasize < sizeof (void *)) if(datasize < sizeof (void *))
datasize = sizeof (void *); datasize = sizeof (void *);
datasize = runtime·rnd(datasize, sizeof (void *)); datasize = ROUND(datasize, sizeof (void *));
init_sizes (hint, &init_power); init_sizes (hint, &init_power);
h->datasize = datasize; h->datasize = datasize;
assert (h->datasize == datasize); assert (h->datasize == datasize);
...@@ -273,7 +273,7 @@ hash_lookup (MapType *t, Hmap *h, void *data, void **pres) ...@@ -273,7 +273,7 @@ hash_lookup (MapType *t, Hmap *h, void *data, void **pres)
struct hash_entry *end_e; struct hash_entry *end_e;
void *key; void *key;
bool eq; bool eq;
hash = h->hash0; hash = h->hash0;
(*t->key->alg->hash) (&hash, t->key->size, data); (*t->key->alg->hash) (&hash, t->key->size, data);
hash &= ~HASH_MASK; hash &= ~HASH_MASK;
...@@ -462,7 +462,7 @@ hash_insert (MapType *t, Hmap *h, void *data, void **pres) ...@@ -462,7 +462,7 @@ hash_insert (MapType *t, Hmap *h, void *data, void **pres)
{ {
uintptr hash; uintptr hash;
int32 rc; int32 rc;
hash = h->hash0; hash = h->hash0;
(*t->key->alg->hash) (&hash, t->key->size, data); (*t->key->alg->hash) (&hash, t->key->size, data);
rc = hash_insert_internal (t, &h->st, 0, hash, h, data, pres); rc = hash_insert_internal (t, &h->st, 0, hash, h, data, pres);
...@@ -618,7 +618,7 @@ hash_iter_init (MapType *t, Hmap *h, struct hash_iter *it) ...@@ -618,7 +618,7 @@ hash_iter_init (MapType *t, Hmap *h, struct hash_iter *it)
it->subtable_state[0].e = h->st->entry; it->subtable_state[0].e = h->st->entry;
it->subtable_state[0].start = h->st->entry; it->subtable_state[0].start = h->st->entry;
it->subtable_state[0].last = h->st->last; it->subtable_state[0].last = h->st->last;
// fastrand1 returns 31 useful bits. // fastrand1 returns 31 useful bits.
// We don't care about not having a bottom bit but we // We don't care about not having a bottom bit but we
// do want top bits. // do want top bits.
...@@ -731,7 +731,7 @@ runtime·makemap_c(MapType *typ, int64 hint) ...@@ -731,7 +731,7 @@ runtime·makemap_c(MapType *typ, int64 hint)
Hmap *h; Hmap *h;
Type *key, *val; Type *key, *val;
uintptr ksize, vsize; uintptr ksize, vsize;
key = typ->key; key = typ->key;
val = typ->elem; val = typ->elem;
...@@ -744,8 +744,8 @@ runtime·makemap_c(MapType *typ, int64 hint) ...@@ -744,8 +744,8 @@ runtime·makemap_c(MapType *typ, int64 hint)
h = runtime·mal(sizeof(*h)); h = runtime·mal(sizeof(*h));
h->flag |= CanFreeTable; /* until reflect gets involved, free is okay */ h->flag |= CanFreeTable; /* until reflect gets involved, free is okay */
ksize = runtime·rnd(key->size, sizeof(void*)); ksize = ROUND(key->size, sizeof(void*));
vsize = runtime·rnd(val->size, sizeof(void*)); vsize = ROUND(val->size, sizeof(void*));
if(ksize > MaxData || vsize > MaxData || ksize+vsize > MaxData) { if(ksize > MaxData || vsize > MaxData || ksize+vsize > MaxData) {
// Either key is too big, or value is, or combined they are. // Either key is too big, or value is, or combined they are.
// Prefer to keep the key if possible, because we look at // Prefer to keep the key if possible, because we look at
...@@ -829,7 +829,7 @@ runtime·mapaccess1(MapType *t, Hmap *h, ...) ...@@ -829,7 +829,7 @@ runtime·mapaccess1(MapType *t, Hmap *h, ...)
bool pres; bool pres;
ak = (byte*)(&h + 1); ak = (byte*)(&h + 1);
av = ak + runtime·rnd(t->key->size, Structrnd); av = ak + ROUND(t->key->size, Structrnd);
runtime·mapaccess(t, h, ak, av, &pres); runtime·mapaccess(t, h, ak, av, &pres);
...@@ -854,7 +854,7 @@ runtime·mapaccess2(MapType *t, Hmap *h, ...) ...@@ -854,7 +854,7 @@ runtime·mapaccess2(MapType *t, Hmap *h, ...)
byte *ak, *av, *ap; byte *ak, *av, *ap;
ak = (byte*)(&h + 1); ak = (byte*)(&h + 1);
av = ak + runtime·rnd(t->key->size, Structrnd); av = ak + ROUND(t->key->size, Structrnd);
ap = av + t->elem->size; ap = av + t->elem->size;
runtime·mapaccess(t, h, ak, av, ap); runtime·mapaccess(t, h, ak, av, ap);
...@@ -952,7 +952,7 @@ runtime·mapassign1(MapType *t, Hmap *h, ...) ...@@ -952,7 +952,7 @@ runtime·mapassign1(MapType *t, Hmap *h, ...)
runtime·panicstring("assignment to entry in nil map"); runtime·panicstring("assignment to entry in nil map");
ak = (byte*)(&h + 1); ak = (byte*)(&h + 1);
av = ak + runtime·rnd(t->key->size, t->elem->align); av = ak + ROUND(t->key->size, t->elem->align);
runtime·mapassign(t, h, ak, av); runtime·mapassign(t, h, ak, av);
} }
...@@ -1171,7 +1171,7 @@ runtime·mapiter2(struct hash_iter *it, ...) ...@@ -1171,7 +1171,7 @@ runtime·mapiter2(struct hash_iter *it, ...)
t = it->t; t = it->t;
ak = (byte*)(&it + 1); ak = (byte*)(&it + 1);
av = ak + runtime·rnd(t->key->size, t->elem->align); av = ak + ROUND(t->key->size, t->elem->align);
res = it->data; res = it->data;
if(res == nil) if(res == nil)
......
...@@ -193,7 +193,7 @@ runtime·convT2I(Type *t, InterfaceType *inter, ...) ...@@ -193,7 +193,7 @@ runtime·convT2I(Type *t, InterfaceType *inter, ...)
elem = (byte*)(&inter+1); elem = (byte*)(&inter+1);
wid = t->size; wid = t->size;
ret = (Iface*)(elem + runtime·rnd(wid, Structrnd)); ret = (Iface*)(elem + ROUND(wid, Structrnd));
ret->tab = itab(inter, t, 0); ret->tab = itab(inter, t, 0);
copyin(t, elem, &ret->data); copyin(t, elem, &ret->data);
} }
...@@ -209,7 +209,7 @@ runtime·convT2E(Type *t, ...) ...@@ -209,7 +209,7 @@ runtime·convT2E(Type *t, ...)
elem = (byte*)(&t+1); elem = (byte*)(&t+1);
wid = t->size; wid = t->size;
ret = (Eface*)(elem + runtime·rnd(wid, Structrnd)); ret = (Eface*)(elem + ROUND(wid, Structrnd));
ret->type = t; ret->type = t;
copyin(t, elem, &ret->data); copyin(t, elem, &ret->data);
} }
...@@ -387,7 +387,7 @@ void ...@@ -387,7 +387,7 @@ void
runtime·convI2I(InterfaceType* inter, Iface i, Iface ret) runtime·convI2I(InterfaceType* inter, Iface i, Iface ret)
{ {
Itab *tab; Itab *tab;
ret.data = i.data; ret.data = i.data;
if((tab = i.tab) == nil) if((tab = i.tab) == nil)
ret.tab = nil; ret.tab = nil;
...@@ -694,7 +694,7 @@ reflect·unsafe_NewArray(Eface typ, uint32 n, void *ret) ...@@ -694,7 +694,7 @@ reflect·unsafe_NewArray(Eface typ, uint32 n, void *ret)
// We know that the pointer to the original // We know that the pointer to the original
// type structure sits before the data pointer. // type structure sits before the data pointer.
t = (Type*)((Eface*)typ.data-1); t = (Type*)((Eface*)typ.data-1);
size = n*t->size; size = n*t->size;
if(t->kind&KindNoPointers) if(t->kind&KindNoPointers)
ret = runtime·mallocgc(size, FlagNoPointers, 1, 1); ret = runtime·mallocgc(size, FlagNoPointers, 1, 1);
......
...@@ -18,10 +18,10 @@ gwrite(void *v, int32 n) ...@@ -18,10 +18,10 @@ gwrite(void *v, int32 n)
runtime·write(2, v, n); runtime·write(2, v, n);
return; return;
} }
if(g->writenbuf == 0) if(g->writenbuf == 0)
return; return;
if(n > g->writenbuf) if(n > g->writenbuf)
n = g->writenbuf; n = g->writenbuf;
runtime·memmove(g->writebuf, v, n); runtime·memmove(g->writebuf, v, n);
...@@ -88,36 +88,36 @@ vprintf(int8 *s, byte *base) ...@@ -88,36 +88,36 @@ vprintf(int8 *s, byte *base)
break; break;
case 'd': // 32-bit case 'd': // 32-bit
case 'x': case 'x':
arg = runtime·rnd(arg, 4); arg = ROUND(arg, 4);
narg = arg + 4; narg = arg + 4;
break; break;
case 'D': // 64-bit case 'D': // 64-bit
case 'U': case 'U':
case 'X': case 'X':
case 'f': case 'f':
arg = runtime·rnd(arg, sizeof(uintptr)); arg = ROUND(arg, sizeof(uintptr));
narg = arg + 8; narg = arg + 8;
break; break;
case 'C': case 'C':
arg = runtime·rnd(arg, sizeof(uintptr)); arg = ROUND(arg, sizeof(uintptr));
narg = arg + 16; narg = arg + 16;
break; break;
case 'p': // pointer-sized case 'p': // pointer-sized
case 's': case 's':
arg = runtime·rnd(arg, sizeof(uintptr)); arg = ROUND(arg, sizeof(uintptr));
narg = arg + sizeof(uintptr); narg = arg + sizeof(uintptr);
break; break;
case 'S': // pointer-aligned but bigger case 'S': // pointer-aligned but bigger
arg = runtime·rnd(arg, sizeof(uintptr)); arg = ROUND(arg, sizeof(uintptr));
narg = arg + sizeof(String); narg = arg + sizeof(String);
break; break;
case 'a': // pointer-aligned but bigger case 'a': // pointer-aligned but bigger
arg = runtime·rnd(arg, sizeof(uintptr)); arg = ROUND(arg, sizeof(uintptr));
narg = arg + sizeof(Slice); narg = arg + sizeof(Slice);
break; break;
case 'i': // pointer-aligned but bigger case 'i': // pointer-aligned but bigger
case 'e': case 'e':
arg = runtime·rnd(arg, sizeof(uintptr)); arg = ROUND(arg, sizeof(uintptr));
narg = arg + sizeof(Eface); narg = arg + sizeof(Eface);
break; break;
} }
......
...@@ -156,19 +156,6 @@ runtime·mchr(byte *p, byte c, byte *ep) ...@@ -156,19 +156,6 @@ runtime·mchr(byte *p, byte c, byte *ep)
return nil; return nil;
} }
uint32
runtime·rnd(uint32 n, uint32 m)
{
uint32 r;
if(m > maxround)
m = maxround;
r = n % m;
if(r)
n += m-r;
return n;
}
static int32 argc; static int32 argc;
static uint8** argv; static uint8** argv;
......
...@@ -390,6 +390,7 @@ struct ParFor ...@@ -390,6 +390,7 @@ struct ParFor
#define nelem(x) (sizeof(x)/sizeof((x)[0])) #define nelem(x) (sizeof(x)/sizeof((x)[0]))
#define nil ((void*)0) #define nil ((void*)0)
#define offsetof(s,m) (uint32)(&(((s*)0)->m)) #define offsetof(s,m) (uint32)(&(((s*)0)->m))
#define ROUND(x, n) (((x)+(n)-1)&~((n)-1)) /* all-caps to mark as macro: it evaluates n twice */
/* /*
* known to compiler * known to compiler
...@@ -533,7 +534,6 @@ void runtime·goenvs_unix(void); ...@@ -533,7 +534,6 @@ void runtime·goenvs_unix(void);
void* runtime·getu(void); void* runtime·getu(void);
void runtime·throw(int8*); void runtime·throw(int8*);
void runtime·panicstring(int8*); void runtime·panicstring(int8*);
uint32 runtime·rnd(uint32, uint32);
void runtime·prints(int8*); void runtime·prints(int8*);
void runtime·printf(int8*, ...); void runtime·printf(int8*, ...);
byte* runtime·mchr(byte*, byte, byte*); byte* runtime·mchr(byte*, byte, byte*);
......
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