/* 文件object.h */
#ifndef OBJECT_H
#define OBJECT_H
typedef enum {
OBJ_INT,
OBJ_PAIR
} ObjectType;
typedef struct sObject {
ObjectType type; //type字段表示对象的类型要么int要么pair
union {
/* OBJ_INT */
int value;
/* OBJ_PAIR */
struct {
struct sObject* head;
struct sObject* tail;
};
};
unsigned char marked;
/* the next object in the list of all object. */
struct sObect* next;
} Object;
#define STACK_MAX 256
/* 基于栈的虚拟机 */
typedef struct {
Object* stack[STACK_MAX];
int stackSize;
/* the first object in the list of all objects */
Object* firstObject;
int numObjects;//total num of currently allocated objects
int maxObjects;//num of objects required to trigger a GC
} VM;
#endif
/* 文件object.c */
#include "object.h"
#include <memory.h>
#include <stdio.h>
#include <assert.h>
#define INI_GC_THRESHOLD 8
VM* newVM() {
VM* vm=(VM*)malloc(sizeof(VM));
vm->stackSize = 0;
vm->firstObject = NULL;
vm->numObjects = 0;
vm->maxObjects = INI_GC_THRESHOLD;
return vm;
}
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];
}
Object* newObject(VM* vm, ObjectType type) {
if (vm->numObjects == vm->maxObjects) gc(vm);
Object* object=malloc(sizeof(Object));
object->type = type;
object->marked = 0;
/* Insert it into the list of allocated objects. */
object->next = vm->firstObject;
vm->firstObject = object;
vm->numObjects++;
return object;
}
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;
}
void mark(Object* object) {
/* If already marked, it's done. Check this first
* to avoid recursing on cycles in the object graph.
*/
if(object->marked) return;
object->marked = 1;
if(object->type == OBJ_PAIR){
mark(object->head);
mark(object->tail);
}
}
void markAll(VM* vm) {
int i=0;
for(;i < vm->stackSize; i++){
mark(vm->stack[i]);
}
}
void sweep(VM* vm) {
Object** object = &vm->firstObject;
while(*object) {
if(!(*object)->marked) {
/* This object wasn't reached,
* so remove it from the list and free it.
*/
Object* unreached = *object;
/* It was pointint to an unreached object,
* but now it's been changed to pointing to the next.
* Comparing to those who using 'p','q','temp' to remove
* a object, this method is better.
*/
*object = unreached->next;
printf("free an object!\n");
free(unreached);
vm->numObjects--;
} else {
/* This object was reached, so unmark it(for the next GC) */
(*object)->marked = 0;
object = &(*object)->next;
}
}
}
void gc(VM* vm) {
markAll(vm);
sweep(vm);
vm->maxObjects = vm->numObjects * 2;
}
#include <stdio.h>
#include <stdlib.h>
#include "object.h"
int main()
{
VM* vm=newVM();
int x;
int order;
unsigned char isExit=0;
while(!isExit){
printf("input order, 1.pushInt 2.pushPair 3.pop 0.exit (0/1/2/3):");
scanf("%d",&order);
switch(order){
case 1:
printf("input the value of integer:\n");
scanf("%d",&x);
pushInt(vm,x);
break;
case 2:
pushPair(vm);
break;
case 3:
pop(vm);
break;
case 0:
isExit=1;
break;
}
printf("\n");
}
return 0;
}