Baby’s First Garbage Collector › 迷你虚拟机
A minimal virtual machine
[#267]
Baby’s First Garbage Collector › 迷你虚拟机 A minimal virtual machine [#267]
现在我们可以在小虚拟机中使用这个数据类型。虚拟机在这个背景中的作用是拥有一个存储当前范围内的变量的栈。大多数语言的虚拟机要么是基于栈的(如 JVM 和 CLR),要么是基于寄存器的(如 Lua)。在这两种情况下,实际上都仍然存在栈。它用于存储表达式中间所需的局部变量和临时变量。我们明确而简单地建模,如下所示:
Now we can use that datatype in a little virtual machine. The VM’s role in this story is to have a stack that stores the variables that are currently in scope. Most language VMs are either stack-based (like the JVM and CLR) or register-based (like Lua). In both cases, there is actually still a stack. It’s used to store local variables and temporary variables needed in the middle of an expression. We model that explicitly and simply like so:
#define STACK_MAX 256
typedef struct {
Object* stack[STACK_MAX];
int stackSize;
} VM;
现在已经有了基本的数据结构,让我们拼凑代码来创建一些东西。首先,编写一个创建并初始化虚拟机的函数:
Now that we’ve got our basic data structures in place, let’s slap together a bit of code to create some stuff. First, let’s write a function that creates and initializes a VM:
VM* newVM() {
VM* vm = malloc(sizeof(VM));
vm->stackSize = 0;
return vm;
}
一旦我们有了虚拟机,我们就需要能够操作它的栈:
Once we have a VM, we need to be able to manipulate its stack:
void push(VM* vm, Object* value) {
assert(vm->stackSize < STACK_MAX, "Stack overflow!");
vm->stack[vm->stackSize++] = value;
}
Object* pop(VM* vm) {
assert(vm->stackSize > 0, "Stack underflow!");
return vm->stack[--vm->stackSize];
}
现在我们可以将东西放入“变量”中,我们需要能够实际创建对象。首先,一个小辅助函数:
Now that we can stick stuff in “variables”, we need to be able to actually create objects. First, a little helper function:
Object* newObject(VM* vm, ObjectType type) {
Object* object = malloc(sizeof(Object));
object->type = type;
return object;
}
这会执行实际的内存分配并设置类型标记。我们稍后会重新讨论这个问题。使用这个函数,我们可以编写其他函数将每种类型的对象推送到虚拟机的栈上:
That does the actual memory allocation and sets the type tag. We’ll be revisiting this in a bit. Using that, we can write functions to push each kind of object onto the VM’s stack:
void pushInt(VM* vm, int intValue) {
Object* object = newObject(vm, OBJ_INT);
object->value = intValue;
push(vm, object);
}
Object* pushPair(VM* vm) {
Object* object = newObject(vm, OBJ_PAIR);
object->tail = pop(vm);
object->head = pop(vm);
push(vm, object);
return object;
}
这就是我们的小虚拟机。如果我们有一个语法分析器和一个解释器来调用这些函数,我们就拥有了一种对上帝诚实的语言。而且,如果我们有无限的内存,它甚至能够运行真正的程序。既然我们不这样做,那我们就开始回收一些垃圾吧。
And that’s it for our little VM. If we had a parser and an interpreter that called those functions, we’d have an honest to God language on our hands. And, if we had infinite memory, it would even be able to run real programs. Since we don’t, let’s start collecting some garbage.