??xml version="1.0" encoding="utf-8" standalone="yes"?>国产成人久久精品激情,精品久久777,久久精品成人免费网站http://m.shnenglu.com/pwq1989/category/20748.htmlzh-cnMon, 22 Dec 2014 20:06:39 GMTMon, 22 Dec 2014 20:06:39 GMT60自撸web框?dodolu(Znginx lua) + lua debuggerhttp://m.shnenglu.com/pwq1989/archive/2014/12/22/209273.html叛_叛_Mon, 22 Dec 2014 10:22:00 GMThttp://m.shnenglu.com/pwq1989/archive/2014/12/22/209273.htmlhttp://m.shnenglu.com/pwq1989/comments/209273.htmlhttp://m.shnenglu.com/pwq1989/archive/2014/12/22/209273.html#Feedback0http://m.shnenglu.com/pwq1989/comments/commentRss/209273.htmlhttp://m.shnenglu.com/pwq1989/services/trackbacks/209273.html背景

前段旉目需要一个点?yn)L务,大致是要Ҏ(gu)用户h的url?qing)数据库中的规则Q匹配出一个结果ƈ记录日志。最开始是一个很的需求,l果业务来复杂,业务逻辑中经常要处理header头和一些其他的信息Q导致代码越来越混ؕ。在一期结束之后,抽时间把q段旉的工作抽象出?jin)一个轻量框架Q只做了(jin)适量的封装,加入?jin)代码生成的模块Q可以帮助开发者迅速做Z个可用的web服务?/p>

介绍

dodolu框架地址(Github)?/p>

该框架只做了(jin)最化的封装,几乎没有性能损失Qƈ提供?jin)根据配|文?meta.lua)Q自动生成route模块Qnginx.conf配置Qlogger模块的功能,减轻?jin)开发工作量Q避免重复手写大量易错的配置或字W串变量Q有助于多h开发统一风格?/p>

详情Github的README

功能

包括三个部分Q一个是web框架Q一个是代码自动生成模块Q一个是改出的luaq程调试?/a>?/p>

web框架部分

只有1k行以下的代码Q集成了(jin)resty.template、resty.cookie、UUID生成{第三方模块。提供request、response、context、util{库方便开发h员用?/p>

代码自动生成部分

可自动生?

  1. 路由配置
  2. 日志记录模块
  3. nginx.conf

主要目的在于解决nginx配置与lua代码的分问?在日志记录中ؓ(f)严重)?/p>

开发h员新建应用步骤:(x)在App文g夹下Q新建lua文gQ然后填?code>do_get()Ҏ(gu)卛_处理相应的gethQ所有配|在meta/meta.lua里面?/p>

一个记录日志ƈq回1x1gif的例子:(x)

-- q个文g下面存放你的业务逻辑
-- q个文g下面存放你的业务逻辑
local app = {} function app.do_get(ctx)      local response = ctx.response     local request = ctx.request     local cookie = ctx.cookie
    response:set_content_type("text/html")     local url = request.uri     -- do some process
    ------------- write log ---------------     -- my_log 日志模块是根据meta.lua自动生成?     local logger = ctx.get_logger('my_log')       local log_data = { a = "xxx"}     logger.write(log_data, other_params)
    ------------- return empty gif -------     response:empty_gif()     response:close() end
function app.do_post(ctx) end function app.do_put(ctx) end function app.do_delete(ctx) end
return app

luaq程调试?/h3>

文详细?a >q里Q这里只演示下用法:(x)
sh debug.shQ然后运行用L(fng)序,成功?br />

Lua Remote Debugger
Run the program you wish to debug
Paused at file a.lua
Type 'help' for commands

下一? n

n
Paused at file a.lua line 8
8: print("Start")


查看源码  l

> l  
source file: a.lua
2:   
3:   local tab = {
4:       foo = 1,
5:       bar = 2
6:   }
7:   
8:>> print("Start")
9:   
10:  local bb = require "b"
11:  bb.foo()
12:   
13:  for i = 1, 10 do
14:      print("Loop")


讄断点   b <file>:<line>   查看    listb

> b a.lua:11
> listb 
a.lua: 11

查看局部变? local

> local {         ["tab"] = {                 {                         ["bar"] = 2,                         ["foo"] = 1,                 },                 "table: 0x2589ee0",         }, }

查看变量   p tab

> p tab
{
        ["bar"] = 2,
        ["foo"] = 1,
}
l箋执行Q直到断? r
> r Paused at file a.lua line 11




叛_ 2014-12-22 18:22 发表评论
]]>Q二QLuajit中的好轮子DynASMhttp://m.shnenglu.com/pwq1989/archive/2013/11/30/204508.html叛_叛_Sat, 30 Nov 2013 04:49:00 GMThttp://m.shnenglu.com/pwq1989/archive/2013/11/30/204508.htmlhttp://m.shnenglu.com/pwq1989/comments/204508.htmlhttp://m.shnenglu.com/pwq1989/archive/2013/11/30/204508.html#Feedback0http://m.shnenglu.com/pwq1989/comments/commentRss/204508.htmlhttp://m.shnenglu.com/pwq1989/services/trackbacks/204508.htmlhttp://m.shnenglu.com/pwq1989/

