﻿<?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>C++博客-右席的搬砖日记-随笔分类-Luajit</title><link>http://www.cppblog.com/pwq1989/category/20748.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 22 Dec 2014 20:06:39 GMT</lastBuildDate><pubDate>Mon, 22 Dec 2014 20:06:39 GMT</pubDate><ttl>60</ttl><item><title>自撸web小框架 dodolu(基于nginx lua) + lua debugger</title><link>http://www.cppblog.com/pwq1989/archive/2014/12/22/209273.html</link><dc:creator>右席</dc:creator><author>右席</author><pubDate>Mon, 22 Dec 2014 10:22:00 GMT</pubDate><guid>http://www.cppblog.com/pwq1989/archive/2014/12/22/209273.html</guid><wfw:comment>http://www.cppblog.com/pwq1989/comments/209273.html</wfw:comment><comments>http://www.cppblog.com/pwq1989/archive/2014/12/22/209273.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/pwq1989/comments/commentRss/209273.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/pwq1989/services/trackbacks/209273.html</trackback:ping><description><![CDATA[<h2>背景</h2>
<p>前段时间项目需要一个点击服务，大致是要根据用户请求的url及数据库中的规则，匹配出一个结果并记录日志。最开始是一个很小的需求，结果业务越来越复杂，业务逻辑中经常要处理header头和一些其他的信息，导致代码越来越混乱。在一期结束之后，抽时间把这段时间的工作抽象出了一个轻量级框架，只做了适量的封装，加入了代码生成的模块，可以帮助开发者迅速做出一个可用的web服务。</p>
<h2>介绍</h2>
<p>dodolu框架地址(<a href="https://github.com/pwq1989/dodolu">Github</a>)。</p>
<p>该框架只做了最小化的封装，几乎没有性能损失，并提供了根据配置文件(meta.lua)，自动生成route模块，nginx.conf配置，logger模块的功能，减轻了开发工作量，避免重复手写大量易错的配置或字符串变量，有助于多人开发统一风格。</p>
<blockquote>
<p>详情<a href="https://github.com/pwq1989/dodolu">Github</a>的README</p>
</blockquote>
<h2>功能</h2>
<p>包括三个部分，一个是<a href="https://github.com/pwq1989/dodolu/tree/master/ddl">web框架</a>，一个是<a href="https://github.com/pwq1989/dodolu/tree/master/tools">代码自动生成</a>模块，一个是魔改出的<a href="https://github.com/pwq1989/dodolu/tree/master/ddl/lualibs/debug">lua远程调试器</a>。</p>
<h3>web框架部分</h3>
<p>只有1k行以下的代码，集成了resty.template、resty.cookie、UUID生成等第三方模块。提供request、response、context、util等库方便开发人员使用。</p>
<h3>代码自动生成部分</h3>
<p>可自动生成:</p>
<ol>
     <li>路由配置</li>
     <li>日志记录模块</li>
     <li>nginx.conf</li>
</ol>
<p>主要目的在于解决nginx配置与lua代码的分离问题(在日志记录中尤为严重)。</p>
<p>开发人员新建应用步骤：在App文件夹下，新建lua文件，然后填入<code>do_get()</code>方法即可处理相应的get请求，所有配置在<code>meta/meta.lua</code>里面。</p>
<p>一个记录日志并返回1x1gif的例子：</p>
<pre><code data-language="">-- 这个文件下面存放你的业务逻辑<br />
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->--&nbsp;这个文件下面存放你的业务逻辑<br />
local&nbsp;app&nbsp;=&nbsp;{}
function&nbsp;app.do_get(ctx)&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;local&nbsp;response&nbsp;=&nbsp;ctx.response
&nbsp;&nbsp;&nbsp;&nbsp;local&nbsp;request&nbsp;=&nbsp;ctx.request
&nbsp;&nbsp;&nbsp;&nbsp;local&nbsp;cookie&nbsp;=&nbsp;ctx.cookie<br />
&nbsp;&nbsp;&nbsp;&nbsp;response:set_content_type("text/html")
&nbsp;&nbsp;&nbsp;&nbsp;local&nbsp;url&nbsp;=&nbsp;request.uri
&nbsp;&nbsp;&nbsp;&nbsp;--&nbsp;<span style="color: #0000FF; ">do</span>&nbsp;some&nbsp;process<br />
&nbsp;&nbsp;&nbsp;&nbsp;-------------&nbsp;write&nbsp;log&nbsp;---------------
&nbsp;&nbsp;&nbsp;&nbsp;--&nbsp;my_log&nbsp;日志模块是根据meta.lua自动生成的
&nbsp;&nbsp;&nbsp;&nbsp;local&nbsp;logger&nbsp;=&nbsp;ctx.get_logger('my_log')&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;local&nbsp;log_data&nbsp;=&nbsp;{&nbsp;a&nbsp;=&nbsp;"xxx"}
&nbsp;&nbsp;&nbsp;&nbsp;logger.write(log_data,&nbsp;other_params<img src="http://www.cppblog.com/Images/dot.gif" alt="" />)<br />
&nbsp;&nbsp;&nbsp;&nbsp;-------------&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;empty&nbsp;gif&nbsp;-------
&nbsp;&nbsp;&nbsp; response:empty_gif()
&nbsp;&nbsp;&nbsp;&nbsp;response:close()
end<br />
function&nbsp;app.do_post(ctx)&nbsp;end
function&nbsp;app.do_put(ctx)&nbsp;end
function&nbsp;app.do_delete(ctx)&nbsp;end<br />
<span style="color: #0000FF; ">return</span>&nbsp;app</div>

