<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-庄周梦蝶，孰蝶是我，我是孰蝶？一梦至今，蝶我已难分-随笔分类-linux &amp; C</title><link>http://www.blogjava.net/killme2008/category/23659.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 07 Apr 2008 12:12:55 GMT</lastBuildDate><pubDate>Mon, 07 Apr 2008 12:12:55 GMT</pubDate><ttl>60</ttl><item><title>lua 5.0的实现（翻译)4,5</title><link>http://www.blogjava.net/killme2008/archive/2008/04/07/191324.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 07 Apr 2008 09:55:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/04/07/191324.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/191324.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/04/07/191324.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/191324.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/191324.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="text-align: left;" align="left"><strong><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">4</span><span style="font-size: 9pt; font-family: 宋体;">、</span><span style="font-size: 9pt; font-family: CMR9;"> </span><span style="font-size: 9pt; font-family: 宋体;">表</span></strong><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>Table</span><span style="font-size: 9pt; font-family: 宋体;">是</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">的主要——实际上，也是唯一的——数据结构。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Table</span><span style="font-size: 9pt; font-family: 宋体;">不仅在语言中，同时也在语言的实现中扮演着重要角色。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Effort spent on a good implementation of tables is
rewarded in the language,because tables are used
for several internal tasks, with no qualms about performance</span><span style="font-size: 10pt; font-family: 宋体;">。这有助于保持实现的小巧。相反的，</span><span style="font-family: 宋体;">任何其他数据结构的机制的缺乏也为</span><span lang="EN-US">table</span><span style="font-family: 宋体;">的高效实现带来了很大压力</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Lua</span><span style="font-family: 宋体;">中的</span><span lang="EN-US">table</span><span style="font-family: 宋体;">是关联数组，也就是可以用任何值做索引（除了</span><span lang="EN-US">nil</span><span style="font-family: 宋体;">），也可以持有任何值。另外，</span><span lang="EN-US">table</span><span style="font-family: 宋体;">是动态的，也就是说当加进数据的时候它们将增长（给迄今不存在的域赋值）而移除数据的时候将萎缩（给域赋</span><span lang="EN-US">nil</span><span style="font-family: 宋体;">值）。</span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 21.75pt;" align="left"><span style="font-family: 宋体;">不像大多数其他脚本语言，</span><span lang="EN-US">lua</span><span style="font-family: 宋体;">没有数组类型。数组被表示为以整数做键的</span><span lang="EN-US">table</span><span style="font-family: 宋体;">。用</span><span lang="EN-US">table</span><span style="font-family: 宋体;">作为数组对于语言是有益的。主要的（益处）显而易见：</span><span lang="EN-US">lua</span><span style="font-family: 宋体;">并不需要操纵表和数组的两套不同的运算符。另外，程序员不用对两种实现做出艰难选择。在</span><span lang="EN-US">lua</span><span style="font-family: 宋体;">中实现稀疏数组是轻而易举的。例如，在</span><span lang="EN-US">Perl</span><span style="font-family: 宋体;">里面，如果你尝试去跑</span><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">$a[1000000000]=1 </span><span style="font-size: 10pt; font-family: 宋体;">这样的程序，你能跑出个内存溢出！（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">you can run out of memory</span><span style="font-size: 10pt; font-family: 宋体;">），因为它触发了一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">10</span><span style="font-size: 10pt; font-family: 宋体;">亿个元素的数组的创建（译注，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Perl</span><span style="font-size: 10pt; font-family: 宋体;">的哲学是：去除不必要的限制）。而等价的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">程序</span><span style="font-size: 10pt; font-family: CMR10;"> </span><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">a={[1000000000]=1}</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">,</span><span style="font-size: 10pt; font-family: 宋体;">（只是）创建了有一个单独的项的表（而已）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<img src="http://www.blogjava.net/images/blogjava_net/killme2008/lua01.jpg" alt="" border="0" /><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
<v:stroke joinstyle="miter" />
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0" />
<v:f eqn="sum @0 1 0" />
<v:f eqn="sum 0 0 @1" />
<v:f eqn="prod @2 1 2" />
<v:f eqn="prod @3 21600 pixelWidth" />
<v:f eqn="prod @3 21600 pixelHeight" />
<v:f eqn="sum @0 0 1" />
<v:f eqn="prod @6 1 2" />
<v:f eqn="prod @7 21600 pixelWidth" />
<v:f eqn="sum @8 21600 0" />
<v:f eqn="prod @7 21600 pixelHeight" />
<v:f eqn="sum @10 21600 0" />
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect" />
<o:lock v:ext="edit" aspectratio="t" />
</v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" style='width:414.75pt;
height:198pt'>
<v:imagedata src="file:///C:\DOCUME~1\cy\LOCALS~1\Temp\msohtml1\08\clip_image001.gif" o:title="2007-12-04_152712" />
</v:shape><![endif]--><!--[if !vml]--><br />
<!--[endif]--><o:p></o:p></span>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 9pt; font-family: 宋体;">直到</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua 4.0</span><span style="font-size: 9pt; font-family: 宋体;">，</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">table</span><span style="font-size: 9pt; font-family: 宋体;">都是作为</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">hash</span><span style="font-size: 9pt; font-family: 宋体;">表严格地实现：所有的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">pair</span><span style="font-size: 9pt; font-family: 宋体;">都被显式地保存。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua5.0</span><span style="font-size: 9pt; font-family: 宋体;">引入了一个新算法来优化作为数组的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">table</span><span style="font-size: 9pt; font-family: 宋体;">：它将以整数为键的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">pair</span><span style="font-size: 9pt; font-family: 宋体;">不再是存储键而是优化成存储值在真正的数组中。更精确地说，在</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua 5.0</span><span style="font-size: 9pt; font-family: 宋体;">中，</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">table</span><span style="font-size: 9pt; font-family: 宋体;">被实现为一个混合数据结构：它们包括一个</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">hash</span><span style="font-size: 9pt; font-family: 宋体;">部分和一个数组部分。图</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">2</span><span style="font-size: 9pt; font-family: 宋体;">展示了一个有</span><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">"x"</span><span style="font-size: 10pt; font-family: 宋体;">&#8594;</span><span style="font-size: 10pt; font-family: CMSY10;"> </span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">9.3, 1 </span><span style="font-size: 10pt; font-family: 宋体;">&#8594;</span><span style="font-size: 10pt; font-family: CMSY10;"> </span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">100,2 </span><span style="font-size: 10pt; font-family: 宋体;">&#8594;</span><span style="font-size: 10pt; font-family: CMSY10;"> </span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">200, 3 </span><span style="font-size: 10pt; font-family: 宋体;">&#8594;</span><span style="font-size: 10pt; font-family: CMSY10;"> </span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">300</span><span style="font-size: 10pt; font-family: 宋体;">对子的表的一种可能结构。注意到数组部分在右边，并没有存储整数的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">key</span><span style="font-size: 10pt; font-family: 宋体;">。这个划分仅仅是在一个低的实现层次进行的，访问</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">仍然是透明的，甚至在虚拟机内部（访问</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">）也是如此。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Table</span><span style="font-size: 10pt; font-family: 宋体;">根据内容自动并且动态地对两个部分进行适配：数组部分试图从</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">1</span><span style="font-size: 10pt; font-family: 宋体;">到</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">的相应地存储值，关联非整数键或者整数键超过数组范围的值被存储在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">当一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">需要增长时，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">重新计算</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分和数组部分的大小。任一部分都可能是空的。重新计算后的数组大小是至少是当前使用的数组部分从</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">1</span><span style="font-size: 10pt; font-family: 宋体;">到</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">的一半情况下的最大</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">值（原文：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">The computed
size of the array part is the largest </span><span style="font-size: 10pt; font-family: CMMI10;" lang="EN-US">n </span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">such that at least half the slots between 1 and </span><span style="font-size: 10pt; font-family: CMMI10;" lang="EN-US">n </span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">are in use</span><span style="font-size: 10pt; font-family: 宋体;">）（稀疏数组时避免浪费空间），并至少有一个（元素）处在</span><span style="font-size: 10pt; font-family: CMMI10;" lang="EN-US">n/</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">2+1</span><span style="font-size: 10pt; font-family: 宋体;">到</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">的槽中（当</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">被</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">2</span><span style="font-size: 10pt; font-family: 宋体;">整除时，避免</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">的这样的数组大小）。计算完大小后，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">创建了&#8220;新&#8221;的部分并将&#8220;旧&#8221;的部分的元素重新插入到的&#8220;新&#8221;的部分。作为一个例子，假设</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">a</span><span style="font-size: 10pt; font-family: 宋体;">是一个空表；它的数组部分和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分的大小都是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">0</span><span style="font-size: 10pt; font-family: 宋体;">。当我们执行</span><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">a[1]=v</span><span style="font-size: 10pt; font-family: 宋体;">时，这个表需要增长到足够容纳新的键。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">将为新的数组部分的大小选择</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n=1</span><span style="font-size: 10pt; font-family: 宋体;">（带有一个项</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">1</span><span style="font-size: 10pt; font-family: 宋体;">&#8594;</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">v</span><span style="font-size: 10pt; font-family: 宋体;">）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分仍然保持为空。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">这个混合的方案有两个优点。首先，访问以整数为键的值加快了，因为不再需要任何的散列行为。其次，也是最重要的，数组部分占用的内存大概是将数组部分存储在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分时的一半，因为</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">key</span><span style="font-size: 10pt; font-family: 宋体;">在数组中是隐式的（译注：也就是数组的下标）而在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分却是显式的。因而，当一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">被用作数组的时，它表现的就像一个数组，只要整数键是密集。另外，不用为</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分付出任何内存和时间上的惩罚，因为它（译注：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分）甚至都不存在。相反的控制：如果</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">被用作关联数组而非一个数组，数组部分可能就是空的。这些内存上的节省是比较重要的，因为</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">程序经常创建一些小的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">，例如</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">被用来实现对象（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Object</span><span style="font-size: 10pt; font-family: 宋体;">）（译注，也就是用</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">来模仿对象，有点类似</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">javascript</span><span style="font-size: 10pt; font-family: 宋体;">中的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">json</span><span style="font-size: 10pt; font-family: 宋体;">）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Hash</span><span style="font-size: 10pt; font-family: 宋体;">部分采用</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Brent's
variation[3]</span><span style="font-size: 10pt; font-family: 宋体;">的组合的链状发散表。这些</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">的主要不变式是如果一个元素没有在它的主要位置上（也就是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">值的原始位置），则冲突的元素在它自己的主要位置上。换句话说，仅当两个元素有相同的主要位置（也就是在当时</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">大小情况下的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">值）时才有冲突的。没有二级冲突。正因为那样，这些</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">的加载因子可以是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">100%</span><span style="font-size: 10pt; font-family: 宋体;">而没有性能上的损失。这部分不是很明白，附上原文：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 20pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">The hash part uses a mix of chained scatter table with
Brent's variation [3].<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">A main invariant of
these tables is that if an element is not in its main position<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">(i.e., the original
position given by its hash value), then the colliding element<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">is in its own main
position. In other words, there are collisions only when two<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">elements have the same
main position (i.e., the same hash values for that table<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">size). There are no
secondary collisions. Because of that, the load factor of these<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">tables can be 100% without performance penalties.<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><strong><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></strong></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><strong><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">5</span></strong><strong><span style="font-size: 10pt; font-family: 宋体;">、函数和闭包</span></strong><strong><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">当</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">编译一个函数的时候，它产生一个模型（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">prototype</span><span style="font-size: 10pt; font-family: 宋体;">），包括了函数的虚拟机指令、常量值（数字，字符串字面量等）和一些调试信息。运行的时候，无论何时</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">执行一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">function&#8230;end</span><span style="font-size: 10pt; font-family: 宋体;">表达式，它都创建一个新的闭包。每个闭包都有一个引用指向相应的模型，一个引用指向环境（</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">environment</span><span style="font-size: 10pt; font-family: 宋体;">）（一张查找全局变量的表，译注：指所谓环境就是这样一张表），和一组用来访问外部</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量的指向</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">的引用。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US"><o:p></o:p></span></p>
<div style="border-style: none none solid; border-color: -moz-use-text-color -moz-use-text-color windowtext; border-width: medium medium 1pt; padding: 0cm 0cm 1pt;">
<p class="MsoNormal" style="border: medium none ; padding: 0cm; text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">词法范围以及</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">first-class</span><span style="font-size: 10pt; font-family: 宋体;">函数的组合导致一个关于（如何）访问外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量的著名难题。考虑图</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">3</span><span style="font-size: 10pt; font-family: 宋体;">中的例子。当</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add2</span><span style="font-size: 10pt; font-family: 宋体;">被调用的时候，它的函数体（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">body</span><span style="font-size: 10pt; font-family: 宋体;">）部分引用了外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x (</span><span style="font-size: 10pt; font-family: 宋体;">函数参数在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">里是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量，译注：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x</span><span style="font-size: 10pt; font-family: 宋体;">就是所谓的自由变量，这里形成了闭包</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">)</span><span style="font-size: 10pt; font-family: 宋体;">。尽管如此，当</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add2</span><span style="font-size: 10pt; font-family: 宋体;">被调用时，生成</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add2</span><span style="font-size: 10pt; font-family: 宋体;">的函数</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add</span><span style="font-size: 10pt; font-family: 宋体;">已经返回。如果在栈中生成变量</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x</span><span style="font-size: 10pt; font-family: 宋体;">，（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x</span><span style="font-size: 10pt; font-family: 宋体;">在栈的）其栈槽将不复存在。（译注，此处的意思应该是说如果在栈保存变量</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x</span><span style="font-size: 10pt; font-family: 宋体;">，那么在调用</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add2</span><span style="font-size: 10pt; font-family: 宋体;">的时候，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add</span><span style="font-size: 10pt; font-family: 宋体;">函数早已经返回，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x</span><span style="font-size: 10pt; font-family: 宋体;">也在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add2</span><span style="font-size: 10pt; font-family: 宋体;">调用前就不在栈里头了，这就是那个著名难题）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
</div>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><!--[if gte vml 1]><v:shape id="_x0000_i1026" type="#_x0000_t75" style='width:415.5pt;height:141pt'>
<v:imagedata src="file:///C:\DOCUME~1\cy\LOCALS~1\Temp\msohtml1\08\clip_image002.gif" o:title="2" />
</v:shape><![endif]--><!--[if !vml]--><img src="http://www.blogjava.net/images/blogjava_net/killme2008/lua02.jpg" alt="" border="0" /><br />
<!--[endif]--><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 37.45pt;" align="left"><span style="font-size: 9pt; font-family: 宋体;">大多数过程语言通过限制词法范围（例如</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">python</span><span style="font-size: 9pt; font-family: 宋体;">），不提供</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">first-class</span><span style="font-size: 9pt; font-family: 宋体;">函数（例如</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Pascal</span><span style="font-size: 9pt; font-family: 宋体;">），或者都两者都采用（例如</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">c,</span><span style="font-size: 9pt; font-family: 宋体;">译注：也就是说</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">c</span><span style="font-size: 9pt; font-family: 宋体;">既不把函数当一等公民，也限制词法范围）来回避这个问题。函数式语言就没有那些限制。围绕着非纯粹函数语言比如</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Scheme</span><span style="font-size: 9pt; font-family: 宋体;">和</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">ML</span><span style="font-size: 9pt; font-family: 宋体;">的研究已经产生了大量的关于闭包的编译技术的知识（参见</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">[19, 1, 21]</span><span style="font-size: 10pt; font-family: 宋体;">）。尽管如此，这些工作并没有尽力去限制编译器的复杂性。以优化的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Scheme</span><span style="font-size: 10pt; font-family: 宋体;">编译器</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Bigloo</span><span style="font-size: 10pt; font-family: 宋体;">的控制流分</span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 37.45pt;" align="left"><img src="http://www.blogjava.net/images/blogjava_net/killme2008/lua03.jpg" alt="" border="0" /><br />
</p>
<p class="MsoNormal" style="text-align: left; text-indent: 37.45pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">析阶段为例，（它的实现）比</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">实现的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">10</span><span style="font-size: 10pt; font-family: 宋体;">倍还大：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Bigloo <st1:chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="2.6" unitname="F" w:st="on">2.6f</st1:chmetcnv></span><span style="font-size: 10pt; font-family: 宋体;">的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Cfa</span><span style="font-size: 10pt; font-family: 宋体;">模块源码有</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">106,350</span><span style="font-size: 10pt; font-family: 宋体;">行</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"> VS. 10,155</span><span style="font-size: 10pt; font-family: 宋体;">行的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua5.0</span><span style="font-size: 10pt; font-family: 宋体;">核心。正如第</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">2</span><span style="font-size: 10pt; font-family: 宋体;">部分已经解释过的（原因），</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">需要简单。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><!--[if gte vml 1]><v:shape id="_x0000_i1027" type="#_x0000_t75" style='width:415.5pt;height:285.75pt'>
<v:imagedata src="file:///C:\DOCUME~1\cy\LOCALS~1\Temp\msohtml1\08\clip_image003.png" o:title="3" />
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 41.6pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">使用了一个称为</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">的结构来实现闭包。任何外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量的访问都是通过一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">间接进行的。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Upvalue</span><span style="font-size: 10pt; font-family: 宋体;">初始指向的是变量存活位置的栈槽（参见图</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">4</span><span style="font-size: 10pt; font-family: 宋体;">的左半部分）。当变量（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x</span><span style="font-size: 10pt; font-family: 宋体;">）已经离开作用域（译注，也就是这里的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add</span><span style="font-size: 10pt; font-family: 宋体;">函数返回时），它就迁移到</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">结构本身一个槽中（参见图</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">4</span><span style="font-size: 10pt; font-family: 宋体;">的右半部分）。因为（对变量的）访问是间接地通过</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">结构中的一个指针进行的，因此这个迁移对于任何写或者读该变量的代码都是透明的。不像它的内嵌函数（译注：例子的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add2</span><span style="font-size: 10pt; font-family: 宋体;">，它是指外部函数</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add</span><span style="font-size: 10pt; font-family: 宋体;">），声明变量的函数访问该变量就像访问它的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量一样：直接到栈。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 41.6pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">通过每个变量最多创建一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">结构并且在必要的时候复用它们，可变状态得以在闭包之间正确地共享。为了保证这一约束，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">维持一个链表，里面是一个栈里（图</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">4</span><span style="font-size: 10pt; font-family: 宋体;">中的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">pending vars</span><span style="font-size: 10pt; font-family: 宋体;">列表）的所有</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">open upvalue</span><span style="font-size: 10pt; font-family: 宋体;">（所谓</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">open upvalue</span><span style="font-size: 10pt; font-family: 宋体;">，是指仍然指向栈的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">结构）。当</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">创建一个新的闭包的时候，它遍历所有的外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量。对于每个（外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">）变量，如果它在列表中找到一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">open upvalue</span><span style="font-size: 10pt; font-family: 宋体;">，那么它就复用这个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">结构。否则，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">就创建一个新的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">并将它放入链表。注意到列表搜索只是探测了少数几个节点，因为列表最多包含一个被内嵌函数使用的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量的项。当一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">closed
upvalue</span><span style="font-size: 10pt; font-family: 宋体;">不再被任何闭包引用的时候，它最后将被当作垃圾并回收。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 41.6pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">一个函数允许访问一个不是它的直接外围函数的外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量，只要（这个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量）是外部函数的（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">outer function</span><span style="font-size: 10pt; font-family: 宋体;">）。在那种情况下，甚至在闭包被创建的时候，（外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">）变量可能就不在栈里了。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">使用扁平闭包（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">flat
</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">closures</span><span style="font-size: 10pt; font-family: 宋体;">）解决这种情况</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">[5]</span><span style="font-size: 10pt; font-family: 宋体;">。通过扁平闭包，一个函数无论何时去访问一个不属于它的外围函数的外部变量，这个变量都将进入外围函数的闭包。从而当一个函数被实例化的时候，所有进入它闭包的变量要么在外围函数的栈里面，要么在外围函数的闭包里。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p><img src ="http://www.blogjava.net/killme2008/aggbug/191324.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-04-07 17:55 <a href="http://www.blogjava.net/killme2008/archive/2008/04/07/191324.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>lua 5.0的实现（翻译)1,2,3</title><link>http://www.blogjava.net/killme2008/archive/2008/04/07/191314.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 07 Apr 2008 09:25:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/04/07/191314.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/191314.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/04/07/191314.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/191314.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/191314.html</trackback:ping><description><![CDATA[<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">三个多月前翻译的，今天又找出来看看,后面的待整理下继续发,有错误的地方请不吝赐教。<br />
</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">原文：http://www.tecgraf.puc-rio.br/~lhf/ftp/doc/jucs05.pdf<br />
</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">翻译：dennis zhuang</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"> (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#107;&#105;&#108;&#108;&#109;&#101;&#50;&#48;&#48;&#56;&#64;&#103;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;">killme2008@gmail.com</a>)<span>&nbsp; </span><a href="http://www.blogjava.net/killme2008">http://www.blogjava.net/killme2008</a><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">转载请注明出处，谢谢。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">摘要：我们讨论了</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua 5.0</span><span style="font-size: 10pt; font-family: 宋体;">实现的主要新特性：基于寄存器的虚拟机，优化表的新算法以便（将表）用作数组，闭包的实现，以及</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">coroutines</span><span style="font-size: 9pt; font-family: 宋体;">（译注：协程）</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 9pt; font-family: 宋体;">关键字</span><span style="font-size: 9pt; font-family: CMBX9;" lang="EN-US">: </span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">compilers, virtual machines, hash tables, closures, coroutines<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 17.85pt; text-indent: -17.85pt;"><!--[if !supportLists]--><strong><span style="font-size: 16pt; font-family: CMR9;" lang="EN-US"><span>1.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp; </span></span></span></strong><!--[endif]--><strong><span style="font-size: 16pt; font-family: 宋体;">介绍</span></strong><strong><span style="font-size: 16pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></strong></p>
<p class="MsoNormal"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 9pt; font-family: 宋体;">作为内部使用的开发工具诞生于学术实验室中，现在却已经被世界范围内许多工业级项目所采用，广泛应用于游戏领域。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 9pt; font-family: 宋体;">为什么能获得这样广泛的应用呢？我们认为答案就来源于我们的设计和实现目标上：提供一种简单、高效、可移植和轻量级的嵌入式脚本语言。这是</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 9pt; font-family: 宋体;">自</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">1993</span><span style="font-size: 9pt; font-family: 宋体;">年诞生以来我们一直追求的目标，并在（语言的）演化过程中遵守。</span><span style="font-size: 10pt; font-family: 宋体;">这些特性，以及</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">一开始就被设计成嵌入大型应用的事实，才使它在早期被工业界所接受。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: 宋体;">广泛的应用产生了对（新的）语言的特性的需求。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">的许多特性来自于工业需求和用户反馈的推动。重要的例如</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua 5.0</span><span style="font-size: 10pt; font-family: 宋体;">引入的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">coroutines</span><span style="font-size: 9pt; font-family: 宋体;">和即将到来的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua 5.1</span><span style="font-size: 9pt; font-family: 宋体;">改进的垃圾收集实现，这些特性对于游戏（编程）特别重要。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 9pt; font-family: 宋体;">在这篇论文中，我们讨论了</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua 5.0</span><span style="font-size: 9pt; font-family: 宋体;">相比于</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua 4.0</span><span style="font-size: 9pt; font-family: 宋体;">的主要新特性：</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 9pt; font-family: 宋体;">基于寄存器的的虚拟机：传统上，绝大多数虚拟机的实际执行都是基于栈，这个趋势开始于</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Pascal</span><span style="font-size: 10pt; font-family: 宋体;">的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Pmachine,</span><span style="font-size: 10pt; font-family: 宋体;">延续到今天的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">java</span><span style="font-size: 10pt; font-family: 宋体;">虚拟机和微软的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">.net</span><span style="font-size: 10pt; font-family: 宋体;">环境。目前，尽管对于基于寄存器的虚拟机的兴趣逐渐增多（比如</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Perl6</span><span style="font-size: 10pt; font-family: 宋体;">计划中的新的虚拟机（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Parrot</span><span style="font-size: 10pt; font-family: 宋体;">）将是基于寄存器的），但是就我们所知，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua 5.0</span><span style="font-size: 10pt; font-family: 宋体;">是第一个被广泛使用的基于寄存器的虚拟机。我们将在第</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">7</span><span style="font-size: 10pt; font-family: 宋体;">部分描述这个虚拟机。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: 宋体;">优化表的新算法以便作为数组：</span><span style="font-size: 10pt; font-family: CMR10;"> </span><span style="font-size: 10pt; font-family: 宋体;">不像其他脚本语言，</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">并没有提供数组类型。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">使用整数索引的普通表来实现数组作为替代。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua 5.0</span><span style="font-size: 10pt; font-family: 宋体;">使用了一个新的算法，可以检测表是否被作为数组使用，并且可以自动将关联着数字索引的值存储进一个真实的数组，而不是将它们放进</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Hash</span><span style="font-size: 10pt; font-family: 宋体;">表。在第</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">4</span><span style="font-size: 10pt; font-family: 宋体;">部分我们将讨论这个算法。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: 宋体;">闭包的实现：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua 5.0</span><span style="font-size: 10pt; font-family: 宋体;">在词法层次上支持</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">first-class
</span><span style="font-size: 10pt; font-family: 宋体;">函数（译注：将函数作为一等公民）。这个机制导致一个著名的语言难题：使用基于数组的栈来存储激活记录。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua </span><span style="font-size: 10pt; font-family: 宋体;">使用了一个新办法来实现函数闭包，保存局部变量在（基于数组）的栈</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">(stack)</span><span style="font-size: 10pt; font-family: 宋体;">上，当它们被内嵌函数引用而从作用域逸出的时候才将它们转移到堆</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">(heap)</span><span style="font-size: 10pt; font-family: 宋体;">上。闭包的实现将在第</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">5</span><span style="font-size: 10pt; font-family: 宋体;">部分讨论。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: 宋体;">添加</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">coroutines</span><span style="font-size: 9pt; font-family: 宋体;">：</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"> lua 5.0</span><span style="font-size: 9pt; font-family: 宋体;">语言引入了</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">coroutines</span><span style="font-size: 9pt; font-family: 宋体;">。尽管</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">coroutines</span><span style="font-size: 9pt; font-family: 宋体;">的实现较为传统，但为了完整性我们将在第</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">6</span><span style="font-size: 9pt; font-family: 宋体;">部分做个简短的概况介绍。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 9pt; font-family: 宋体;">其他部分是为了讨论的完整性或者提供背景资料。在第</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">2</span><span style="font-size: 9pt; font-family: 宋体;">部分我们介绍了</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">的设计目标以及这个目标如何驱动实现的概况。在第</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">3</span><span style="font-size: 9pt; font-family: 宋体;">部分我们介绍了</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">是如何表示值的。尽管就这个过程本身没有什么新意，但是为了（理解）其他部分我们需要这些资料。最后，在第</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">8</span><span style="font-size: 9pt; font-family: 宋体;">部分，我们介绍了一个小型的基准测试来得到一些结论。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt;"><!--[if !supportLists]--><strong><span style="font-size: 16pt; font-family: CMR9;" lang="EN-US"><span>2.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp; </span></span></span></strong><!--[endif]--><strong><span style="font-size: 16pt; font-family: CMR9;" lang="EN-US">lua</span></strong><strong><span style="font-size: 16pt; font-family: 宋体;">设计和实现概况</span></strong><strong><span style="font-size: 16pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: 宋体;">在介绍部分提到过的，</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">实现的主要目标是：</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: 宋体;">简单性：我们探索我们能提供的最简单的语言，以及实现（这样的）语言的最简单的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">C</span><span style="font-size: 9pt; font-family: 宋体;">代码。这就意味着（需要）不会偏离传统很远的拥有很少语言结构的简单语法。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: 宋体;">效率：我们探索编译和执行</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">程序的最快方法，这就意味着（需要）一个高效的、聪明的一遍扫描编译器和一个高效的虚拟机。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: 宋体;">可移植性：我们希望</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">能跑在尽可能多的平台上。我们希望能在任何地方不用修改地编译</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">核心，在任何一个带有合适的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">解释器的平台上不用修改地运行</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">程序。这就意味着一个对可移植性特别关注的干净的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">ANSI C</span><span style="font-size: 9pt; font-family: 宋体;">的实现，例如避开</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">C</span><span style="font-size: 9pt; font-family: 宋体;">和标准库库中的陷阱缺陷，并确保能以</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">c++</span><span style="font-size: 9pt; font-family: 宋体;">方式干净地编译。我们追求</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">w</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">arning-free</span><span style="font-size: 10pt; font-family: 宋体;">的编译（实现）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 10pt; font-family: 宋体;">嵌入性：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">是一门扩展语言，它被设计用来为大型程序提供脚本设施。这个以及其他目标就意味着一个简单并且强大的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C API</span><span style="font-size: 10pt; font-family: 宋体;">实现，但这样将更多地依赖内建的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">类型。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 10pt; font-family: 宋体;">嵌入的低成本：我们希望能容易地将</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">添加进一个应用，而不会使应用变的臃肿。这就意味着（需要）紧凑的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">代码和一个小的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">核心，扩展将作为用户库来添加。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: 宋体;">这些目标是有所权衡的。例如，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">经常被用作数据描述语言，用于保存和加载文件，有时是非常大的数据库</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">(</span><span style="font-size: 10pt; font-family: 宋体;">几</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">M</span><span style="font-size: 10pt; font-family: 宋体;">字节的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">程序不常见</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">)</span><span style="font-size: 10pt; font-family: 宋体;">。这就意味着我们需要一个快速的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">编译器。另一方面，我们想让</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">程序运行快速，这就意味着（需要）一个可以为虚拟机产生优秀代码的聪明的编译器。因此，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">LUA</span><span style="font-size: 10pt; font-family: 宋体;">编译器的实现必须在这两种需求中寻找平衡。尽管如此，编译器还是不能太大，否则将使整个发行包变的臃肿。目前编译器大约占</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">核心大小的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">30%</span><span style="font-size: 10pt; font-family: 宋体;">。在内存受限的应用中，比如嵌入式系统，嵌入不带有编译器的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">是可能的，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">程序将被离线预编译，然后被一个小模块（这个小模块也是快速的，因为它加载的是二进制文件）在运行时加载。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">使用了一个手写的扫描器和一个手写的递归下降解释器。直到</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">3.0</span><span style="font-size: 10pt; font-family: 宋体;">版本，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">还在使用一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">YACC</span><span style="font-size: 10pt; font-family: 宋体;">产生的解释器，这在语言的语法不够稳定的时候很有价值的。然而，手写的解释器更小、更高效、更轻便以及完全可重入，也能提供更好的出错信息（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">error message</span><span style="font-size: 10pt; font-family: 宋体;">）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">编译器没有使用中间代码表示（译注：也就是不生成中间代码）。当解释一个程序的时候，它以&#8220;</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">on-the-fly&#8221;</span><span style="font-size: 10pt; font-family: 宋体;">的方式给虚拟机发出指令。不过，它会进行一些优化。例如，它会推迟像变量和常量这样的基本表达式的代码生成。当它解释这样的表达式的时候，没有产生任何代码，而是使用一种简单的结构来表示它们。所以，判断一个给定指令的操作数是常量还是变量以及将它们的值直接应用在指令都变的非常容易，避免了不必要的和昂贵的移动。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: 宋体;">为了轻便地在许许多多不同的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">编译器和平台之间移植，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">不能使用许多解释器通常使用的技巧，例如</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">direct threaded code [8, 16]</span><span style="font-size: 10pt; font-family: 宋体;">。作为替代，它（译注：指</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">解释器）使用了标准的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">while-switch</span><span style="font-size: 10pt; font-family: 宋体;">分发循环。此处的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">代码看起来过于复杂，但是复杂性也是为了确保可移植性。当</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">在许多不同的平台上（包括</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">64</span><span style="font-size: 10pt; font-family: 宋体;">位平台和一些</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">16</span><span style="font-size: 10pt; font-family: 宋体;">位平台）被很多不同的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">编译器编译，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">实现的可移植性一直以来变的越来越稳定了。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">我们认为我们已经达到我们的设计和实现目标了。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">是一门非常轻便的语言，它能跑在任何一个带有</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">ANSI C</span><span style="font-size: 10pt; font-family: 宋体;">编译器的平台上，从嵌入式系统到大型机。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">确实是轻量级的：例如，它在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">linux</span><span style="font-size: 10pt; font-family: 宋体;">平台上的独立解释器包括所有的标准库，占用的空间小于</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">150K;</span><span style="font-size: 10pt; font-family: 宋体;">核心更是小于</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">100K</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">是高效的：独立的基准测试表明</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">是脚本语言（解释的、动态类型的语言）领域中最快的语言之一。主观上我们也认为</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">是一门简单的语言，语法上类似</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Pascal</span><span style="font-size: 10pt; font-family: 宋体;">，语义上类似</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Scheme</span><span style="font-size: 10pt; font-family: 宋体;">（译注：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lisp</span><span style="font-size: 10pt; font-family: 宋体;">的一种方言）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><strong><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">3</span></strong><strong><span style="font-size: 9pt; font-family: 宋体;">、值的表示</span></strong><strong><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 9pt; font-family: 宋体;">是动态类型语言：类型依附于值而不是变量。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 9pt; font-family: 宋体;">有</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">8</span><span style="font-size: 9pt; font-family: 宋体;">种基本类型：</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">nil</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">, </span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">boolean</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">, </span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">number</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">, </span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">string</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">, </span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">, </span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">function</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">,</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">userdata</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">, </span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">thread</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">Nil</span><span style="font-size: 10pt; font-family: 宋体;">是一个标记类型，它只拥有一个值也叫</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">nil</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">Boolean</span><span style="font-size: 10pt; font-family: 宋体;">就是通常的</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">true</span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">false</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">Number</span><span style="font-size: 10pt; font-family: 宋体;">是双精度浮点数，对应于</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">语言中的</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">类型，但用</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">float</span><span style="font-size: 10pt; font-family: 宋体;">或者</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">long</span><span style="font-size: 10pt; font-family: 宋体;">作为替代来编译</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">也很容易（不少游戏</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">consoles</span><span style="font-size: 10pt; font-family: 宋体;">或者小机器都缺乏对</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">的硬件支持）</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">String</span><span style="font-size: 10pt; font-family: 宋体;">是有显式大小的字节数组，因此可以存储任意的二进制类型，包括嵌入零。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">Table</span><span style="font-size: 10pt; font-family: 宋体;">类型就是关联的数组，可以用任何值做索引（除了</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">nil</span><span style="font-size: 10pt; font-family: 宋体;">），也可以持有任何值。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">Function</span><span style="font-size: 10pt; font-family: 宋体;">是依据与</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">虚拟机连接的协议编写的</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">函数或者</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">函数。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">Userdata</span><span style="font-size: 10pt; font-family: 宋体;">本质上是指向用户内存区块（</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">user memory block</span><span style="font-size: 10pt; font-family: 宋体;">）的指针，有两种风格：重量级</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">,</span><span style="font-size: 10pt; font-family: 宋体;">由</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">分配块并由</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">GC</span><span style="font-size: 10pt; font-family: 宋体;">回收；轻量级，由用户分配和释放（内存）块。最后，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">thread</span><span style="font-size: 10pt; font-family: 宋体;">表示</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">coroutines</span><span style="font-size: 10pt; font-family: 宋体;">。所有类型的值都是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">first-class</span><span style="font-size: 10pt; font-family: 宋体;">值：我们可以将它们作为全局变量、局部变量和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">的域来存储，作为参数传递给函数，作为函数的返回值等等。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">typedef struct {<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;</span>typedef union {<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">int t; <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>GCObject
*gc;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">Value v; <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>void *p;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">} TObject; <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>lua_Number n;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 215pt;" align="left"><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">int b;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 185pt;" align="left"><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">} Value;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 60pt;" align="left"><span style="font-size: 10pt; font-family: CMBX10;" lang="EN-US">Figure 1: </span><span style="font-size: 10pt; font-family: 宋体;">带标签的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">表示</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">值</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 60pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 60pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">将值表示为带标签的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union(tagged unions)</span><span style="font-size: 10pt; font-family: 宋体;">，也就是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">pairs(t,v)</span><span style="font-size: 10pt; font-family: 宋体;">，其中</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">t</span><span style="font-size: 10pt; font-family: 宋体;">是一个决定了值</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">v</span><span style="font-size: 10pt; font-family: 宋体;">类型的整数型标签，而</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">v</span><span style="font-size: 10pt; font-family: 宋体;">是一个实现了</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">类型的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">语言的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">结构。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Nil</span><span style="font-size: 10pt; font-family: 宋体;">拥有一个单独的值（译注：也就是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">nil</span><span style="font-size: 10pt; font-family: 宋体;">）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Booleans</span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">numbers</span><span style="font-size: 10pt; font-family: 宋体;">被实现为&#8220;拆箱式&#8221;的值：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">v</span><span style="font-size: 10pt; font-family: 宋体;">在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">中直接表示这些类型的值。这就意味着</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">（译注：指图中的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Value</span><span style="font-size: 10pt; font-family: 宋体;">）必须有足够的空间容纳</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">（类型）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Strings,tables,
functions, threads, </span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"> userdata</span><span style="font-size: 10pt; font-family: 宋体;">类型的值通过引用来实现：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">v</span><span style="font-size: 10pt; font-family: 宋体;">拥有指向实现这些类型的结构的指针。这些结构（译注：指实现</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Strings,tables, functions, threads, </span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"> userdata</span><span style="font-size: 10pt; font-family: 宋体;">这些类型的具体结构）共享一个共同的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">head</span><span style="font-size: 10pt; font-family: 宋体;">，用来保存用于垃圾收集的信息。结构的剩下的部分专属于各自的类型。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><span>&nbsp;</span>Figure1</span><span style="font-size: 10pt; font-family: 宋体;">展示了一个实际的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">值的实现。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">TObject</span><span style="font-size: 10pt; font-family: 宋体;">是这个实现的主要结构体：它表示了上文描述的带标签的联合体（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">tagged unions</span><span style="font-size: 10pt; font-family: 宋体;">）</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"> (t,v)</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Value</span><span style="font-size: 10pt; font-family: 宋体;">是实现了值的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">类型。类型</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">nil</span><span style="font-size: 10pt; font-family: 宋体;">的值没有显式表示在这个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">类型中是因为标签已经足够标识它们。域</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">用来表示</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">numbers</span><span style="font-size: 10pt; font-family: 宋体;">类型（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua_Number</span><span style="font-size: 10pt; font-family: 宋体;">默认是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">类型）。同样，域</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">b</span><span style="font-size: 10pt; font-family: 宋体;">是给</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">booleans</span><span style="font-size: 10pt; font-family: 宋体;">类型用的，域</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">p</span><span style="font-size: 10pt; font-family: 宋体;">是给轻量级的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">userdata</span><span style="font-size: 10pt; font-family: 宋体;">类型。而域</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">gc</span><span style="font-size: 10pt; font-family: 宋体;">是为会被垃圾回收的其他类型准备的（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">(strings, tables, functions, </span><span style="font-size: 10pt; font-family: 宋体;">重量级</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">userdata, </span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">threads)</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">使用带标签的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">实现</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">值的一个后果就是拷贝值的代价稍微昂贵了一点：在一台支持</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">64</span><span style="font-size: 10pt; font-family: 宋体;">位</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">类型的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">32</span><span style="font-size: 10pt; font-family: 宋体;">位机器上，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">TObject</span><span style="font-size: 10pt; font-family: 宋体;">的大小是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">12</span><span style="font-size: 10pt; font-family: 宋体;">字节（或者</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">16</span><span style="font-size: 10pt; font-family: 宋体;">字节，如果</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">按</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">8</span><span style="font-size: 10pt; font-family: 宋体;">字节对齐的话），因此拷贝一个值将需要拷贝</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">3</span><span style="font-size: 10pt; font-family: 宋体;">（或者</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">4</span><span style="font-size: 10pt; font-family: 宋体;">）个机器字长。尽管如此，想在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">ANSI C</span><span style="font-size: 10pt; font-family: 宋体;">中实现一个更好的值的表示是困难的。一些动态类型语言（例如</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Smalltalk80</span><span style="font-size: 10pt; font-family: 宋体;">的原始实现）在每个指针中使用多余的位来存储值的类型标签。这个技巧在绝大多数机器上正常工作，这是因为一个指针的最后两个或者三个位由于对齐将总是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">0</span><span style="font-size: 10pt; font-family: 宋体;">，所以可以被用作他途。但是，这项技术既不是可移植的也无法在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">ANSI C</span><span style="font-size: 10pt; font-family: 宋体;">中实现，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C </span><span style="font-size: 10pt; font-family: 宋体;">语言标准甚至都不保证指针适合任何整数类型，所以没有在指针上操作位的标准方法。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">减小值大小的另一个观点就是持有显式标签，从而避免在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">中放置一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">类型。例如，所有的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">number</span><span style="font-size: 10pt; font-family: 宋体;">类型可以表示为堆分配的对象，就像</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">String</span><span style="font-size: 10pt; font-family: 宋体;">那样。（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">python</span><span style="font-size: 10pt; font-family: 宋体;">使用了这项技术，除了预先分配了一些小的整数值）。尽管如此，这样的表示方法将使语言变的非常缓慢。作为选择，整数的值可以表示位&#8220;拆箱式&#8221;的值，直接存储在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">中，而浮点值放在堆中。这个办法将极大地增加所有算术运算操作的实现复杂度。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">类似早期的解释型语言，例如</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Snobol [11] </span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"> Icon [10]</span><span style="font-size: 10pt; font-family: 宋体;">，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">在一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">表中&#8220;拘留&#8221;</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">(</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">internalizes)</span><span style="font-size: 10pt; font-family: 宋体;">字符串：（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">表）没有重复地持有每个字符串的单独拷贝。此外，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">String</span><span style="font-size: 10pt; font-family: 宋体;">是不可变的：一个字符串一旦被&#8220;拘留&#8221;，将不能再被改变。字符串的哈希值依据一个混合了位和算术运算的简单表达式来计算，囊括所有的位。当字符串被&#8220;拘留&#8221;时，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">值保存（到</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">表），以支持更快的字符串比较和表索引。如果字符串太长的话，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">函数并不会用到字符串的所有字节，这有利于快速地散列长字符串。避免处理长字符串带来的性能损失是重要的，因为（这样的操作）在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">中是很普遍的。例如，用</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">处理文件的时候经常将整个文件内容作为一个单独的长字符串读入内存。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p><img src ="http://www.blogjava.net/killme2008/aggbug/191314.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-04-07 17:25 <a href="http://www.blogjava.net/killme2008/archive/2008/04/07/191314.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重定向和管道的实现</title><link>http://www.blogjava.net/killme2008/archive/2008/02/29/182868.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 29 Feb 2008 03:16:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/02/29/182868.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/182868.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/02/29/182868.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/182868.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/182868.html</trackback:ping><description><![CDATA[重定向标准输入的实现：<br />
1）close-then-open: close(0) ; fd=open("test",O_RDONLY); fd将是stdin。<br />
2)open-close-dup-close:<br />
fd=open(file),打开stdin将要重定向的文件；close(0);new_fd=dup(file);close(fd);new_fd就是被重定向的stdin<br />
3)open-dup2-close:<br />
fd=open(file);new_fd=dup2(fd,0);close(fd);<br />
<br />
重定向标准输出的实现：<br />
&nbsp;
父进程fork();子进程close(1);create("g",0644)，此时子进程的stdout被重定向到g;接下来子进程exec某个程序，文件描述符属于进程属性，exec调用不会改变他们，那么运行的程序的标准输出将被送到g，由此实现了标准输出重定向。<br />
<br />
本质上重定向的实现是依赖两个原则：<br />
1、标准输入、标准输出和标准错误分别是0、1和2<br />
2、最低可用描述符：打开文件时，为此文件安排的描述符总是进程内打开文件数组的最低可用位置的索引。<br />
<br />
管道：<br />
&nbsp; 匿名管道：适合于有亲缘关系的进程，通过pipe函数实现。<br />
&nbsp; 有名管道：通过mkfifo函数实现，实现进程间的双向通讯可以采用两个有名管道实现，也可以采用socketpair调用。<img src ="http://www.blogjava.net/killme2008/aggbug/182868.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-02-29 11:16 <a href="http://www.blogjava.net/killme2008/archive/2008/02/29/182868.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>写操作系统？看看这个（转载）</title><link>http://www.blogjava.net/killme2008/archive/2008/02/22/181476.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 22 Feb 2008 09:53:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/02/22/181476.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/181476.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/02/22/181476.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/181476.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/181476.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 今天在pongba的邮件列表里看到了这个<a href="http://blog.solrex.cn/articles/free-ebook-write-os-with-free-software-revision-1-released.html">《免费电子书&lt;使用开源软件——自己动手写操作系统&gt;》 </a><br />
&nbsp;&nbsp;&nbsp; 只能说太酷了，china-pub上一直有本书《自己动手写操作系统》，牛人看到这本书使用的是商业软件做示范，于是动念想是不是能使用开源软件来实现书中所有的demo，于是就有了这本宝贵的电子书。<br />
&nbsp;&nbsp;&nbsp; 项目主页：http://share.solrex.cn/WriteOS/<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/181476.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-02-22 17:53 <a href="http://www.blogjava.net/killme2008/archive/2008/02/22/181476.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>视频站点的搭建</title><link>http://www.blogjava.net/killme2008/archive/2007/12/19/168788.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 19 Dec 2007 08:46:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/12/19/168788.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/168788.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/12/19/168788.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/168788.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/168788.html</trackback:ping><description><![CDATA[&nbsp; &nbsp; 挺久没动笔写blog了，换了新工作比较忙是一个原因。最近的工作是做一个素材管理的系统，其中有个要求做视频预览，将用户上传的视频转换并在网页上预览。在网页上看视频，现在大多数视频网站都是采用flv流媒体文件，用flash做的播放器播放，我们也采用了这种方式。流程大概主要：用户上传文件-&gt;后台转换文件成flv格式-&gt;flv播放器调用flv文件。<br />
&nbsp;&nbsp;&nbsp; 转换视频、音频文件到flv格式可以使用mencoder或者ffmpeg，我们采用了mencoder，在linux上的安装参考<a href="http://hi.baidu.com/flash%5Fzb/blog/item/bbf7668de6f85912b21bbae0.html">这里</a>,安装结束后记的设置环境变量：export LD_LIBRARY_PATH=/usr/local/lib:LD_LIBRARY_PATH<br />
&nbsp;&nbsp;&nbsp; java调用的话就是通过Process：<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 0);">&nbsp;Process&nbsp;process&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;runtime.exec(cmd);</span></div>
<br />
mencoder转换视频音频成flv命令：<br />
mencoder 源文件 -o 目标文件.flv -of lavf&nbsp;&nbsp;&nbsp; -lavfopts i_certify_that_my_video_stream_does_not_use_b_frames -oac mp3lame -lameopts abr:br=56 -ovc lavc -lavcopts vcodec=flv:vbitrate=400:mbd=2:mv0:trell:v4mv:cbp:last_pred=3:dia=4:cmp=6:vb_strategy=1 -vf scale=200:-3 -ofps 12 -srate 22050<br />
<br />
取视频元信息命令（视频比特率、长宽等信息）：<br />
mplayer -identify 文件名 -ao null -vo null -frames 0 <br />
<br />
切割视频命令：<br />
mencoder -ss 开始时间 -oac copy -ovc copy -endpos 终止时间 文件名 -o 目标文件名<br />
<br />
&nbsp;&nbsp;&nbsp; 操作flv文件（给视频打上信息、切割之类）可以采用<a href="http://rubyforge.org/projects/flvtool2/">flvtool2</a>。<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 需要注意的是通过java调用的话，一定要处理标准输出和标准错误输出，不然进程会挂在那结束不了，可以开个线程取处理。在网页播放的话，可以考虑用<a href="http://hi.baidu.com/lzxinta/blog/item/4c02d55103216d2643a75b7b.html">这个播放器</a>，具体参数看它的说明。最后一个问题，IE6的flash控件需要激活，这个问题的解决可以采用<a href="http://blog.deconcept.com/swfobject/">swfobject.js</a>。<br />
&nbsp;&nbsp;&nbsp; 有兴趣的老大们可以考虑自己搭个&#8220;土豆网&#8221;，说不定哪天拿了风投.....浮云<br /><img src ="http://www.blogjava.net/killme2008/aggbug/168788.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-12-19 16:46 <a href="http://www.blogjava.net/killme2008/archive/2007/12/19/168788.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>今天长见识了</title><link>http://www.blogjava.net/killme2008/archive/2007/11/29/164069.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 29 Nov 2007 10:17:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/11/29/164069.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/164069.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/11/29/164069.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/164069.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/164069.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 先是读《Programming in Lua》第9章讲<span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">coroutine，然后去google </span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">coroutine，找到</span><em><a href="http://pobox.com/%7Eanakin/">Simon Tatham</a>写的</em><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">一篇</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US"><a href="http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html">coroutine in c</a>，讲怎么在C语言中实现</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">coroutine，文中</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">先ugly地基于栈实现了一个：<br />
</span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;function(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i,&nbsp;state&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">switch</span><span style="color: #000000;">&nbsp;(state)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">:&nbsp;</span><span style="color: #0000ff;">goto</span><span style="color: #000000;">&nbsp;LABEL0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">:&nbsp;</span><span style="color: #0000ff;">goto</span><span style="color: #000000;">&nbsp;LABEL1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;LABEL0:&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;start&nbsp;of&nbsp;function&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">10</span><span style="color: #000000;">;&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;state&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;so&nbsp;we&nbsp;will&nbsp;come&nbsp;back&nbsp;to&nbsp;LABEL1&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;i;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LABEL1:;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;resume&nbsp;control&nbsp;straight&nbsp;after&nbsp;the&nbsp;return&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<br />
这个方法简单，但是相当丑陋，你必须手工维护这些标签。然后提到了Duff's Device技巧：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">switch</span><span style="color: #000000;">&nbsp;(count&nbsp;</span><span style="color: #000000;">%</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">8</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;">&nbsp;{&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">7</span><span style="color: #000000;">:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">6</span><span style="color: #000000;">:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;((count&nbsp;</span><span style="color: #000000;">-=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">8</span><span style="color: #000000;">)&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<br />
这段代码能编译通过吗？能的，不信你试试，这是一段用于拷贝数组的代码，我们一般拷贝数组是这样做的：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">send(to,&nbsp;from,&nbsp;count)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;register&nbsp;</span><span style="color: #0000ff;">short</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to,&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;register&nbsp;count;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">(</span><span style="color: #000000;">--</span><span style="color: #000000;">count</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
如果循环的中的操作足够快，那么其实大部分时间都是浪费在判断循环条件上面的，而通过Duff's Device通过switch语句将要进行的连续循环操作的次数进行了预判（根据擦case语句的位置）然后依次执行，而不必每次都去进 行测试条件，从而加速循环。这个技巧怎么应用于实现更优雅的<span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">coroutine呢？看代码<br />
<br />
</span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;function(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i,&nbsp;state&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">switch</span><span style="color: #000000;">&nbsp;(state)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">:&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;start&nbsp;of&nbsp;function&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">10</span><span style="color: #000000;">;&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;state&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;so&nbsp;we&nbsp;will&nbsp;come&nbsp;back&nbsp;to&nbsp;"case&nbsp;1"&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;i;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">:;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;resume&nbsp;control&nbsp;straight&nbsp;after&nbsp;the&nbsp;return&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
更好的方式是使用宏：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">#define</span><span style="color: #000000;">&nbsp;crBegin&nbsp;static&nbsp;int&nbsp;state=0;&nbsp;switch(state)&nbsp;{&nbsp;case&nbsp;0:</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">#define</span><span style="color: #000000;">&nbsp;crReturn(i,x)&nbsp;do&nbsp;{&nbsp;state=i;&nbsp;return&nbsp;x;&nbsp;case&nbsp;i:;&nbsp;}&nbsp;while&nbsp;(0)</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">#define</span><span style="color: #000000;">&nbsp;crFinish&nbsp;}</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;function(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i;<br />
&nbsp;&nbsp;&nbsp;&nbsp;crBegin;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">10</span><span style="color: #000000;">;&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;crReturn(</span><span style="color: #000000;">1</span><span style="color: #000000;">,&nbsp;i);<br />
&nbsp;&nbsp;&nbsp;&nbsp;crFinish;<br />
}</span></div>
<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/164069.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-11-29 18:17 <a href="http://www.blogjava.net/killme2008/archive/2007/11/29/164069.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hack,hacker</title><link>http://www.blogjava.net/killme2008/archive/2007/10/15/152846.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 15 Oct 2007 01:09:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/10/15/152846.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/152846.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/10/15/152846.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/152846.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/152846.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; hack有水平高低之分，最近看到一个blog，牛人的hack水平让你不得不服。情况是这样的，牛人在使用 <a href="http://public.railsplugins.net/repos/mongrel_light_cluster/trunk/">mongrel_light_cluster</a>的过程中，发现这个cluster违反了copy-on-write的语义，导致占用了太多的内存。根本原因在于Ruby的GC机制是<a href="http://blog.beaver.net/2005/03/ruby_gc_and_copyonwrite.html">marks all memory pages as dirty</a>。为了减少内存的占用，让集群跑更多mongrel，牛人走上了hack之路，给c ruby打补丁，他也真的<a href="http://izumi.plan99.net/blog/index.php/2007/10/13/making-ruby%e2%80%99s-garbage-collector-copy-on-write-friendly-part-4/">做到了</a>。c ruby的GC使用的是mark and sweep(标记并清除)的垃圾收集算法，他发现在mark过程中使用了<a href="http://www.blogjava.net/killme2008/archive/2007/09/18/146234.html">st_table</a>，这个数据结构占用了很大的内存，那么就改用<a href="http://code.google.com/p/google-sparsehash/">Google&#8217;s sparse_hash</a>。然后他又写了一个memory pool，以应对marking和sweep使用过程中对malloc和free调用带来的内存损失，因为在x86 GNU/linux gcc上，malloc函数如果申请的内存小于76KB，那么当free的时候这些内存不会被返还给操作系统。他的hack之路还没结束，有兴趣的关注他的blog: <br />
<br />
&nbsp;http://izumi.plan99.net/blog/index.php/<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/152846.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-10-15 09:09 <a href="http://www.blogjava.net/killme2008/archive/2007/10/15/152846.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ruby变量在c ruby中的存储</title><link>http://www.blogjava.net/killme2008/archive/2007/09/20/146799.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 20 Sep 2007 08:17:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/09/20/146799.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/146799.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/09/20/146799.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/146799.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/146799.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 读完ruby hacking guide第6章，彻底总结下：<br />
1.在Ruby中，类也是一个对象，因此有实例变量。类的实例变量、类变量、常量都是存储在RClass struct的iv_tbl中，<br />
struct RClass {<br />
&nbsp;&nbsp;&nbsp; struct RBasic basic;<br />
&nbsp;&nbsp;&nbsp; struct st_table *iv_tbl;<br />
&nbsp;&nbsp;&nbsp; struct st_table *m_tbl;<br />
&nbsp;&nbsp;&nbsp; VALUE super;<br />
};<br />
iv_tbl的类型是st_table，我在<a href="http://www.blogjava.net/killme2008/archive/2007/09/18/146234.html">这里</a>用java实现了一下。<br />
<br />
2.用户自定义类的对象（ruby层次声明的类的对象)的实例变量存储在RObject struct的iv_tbl中，<br />
struct RObject {<br />
&nbsp; struct RBasic basic;<br />
&nbsp; struct st_table *iv_tbl;<br />
&nbsp;};<br />
调用方法，本质上是一个查表操作。buildin的几个类，比如String、Array、Hash等(在c层次上实现的类），它们的结构并没有iv_table，这是从节省内存空间的角度考虑，它们的实例变量存储在一张全局的st_table中。这张表比较特别，其中的每一个对应的值又是一个st_table，也就是一个&#8220;二元结构&#8221;，第一层结构是类名与实例变量表的映射，第二层才是实例变量名与实际值的映射。<br />
<br />
3.全局变量存储在一张全局的st_table中，这个表的键就是变量名ID，由于全局变量允许通过alias来设置别名，因此这张全局表中真正存储的是下面这个struct<br />
<br />
334  struct global_entry {<br />
335      struct global_variable *var;<br />
336      ID id;<br />
337  };<br />
<br />
324  struct global_variable {<br />
325      int   counter;      /* 引用计数 */<br />
326      void *data;         /* 变量值 */<br />
327      VALUE (*getter)();  /* 取值函数 */<br />
328      void  (*setter)();  /* 设置函数 */<br />
329      void  (*marker)();  /* 标记函数 */<br />
330      int block_trace;<br />
331      struct trace_var *trace;<br />
332  };<br />
(variable.c)<br />
<br />
当不同变量名（通过别名声明）指向的是同一个全局变量，其实它们指向的是同一个struct global_variable