上一对Luajit的代码结构和~译q程做了(jin)单的描述Q这一就讲一下buildvm在第一步预处理dasc文g的过E和DynASMq个轮子?br />
官方q接Q?a >http://luajit.org/dynasm.html

是ؓ(f)?jin)让你更优雅的C里面撸汇~的一个工P我记得以前看q一个老外的blogҎ(gu)q同样功能的jit code generator的语法,Luajit的作者显然品位还是很高的?br />
我们先来看看如果不用工具生生撸代码的话?x)发生什么?br />1、你往一D内存里面写0xB8,0x00,0x01....
2、你在文仉定义好多labelQ写个copy section的宏往内存里面复制Q你q不能确定里面到底是什么。(哦。。这个的术语叫Threaded。。。)(j)

然后再对比下AsmJit或?a title="Xbyak" target="_blank">Xbyak的例子看看(他们的功能差不多Q,DynASMq提供了(jin).marco实现Q就?x)发现语法真是sweeeet~

q是我写着玩的一个草泥马语jit解释器(https://github.com/pwq1989/GMHjitQ语法真是清新自然啊Q如果你想看工业U的应用Q可以看看Google的Haberman写的protobuf的upb库,里面用DynASMq行?jin)jitQ号U快?jin)多多(不去考证?jin)?j)Q或者是agentzh写的sregex正则库,也是用它做了(jin)jit。一般来说DSL配上jit的话一定会(x)快很多就错不?jin)?jin)?br />
下面l一个DynASM的DemoE序Q摘抄自q个blogQ?br />
 1 // DynASM directives.
 2 |.arch x64
 3 |.actionlist actions
 4  
 5 // This define affects "|" DynASM lines.  "Dst" must
 6 // resolve to a dasm_State** that points to a dasm_State*.
 7 #define Dst &state
 8  
 9 int main(int argc, char *argv[]) {
10   if (argc < 2) {
11     fprintf(stderr, "Usage: jit1 <integer>\n");
12     return 1;
13   }
14  
15   int num = atoi(argv[1]);
16   dasm_State *state;
17   initjit(&state, actions);
18  
19   // Generate the code.  Each line appends to a buffer in
20   // "state", but the code in this buffer is not fully linked
21   // yet because labels can be referenced before they are
22   // defined.
23   //
24   // The run-time value of C variable "num" is substituted
25   // into the immediate value of the instruction.
26   |  mov eax, num
27   |  ret
28  
29   // Link the code and write it to executable memory.
30   int (*fptr)() = jitcode(&state);
31  
32   // Call the JIT-ted function.
33   int ret = fptr();
34   assert(num == ret);
35  
36   // Free the machine code.
37   free_jitcode(fptr);
38  
39   return ret;
40 }

预处理之后那׃(x)变成q样子:(x)
 1 //|.arch x64
 2 //|.actionlist actions
 3 static const unsigned char actions[4] = {
 4   184,237,195,255
 5 };
 6  
 7 // []
 8  
 9 //|  mov eax, num
10 //|  ret
11 dasm_put(Dst, 0, num);
dasm_put是把num参数和actions[]一h入了(jin)DstQ?define Dst &stateQ的制定的内存中Q这时候已l是机器码的形式?jin)?br />下面是对于acitons[]数组内容的解释:(x)
184(B8)-- mov eax, [immediate] 指o(h)的第一个字?br />237       -- 内置的标志DASM_IMM_D, 指明应该攑օ一?字节宽度的参敎ͼ与上一条指令完成一个MOV
195(C3)-- 对应ret指o(h)
255       -- 内置的标志DASM_STOP

