我正在开发一种脚本语言,它可以编译自己的虚拟机,这是一个简单的脚本语言,可以处理某些数据,如点,向量,浮点数等等.内存单元以这种方式表示:
struct memory_cell
{
u32 id;
u8 type;
union
{
u8 b; /* boolean */
double f; /* float */
struct { double x, y, z; } v; /* vector */
struct { double r, g, b; } c; /* color */
struct { double r, g, b; } cw; /* color weight */
struct { double x, y, z; } p; /* point variable */
struct { u16 length; memory_cell **cells; } l; …Run Code Online (Sandbox Code Playgroud) 我对一些优化方法或通用字节码设计很感兴趣,与AST的解释相比,这可能有助于加快使用VM的执行速度.
从 Java 虚拟机实现 ( http://docs.oracle.com/javase/specs/jvms/se7/html/index.html )可以明显看出,堆栈帧存在于存储方法运行时数据的堆上。但是java中堆栈帧的内容是什么,堆栈帧是如何组织起来存储局部变量和中间结果的值的。数据结构是如何组织的。
在Java中,虚拟机预先分配了一个无法在运行时扩展的内存堆.当VM加载时,开发人员可以使用-Xmx开关增加堆的大小,但是无法在运行时增加堆的最大大小.为什么是这样?
我正在构建一个从C语言到堆栈机器的玩具编译器,我正处于需要弄清楚如何处理函数和阻塞局部变量的地方.从抽象的角度思考它看起来我在频谱的两端有两个选项:1)为每个变量预处理和预分配堆栈空间,2)向VM添加特殊指令以遍历堆栈.
这样做的好处是可以提前给我变量的所有地址,这样我就不必非常聪明,或者在虚拟机上添加任何额外的指令来移动堆栈.缺点是它可能非常浪费,因为从不执行但是声明一大堆变量的条件代码将占用大量不必要的空间.例如,
a : t1 = value;
if (test) {
b : t2; c : t3; d : t4; ...;
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,即使test总是为false,我仍然会为条件分支中的所有变量分配空间.
我可以想到的另一种方法是为每个变量声明生成代码,然后添加一些特殊的VM指令以在运行时找出这些变量的地址.这解决了浪费堆栈空间的问题,但随后增加了一些计算开销,我可以通过一些缓存方法来解决这个问题.
那么什么是正确的方法,还有另一种我没想到的方法更好吗?
compiler-construction variables stack-machine vm-implementation
通常在动态类型编程语言中,对象struct具有用于标识对象类型的标记字段.例如:
struct myObject {
int tag;
...
}
Run Code Online (Sandbox Code Playgroud)
因此,使用基于标记字段的switch语句可以轻松执行不同的操作.例如:
switch (obj->tag) {
case OBJ_INTEGER: ...
case OBJ_STRING: ...
case OBJ_FUNC:...
}
Run Code Online (Sandbox Code Playgroud)
在我的情况下,我使用了一个void*isa指针而不是int标签字段,该指针指向代表该对象的类.一切正常,我不得不使用优雅的switch语句而不是使用一系列if/else语句.例如:
if (obj->isa == class_integer) {
...
} else if (obj->isa == class_string) {
...
} else if (obj->isa == class_func) {
...
}
Run Code Online (Sandbox Code Playgroud)
我知道我不能在C开关语句中使用指针,但我想知道我是否可以使用一些聪明的技巧来加速if语句系列.
任何人都可以解释MoSync 的运行时架构吗?
VM Core不是问题.我认为这是一个在java vm中运行的虚拟机,并逐行解释代码.
但是Recompiler Core如何工作?这是一种在本机代码中运行时编译应用程序的Ahead-Of-Time编译器吗?但后来我不明白这张照片.或者我是否可能需要运行时的其他模块甚至是机器代码?
谢谢
compiler-construction interpreter cross-platform runtime vm-implementation
我在C中编写了一个简单的VM,使用简单的指令切换,没有任何指令解码,但性能很糟糕.
对于简单的aritmetic操作,对于相同的操作,VM比本机C代码慢大约4000倍.我测试了一组长度为1000万的数组,第一个包含程序指令,随机+ - */操作,2个数组保存随机整数,第三个数组是操作目标存储.
我期待看到算术性能下降3-4倍,因此`4000x真的让我感到震惊.即使是最慢的解释语言似乎也能提供更高的性能.所以我的方法出错了,如何在不借助JIT编译到机器代码的情况下提高性能?
实施是......基本上我能想到的最简单:
begin:
{
switch (*(op+(c++)))
{
case 0:
add(in1+c, in2+c, out+c); goto begin;
case 1:
sub(in1+c, in2+c, out+c); goto begin;
case 2:
mul(in1+c, in2+c, out+c); goto begin;
case 3:
div(in1+c, in2+c, out+c); goto begin;
case 4:
cout << "end of program" << endl;
goto end;
default:
cout << "ERROR!!!" << endl;
}
}
end:
Run Code Online (Sandbox Code Playgroud)
更新:当我注意到我用于配置文件的QElapsedTimer实际上已被破坏时,我正在玩弄程序的长度.现在我正在使用clock()函数,根据它,计算的goto实际上与本机代码相同,可能稍微低一点.这个结果合法吗?这是完整的来源(我知道它很难看,它毕竟只是用于测试):
#include <QtGlobal>
#include <iostream>
#include <stdio.h>
#include <ctime>
using namespace std;
#define LENGTH 70000000
void add(int & a, int & …Run Code Online (Sandbox Code Playgroud) 我正在阅读LLVM并尝试学习编译器设计.我的问题是:如果有任何专用Scala运行时的计划,在其他运行时如JVM,.net上具有字节代码可移植性
此外,还有任何现有的LLVM实现.
interpreter ×3
c ×2
c++ ×2
java ×2
jvm ×2
bytecode ×1
heap ×1
lua ×1
memory ×1
optimization ×1
performance ×1
runtime ×1
scala ×1
variables ×1