From 77ac95b9985f5669d6659bfb54728786d28c2ef0 Mon Sep 17 00:00:00 2001 From: chai Date: Mon, 20 Jul 2020 09:42:30 +0800 Subject: *misc --- src/lua51/lstring.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'src/lua51/lstring.c') diff --git a/src/lua51/lstring.c b/src/lua51/lstring.c index 4911315..ec1fcdb 100644 --- a/src/lua51/lstring.c +++ b/src/lua51/lstring.c @@ -19,25 +19,29 @@ +//c 重新分配global_State->strt每个桶的数据量 +//c 当桶的大小远超字符串容量,重新分配大小,删掉一些空桶(空位) void luaS_resize (lua_State *L, int newsize) { GCObject **newhash; stringtable *tb; int i; - if (G(L)->gcstate == GCSsweepstring) + if (G(L)->gcstate == GCSsweepstring)//如果GC在回收字符串阶段,不要rehash return; /* cannot resize during GC traverse */ - newhash = luaM_newvector(L, newsize, GCObject *); - tb = &G(L)->strt; + newhash = luaM_newvector(L, newsize, GCObject *); //建立一个新的散列桶,并清空 + tb = &G(L)->strt;//旧的散列桶 for (i=0; isize; i++) { GCObject *p = tb->hash[i]; while (p) { /* for each node in the list */ GCObject *next = p->gch.next; /* save next */ unsigned int h = gco2ts(p)->hash; + //新的散列值 int h1 = lmod(h, newsize); /* new position */ lua_assert(cast_int(h%newsize) == lmod(h, newsize)); - p->gch.next = newhash[h1]; /* chain it */ - newhash[h1] = p; + p->gch.next = newhash[h1];//c 接在同一个hash的最前面 /* chain it */ + newhash[h1] = p; //c 将p作为桶内第一个存起来 p = next; } } @@ -47,6 +51,7 @@ void luaS_resize (lua_State *L, int newsize) { } +//c 新建字符串 static TString *newlstr (lua_State *L, const char *str, size_t l, unsigned int h) { TString *ts; @@ -62,42 +67,53 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, memcpy(ts+1, str, l*sizeof(char)); ((char *)(ts+1))[l] = '\0'; /* ending 0 */ tb = &G(L)->strt; + // 计算hash值 h = lmod(h, tb->size); ts->tsv.next = tb->hash[h]; /* chain new entry */ tb->hash[h] = obj2gco(ts); tb->nuse++; + //c 给字符串通扩容,如果字符串数量大于桶容量 + //c 给桶扩容为2倍 if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) luaS_resize(L, tb->size*2); /* too crowded */ return ts; } +//c 创建字符串 TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { GCObject *o; unsigned int h = cast(unsigned int, l); /* seed */ size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ size_t l1; + //c 如果字符串非常长,不要逐位计算散列值,每step步取一个字符计算即可 for (l1=l; l1>=step; l1-=step) /* compute hash */ h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; o != NULL; o = o->gch.next) { TString *ts = rawgco2ts(o); - if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { + if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {//c 如果散列值相同,用memcmp快速对比 + //c 如果字符串被标记了回收(gch.marked),重新标记它不要回收 /* string may be dead */ if (isdead(G(L), o)) changewhite(o); return ts; } } + //c 如果global->strt里没有这个字符串,新建立一个,并加到哈希桶里 return newlstr(L, str, l, h); /* not found */ } - +//c 创建userdata +//c userdata的gc和普通对象(udata和uv除外的)是分开的 Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { Udata *u; if (s > MAX_SIZET - sizeof(Udata)) luaM_toobig(L); u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); + //c udata和普通对象在GC上的区别在于不调用luaC_link,因为不会加在 + //c G(L)->rootgc链上,而是加在G(L)->mainthread后面 + //c udata标记为 white u->uv.marked = luaC_white(G(L)); /* is not finalized */ u->uv.tt = LUA_TUSERDATA; u->uv.len = s; @@ -105,7 +121,10 @@ Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { u->uv.env = e; /* chain it on udata list (after main thread) */ u->uv.next = G(L)->mainthread->next; - G(L)->mainthread->next = obj2gco(u); - return u; + // 可见所有userdata都跟在mainthread之后第一个 + // 这样是为了方便,是一个hack + // 由于userdata可能会定义了__gc,所以统一处理 + G(L)->mainthread->next = obj2gco(u); + return u; } -- cgit v1.1-26-g67d0