以上是最单的例子Qdasm_growpc()是内|的函数Q用来增长maxpc, q样在程序里面就可以方便写出jmp => label q样的指令了(jin)?br />
׃DynASM的文很,q怺q有几个例子Q除?jin)例子唯一能看的就是源码了(jin)Q所以在用的时候出现问题是很痛苦的。。当时写GMHjit发C(jin)蛋疼的pre-process period bugQ后来绕q去?jin)?br />
源码文g有这么几?br />-- dynasm.lua
-- dynasm_proto.h
-- dynasm_*.lua
-- dynasm_*.h  // * x64  x86  ppc mips arm {target

用v来就是lua dynasm.lua a.dasm > a.h 

下面׃dynasm.lua开始分析下他的源码

入口是parseargs函数Q里面给的g_opt参数赋默认的|一个repeat 中调用parseopt解析参数Qopt_map是option对args的函数映?br />
函数wlineQwcommentQwsyncQwdumplines都是对输出的目标文g的操作?br />
真正的主函数?translateQ把input file变成 output fileQ在readfile中的doline函数是真正的处理q程Q里面判断是否是Assembler line之后Emit C codeQ调用dostmt(aline)。里面l有map_coreop[*]来处理section macro arch nop_ error_1 include  if endif elseif {关键字Q想深入研究的可以自己去看,其中在loadarch中根据a(chn)rch加蝲不同的lua?br />
如果arch是x64的话Q本质还是require x86
来看dasm_x86.lua文g

_M.mergemapsq是关键的方法,讄?个Map的元Ҏ(gu)Q然后返回,相当于是把方法绑定在table里面传递了(jin)出去。处理后文g中关键的actionlist[]数组和Dasm_put(Dst, ...)的输出就是这个lua文g的方法?/div>里面提供?jin)很多dumpҎ(gu)Q可以供我们遇到问题时候调试处理过E?br />
action_names是以后生成的action_list中的内置标志定义Q必Mdasm_x86.h中的enum定义一致?/div>表明?jin)代表的参数和长度等信息?br />q个文g里面所有的函数是做了(jin)一件事Q把你的 |...  q样子的代码处理成数l输出到目标文g中(我是汇编渣渣Q里面貌似支持SSE2??+Q看不懂Q等C后看到traced jit的时候再ȝ手册把)(j)

预处理完成之后,是#include "dasm_x86.h"Q里面有最关键的dasm_Statel构体的定义Q几乎里面所有的函数都是对外的APIQ有init,setup,free{等Q除d始化与free之外Q有三个步骤是需要出现在你都代码中:(x)
1、dasm_put(Dst,...) q个是自动生成的Q不用我们操?j),?gu)a(chn)ctionlist[]和运行时的参数写入到Dst指定的内存(Dst->sectionQ中.
2、dasm_link() W二个参数是q回的代码长度大,q个函数把section合ƈCP处理偏移{等?br />3、dasm_encode() W二个参数是一个接受encode输出的buffer指针?br />
然后可以用一个函数指针,比如声明一?int (*f)(*int), int ret = f(param) 直接q行刚刚生成的机器码?jin)?br />







叛_ 2013-11-30 12:49 发表评论
]]>Q一Q初识Luajithttp://m.shnenglu.com/pwq1989/archive/2013/11/28/204487.html叛_叛_Thu, 28 Nov 2013 11:23:00 GMThttp://m.shnenglu.com/pwq1989/archive/2013/11/28/204487.htmlhttp://m.shnenglu.com/pwq1989/comments/204487.htmlhttp://m.shnenglu.com/pwq1989/archive/2013/11/28/204487.html#Feedback2http://m.shnenglu.com/pwq1989/comments/commentRss/204487.htmlhttp://m.shnenglu.com/pwq1989/services/trackbacks/204487.htmlhttp://m.shnenglu.com/pwq1989/

