及时编译器

自从 3.12

由于 LLVM 不向后兼容,旧的即时编译器不再工作。由于我们没有来自作者的消息,我决定从头开始编写一个新的即时编译器。

顺便说一句,我想知道 LLVM 开发人员和 GTK+ 开发人员是否是同一个人......

这次不幸的经历让我很伤心,所以我决定以不同的方式设计它。新的 Gambas JIT 编译器将 Gambas 代码转换为 C,取代所有依赖可能的编译器的不确定移动改变的beta API。

它的工作方式

流程如下:

  • 当第一次调用带有 FAST 关键字标记的函数时,将调用JIT编译器。

  • 如果尚未完成,JIT 编译器会将当前项目(或组件)的 所有快速方法 转换为一个大的 C 源文件。

  • 然后调用 C 编译器从该大 C 源文件生成共享库。

  • 共享库是动态加载的。

  • 调用 JIT 编译的函数。

这种设计有很多优点:
  • 您可以使用 或gcc、clang或tcc(见下文)。

  • 只要C标准不改变,JIT编译器就不会崩溃。

但也有一些缺点:
  • 代码生成速度较慢(使用 gcc 时甚至更慢)。为了解决这种缓慢的问题,编译是在后台进程中完成的。

  • 有时,编译器的怪癖会困扰您(例如,使用 __attribute__((noreturn)) 会使 gcc 优化器变得疯狂且缓慢)。

JIT编译器是在需要时可自动加载的一个组件中实现的。它有一个C部分,实现从Gambas到C代码的转换器,还有一个Gambas部分,用于从可执行的归档文件中提取Gambas源代码,并将所有汇编翻译组成一个大文件。

语法

语法没有改变:将关键字FAST放在Gambas类文件的顶部,用于类的所有函数

要JIT编译而不是解释执行,或者加在函数声明开始时,以便只对该函数进行JIT编译。

JIT编译是有成本的,所以尽量只在需要提升的特定方法上使用它。

注意事项

目前不支持某些语言语法:
  • BYREF关键字

  • 将变量参数传到以 ... 可变参数方式调用的另一个函数。

  • 使用g tcc 是可能的,但该编译器不太可靠,可能会生成不正确的代码。

性能

速度增长最大的将是使用大量低级别的函数计算和控制流( For Each 循环除外)的场合,例如

做大量的数学运算。但是,如果函数主要调用其他库,则不大会看到速度有大的提高。

在字符串管理中,您不会看到任何有意义的收获。

更多细节可以参见 一些基准小测试

Debugging

目前,一些环境变量控制JIT编译器的行为。

Environment variable Description
GB_NO_JIT Set to 1 if you want to disable the JIT compiler entirely.
GB_JIT_DEBUG Set to 1 if you want to see the debugging message emitted by the JIT compiler.
GB_JIT_CC Set to the name of the compiler to use. By default gcc is used. But you can put clang instead, or anything else provided that it uses the same options as gcc or support for it is added in the JIT compiler Gambas part.
GB_JIT_CFLAGS Set it to the flags used for compiling the C code. The default is -O3.

See also