RocksEngine::~RocksEngine() { cleanShutdown(); }
void InterpreterExecute(const LinkedProgram *program, int target) { VM *masterVM; IVInit(&temp, 16); vmBytecode = program->bytecode; vmLineNumbers = program->lineNumbers; masterVM = VMCreate(program); initStackFrame(masterVM, &masterVM->ip, &masterVM->bp, target, 0); for (;;) { VMBase *vmBase = &masterVM->base; bool idle = true; /* Traverse VMs, letting all non-idle execute for a while. Note that the tree can change as a result of executing. */ for (;;) { if (vmBase->fullVM) { VM *vm = (VM*)vmBase; if (!vm->idle) { /* TODO: Cloning new VMs can cause infinite traversal. */ vm = execute(vm); idle = false; } else if (vm->child) { vmBase = vm->child; continue; } { VMBase *parent = vm->base.parent; VMBase *child = &vm->base; VMBase **p; if (!parent) { break; } while (parent->fullVM || ((VMBranch*)parent)->children[ ((VMBranch*)parent)->childCount - 1] == child) { child = parent; parent = parent->parent; if (!parent) { goto done; } } for (p = ((VMBranch*)parent)->children; *p != child; p++) { assert(p < ((VMBranch*)parent)->children + ((VMBranch*)parent)->childCount); } vmBase = *(p + 1); } } else { VMBranch *vmBranch = (VMBranch*)vmBase; assert(vmBranch->childCount); vmBase = vmBranch->children[0]; } } done: if (idle) { if (masterVM->job) { JobExecute(masterVM->job); } else if (masterVM->idle) { break; } } } if (masterVM->failMessage) { const char *filename; int line = BytecodeLineNumber(program->lineNumbers, (int)(masterVM->ip - vmBytecode), &filename); char *msg = VGetStringCopy(masterVM->failMessage); fprintf(stderr, "%s:%d: %s\n", filename, line, msg); #ifdef VALGRIND free(msg); #endif cleanShutdown(EXIT_FAILURE); } #ifdef VALGRIND VMDispose(&masterVM->base); IVDispose(&temp); #endif }