W一对Luajit做一个大概的介绍Q我目前也正在慢慢的读通源码中Q以后发C(jin)C西就补充在这里?br />
大家可以从官|下载到源码Q?a >http://luajit.org/Q,也可以从GithubQ?a >https://github.com/LuaDist/luajitQdown下来Q顺便还可以看下commit记录?br />
大家对着luajit的wikil合源码看的话会(x)更好些,因ؓ(f)。。文档太特么了(jin)Q!

目录l构Q?br /> -- src
    -- host
    -- jit
    *.c
    *.h
    *.dasc
{等Q别的不是很重要

最开始我是从main函数开始看的,然后。。碰?jin)一d灎ͼ后来研究下他的makefileQ发C是这样子的编译的Q脓(chung)一下关键的msvcbuild.bat的代码(q个更容易看懂)(j)
 1 :X64
 2 minilua %DASM% -LN %DASMFLAGS% -o host\buildvm_arch.h vm_x86.dasc
 3 @if errorlevel 1 goto :BAD
 4 
 5 %LJCOMPILE% /I "." /I %DASMDIR% host\buildvm*.c
 6 @if errorlevel 1 goto :BAD
 7 %LJLINK% /out:buildvm.exe buildvm*.obj
 8 @if errorlevel 1 goto :BAD
 9 if exist buildvm.exe.manifest^
10   %LJMT% -manifest buildvm.exe.manifest -outputresource:buildvm.exe
11 
12 buildvm -m peobj -o lj_vm.obj
13 @if errorlevel 1 goto :BAD
14 buildvm -m bcdef -o lj_bcdef.h %ALL_LIB%
15 @if errorlevel 1 goto :BAD
16 buildvm -m ffdef -o lj_ffdef.h %ALL_LIB%
17 @if errorlevel 1 goto :BAD
18 buildvm -m libdef -o lj_libdef.h %ALL_LIB%
19 @if errorlevel 1 goto :BAD
20 buildvm -m recdef -o lj_recdef.h %ALL_LIB%
21 @if errorlevel 1 goto :BAD
22 buildvm -m vmdef -o jit\vmdef.lua %ALL_LIB%
23 @if errorlevel 1 goto :BAD
24 buildvm -m folddef -o lj_folddef.h lj_opt_fold.c
25 @if errorlevel 1 goto :BAD

先创Z(jin)一个buildvm.exe的中间工P来自动生成代码,分别生成?span style="font-size: 13.333333015441895px; background-color: #eeeeee;">lj_vm.objQ?/span>lj_bcdef.hQ?/span>lj_ffdef.h Q?/span>lj_recdef.h Q?/span>jit\vmdef.luaQ?/span>lj_folddef.hQ?lj_libdef.h

其中lv_vm.obj是依赖于host\buildvm_arch.h的,q个是用DynASM预处理vm_x86.dasc生成的,q个工具的具体分析会(x)在下一博客提?qing)?br />
先来看下上面自动生成的代码:(x)
lj_bcdef.h:
 1 LJ_DATADEF const uint16_t lj_bc_ofs[] = {
 2 0,
 3 71,
 4 142,
 5 213,
 6 284,
 7 
 8 };
 9 
10 LJ_DATADEF const uint16_t lj_bc_mode[] = {
11 BCDEF(BCMODE)
12 BCMODE_FF,
13 BCMODE_FF,
14 BCMODE_FF,
15 BCMODE_FF,
16 BCMODE_FF,
17 
18 };

