Soft_Job 板


LINE

Update: 睡前简单弄个小更新 把我回文中说的code cache的hashtable快速弄出来了 第一次呼叫时会emite code,第二次因为hashtable查找成功则直接呼叫 另外就是把mmap要记忆体时的可读可写可执行,改成仅可读可写 後面再透过mprotect改成可读可执行 这样可以防止後来有人窜改JIT emit的code cache patch放在这边: https://paste.plurk.com/show/2636452/ P.S. 我不用github放的原因是因为我不想暴露我的主ID 还请担待 = = = = = = = = = = = = 中午吃饱饭有点胀气 看到某篇回文的推文中有人想要看JIT范例 所以简单写了个很粗糙的版本 前後花不到15分钟 所以觉得coding style很烂、没效率是很正常的,别打我QQ (结果真的被转出去了Orz 我晚点忙完会来修code 真的assembly code gen会找时间补上的) 大抵上的思路就是你吃到虚拟机的bytecode, 就把它转成host平台的native code 接着把它塞进你跟系统动态要的、可以执行的记忆体区段 然後就很快乐的开始执行它 黄色上色的地方,每个作业系统给的API不一样 Linux、OSX、FreeBSD ... (most of *NIX OSes): mprotect()、mmap() with proper permissions. Windows: VirtualAlloc() = = = = = = = = = = = /** * * This piece of code is to demo simple VM/JIT knowledge * and is released under 2-clause BSD license. * * Copyright 2018/05/16 snaketsai * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * U2FsdGVkX19w8Ikk1T7xBlbh4vDhIEvZzshUhXft6XMFugC9M27uV9LDszf7/8gP * OtF2AZwYaUQqzLLY5vXhCQ== * **/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> #ifdef _NOJIT static inline int IAdd(int inp1, int inp2) { puts("Non-JIT version iadd."); return inp1+inp2; } static inline int ISub(int inp1, int inp2) { puts("Non-JIT version isub."); return inp1-inp2; } #else // Nope, I'm not gonna write an assembler. // Just pretend that we _magically_ get assembly pieces we need. const unsigned char _add[] = \ "\x55\x48\x89\xe5\x89\x7d\xfc\x89\x75\xf8\x8b\x55\xfc\x8b\x45\xf8\x01\xd0\x5d\xc3\x00"; const unsigned char _sub[] = \ "\x55\x48\x89\xe5\x89\x7d\xfc\x89\x75\xf8\x8b\x45\xfc\x2b\x45\xf8\x5d\xc3\x00"; #define MAXCODECAHE_SIZE 4096 void* AllocExeMem(size_t size) { void* memPtr = mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (memPtr == (void*)-1) { perror("mmap() failed."); return NULL; } return memPtr; } void *CodeCachePool; int (*IAdd)(int, int); int (*ISub)(int, int); #endif /** Very Simple VM spec - - Every insn. is 3 byte long. opcodes are listed below: 0x00 HCF, halt and catch fire. 0x01 IADD, humbly add two signed integers and print the result. 0x02 ISUB, humbly substract two signed integers and print the result. The bytecode stream should end with a 0xff byte mark. **/ const unsigned char BytecodeStream[] = \ "\x01\x02\x03\x02\x05\x04\x00\x00\x00\xff"; int runVM(const unsigned char* bstream) { unsigned char insn[3]; while(bstream[0] != 0xff) { memcpy(&insn,bstream,3); switch(insn[0]) { case 0x00: puts("Dave, stop, will you ?"); return 0; case 0x01: #ifndef _NOJIT // emit code to code cache. memcpy(CodeCachePool, _add, sizeof(_add)); #endif printf("iadd: %d\n", IAdd((int)insn[1], (int)insn[2])); break; case 0x02: #ifndef _NOJIT memcpy(CodeCachePool, _sub, sizeof(_sub)); #endif printf("isub: %d\n", ISub((int)insn[1], (int)insn[2])); break; default : // Unrecognized insn. perror("Sorry Dave, I can't do that."); return -1; } bstream+=3; } } int main(int ac, char* av[]) { int ret = -1; #ifndef _NOJIT CodeCachePool = AllocExeMem(MAXCODECAHE_SIZE); IAdd = CodeCachePool; ISub= CodeCachePool; #endif ret = runVM(BytecodeStream); if(ret == 0) { perror("VM exited successfully."); } else { perror("Unexpected error occured."); } return 0; } -- Linux is the bone of my world. Kernel is mybody, and initramfs is myblood, have created over a thousand Distros. Unknown to impossibility. Nor known to limitation. --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 140.113.167.181
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Soft_Job/M.1526451691.A.2E2.html ※ 编辑: snaketsai (140.113.167.181), 05/16/2018 14:58:35
1F:推 cklppt: 只看到HAL(遮脸w 05/16 18:51
2F:推 LinuxKernel: 113就是猛 可是没有人推文QQ 05/16 19:56
这整份code其实没什麽技术背景,大概上过compiler课的人都会写 唯一需要额外知道的,是如何去要一块可塞code又可执行的记忆体 这个课堂上不会教
3F:推 soheadsome: 超赞 05/16 19:58
4F:→ weiyucsie: 原来IAdd,ISub有个puts,难怪机器码这麽长 05/16 20:23
没欸,会那麽长是因为包含function call要的prologue跟epilogue 我其实弄得比较像intrinsic fnuction 所以Non-JIT的部份可以直接跟JIT的无缝接在一起
5F:→ weiyucsie: https://nullprogram.com/blog/2015/03/19/ 05/16 22:22
没想到有这麽完整的write up 马上google一下"mprotect/mmap"+"JIT"发现已经不少文章在讲 我第一次知道JIT大概是2011年,当时文章还真的不多 稍微说一下我这篇目前离实用code的差距在: (1) 缺真正的asm codegen,我上面的asm snippet是用gcc -c去编C code来生的 (2) JIT emit code後没有code reuse、每次都还会重新emit 实务上会是个hashtable,查找失败emit、查找成功直接call 更进阶一点会有所谓的block chaining,也就是把能接在一起的native code串在一起跑 这样可以节省跳进、又跳出VM code的时间 (3) mmap权限直接开executable其实有点危险,比较正确的作法会分两段: 先mmap开rw要记忆体、把code塞进去 然後用mprotect把它改设成rx ※ 编辑: snaketsai (140.113.167.181), 05/16/2018 23:24:51
6F:→ weiyucsie: 想说add,sub都有instruction,怎麽会那麽长XD 05/17 00:05
7F:→ weiyucsie: 这篇文章把可执行的部分点出来,只是没codegen 05/17 00:06
8F:→ weiyucsie: 也不知道可不可以叫做即时编译 05/17 00:07
9F:→ weiyucsie: 阿 我想到了,x86的calling convention是推入堆叠 05/17 00:10
10F:→ weiyucsie: 也许是这样会比较复杂吧 05/17 00:10
应该是那样没错 ※ 编辑: snaketsai (140.113.167.181), 05/17/2018 02:53:13
11F:推 pptsodog: 推 05/17 05:09
12F:→ weiyucsie: 看了一下-O0编出来的,好像真的有前後两段 05/17 17:11
13F:→ weiyucsie: 不过有下最佳化参数後就只剩几行 05/17 17:12
14F:→ weiyucsie: 可能就你说的prologue和epilogue 05/17 17:13
15F:→ snaketsai: 如果是add的话,gcc -O3会优化到只剩下lea就retq了XD 05/17 18:58
16F:→ snaketsai: 其实我现在正在看要怎麽模仿tcg的codegen来做 05/17 19:01
17F:→ snaketsai: tcg在backend时只负责gen中间的部份 05/17 19:01
18F:→ snaketsai: 真正vcpu在cpu-exec时会macro刻意把进入换成平台相依的 05/17 19:02
19F:→ snaketsai: prologue、然後才跳进去code cache、出去时叫epilogue 05/17 19:02







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:BuyTogether 或 站内搜寻

TOP