一般基于 LLVM 的引擎可以直接使用 LLVM 内建的 JIT 支持,
JVM 大概也有一个实验性基于 LLVM 的 JIT 编译器... 也不知道是不是 C2 就基于 LLVM
Chez Scheme 也支持 JIT, 不过据淫王说连汇编器都是自己的... 🌚
PLT Scheme 大概是基于 GNU Lightning https://www.gnu.org/software/lightning/manual/lightning.html 的 (虽然我都不懂....
http://users.racket-lang.narkive.com/CeO6zgKL/plt-scheme-nanojit-an-alternative-to-llvm 9 years ago
MJIT 目前好像支持 clang 和 GCC C 两款 C 编译器,,,,, 也不知道是不是大都内联汇编
看到 MJIT 有这么清奇的设计 GeekApk API 如果不能上 OAuth 我就放心了(
JVM 大概也有一个实验性基于 LLVM 的 JIT 编译器... 也不知道是不是 C2 就基于 LLVM
Chez Scheme 也支持 JIT, 不过据淫王说连汇编器都是自己的... 🌚
PLT Scheme 大概是基于 GNU Lightning https://www.gnu.org/software/lightning/manual/lightning.html 的 (虽然我都不懂....
http://users.racket-lang.narkive.com/CeO6zgKL/plt-scheme-nanojit-an-alternative-to-llvm 9 years ago
MJIT 目前好像支持 clang 和 GCC C 两款 C 编译器,,,,, 也不知道是不是大都内联汇编
看到 MJIT 有这么清奇的设计 GeekApk API 如果不能上 OAuth 我就放心了(
www.gnu.org
GNU lightning
Next: Introduction to GNU lightning
膜拜语言实现 dalao, 我对底层一无所知(
(不仅如此连 Java 类型系统都不了解
(更别说 C# 那些更高级的语言特性和 CLR 非托管代码这些...
(连 Ruby 这么简单的东西都未曾完全了解
(Duck typing 比 C#和 Java 那一套是简单多了....
因为 这么菜
所以才只能做 GeekApk 这么低级的工作(
(不仅如此连 Java 类型系统都不了解
(更别说 C# 那些更高级的语言特性和 CLR 非托管代码这些...
(连 Ruby 这么简单的东西都未曾完全了解
(Duck typing 比 C#和 Java 那一套是简单多了....
因为 这么菜
所以才只能做 GeekApk 这么低级的工作(
4.1 A function which increments a number by one
Let’s see how to create and use the sample incr function created in GNU lightning’s instruction set:
#include <stdio.h>
#include <lightning.h>
static jit_state_t *_jit;
typedef int (*pifi)(int); /* Pointer to Int Function of Int */
int main(int argc, char *argv[])
{
jit_node_t *in;
pifi incr;
init_jit(argv[0]);
_jit = jit_new_state();
jit_prolog(); /* prolog */
in = jit_arg(); /* in = arg */
jit_getarg(JIT_R0, in); /* getarg R0 */
jit_addi(JIT_R0, JIT_R0, 1); /* addi R0, R0, 1 */
jit_retr(JIT_R0); /* retr R0 */
incr = jit_emit();
jit_clear_state();
/* call the generated code, passing 5 as an argument */
printf("%d + 1 = %d\n", 5, incr(5));
jit_destroy_state();
finish_jit();
return 0;
}
Let’s examine the code line by line (well, almost…):
#include <lightning.h>
You already know about this. It defines all of GNU lightning’s macros.
static jit_state_t *_jit;
You might wonder about what is jit_state_t. It is a structure that stores jit code generation information. The name _jit is special, because since multiple jit generators can run at the same time, you must either #define _jit my_jit_state or name it _jit.
typedef int (*pifi)(int);
Just a handy typedef for a pointer to a function that takes an int and returns another.
jit_node_t *in;
Declares a variable to hold an identifier for a function argument. It is an opaque pointer, that will hold the return of a call to arg and be used as argument to getarg.
pifi incr;
Declares a function pointer variable to a function that receives an int and returns an int.
init_jit(argv[0]);
You must call this function before creating a jit_state_t object. This function does global state initialization, and may need to detect CPU or Operating System features. It receives a string argument that is later used to read symbols from a shared object using GNU binutils if disassembly was enabled at configure time. If no disassembly will be performed a NULL pointer can be used as argument.
_jit = jit_new_state();
This call initializes a GNU lightning jit state.
jit_prolog();
Ok, so we start generating code for our beloved function…
in = jit_arg();
jit_getarg(JIT_R0, in);
We retrieve the first (and only) argument, an integer, and store it into the general-purpose register R0.
jit_addi(JIT_R0, JIT_R0, 1);
We add one to the content of the register.
jit_retr(JIT_R0);
This instruction generates a standard function epilog that returns the contents of the R0 register.
incr = jit_emit();
This instruction is very important. It actually translates the GNU lightning macros used before to machine code, flushes the generated code area out of the processor’s instruction cache and return a pointer to the start of the code.
jit_clear_state();
This call cleanups any data not required for jit execution. Note that it must be called after any call to jit_print or jit_address, as this call destroy the GNU lightning intermediate representation.
printf("%d + 1 = %d", 5, incr(5));
Calling our function is this simple—it is not distinguishable from a normal C function call, the only difference being that incr is a variable.
jit_destroy_state();
Releases all memory associated with the jit context. It should be called after known the jit will no longer be called.
finish_jit();
This call cleanups any global state hold by GNU lightning, and is advisable to call it once jit code will no longer be generated.
GNU lightning abstracts two phases of dynamic code generation: selecting instructions that map the standard representation, and emitting binary code for these instructions. The client program has the responsibility of describing the code to be generated using the standard GNU lightning instruction set.
GNU Lightning JIT 库选了一个片段快速了解(
x86_64
sub $0x30,%rsp
mov %rbp,(%rsp)
mov %rsp,%rbp
sub $0x18,%rsp
mov %rdi,%rax mov %rdi, %rax
add $0x1,%rax inc %rax
mov %rbp,%rsp
mov (%rsp),%rbp
add $0x30,%rsp
retq retq
新增 yield_self 来使用当前上下文 yield 代码块。不同于 tap,此方法会返回代码块的运行结果。[功能 #6721&]
🌚 emmm 才知道 tap 居然还可以这么用(
定向思维
🌚 emmm 才知道 tap 居然还可以这么用(
定向思维
> %w[a b c].tap { |s| print(s) }.join &:+ #=> "abc" -> abc
> to_s #=> "main"
> tap { |o| o.to_s } #=> main (toplevel object)
> yield_self { |s| s.to_s } #=> "main" (block yielding result)[38] pry(main)> st = Struct.new(:foo, :bar)
=> #<Class:0x000055dca2b6c630>
[39] pry(main)> st.ancestors
=> [#<Class:0x000055dca2b6c630>, Struct, Enumerable, Object, PP::ObjectMixin, Kernel, BasicObject]
duangsuse::Echo
#Ruby [42] pry(main)> st.superclass => Struct emmm, Singleton class 居然出现在了(非内部)超类链里面....
`[45] pry(main)> Class.new.ancestors
=> [#<Class:0x000055dca3054b70>, Object, PP::ObjectMixin, Kernel, BasicObject]
`
🌑 说好的 singleton class 只是内部概念呢...
=> [#<Class:0x000055dca3054b70>, Object, PP::ObjectMixin, Kernel, BasicObject]
`
🌑 说好的 singleton class 只是内部概念呢...
通过在字节码中移除了全部 trace 指令提升了大约 5-10% 的性能。trace 指令的引入是为了提供 TracePoint 的支持。然而,在大多数情况,TracePoint 不会被用到,trace 指令增加了额外的开销。作为替代,我们实现了一个动态指令技术,详情见 [功能 #14104]。
这是 MRI 2.5 的更新记录,看来 《Ruby Under a Microscope》 里面的 YARY 指令又落后了(跑
删除顶层常量查找。[功能 #11547]🌑 居然有这种操作( 又是居然没想到.... ( 本来通过词法作用域链就可以一直查找到 顶层作用域的...
dse@susepc:~$ pry
[1] pry(main)> Class::Struct
NameError: uninitialized constant Class::Struct
Did you mean? Struct
from (pry):1:in `__pry__'
dse@susepc:~$ ruby2.3
require 'irb'
IRB.start
irb(main):001:0> Class::Struct
(irb):1: warning: toplevel constant Struct referenced by Class::Struct
=> Struct
duangsuse::Echo
删除顶层常量查找。[功能 #11547] 🌑 居然有这种操作( 又是居然没想到.... ( 本来通过词法作用域链就可以一直查找到 顶层作用域的... dse@susepc:~$ pry [1] pry(main)> Class::Struct NameError: uninitialized constant Class::Struct Did you mean? Struct from (pry):1:in `__pry__' dse@susepc:~$ ruby2.3 require 'irb'…
dse@susepc:~$ pry
[1] pry(main)> Object::Class
=> Class
[2] pry(main)> Class.ancestors
=> [Class, Module, Object, PP::ObjectMixin, Kernel, BasicObject]
duangsuse::Echo
删除顶层常量查找。[功能 #11547] 🌑 居然有这种操作( 又是居然没想到.... ( 本来通过词法作用域链就可以一直查找到 顶层作用域的... dse@susepc:~$ pry [1] pry(main)> Class::Struct NameError: uninitialized constant Class::Struct Did you mean? Struct from (pry):1:in `__pry__' dse@susepc:~$ ruby2.3 require 'irb'…
经典的 「Rails 驱动 Ruby 开发」例子 😂
(据说是由于 查找到在顶级作用域定义的类 导致 Rails 的 autoload 出现问题才提交修改)
(据说是由于 查找到在顶级作用域定义的类 导致 Rails 的 autoload 出现问题才提交修改)