lj_bc_ofs[]可能是bc在vm代码D中的偏U量Q这个我q没深入q去调试一下)(j)Qvm的一部分是用DynASM直接撸汇~撸出来的,wiki中也有提C一步jit化的opcode{等?br />
lj_bc_mode[]的用来根据压~后的bytecode构造,分离出操作数Q第一行的两个宏的定义?br />
#define BCMODE(name, ma, mb, mc, mm) \
  (BCM##ma|(BCM##mb<<3)|(BCM##mc<<7)|(MM_##mm<<11)),
#define BCMODE_FF 0

#define BCDEF(_) \
  /* Comparison ops. ORDER OPR. */ \
  _(ISLT, var, ___, var, lt) \
  _(ISGE, var, ___, var, lt) \
  _(ISLE, var, ___, var, le) \
  _(ISGT, var, ___, var, le) \
...
M是充斥着各种拼接h的宏

lj_ffdef.h:
1 FFDEF(assert)
2 FFDEF(type)
3 FFDEF(next)
4 FFDEF(pairs)
5 FFDEF(ipairs_aux)
6 
FFDEF的定义是?br />
1 /* Fast function ID. */
2 typedef enum {
3   FF_LUA_ = FF_LUA,    /* Lua function (must be 0). */
4   FF_C_ = FF_C,        /* Regular C function (must be 1). */
5 #define FFDEF(name)    FF_##name,
6 #include "lj_ffdef.h"
7   FF__MAX
8 } FastFunc;
差不多就是用FF_##name把上面的名字拼接hQ然后生成在enum里面Q这样就能当成是数字Q在数组中迅速找到入口了(jin)

vmdef.lua:
q个里面内容׃贴了(jin)Q包括bcname,irname,irfpm,irfield,ircall 的定义,在jit文g夹下面,用于调试{,比如在dump.lua中就有用?br />
local jit = require("jit")
assert(jit.version_num == 20002, "LuaJIT core/library version mismatch")
local jutil = require("jit.util")
local vmdef = require("jit.vmdef")  // ← ← ← ←

当你用luajit -jdump的时候,是调用的lua的jit库里面的lua函数

lj_recdef.h:
 1 static const uint16_t recff_idmap[] = {
 2 0,
 3 0x0100,
 4 0x0200,
 5 0x0300,
 6 0,
 7 0,
 8 0x0400,
 9 
10 };
11 
12 static const RecordFunc recff_func[] = {
13 recff_nyi,
14 recff_c,
15 recff_assert,
16 recff_type,
17 recff_ipairs_aux,
18 
19 };
其中recff_func[]是被注册的被traced jit 跟踪的函敎ͼ具体可是在lj_ffrecord.c里面看到
recff_idmap[]被用在lj_ffrecord_funcq个函数中,有一个关键的数据l构RecordFFDataQ用来记录在traceq程中被调用函数的参数和q回g敎ͼ和一些辅助数据,opcodeQliteral{等。通过recff_idmap[]保存的值来区分函数Q待仔细研究Q?br />

lj_folddef.h:
 1 static const FoldFunc fold_func[] = {
 2   fold_kfold_numarith,
 3   fold_kfold_ldexp,
 4   fold_kfold_fpmath,
 5   fold_kfold_numpow,
 6 
 7 };
 8 
 9 static const uint32_t fold_hash[916] = {
10 0xffffffff,
11 0xffffffff,
12 0x5b4c8016,
13 
14 };
用在FOLD optimization中,见lj_opt_fold.cQ主要在
1 if ((fh & 0xffffff) == k || (fh = fold_hash[h+1], (fh & 0xffffff) == k)) {
2       ref = (IRRef)tref_ref(fold_func[fh >> 24](J));
3       if (ref != NEXTFOLD)
4     break;
5     }
是根据数l偏U获取函敎ͼ直接执行?br />Q这个Optimation略复杂,以后的博文中再说Q?br />
----------------------------------------分割U?------------------------------------------

以上是buildvm生成代码Q在很多.c的文件中Q他加入?jin)一些无意义的MARCOQ目的是Z(jin)能被buildvm识别?br />
下面说说src根目录下面的文gQ?br />
lauxlib.hQ?br />用户开发扩展和与C交互的时候的头文?br />
lib_*.h /.c:
֐思义Q就是利用LuaAPI写的内部标准库,?x)在?gu)上表明是否会(x)被trace ( LJLIB_REC(.) )?br />
ljamalg.c:
文g的合q?br />
lj_alloc.h /.c:
定制的Memory Allocator

lj_api.c:
Public Lua/C API.

lj_arch.h:
Target architecture selection

lj_jit.h:
jit~译器里面数据结构的定义

lj_asm.h/ .c  lj_asm_*.c lj_emit_*.h lj_target_*.h/.c :
IR~译成Machine CodeQ关键的数据l构ASMStateQ线性扫描的O(n2)分配法

lj_bc.h/ .cQ?br />Luajit字节码的定义和内存布局

lj_bcdump.c lj_bcread.c  lj_bcwrite.c:
围绕着字节码的操作

lj_carith.c:
C实现的一些数字运?/div>
lj_ccall.h/ .c  lj_ccallback.h / .c :
FFI C语言函数调用和回调绑?br />
lj_debug.h/.c :
调试与自省用

lj_def.h:
q个很重要,重要的类型和一些宏定义在这?br />
lj_c*.h/ .c:
和C语言先关的,比如cd转化Qchar理Q数据管?br />
lj_frame.h:
Luajit的栈帧管?br />
lj_func.h/.c:
Function handle和闭包有关的upvalue数据l构

lj_gc.h/.c:
GC相关QGC可以看下luajit的wikiQ里面涉?qing)不增量式GC的paper和作者的看法

