Ejemplo n.º 1
0
Archivo: vm.cpp Proyecto: 0x7CFE/llst
SmalltalkVM::TExecuteResult SmalltalkVM::execute(TProcess* p, uint32_t ticks)
{
    // Protecting the process pointer
    hptr<TProcess> currentProcess = newPointer(p);

    assert(currentProcess->context != 0);
    assert(currentProcess->context->method != 0);

    // Initializing an execution context
    TVMExecutionContext ec(m_memoryManager, this);
    ec.currentContext = currentProcess->context;
    ec.loadPointers(); // Loads bytePointer & stackTop

    while (true)
    {
        assert(ec.currentContext != 0);
        assert(ec.currentContext->method != 0);
        assert(ec.currentContext->stack != 0);
        assert(ec.bytePointer <= ec.currentContext->method->byteCodes->getSize());
        assert(ec.currentContext->arguments->getSize() >= 1);
        assert(ec.currentContext->arguments->getField(0) != 0);

        // Initializing helper references
        TByteObject&  byteCodes = * ec.currentContext->method->byteCodes;

        TObjectArray& temporaries       = * ec.currentContext->temporaries;
        TObjectArray& arguments         = * ec.currentContext->arguments;
        TObjectArray& instanceVariables = * arguments.getField<TObjectArray>(0);
        TSymbolArray& literals          = * ec.currentContext->method->literals;

        if (ticks && (--ticks == 0)) {
            // Time frame expired
            ec.storePointers();
            currentProcess->context = ec.currentContext;
            currentProcess->result  = ec.returnedValue;

            return returnTimeExpired;
        }

        // Decoding the instruction
        const uint16_t lastBytePointer = ec.bytePointer;
        ec.instruction = st::InstructionDecoder::decodeAndShiftPointer(byteCodes, ec.bytePointer);

        // And executing it
        switch (ec.instruction.getOpcode()) {
            case opcode::pushInstance:    ec.stackPush(instanceVariables[ec.instruction.getArgument()]); break;
            case opcode::pushArgument:    ec.stackPush(arguments[ec.instruction.getArgument()]);         break;
            case opcode::pushTemporary:   ec.stackPush(temporaries[ec.instruction.getArgument()]);       break;
            case opcode::pushLiteral:     ec.stackPush(literals[ec.instruction.getArgument()]);          break;
            case opcode::pushConstant:    doPushConstant(ec);                                  break;
            case opcode::pushBlock:       doPushBlock(ec);                                     break;

            case opcode::assignTemporary: temporaries[ec.instruction.getArgument()] = ec.stackLast();    break;
            case opcode::assignInstance: {
                TObject*  newValue   =   ec.stackLast();
                TObject** objectSlot = & instanceVariables[ec.instruction.getArgument()];

                // Checking whether we need to register current object slot in the GC
                checkRoot(newValue, objectSlot);

                // Performing the assignment
                *objectSlot = newValue;
            } break;

            case opcode::markArguments: doMarkArguments(ec); break;

            case opcode::sendMessage:   doSendMessage(ec);   break;
            case opcode::sendUnary:     doSendUnary(ec);     break;
            case opcode::sendBinary:    doSendBinary(ec);    break;

            case opcode::doPrimitive: {
                TExecuteResult result = doPrimitive(currentProcess, ec);
                if (result != returnNoReturn)
                    return result;
            } break;

            case opcode::doSpecial: {
                TExecuteResult result = doSpecial(currentProcess, ec);
                if (result != returnNoReturn)
                    return result;
            } break;

            default:
                std::fprintf(stderr, "VM: Invalid opcode %d at offset %d in method ", ec.instruction.getOpcode(), lastBytePointer);
                std::fprintf(stderr, "'%s'\n", ec.currentContext->method->name->toString().c_str() );
                std::exit(1);
        }
    }
}
Ejemplo n.º 2
0
void Interpreter::Start() {
    // initialization
    method = GetFrame()->GetMethod();
    currentBytecodes = method->GetBytecodes();

    void* loopTargets[] = {
        &&LABEL_BC_HALT,
        &&LABEL_BC_DUP,
        &&LABEL_BC_PUSH_LOCAL,
        &&LABEL_BC_PUSH_ARGUMENT,
        &&LABEL_BC_PUSH_FIELD,
        &&LABEL_BC_PUSH_BLOCK,
        &&LABEL_BC_PUSH_CONSTANT,
        &&LABEL_BC_PUSH_GLOBAL,
        &&LABEL_BC_POP,
        &&LABEL_BC_POP_LOCAL,
        &&LABEL_BC_POP_ARGUMENT,
        &&LABEL_BC_POP_FIELD,
        &&LABEL_BC_SEND,
        &&LABEL_BC_SUPER_SEND,
        &&LABEL_BC_RETURN_LOCAL,
        &&LABEL_BC_RETURN_NON_LOCAL,
        &&LABEL_BC_JUMP_IF_FALSE,
        &&LABEL_BC_JUMP_IF_TRUE,
        &&LABEL_BC_JUMP
    };

    goto *loopTargets[currentBytecodes[bytecodeIndexGlobal]];

    //
    // THIS IS THE former interpretation loop
    LABEL_BC_HALT:
      PROLOGUE(1);
      return; // handle the halt bytecode

    LABEL_BC_DUP:
      PROLOGUE(1);
      doDup();
      DISPATCH_NOGC();

    LABEL_BC_PUSH_LOCAL:       
      PROLOGUE(3);
      doPushLocal(bytecodeIndexGlobal - 3);
      DISPATCH_NOGC();

    LABEL_BC_PUSH_ARGUMENT:
      PROLOGUE(3);
      doPushArgument(bytecodeIndexGlobal - 3);
      DISPATCH_NOGC();

    LABEL_BC_PUSH_FIELD:
      PROLOGUE(2);
      doPushField(bytecodeIndexGlobal - 2);
      DISPATCH_NOGC();

    LABEL_BC_PUSH_BLOCK:
      PROLOGUE(2);
      doPushBlock(bytecodeIndexGlobal - 2);
      DISPATCH_GC();

    LABEL_BC_PUSH_CONSTANT:
      PROLOGUE(2);
      doPushConstant(bytecodeIndexGlobal - 2);
      DISPATCH_NOGC();

    LABEL_BC_PUSH_GLOBAL:
      PROLOGUE(2);
      doPushGlobal(bytecodeIndexGlobal - 2);
      DISPATCH_GC();

    LABEL_BC_POP:
      PROLOGUE(1);
      doPop();
      DISPATCH_NOGC();

    LABEL_BC_POP_LOCAL:
      PROLOGUE(3);
      doPopLocal(bytecodeIndexGlobal - 3);
      DISPATCH_NOGC();

    LABEL_BC_POP_ARGUMENT:
      PROLOGUE(3);
      doPopArgument(bytecodeIndexGlobal - 3);
      DISPATCH_NOGC();

    LABEL_BC_POP_FIELD:
      PROLOGUE(2);
      doPopField(bytecodeIndexGlobal - 2);
      DISPATCH_NOGC();

    LABEL_BC_SEND:
      PROLOGUE(2);
      doSend(bytecodeIndexGlobal - 2);
      DISPATCH_GC();

    LABEL_BC_SUPER_SEND:
      PROLOGUE(2);
      doSuperSend(bytecodeIndexGlobal - 2);
      DISPATCH_GC();

    LABEL_BC_RETURN_LOCAL:
      PROLOGUE(1);
      doReturnLocal();
      DISPATCH_NOGC();

    LABEL_BC_RETURN_NON_LOCAL:
      PROLOGUE(1);
      doReturnNonLocal();
      DISPATCH_NOGC();

    LABEL_BC_JUMP_IF_FALSE:
      PROLOGUE(5);
      doJumpIfFalse(bytecodeIndexGlobal - 5);
      DISPATCH_NOGC();

    LABEL_BC_JUMP_IF_TRUE:
      PROLOGUE(5);
      doJumpIfTrue(bytecodeIndexGlobal - 5);
      DISPATCH_NOGC();

    LABEL_BC_JUMP:
      PROLOGUE(5);
      doJump(bytecodeIndexGlobal - 5);
      DISPATCH_NOGC();
}

VMFrame* Interpreter::PushNewFrame(VMMethod* method) {
    SetFrame(GetUniverse()->NewFrame(GetFrame(), method));
    return GetFrame();
}