Пример #1
0
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
}
Пример #2
0
/* VMChunkCreate -- create a chunk
 *
 * chunkReturn, return parameter for the created chunk.
 * vmArena, the parent VMArena.
 * size, approximate amount of virtual address that the chunk should reserve.
 */
static Res VMChunkCreate(Chunk *chunkReturn, VMArena vmArena, Size size)
{
  Res res;
  Addr base, limit, chunkStructLimit;
  Align pageSize;
  VM vm;
  BootBlockStruct bootStruct;
  BootBlock boot = &bootStruct;
  VMChunk vmChunk;
  void *p;

  AVER(chunkReturn != NULL);
  AVERT(VMArena, vmArena);
  AVER(size > 0);

  res = VMCreate(&vm, size, vmArena->vmParams);
  if (res != ResOK)
    goto failVMCreate;

  pageSize = VMAlign(vm);
  /* The VM will have aligned the userSize; pick up the actual size. */
  base = VMBase(vm);
  limit = VMLimit(vm);

  res = BootBlockInit(boot, (void *)base, (void *)limit);
  if (res != ResOK)
    goto failBootInit;

  /* Allocate and map the descriptor. */
  /* See <design/arena/>.@@@@ */
  res = BootAlloc(&p, boot, sizeof(VMChunkStruct), MPS_PF_ALIGN);
  if (res != ResOK)
    goto failChunkAlloc;
  vmChunk = p;
  /* Calculate the limit of the page where the chunkStruct resides. */
  chunkStructLimit = AddrAlignUp((Addr)(vmChunk + 1), pageSize);
  res = vmArenaMap(vmArena, vm, base, chunkStructLimit);
  if (res != ResOK)
    goto failChunkMap;
  vmChunk->overheadMappedLimit = chunkStructLimit;

  vmChunk->vm = vm;
  res = ChunkInit(VMChunk2Chunk(vmChunk), VMArena2Arena(vmArena),
                  base, limit, pageSize, boot);
  if (res != ResOK)
    goto failChunkInit;

  BootBlockFinish(boot);

  vmChunk->sig = VMChunkSig;
  AVERT(VMChunk, vmChunk);

  *chunkReturn = VMChunk2Chunk(vmChunk);
  return ResOK;

failChunkInit:
  /* No need to unmap, as we're destroying the VM. */
failChunkMap:
failChunkAlloc:
failBootInit:
  VMDestroy(vm);
failVMCreate:
  return res;
}