lj_gdbjit.h/.c :
对gdb的支?br />
lj_ir*.h/.c:
SSAQIR相关Q这个和bytecodeq是不一L(fng)Q操作和优化

lj_lex.h/.c  lj_parse.h/.c:
lexer和parser

lj_mcode.h/.c:
Machine Code理

lj_opt_*.h:
各种bytecode层面上的优化

lj_snap.h/.c:
快照支持

lj_state.h/.c:
LuaState和Stack的操?br />
lj_str*.h/.c  lj_tab.h/.c:
原生cdstring和table操作

lj_udata.h/.c:
cduser data的操?br />
lj_vm.h/.c  lj_vmevent.h/.c:
vm的API和事件注册(lj_vmevent_sendQ?br />
lj_vmmath.h/.cQ?br />对vm支持的math?br />
lua.h:
luaState{基本的Lual构

lualib.h:
和Lua一P标准库的API

luajit.h:
luajit 的public API

vm_*.dasc:
~译期被DynASM预处理的源文Ӟ下一讲DynASM时候介ldasc文g

wmain.c:
windows下面的main入口

和Trace相关的:(x)
lj_crecord.h/.c  Q?C操作的trace record
lj_dispatch.h/.c :  指o(h)分发Q调用ASMFuctionQ处理指令前的hook和记录trace用的hot countQ有一个重要的数据l构 GG_State
lj_ff*.h/.c: 上面讲lj_ffdef.h的时候提q,trace的时?记录Fast Function的调用记?br />lj_trace.h/.c: trace的具体过E?br />lj_traceerr.h : trace error


叛_ 2013-11-28 19:23 发表评论
]]> Ʒþ8xѹۿ| 99þˬ޾ƷŮ| ˾þþƷӰԺ| Ƭѹۿþ| þþþAVۿ| þþþþҹӰԺ| þۺĻ| ŷۺҹҹþ| þ޾Ʒҳ| þþù99þùһ| TOKYOۺϾþþƷ| þþĻ| þþþƷ| þù׾Ʒǿ| ޹徫Ʒ߾þ| avպƷþþþþa| þ㽶һëƬ| Ʒþһ| þþþѾƷ| ޾ƷþþþĻ| þþƷAV㽶| þֻоƷƵ99| ھƷþþþӰԺ| ձ޿һþ| þ¾Ʒ| ҹþþþþýӰ| ۺһ˾þþƷ| þèDձɫۺϾþ| þþƷAV͵| þþþùƷ| պʮ˽һþ| þþƷƵ| þ99Ʒ99þ6| ݺݾþ| þҹҹݺ2022| Ʒ99þò| þ96Ʒþþ| ƷŮþþ| ƷŮͬþþþõӰԺ | һɫۺϾþ| ۲ӰԺþþƷ|