• C语言程序简单模拟JVM模板解释器、JIT用到的硬编码编织技术


    首先,我们调用一个普通函数的代码如下:

    #include <stdio.h>
    
    int new();
    
    int main() {
        int obj1 = new();
    
        printf("obj1=%d\n", obj1);
    
        return 0;
    }
    
    int new() {
        return 16;
    }
    

    接着,我们借助 Clion 中 GDB 工具查看函数 new 的反汇编代码:

    (gdb) disassemble /mr new
    Dump of assembler code for function new:
    13	int new() {
       0x000055555555517f <+0>:	f3 0f 1e fa	endbr64 
       0x0000555555555183 <+4>:	55	push   %rbp
       0x0000555555555184 <+5>:	48 89 e5	mov    %rsp,%rbp
    
    14	    return 16;
       0x0000555555555187 <+8>:	b8 10 00 00 00	mov    $0x10,%eax
    
    15	}
    => 0x000055555555518c <+13>:	5d	pop    %rbp
       0x000055555555518d <+14>:	c3	ret    
    
    End of assembler dump.
    

    注意,我这里用的是C语言工程,因为 C++ 中 new 是关键字,那你可能要换个函数名。

    接着,我就把汇编编译后的原始字节值存入了以下源码的 asm_code 数组中,

    #include <stdio.h>
    #include <sys/mman.h>
    #include <unistd.h>
    #include <memory.h>
    
    int new();
    
    int template_new();
    
    int main() {
        int obj1 = new();
        int obj2 = template_new();
    
        printf("obj1=%d\n", obj1);
        printf("obj2=%d\n", obj2);
    
        return 0;
    }
    
    int new() {
        return 16;
    }
    
    int template_new() {
        typedef int (*p_fun)();
    
        char asm_code[] = {
                0x55,
                0x48, 0x89, 0xe5,
                0xb8, 0x10, 0x00, 0x00, 0x00,
                0x5d,
                0xc3
        };
    
        void* temp = mmap(NULL, // 映射区的开始地址,设置NULL或者0表示由系统决定
                          getpagesize(), // 申请的内存大小按照内存页对齐,这里直接调用函数获取内存页大小
                          PROT_READ | PROT_WRITE | PROT_EXEC, // 映射的内存区的权限,可读可写可执行
                          MAP_ANONYMOUS | MAP_PRIVATE, // 映射对象类型
                          -1,
                          0);
    
        // 将函数机器码写入内存
        memcpy(temp, asm_code, sizeof(asm_code));
    
        p_fun fun = temp;
    
        return fun();
    }
    

    asm_code 中代码还可以进一步精简。

    JVM模板解释器针对的是单个字节码指令的优化;
    JIT针对的是热点代码的优化;

  • 相关阅读:
    『华为』[行业要闻]华为,我们的光环还能顶多久(转)
    总结几点Quartz的经验
    LVS
    postfix邮件服务器安全
    让IE浏览器支持RGBA颜色
    PostgreSQL在何处处理 sql查询之六十四
    PostgreSQL在何处处理 sql查询之六十三
    PostgreSQL在何处处理 sql查询之六十五
    对PostgreSQL的prepared statement 的理解
    PostgreSQL在何处处理 sql查询之六十六
  • 原文地址:https://www.cnblogs.com/kendoziyu/p/16418997.html
Copyright © 2020-2023  润新知