</code></pre>
<h3>lua远程调试器</h3>
<p>文档详细见<a href="https://github.com/pwq1989/dodolu/tree/master/ddl/lualibs/debug">这里</a>，这里只演示下用法：<br />
<code>sh debug.sh</code>，然后运行用户程序，成功后<br />
<br />
</p>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->Lua&nbsp;Remote&nbsp;Debugger<br />
Run&nbsp;the&nbsp;program&nbsp;you&nbsp;wish&nbsp;to&nbsp;debug<br />
Paused&nbsp;at&nbsp;file&nbsp;a.lua<br />
Type&nbsp;'help'&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;commands<br />
&gt;&nbsp;</div>
<pre><br />
</pre>
<p>下一步 &nbsp;<code>n<br />
<br />
</code></p>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->n<br />
Paused&nbsp;at&nbsp;file&nbsp;a.lua&nbsp;line&nbsp;8<br />
8:&nbsp;print("Start")<br />
&gt;&nbsp;</div>
<p><br />
查看源码<font face="monospace">&nbsp; l<br />
<br />
</font></p>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->&gt;&nbsp;l&nbsp;&nbsp;<br />
source&nbsp;file:&nbsp;a.lua<br />
2:&nbsp;&nbsp;&nbsp;<br />
3:&nbsp;&nbsp;&nbsp;local&nbsp;tab&nbsp;=&nbsp;{<br />
4:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foo&nbsp;=&nbsp;1,<br />
5:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bar&nbsp;=&nbsp;2<br />
6:&nbsp;&nbsp;&nbsp;}<br />
7:&nbsp;&nbsp;&nbsp;<br />
8:&gt;&gt;&nbsp;print("Start")<br />
9:&nbsp;&nbsp;&nbsp;<br />
10:&nbsp;&nbsp;local&nbsp;bb&nbsp;=&nbsp;require&nbsp;"b"<br />
11:&nbsp;&nbsp;bb.foo()<br />
12:&nbsp;&nbsp;&nbsp;<br />
13:&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;i&nbsp;=&nbsp;1,&nbsp;10&nbsp;<span style="color: #0000FF; ">do</span><br />
14:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print("Loop")</div>
<p><br />
</p>
<p>设置断点 &nbsp;&nbsp;<code>b &lt;file&gt;:&lt;line&gt;</code>&nbsp; &nbsp;查看 &nbsp; &nbsp;<code>listb<br />
<br />
</code></p>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->&gt;&nbsp;b&nbsp;a.lua:11<br />
&gt;&nbsp;listb&nbsp;<br />
a.lua:&nbsp;11</div>
<p>查看局部变量 &nbsp;<code>local</code></p><pre><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->&gt;&nbsp;local
{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;["tab"]&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;["bar"]&nbsp;=&nbsp;2,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;["foo"]&nbsp;=&nbsp;1,
&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;"table:&nbsp;0x2589ee0",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
}</div>
</pre>
<p>查看变量 &nbsp;&nbsp;<code>p tab<br />
<br />
</code></p>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->&gt;&nbsp;p&nbsp;tab<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;["bar"]&nbsp;=&nbsp;2,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;["foo"]&nbsp;=&nbsp;1,<br />
}</div>
<pre><span style="font-family: verdana, 'courier new';">继续执行，直到断点 &nbsp;</span><code>r</code></pre><pre><code data-language=""><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->&gt;&nbsp;r
Paused&nbsp;at&nbsp;file&nbsp;a.lua&nbsp;line&nbsp;11</div>

