lua源码解析

(一)概述:

lua核心部分仅包括lua虚拟机的运转。lua虚拟机的行为是由一组组opcode控制的。这些opcode定义在lopcodes.h及lopcodes.c中。而虚拟机对opcode 的解析和运作在lvm.c中,其API以luaV为前缀。lua虚拟机的外在数据形式是一个lua_State结构体,取名State大概意为 Lua虚拟机的当前状态。全局State引用了整个虚拟机的所有数据。这个全局State的相关代码放在lstate.c中,API使用luaE为前缀。函数的运行流程:函数调用及返回则放在ldo.c中,相关API以luaD为前缀。


(二)字符串:

(1)字符串的初始化

在Lua状态机内有两种内部形式,短字符串和长字符串

#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4))  /* short strings */
#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4))  /* long strings */

typedef union TString {
L_Umaxalign dummy; /* ensures maximum alignment for strings */ 
struct {
CommonHeader;//用于GC
lu_byte extra; /* reserved words for short strings; "has hash" for longs */
unsigned int hash;//记录字符串的hash用来加快字符串的匹配
size_t len; /* number of characters in string */ //Lua不是以\0结尾,需要len表示字符串的长度
} tsv;
} TString;

所有短字符串均被存放在全局表(global_State)的strt域中,strt是string table的简写,是一个hash表。

typedef struct stringtable {
GCObject **hash;
lu_int32 nuse; /* number of elements */ 
int size;
} stringtable;
相同的短字符串在同一个Lua State中只存在唯一一份,这被称为字符串的内部化。
长字符串则独立存放,从外部压入一个长字符串时,简单复制一遍字符串,并不立刻计算其hash值,而是标记一下extra域。直到需要对字符串做键匹配时,才惰性计算hash值,加快以后的键比较过程

unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { 
unsigned int h = seed ^ cast(unsigned int, l);
size_t l1;
size_t step = (l >> LUAI_HASHLIMIT) + 1;
for (l1 = l; l1 >= step; l1 -= step)
h = h ^ ((h<<5) + (h>>2) + cast_byte(str[l1 - 1]));
return h; 
}//为了跳跃。 

(2)字符串的比较

int luaS_eqstr (TString *a, TString *b) { return (a->tsv.tt == b->tsv.tt) &&(a->tsv.tt == LUA_TSHRSTR ? eqshrstr(a, b) : luaS_eqlngstr(a, b));}

a.短字符串因为经过的内部化,所以在字符串比较时不必比较字符串内容,而仅需要比较对象地址即可。 

static TString *internshrstr (lua_State *L, const char *str, size_t l) { 
GCObject *o;
global_State *g = G(L);
unsigned int h = luaS_hash(str, l, g->seed);
for (o = g->strt.hash[lmod(h, g->strt.size)]; o != NULL;o = gch(o)->next) 
{ TString *ts = rawgco2ts(o);
if (h == ts->tsv.hash &&l == ts->tsv.len &&(memcmp(str, getstr(ts), l * sizeof(char)) == 0)) {
if (isdead(G(L), o)) /* string is dead (but was not collected yet)? */
changewhite(o); /* resurrect it */ return ts;

}
return newshrstr(L, str, l, h); /* not found; create a new string */ 
}

这是一个开散列的哈希表实现。一个字符串被放入字符串表的时候,先检查一下表中有没有相同的字符串。如果有,则复用已有的字符串;没有则创建一个新的。碰到哈希值相同的字符串,简单的串在同一个哈希位的链表上即可. 

当哈希表中字符串的数量超过预定容量时,会发生冲出,此时需要luaS_resize把字符串表的哈希链表数组扩大,重排所有字符串的位置。

void luaS_resize (lua_State *L, int newsize) { 
int i;
stringtable *tb = &G(L)->strt;
/* cannot resize while GC is traversing strings */
luaC_runtilstate(L, ~bitmask(GCSsweepstring)); 
if (newsize > tb->size) { <

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值