<br />
<br />
</code></pre><img src ="http://www.cppblog.com/pwq1989/aggbug/209273.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/pwq1989/" target="_blank">右席</a> 2014-12-22 18:22 <a href="http://www.cppblog.com/pwq1989/archive/2014/12/22/209273.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（二）Luajit中的好轮子DynASM</title><link>http://www.cppblog.com/pwq1989/archive/2013/11/30/204508.html</link><dc:creator>右席</dc:creator><author>右席</author><pubDate>Sat, 30 Nov 2013 04:49:00 GMT</pubDate><guid>http://www.cppblog.com/pwq1989/archive/2013/11/30/204508.html</guid><wfw:comment>http://www.cppblog.com/pwq1989/comments/204508.html</wfw:comment><comments>http://www.cppblog.com/pwq1989/archive/2013/11/30/204508.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/pwq1989/comments/commentRss/204508.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/pwq1989/services/trackbacks/204508.html</trackback:ping><description><![CDATA[本人博客地址：<a href="http://www.cppblog.com/pwq1989/">http://www.cppblog.com/pwq1989/</a><br /><br />上一篇对Luajit的代码结构和编译过程做了简单的描述，这一篇就讲一下buildvm在第一步预处理dasc文件的过程和DynASM这个轮子。<br /><br />官方连接：<a href="http://luajit.org/dynasm.html">http://luajit.org/dynasm.html</a><br /><br />是为了让你更优雅的C里面撸汇编的一个工具，我记得以前看过一个老外的blog对比过同样功能的jit code generator的语法，Luajit的作者显然品位还是很高的。<br /><br />我们先来看看如果不用工具硬生生撸代码的话会发生什么。<br />1、你往一段内存里面写0xB8,0x00,0x01....<br />2、你在文件里定义好多label，写个copy section的宏往内存里面复制，你还不能确定里面到底是什么。（哦。。这个的术语叫Threaded。。。）<br /><br />然后再对比下<a href="https://code.google.com/p/asmjit/wiki/Examples" title="AsmJit" target="_blank">AsmJit</a>或者<a href="https://github.com/herumi/xbyak/blob/master/sample/bf.cpp" title="Xbyak" target="_blank">Xbyak</a>的例子看看（他们的功能差不多），DynASM还提供了.marco实现，就会发现语法真是sweeeet~<br /><br />这是我写着玩的一个草泥马语jit解释器（<a href="https://github.com/pwq1989/GMHjit">https://github.com/pwq1989/GMHjit</a>）语法真是清新自然啊，如果你想看工业级的应用，可以看看Google的Haberman写的protobuf的upb库，里面用DynASM进行了jit，号称快了多少多少（不去考证了），或者是agentzh写的sregex正则库，也是用它做了jit。一般来说DSL配上jit的话一定会快很多就错不了了。<br /><br />下面给一个DynASM的Demo程序（摘抄自<a href="http://blog.reverberate.org/2012/12/hello-jit-world-joy-of-simple-jits.html" title="这个blog">这个blog</a>）<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;DynASM&nbsp;directives.</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #008000; "></span>|.arch&nbsp;x64<br /><span style="color: #008080; ">&nbsp;3</span>&nbsp;|.actionlist&nbsp;actions<br /><span style="color: #008080; ">&nbsp;4</span>&nbsp;&nbsp;<br /><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;This&nbsp;define&nbsp;affects&nbsp;"|"&nbsp;DynASM&nbsp;lines.&nbsp;&nbsp;"Dst"&nbsp;must<br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #008000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;resolve&nbsp;to&nbsp;a&nbsp;dasm_State**&nbsp;that&nbsp;points&nbsp;to&nbsp;a&nbsp;dasm_State*.</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #008000; "></span><span style="color: #0000FF; ">#define</span>&nbsp;Dst&nbsp;&amp;state<br /><span style="color: #008080; ">&nbsp;8</span>&nbsp;&nbsp;<br /><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;main(<span style="color: #0000FF; ">int</span>&nbsp;argc,&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;*argv[])&nbsp;{<br /><span style="color: #008080; ">10</span>&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(argc&nbsp;&lt;&nbsp;2)&nbsp;{<br /><span style="color: #008080; ">11</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,&nbsp;"Usage:&nbsp;jit1&nbsp;&lt;integer&gt;\n");<br /><span style="color: #008080; ">12</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;1;<br /><span style="color: #008080; ">13</span>&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">14</span>&nbsp;&nbsp;<br /><span style="color: #008080; ">15</span>&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;num&nbsp;=&nbsp;atoi(argv[1]);<br /><span style="color: #008080; ">16</span>&nbsp;&nbsp;&nbsp;dasm_State&nbsp;*state;<br /><span style="color: #008080; ">17</span>&nbsp;&nbsp;&nbsp;initjit(&amp;state,&nbsp;actions);<br /><span style="color: #008080; ">18</span>&nbsp;&nbsp;<br /><span style="color: #008080; ">19</span>&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Generate&nbsp;the&nbsp;code.&nbsp;&nbsp;Each&nbsp;line&nbsp;appends&nbsp;to&nbsp;a&nbsp;buffer&nbsp;in<br /></span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;"state",&nbsp;but&nbsp;the&nbsp;code&nbsp;in&nbsp;this&nbsp;buffer&nbsp;is&nbsp;not&nbsp;fully&nbsp;linked<br /></span><span style="color: #008080; ">21</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;yet&nbsp;because&nbsp;labels&nbsp;can&nbsp;be&nbsp;referenced&nbsp;before&nbsp;they&nbsp;are<br /></span><span style="color: #008080; ">22</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;defined.<br /></span><span style="color: #008080; ">23</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">24</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;The&nbsp;run-time&nbsp;value&nbsp;of&nbsp;C&nbsp;variable&nbsp;"num"&nbsp;is&nbsp;substituted<br /></span><span style="color: #008080; ">25</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;into&nbsp;the&nbsp;immediate&nbsp;value&nbsp;of&nbsp;the&nbsp;instruction.</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">26</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;|&nbsp;&nbsp;mov&nbsp;eax,&nbsp;num<br /><span style="color: #008080; ">27</span>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;ret<br /><span style="color: #008080; ">28</span>&nbsp;&nbsp;<br /><span style="color: #008080; ">29</span>&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Link&nbsp;the&nbsp;code&nbsp;and&nbsp;write&nbsp;it&nbsp;to&nbsp;executable&nbsp;memory.</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">30</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;(*fptr)()&nbsp;=&nbsp;jitcode(&amp;state);<br /><span style="color: #008080; ">31</span>&nbsp;&nbsp;<br /><span style="color: #008080; ">32</span>&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Call&nbsp;the&nbsp;JIT-ted&nbsp;function.</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">33</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;ret&nbsp;=&nbsp;fptr();<br /><span style="color: #008080; ">34</span>&nbsp;&nbsp;&nbsp;assert(num&nbsp;==&nbsp;ret);<br /><span style="color: #008080; ">35</span>&nbsp;&nbsp;<br /><span style="color: #008080; ">36</span>&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Free&nbsp;the&nbsp;machine&nbsp;code.</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">37</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;free_jitcode(fptr);<br /><span style="color: #008080; ">38</span>&nbsp;&nbsp;<br /><span style="color: #008080; ">39</span>&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;ret;<br /><span style="color: #008080; ">40</span>&nbsp;}</div><br />预处理之后那就会变成这样子：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">|.arch&nbsp;x64<br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #008000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">|.actionlist&nbsp;actions</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #008000; "></span><span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;actions[4]&nbsp;=&nbsp;{<br /><span style="color: #008080; ">&nbsp;4</span>&nbsp;&nbsp;&nbsp;184,237,195,255<br /><span style="color: #008080; ">&nbsp;5</span>&nbsp;};<br /><span style="color: #008080; ">&nbsp;6</span>&nbsp;&nbsp;<br /><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;[<img src="http://www.cppblog.com/Images/dot.gif" alt="" />]<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #008000; ">&nbsp;<br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #008000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">|&nbsp;&nbsp;mov&nbsp;eax,&nbsp;num<br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #008000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">|&nbsp;&nbsp;ret</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #008000; "></span>dasm_put(Dst,&nbsp;0,&nbsp;num);</div>dasm_put就是把num参数和actions[]一起放入了Dst（#define Dst &amp;state）的制定的内存中，这时候已经是机器码的形式了。<br />下面是对于acitons[]数组内容的解释：<br />184(B8)-- mov eax, [immediate] 指令的第一个字节<br />237 &nbsp; &nbsp; &nbsp; -- 内置的标志DASM_IMM_D, 指明应该放入一个4字节宽度的参数，与上一条指令完成一个MOV<br />195(C3)-- 对应ret指令<br />255 &nbsp; &nbsp; &nbsp; --&nbsp;内置的标志DASM_STOP<br /><br />以上就是最简单的例子，dasm_growpc()是内置的函数，用来增长maxpc, 这样在程序里面就可以方便写出jmp =&gt; label 这样的指令了。<br /><br />由于DynASM的文档很少，幸亏还有几个例子，除了例子唯一能看的就是源码了，所以在用的时候出现问题是很痛苦的。。当时写GMHjit就发现了蛋疼的pre-process period bug，后来绕过去了。<br /><br />源码文件有这么几个<br />-- dynasm.lua<br />-- dynasm_proto.h<br />-- dynasm_*.lua<br />-- dynasm_*.h &nbsp;// * x64 &nbsp;x86 &nbsp;ppc mips arm 等target<br /><br />用起来就是lua dynasm.lua a.dasm &gt; a.h&nbsp;<br /><br />下面就从dynasm.lua开始分析下他的源码<br /><br />入口是parseargs函数，里面给的g_opt参数赋默认的值，一个repeat 中调用parseopt解析参数，opt_map就是option对args的函数映射。<br /><br />函数wline，wcomment，wsync，wdumplines都是对输出的目标文件的操作。<br /><br />真正的主函数是 translate，把input file变成 output file，在readfile中的doline函数是真正的处理过程，里面判断是否是Assembler line之后Emit C code，调用dostmt(aline)。里面继续有map_coreop[*]来处理section macro arch nop_ error_1 include &nbsp;if endif elseif 等关键字，想深入研究的可以自己去看，其中在loadarch中根据arch加载不同的lua库<br /><br />如果arch是x64的话，本质还是require x86<br />来看dasm_x86.lua文件<br /><br /><div>_M.mergemaps这是关键的方法，设置了2个Map的元方法，然后返回，相当于是把方法绑定在table里面传递了出去。处理后文件中关键的actionlist[]数组和Dasm_put(Dst, ...)的输出就是这个lua文件的方法。</div>里面提供了很多dump方法，可以供我们遇到问题时候调试处理过程。<br /><br /><div>action_names就是以后生成的action_list中的内置标志定义，必须与dasm_x86.h中的enum定义一致。</div>表明了代表的参数和长度等信息。<br />这个文件里面所有的函数就是做了一件事，把你的 |... &nbsp;这样子的代码处理成数组输出到目标文件中（我是汇编渣渣，里面貌似支持SSE2、3、4+，看不懂，等到以后看到traced jit的时候再去翻手册把）<br /><br />预处理完成之后，就是#include "dasm_x86.h"，里面有最关键的dasm_State结构体的定义，几乎里面所有的函数都是对外的API，有init,setup,free等等，除去初始化与free之外，有三个步骤是需要出现在你都代码中：<br />1、dasm_put(Dst,...) 这个是自动生成的，不用我们操心，根据actionlist[]和运行时的参数写入到Dst指定的内存（Dst-&gt;section）中.<br />2、dasm_link() 第二个参数是返回的代码长度大小，这个函数把section合并到一起，处理偏移等等。<br />3、dasm_encode() 第二个参数是一个接受encode输出的buffer指针。<br /><br />然后就可以用一个函数指针，比如声明一个 int (*f)(*int), int ret = f(param) 直接运行刚刚生成的机器码了。<br /><br /><br /><br /><br /><br /><a href="http://luajit.org/dynasm.html"><br /></a><img src ="http://www.cppblog.com/pwq1989/aggbug/204508.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/pwq1989/" target="_blank">右席</a> 2013-11-30 12:49 <a href="http://www.cppblog.com/pwq1989/archive/2013/11/30/204508.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（一）初识Luajit</title><link>http://www.cppblog.com/pwq1989/archive/2013/11/28/204487.html</link><dc:creator>右席</dc:creator><author>右席</author><pubDate>Thu, 28 Nov 2013 11:23:00 GMT</pubDate><guid>http://www.cppblog.com/pwq1989/archive/2013/11/28/204487.html</guid><wfw:comment>http://www.cppblog.com/pwq1989/comments/204487.html</wfw:comment><comments>http://www.cppblog.com/pwq1989/archive/2013/11/28/204487.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/pwq1989/comments/commentRss/204487.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/pwq1989/services/trackbacks/204487.html</trackback:ping><description><![CDATA[本人博客地址：<a href="http://www.cppblog.com/pwq1989/">http://www.cppblog.com/pwq1989/</a><br /><br />第一篇对Luajit做一个大概的介绍，我目前也正在慢慢的读通源码中，以后发现了新东西就补充在这里。<br />
<br />
大家可以从官网下载到源码（<a href="http://luajit.org/">http://luajit.org/</a>），也可以从Github（<a href="https://github.com/LuaDist/luajit">https://github.com/LuaDist/luajit</a>）down下来，顺便还可以看下commit记录。<br />
<br />
大家对着luajit的wiki结合源码看的话会更好些，因为。。文档太特么少了！！<br />
<br />
目录结构：<br />
-- src<br />
&nbsp; &nbsp; -- host<br />
&nbsp; &nbsp; -- jit<br />
&nbsp; &nbsp; *.c<br />
&nbsp; &nbsp; *.h<br />
&nbsp; &nbsp; *.dasc<br />
等等，别的不是很重要<br />
<br />
最开始我是从main函数开始看的，然后。。碰了一鼻子灰，后来研究下他的makefile，发现他是这样子的编译的，贴一下关键的msvcbuild.bat的代码（这个更容易看懂）<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080; ">&nbsp;1</span>&nbsp;:X64<br />
<span style="color: #008080; ">&nbsp;2</span>&nbsp;minilua&nbsp;%DASM%&nbsp;-LN&nbsp;%DASMFLAGS%&nbsp;-o&nbsp;host\buildvm_arch.h&nbsp;vm_x86.dasc<br />
<span style="color: #008080; ">&nbsp;3</span>&nbsp;@if&nbsp;errorlevel&nbsp;1&nbsp;<span style="color: #0000FF; ">goto</span>&nbsp;:BAD<br />
<span style="color: #008080; ">&nbsp;4</span>&nbsp;<br />
<span style="color: #008080; ">&nbsp;5</span>&nbsp;%LJCOMPILE%&nbsp;/I&nbsp;"."&nbsp;/I&nbsp;%DASMDIR%&nbsp;host\buildvm*.c<br />
<span style="color: #008080; ">&nbsp;6</span>&nbsp;@if&nbsp;errorlevel&nbsp;1&nbsp;<span style="color: #0000FF; ">goto</span>&nbsp;:BAD<br />
<span style="color: #008080; ">&nbsp;7</span>&nbsp;%LJLINK%&nbsp;/<span style="color: #0000FF; ">out</span>:buildvm.exe&nbsp;buildvm*.obj<br />
<span style="color: #008080; ">&nbsp;8</span>&nbsp;@if&nbsp;errorlevel&nbsp;1&nbsp;<span style="color: #0000FF; ">goto</span>&nbsp;:BAD<br />
<span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;exist&nbsp;buildvm.exe.manifest^<br />
<span style="color: #008080; ">10</span>&nbsp;&nbsp;&nbsp;%LJMT%&nbsp;-manifest&nbsp;buildvm.exe.manifest&nbsp;-outputresource:buildvm.exe<br />
<span style="color: #008080; ">11</span>&nbsp;<br />
<span style="color: #008080; ">12</span>&nbsp;buildvm&nbsp;-m&nbsp;peobj&nbsp;-o&nbsp;lj_vm.obj<br />
<span style="color: #008080; ">13</span>&nbsp;@if&nbsp;errorlevel&nbsp;1&nbsp;<span style="color: #0000FF; ">goto</span>&nbsp;:BAD<br />
<span style="color: #008080; ">14</span>&nbsp;buildvm&nbsp;-m&nbsp;bcdef&nbsp;-o&nbsp;lj_bcdef.h&nbsp;%ALL_LIB%<br />
<span style="color: #008080; ">15</span>&nbsp;@if&nbsp;errorlevel&nbsp;1&nbsp;<span style="color: #0000FF; ">goto</span>&nbsp;:BAD<br />
<span style="color: #008080; ">16</span>&nbsp;buildvm&nbsp;-m&nbsp;ffdef&nbsp;-o&nbsp;lj_ffdef.h&nbsp;%ALL_LIB%<br />
<span style="color: #008080; ">17</span>&nbsp;@if&nbsp;errorlevel&nbsp;1&nbsp;<span style="color: #0000FF; ">goto</span>&nbsp;:BAD<br />
<span style="color: #008080; ">18</span>&nbsp;buildvm&nbsp;-m&nbsp;libdef&nbsp;-o&nbsp;lj_libdef.h&nbsp;%ALL_LIB%<br />
<span style="color: #008080; ">19</span>&nbsp;@if&nbsp;errorlevel&nbsp;1&nbsp;<span style="color: #0000FF; ">goto</span>&nbsp;:BAD<br />
<span style="color: #008080; ">20</span>&nbsp;buildvm&nbsp;-m&nbsp;recdef&nbsp;-o&nbsp;lj_recdef.h&nbsp;%ALL_LIB%<br />
<span style="color: #008080; ">21</span>&nbsp;@if&nbsp;errorlevel&nbsp;1&nbsp;<span style="color: #0000FF; ">goto</span>&nbsp;:BAD<br />
<span style="color: #008080; ">22</span>&nbsp;buildvm&nbsp;-m&nbsp;vmdef&nbsp;-o&nbsp;jit\vmdef.lua&nbsp;%ALL_LIB%<br />
<span style="color: #008080; ">23</span>&nbsp;@if&nbsp;errorlevel&nbsp;1&nbsp;<span style="color: #0000FF; ">goto</span>&nbsp;:BAD<br />
<span style="color: #008080; ">24</span>&nbsp;buildvm&nbsp;-m&nbsp;folddef&nbsp;-o&nbsp;lj_folddef.h&nbsp;lj_opt_fold.c<br />
<span style="color: #008080; ">25</span>&nbsp;@if&nbsp;errorlevel&nbsp;1&nbsp;<span style="color: #0000FF; ">goto</span>&nbsp;:BAD</div>
<br />
先创建了一个buildvm.exe的中间工具，来自动生成代码，分别生成了<span style="font-size: 13.333333015441895px; background-color: #eeeeee;">lj_vm.obj，</span><span style="font-size: 13.333333015441895px; background-color: #eeeeee;">lj_bcdef.h，</span><span style="font-size: 13.333333015441895px; background-color: #eeeeee;">lj_ffdef.h ，</span><span style="font-size: 13.333333015441895px; background-color: #eeeeee;">lj_recdef.h ，</span><span style="font-size: 13.333333015441895px; background-color: #eeeeee;">jit\vmdef.lua，</span><span style="font-size: 13.333333015441895px; background-color: #eeeeee;">lj_folddef.h， lj_libdef.h<br />
<br />
</span>其中lv_vm.obj是依赖于<span style="font-size: 13.333333015441895px; background-color: #eeeeee;">host\buildvm_arch.h</span>的，这个是用DynASM预处理vm_x86.dasc生成的，这个工具的具体分析会在下一篇博客提及。<br />
<br />
先来看下上面自动生成的代码：<br />
lj_bcdef.h:<br />
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080; ">&nbsp;1</span>&nbsp;LJ_DATADEF&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;uint16_t&nbsp;lj_bc_ofs[]&nbsp;=&nbsp;{<br />
<span style="color: #008080; ">&nbsp;2</span>&nbsp;0,<br />
<span style="color: #008080; ">&nbsp;3</span>&nbsp;71,<br />
<span style="color: #008080; ">&nbsp;4</span>&nbsp;142,<br />
<span style="color: #008080; ">&nbsp;5</span>&nbsp;213,<br />
<span style="color: #008080; ">&nbsp;6</span>&nbsp;284,<br />
<span style="color: #008080; ">&nbsp;7</span>&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><br />
<span style="color: #008080; ">&nbsp;8</span>&nbsp;};<br />
<span style="color: #008080; ">&nbsp;9</span>&nbsp;<br />
<span style="color: #008080; ">10</span>&nbsp;LJ_DATADEF&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;uint16_t&nbsp;lj_bc_mode[]&nbsp;=&nbsp;{<br />
<span style="color: #008080; ">11</span>&nbsp;BCDEF(BCMODE)<br />
<span style="color: #008080; ">12</span>&nbsp;BCMODE_FF,<br />
<span style="color: #008080; ">13</span>&nbsp;BCMODE_FF,<br />
<span style="color: #008080; ">14</span>&nbsp;BCMODE_FF,<br />
<span style="color: #008080; ">15</span>&nbsp;BCMODE_FF,<br />
<span style="color: #008080; ">16</span>&nbsp;BCMODE_FF,<br />
<span style="color: #008080; ">17</span>&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><br />
<span style="color: #008080; ">18</span>&nbsp;};</div>
<br />lj_bc_ofs[]可能是bc在vm代码段中的偏移量（这个我还没深入进去调试一下），vm的一部分是用DynASM直接撸汇编撸出来的，wiki中也有提到下一步jit化的opcode等等。<br /><div>lj_bc_mode[]的用来根据压缩后的bytecode构造，分离出操作数，第一行的两个宏的定义是<br /><div>#define BCMODE(name, ma, mb, mc, mm) \</div><div>&nbsp; (BCM##ma|(BCM##mb&lt;&lt;3)|(BCM##mc&lt;&lt;7)|(MM_##mm&lt;&lt;11)),</div><div>#define BCMODE_FF<span style="white-space:pre">	</span>0<br /><br /><div>#define BCDEF(_) \</div><div>&nbsp; /* Comparison ops. ORDER OPR. */ \</div><div>&nbsp; _(ISLT,<span style="white-space:pre">	</span>var,<span style="white-space:pre">	</span>___,<span style="white-space:pre">	</span>var,<span style="white-space:pre">	</span>lt) \</div><div>&nbsp; _(ISGE,<span style="white-space:pre">	</span>var,<span style="white-space:pre">	</span>___,<span style="white-space:pre">	</span>var,<span style="white-space:pre">	</span>lt) \</div><div>&nbsp; _(ISLE,<span style="white-space:pre">	</span>var,<span style="white-space:pre">	</span>___,<span style="white-space:pre">	</span>var,<span style="white-space:pre">	</span>le) \</div><div>&nbsp; _(ISGT,<span style="white-space:pre">	</span>var,<span style="white-space:pre">	</span>___,<span style="white-space:pre">	</span>var,<span style="white-space:pre">	</span>le) \<br />...<br />总之就是充斥着各种拼接起来的宏<br /><br />lj_ffdef.h:<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">1</span>&nbsp;FFDEF(assert)<br /><span style="color: #008080; ">2</span>&nbsp;FFDEF(type)<br /><span style="color: #008080; ">3</span>&nbsp;FFDEF(next)<br /><span style="color: #008080; ">4</span>&nbsp;FFDEF(pairs)<br /><span style="color: #008080; ">5</span>&nbsp;FFDEF(ipairs_aux)<br /><span style="color: #008080; ">6</span>&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /></div>FFDEF的定义是在<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">1</span>&nbsp;<span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;Fast&nbsp;function&nbsp;ID.&nbsp;</span><span style="color: #008000; ">*/</span><br /><span style="color: #008080; ">2</span>&nbsp;typedef&nbsp;<span style="color: #0000FF; ">enum</span>&nbsp;{<br /><span style="color: #008080; ">3</span>&nbsp;&nbsp;&nbsp;FF_LUA_&nbsp;=&nbsp;FF_LUA,&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;Lua&nbsp;function&nbsp;(must&nbsp;be&nbsp;0).&nbsp;</span><span style="color: #008000; ">*/</span><br /><span style="color: #008080; ">4</span>&nbsp;&nbsp;&nbsp;FF_C_&nbsp;=&nbsp;FF_C,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;Regular&nbsp;C&nbsp;function&nbsp;(must&nbsp;be&nbsp;1).&nbsp;</span><span style="color: #008000; ">*/</span><br /><span style="color: #008080; ">5</span>&nbsp;<span style="color: #0000FF; ">#define</span>&nbsp;FFDEF(name)&nbsp;&nbsp;&nbsp;&nbsp;FF_##name,<br /><span style="color: #008080; ">6</span>&nbsp;#include&nbsp;"lj_ffdef.h"<br /><span style="color: #008080; ">7</span>&nbsp;&nbsp;&nbsp;FF__MAX<br /><span style="color: #008080; ">8</span>&nbsp;}&nbsp;FastFunc;</div>差不多就是用FF_##name把上面的名字拼接起来，然后生成在enum里面，这样就能当成是数字，在数组中迅速找到入口了<br /><br />vmdef.lua:<br />这个里面内容就不贴了，包括bcname,irname,irfpm,irfield,ircall 的定义，在jit文件夹下面，用于调试等，比如在dump.lua中就有用到<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->local&nbsp;jit&nbsp;=&nbsp;require("jit")<br />assert(jit.version_num&nbsp;==&nbsp;20002,&nbsp;"LuaJIT&nbsp;core/library&nbsp;version&nbsp;mismatch")<br />local&nbsp;jutil&nbsp;=&nbsp;require("jit.util")<br />local&nbsp;vmdef&nbsp;=&nbsp;require("jit.vmdef") &nbsp;// &#8592;&nbsp;&#8592;&nbsp;&#8592;&nbsp;&#8592;</div><br />当你用luajit -jdump的时候，就是调用的lua的jit库里面的lua函数<br /><br />lj_recdef.h:<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;uint16_t&nbsp;recff_idmap[]&nbsp;=&nbsp;{<br /><span style="color: #008080; ">&nbsp;2</span>&nbsp;0,<br /><span style="color: #008080; ">&nbsp;3</span>&nbsp;0x0100,<br /><span style="color: #008080; ">&nbsp;4</span>&nbsp;0x0200,<br /><span style="color: #008080; ">&nbsp;5</span>&nbsp;0x0300,<br /><span style="color: #008080; ">&nbsp;6</span>&nbsp;0,<br /><span style="color: #008080; ">&nbsp;7</span>&nbsp;0,<br /><span style="color: #008080; ">&nbsp;8</span>&nbsp;0x0400,<br /><span style="color: #008080; ">&nbsp;9</span>&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><br /><span style="color: #008080; ">10</span>&nbsp;};<br /><span style="color: #008080; ">11</span>&nbsp;<br /><span style="color: #008080; ">12</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;RecordFunc&nbsp;recff_func[]&nbsp;=&nbsp;{<br /><span style="color: #008080; ">13</span>&nbsp;recff_nyi,<br /><span style="color: #008080; ">14</span>&nbsp;recff_c,<br /><span style="color: #008080; ">15</span>&nbsp;recff_assert,<br /><span style="color: #008080; ">16</span>&nbsp;recff_type,<br /><span style="color: #008080; ">17</span>&nbsp;recff_ipairs_aux,<br /><span style="color: #008080; ">18</span>&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><br /><span style="color: #008080; ">19</span>&nbsp;};</div>其中recff_func[]是被注册的被traced jit 跟踪的函数，具体可是在lj_ffrecord.c里面看到<br />recff_idmap[]被用在lj_ffrecord_func这个函数中，有一个关键的数据结构RecordFFData，用来记录在trace过程中被调用函数的参数和返回值个数，和一些辅助数据，opcode，literal等等。通过recff_idmap[]保存的值来区分函数（待仔细研究）<br /><br /><br />lj_folddef.h:<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;FoldFunc&nbsp;fold_func[]&nbsp;=&nbsp;{<br /><span style="color: #008080; ">&nbsp;2</span>&nbsp;&nbsp;&nbsp;fold_kfold_numarith,<br /><span style="color: #008080; ">&nbsp;3</span>&nbsp;&nbsp;&nbsp;fold_kfold_ldexp,<br /><span style="color: #008080; ">&nbsp;4</span>&nbsp;&nbsp;&nbsp;fold_kfold_fpmath,<br /><span style="color: #008080; ">&nbsp;5</span>&nbsp;&nbsp;&nbsp;fold_kfold_numpow,<br /><span style="color: #008080; ">&nbsp;6</span>&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><br /><span style="color: #008080; ">&nbsp;7</span>&nbsp;};<br /><span style="color: #008080; ">&nbsp;8</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;uint32_t&nbsp;fold_hash[916]&nbsp;=&nbsp;{<br /><span style="color: #008080; ">10</span>&nbsp;0xffffffff,<br /><span style="color: #008080; ">11</span>&nbsp;0xffffffff,<br /><span style="color: #008080; ">12</span>&nbsp;0x5b4c8016,<br /><span style="color: #008080; ">13</span>&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><br /><span style="color: #008080; ">14</span>&nbsp;};</div>用在FOLD optimization中，见lj_opt_fold.c，主要在<br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">1</span>&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;((fh&nbsp;&amp;&nbsp;0xffffff)&nbsp;==&nbsp;k&nbsp;||&nbsp;(fh&nbsp;=&nbsp;fold_hash[h+1],&nbsp;(fh&nbsp;&amp;&nbsp;0xffffff)&nbsp;==&nbsp;k))&nbsp;{<br /><span style="color: #008080; ">2</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">ref</span>&nbsp;=&nbsp;(IRRef)tref_ref(fold_func[fh&nbsp;&gt;&gt;&nbsp;24](J));<br /><span style="color: #008080; ">3</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(<span style="color: #0000FF; ">ref</span>&nbsp;!=&nbsp;NEXTFOLD)<br /><span style="color: #008080; ">4</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">break</span>;<br /><span style="color: #008080; ">5</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div>是根据数组偏移获取函数，直接执行。<br />（这个Optimation略复杂，以后的博文中再说）<br /><br />----------------------------------------分割线-------------------------------------------<br /><br />以上就是buildvm生成代码，在很多.c的文件中，他加入了一些无意义的MARCO，目的是为了能被buildvm识别出<br /><br />下面说说src根目录下面的文件：<br /><br />lauxlib.h：<br />用户开发扩展和与C交互的时候的头文件<br /><br />lib_*.h /.c:<br />顾名思义，就是利用LuaAPI写的内部标准库，会在方法上表明是否会被trace ( LJLIB_REC(.) )。<br /><br />ljamalg.c:<br />文件的合并<br /><br />lj_alloc.h /.c:<br />定制的Memory Allocator<br /><br />lj_api.c:<br /><div>Public Lua/C API.</div><br />lj_arch.h:<br /><div>Target architecture selection<br /><br />lj_jit.h:<br />jit编译器里面数据结构的定义</div><br />lj_asm.h/ .c &nbsp;lj_asm_*.c lj_emit_*.h lj_target_*.h/.c :<br />将IR编译成Machine Code，关键的数据结构ASMState，线性扫描的O(n2)分配算法<br /><br />lj_bc.h/ .c：<br />Luajit字节码的定义和内存布局<br /><br />lj_bcdump.c lj_bcread.c &nbsp;lj_bcwrite.c:<br />围绕着字节码的操作<br /><br />lj_carith.c:<br /><div>C实现的一些数字运算</div><br />lj_ccall.h/ .c &nbsp;lj_ccallback.h / .c :<br />FFI C语言函数调用和回调绑定<br /><br />lj_debug.h/.c :<br />调试与自省用<br /><br />lj_def.h:<br />这个很重要，重要的类型和一些宏定义在这里<br /><br />lj_c*.h/ .c:<br />和C语言先关的，比如类型转化，char管理，数据管理<br /><br />lj_frame.h:<br />Luajit的栈帧管理<br /><br />lj_func.h/.c:<br />Function handle和闭包有关的upvalue数据结构<br /><br />lj_gc.h/.c:<br />GC相关，GC可以看下luajit的wiki，里面涉及不少增量式GC的paper和作者的看法<br /><br />lj_gdbjit.h/.c :<br />对gdb的支持<br /><br />lj_ir*.h/.c:<br />SSA，IR相关（这个和bytecode还是不一样的）操作和优化<br /><br />lj_lex.h/.c &nbsp;lj_parse.h/.c:<br />lexer和parser<br /><br />lj_mcode.h/.c:<br />Machine Code管理<br /><br />lj_opt_*.h:<br />各种bytecode层面上的优化<br /><br />lj_snap.h/.c:<br />快照支持<br /><br />lj_state.h/.c:<br />LuaState和Stack的操作<br /><br />lj_str*.h/.c &nbsp;lj_tab.h/.c:<br />原生类型string和table操作<br /><br />lj_udata.h/.c:<br />类型user data的操作<br /><br />lj_vm.h/.c &nbsp;lj_vmevent.h/.c:<br />vm的API和事件注册（lj_vmevent_send）<br /><br />lj_vmmath.h/.c：<br />对vm支持的math库<br /><br />lua.h:<br />luaState等基本的Lua结构<br /><br />lualib.h:<br />和Lua一样，标准库的API<br /><br />luajit.h:<br />luajit 的public API<br /><br />vm_*.dasc:<br />编译期被DynASM预处理的源文件，下一篇讲DynASM时候介绍dasc文件<br /><br />wmain.c:<br />windows下面的main入口<br /><br />和Trace相关的：<br />lj_crecord.h/.c &nbsp;： C操作的trace record<br />lj_dispatch.h/.c : &nbsp;指令分发，调用ASMFuction，处理指令前的hook和记录trace用的hot count，有一个重要的数据结构 GG_State<br />lj_ff*.h/.c: 上面讲lj_ffdef.h的时候提过，trace的时候 记录Fast Function的调用记数<br />lj_trace.h/.c: trace的具体过程<br />lj_traceerr.h : trace error</div></div></div><img src ="http://www.cppblog.com/pwq1989/aggbug/204487.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/pwq1989/" target="_blank">右席</a> 2013-11-28 19:23 <a href="http://www.cppblog.com/pwq1989/archive/2013/11/28/204487.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>