Example #1
0
void BytecodeInterpreter::interpret()
{
    while (bci() < bc()->length()) {
        bool jmp = false;
        Value first;
        Value second;

        switch (bc()->getInsn(bci())) {
        case BC_STOP:
            return;

        case BC_DLOAD0:
            pushValue(0.0);
            break;
        case BC_ILOAD0:
            pushValue<int64_t>(0);
            break;
        case BC_DLOAD1:
            pushValue(1.0);
            break;
        case BC_ILOAD1:
            pushValue<int64_t>(1);
            break;
        case BC_DLOADM1:
            pushValue(-1.0);
            break;
        case BC_ILOADM1:
            pushValue<int64_t>(-1);
            break;
        case BC_DLOAD:
            pushValue(bc()->getDouble(bci() + 1));
            break;
        case BC_ILOAD:
            pushValue(bc()->getInt64(bci() + 1));
            break;
        case BC_SLOAD:
            pushValue(m_code->constantById(bc()->getUInt16(bci() + 1)).c_str());
            break;

        case BC_CALLNATIVE:
            pushValue(callNativeFunction(bc()->getUInt16(bci() + 1)));
            break;
        case BC_CALL:
            m_locals.push(bc()->getUInt16(bci() + 1));
            pushFunc(bc()->getUInt16(bci() + 1));
            pushBci();
            jmp = true;
            break;
        case BC_RETURN:
            m_locals.pop();
            popFunc();
            popBci();
            //jmp = true;
            break;

#define LOAD_VAR_N(type, n) \
    pushValue(m_locals.load(1, n).type()); \
    break;
        case BC_LOADDVAR0:
            LOAD_VAR_N(doubleValue, 0)
        case BC_LOADDVAR1:
            LOAD_VAR_N(doubleValue, 1)
        case BC_LOADDVAR2:
            LOAD_VAR_N(doubleValue, 2)
        case BC_LOADDVAR3:
            LOAD_VAR_N(doubleValue, 3)
        case BC_LOADIVAR0:
            LOAD_VAR_N(intValue, 0)
        case BC_LOADIVAR1:
            LOAD_VAR_N(intValue, 1)
        case BC_LOADIVAR2:
            LOAD_VAR_N(intValue, 2)
        case BC_LOADIVAR3:
            LOAD_VAR_N(intValue, 3)
        case BC_LOADSVAR0:
            LOAD_VAR_N(stringValue, 0)
        case BC_LOADSVAR1:
            LOAD_VAR_N(stringValue, 1)
        case BC_LOADSVAR2:
            LOAD_VAR_N(stringValue, 2)
        case BC_LOADSVAR3:
            LOAD_VAR_N(stringValue, 3)
#undef LOAD_VAR_N

#define STORE_VAR_N(type, n) \
    pushValue(m_locals.load(1, n).type()); \
    break;
        case BC_STOREDVAR0:
            STORE_VAR_N(doubleValue, 0)
        case BC_STOREDVAR1:
            STORE_VAR_N(doubleValue, 1)
        case BC_STOREDVAR2:
            STORE_VAR_N(doubleValue, 2)
        case BC_STOREDVAR3:
            STORE_VAR_N(doubleValue, 3)
        case BC_STOREIVAR0:
            STORE_VAR_N(intValue, 0)
        case BC_STOREIVAR1:
            STORE_VAR_N(intValue, 1)
        case BC_STOREIVAR2:
            STORE_VAR_N(intValue, 2)
        case BC_STOREIVAR3:
            STORE_VAR_N(intValue, 3)
        case BC_STORESVAR0:
            STORE_VAR_N(stringValue, 0)
        case BC_STORESVAR1:
            STORE_VAR_N(stringValue, 1)
        case BC_STORESVAR2:
            STORE_VAR_N(stringValue, 2)
        case BC_STORESVAR3:
            STORE_VAR_N(stringValue, 3)
#undef STORE_VAR_N

#define LOAD_VAR(type) \
    pushValue(m_locals.load(1, bc()->getUInt16(bci() + 1)).type()); \
    break;
        case BC_LOADDVAR:
            LOAD_VAR(doubleValue)
        case BC_LOADIVAR:
            LOAD_VAR(intValue)
        case BC_LOADSVAR:
            LOAD_VAR(stringValue)
#undef LOAD_CTX_VAR

#define STORE_VAR(type) \
    m_locals.store(popValue().type(), 1, bc()->getUInt16(bci() + 1)); \
    break;
        case BC_STOREDVAR:
            STORE_VAR(doubleValue)
        case BC_STOREIVAR:
            STORE_VAR(intValue)
        case BC_STORESVAR:
            STORE_VAR(stringValue)
#undef STORE_VAR

#define LOAD_CTX_VAR(type) \
    pushValue(m_locals.load(bc()->getUInt16(bci() + 1), \
                            bc()->getUInt16(bci() + 3)).type()); \
    break;
        case BC_LOADCTXDVAR:
            LOAD_CTX_VAR(doubleValue)
        case BC_LOADCTXIVAR:
            LOAD_CTX_VAR(intValue)
        case BC_LOADCTXSVAR:
            LOAD_CTX_VAR(stringValue)
#undef LOAD_CTX_VAR

#define STORE_CTX_VAR(type) \
    m_locals.store(popValue().type(), \
                   bc()->getUInt16(bci() + 1), \
                   bc()->getUInt16(bci() + 3)); \
    break;
        case BC_STORECTXDVAR:
            STORE_CTX_VAR(doubleValue)
        case BC_STORECTXIVAR:
            STORE_CTX_VAR(intValue)
        case BC_STORECTXSVAR:
            STORE_CTX_VAR(stringValue)
#undef STORE_CTX_VAR

#define CMP_JMP(op) \
    first = popValue(); \
    second = popValue(); \
    if (first.intValue() op second.intValue()) { \
        bci() += bc()->getInt16(bci() + 1) + 1; \
        jmp = true; \
    } \
    break;
        case BC_IFICMPNE:
            CMP_JMP(!=)
        case BC_IFICMPE:
            CMP_JMP(==)
        case BC_IFICMPG:
            CMP_JMP(>)
        case BC_IFICMPGE:
            CMP_JMP(>=)
        case BC_IFICMPL:
            CMP_JMP(<)
        case BC_IFICMPLE:
            CMP_JMP(<=)
#undef CMP_JMP

        case BC_JA:
            bci() += bc()->getInt16(bci() + 1) + 1;
            jmp = true;
            break;

#define BINARY_OP(type, op) \
    first = popValue(); \
    second = popValue(); \
    pushValue(first.type() op second.type()); \
    break;
        case BC_DADD:
            BINARY_OP(doubleValue, +)
        case BC_IADD:
            BINARY_OP(intValue, +)
        case BC_DSUB:
            BINARY_OP(doubleValue, -)
        case BC_ISUB:
            BINARY_OP(intValue, -)
        case BC_DMUL:
            BINARY_OP(doubleValue, *)
        case BC_IMUL:
            BINARY_OP(intValue, *)
        case BC_DDIV:
            BINARY_OP(doubleValue, /)
        case BC_IDIV:
            BINARY_OP(intValue, /)
        case BC_IMOD:
            BINARY_OP(intValue, %)
        case BC_IAOR:
            BINARY_OP(intValue, |)
        case BC_IAAND:
            BINARY_OP(intValue, &)
        case BC_IAXOR:
            BINARY_OP(intValue, ^)
#undef BINARY_OP

#define CMP(type) \
    first = popValue(); \
    second = popValue(); \
    if (first.type() < second.type()) \
        pushValue<int64_t>(-1); \
    else if (first.type() == second.type()) \
        pushValue<int64_t>(0); \
    else \
        pushValue<int64_t>(1); \
    break;
        case BC_DCMP:
            CMP(doubleValue)
        case BC_ICMP:
            CMP(intValue)
#undef CMP

        case BC_DNEG:
            pushValue(-popValue().doubleValue());
            break;
        case BC_INEG:
            pushValue(-popValue().intValue());
            break;

        case BC_S2I:
            first = popValue();
            pushValue<int64_t>(first.stringValue() != 0);
            break;
        case BC_I2D:
            pushValue<double>(popValue().intValue());
            break;
        case BC_D2I:
            pushValue<int64_t>(popValue().doubleValue());
            break;
        case BC_SWAP:
            first = popValue();
            second = popValue();
            pushValue(first);
            pushValue(second);
            break;
        case BC_POP:
            popValue();
            break;

        case BC_IPRINT:
            writeValue(std::cout, popValue(), VT_INT);
            break;
        case BC_DPRINT:
            writeValue(std::cout, popValue(), VT_DOUBLE);
            break;
        case BC_SPRINT:
            writeValue(std::cout, popValue(), VT_STRING);
            break;
        case BC_DUMP:
            first = popValue();
            writeValue(std::cerr, first, first.type());
            break;

        case BC_BREAK:
        case BC_SLOAD0:
        default:
            throw BytecodeException("Unsupported bytecode");
        }

        moveBci(jmp);
    }

    throw BytecodeException("STOP bytecode is not found");
}
Example #2
0
static unsigned int handleGoto(char * assembled, unsigned int currentPoint, unsigned int length, int threadId) {
#else
static unsigned int handleGoto(char * assembled, unsigned int currentPoint, unsigned int length) {
#endif
    return getUShort(&assembled[currentPoint]);
}

#ifdef HOST_INTERPRETER
static unsigned int handleNative(char * assembled, unsigned int currentPoint, unsigned int length, struct value_defn * returnValue, int threadId) {
#else
static unsigned int handleNative(char * assembled, unsigned int currentPoint, unsigned int length, struct value_defn * returnValue) {
#endif
    unsigned char fnCode=getUChar(&assembled[currentPoint]);
    currentPoint+=sizeof(unsigned char);
    unsigned short numArgs=getUShort(&assembled[currentPoint]);
    currentPoint+=sizeof(unsigned short);

    struct value_defn toPassValues[numArgs];
    int i;
    for (i=0; i<numArgs; i++) {
#ifdef HOST_INTERPRETER
        toPassValues[i]=getExpressionValue(assembled, &currentPoint, length, threadId);
#else
        toPassValues[i]=getExpressionValue(assembled, &currentPoint, length);
#endif
    }
    if (returnValue != NULL) {
#ifdef HOST_INTERPRETER
        callNativeFunction(returnValue, fnCode, numArgs, toPassValues, numActiveCores[threadId], localCoreId[threadId], currentSymbolEntries[threadId], symbolTable[threadId], threadId);
#else
        callNativeFunction(returnValue, fnCode, numArgs, toPassValues, numActiveCores, localCoreId, currentSymbolEntries, symbolTable);
#endif
    } else {
        struct value_defn dummy;
#ifdef HOST_INTERPRETER
        callNativeFunction(&dummy, fnCode, numArgs, toPassValues, numActiveCores[threadId], localCoreId[threadId], currentSymbolEntries[threadId], symbolTable[threadId], threadId);
#else
        callNativeFunction(&dummy, fnCode, numArgs, toPassValues, numActiveCores, localCoreId, currentSymbolEntries, symbolTable);
#endif
    }
    return currentPoint;
}

/**
 * Calls some function and stores the call point in the function call stack for returning from this function
 */
#ifdef HOST_INTERPRETER
static unsigned int handleFnCall(char * assembled, unsigned int currentPoint, unsigned int * functionAddress, unsigned int length, char calledByVar, int threadId) {
#else
static unsigned int handleFnCall(char * assembled, unsigned int currentPoint, unsigned int * functionAddress, unsigned int length, char calledByVar) {
#endif
    unsigned short fnAddress;
    if (calledByVar) {
#ifdef HOST_INTERPRETER
        struct symbol_node* callVar=getVariableSymbol(getUShort(&assembled[currentPoint]), fnLevel[threadId], threadId, 1);
#else
        struct symbol_node* callVar=getVariableSymbol(getUShort(&assembled[currentPoint]), fnLevel, 1);
#endif
        if (callVar->value.type != FN_ADDR_TYPE) raiseError(ERR_FNCALL_VAR_NOT_CONTAINING_FN_PTR);
        char *ptr;
        cpy(&ptr, callVar->value.data, sizeof(char*));
        fnAddress=getUShort(ptr);
    } else {
        fnAddress=getUShort(&assembled[currentPoint]);
    }
    currentPoint+=sizeof(unsigned short);

    unsigned short fnNumArgs=getUShort(&assembled[fnAddress]);
    fnAddress+=sizeof(unsigned short);

    unsigned short callerNumArgs=getUShort(&assembled[currentPoint]);
    currentPoint+=sizeof(unsigned short);
    struct symbol_node* srcSymbol, *targetSymbol;
    int i, numArgs;
    numArgs=fnNumArgs > callerNumArgs ? fnNumArgs : callerNumArgs;
    for (i=0; i<numArgs; i++) {
        if (i<callerNumArgs && i<fnNumArgs) {
#ifdef HOST_INTERPRETER
            srcSymbol=getVariableSymbol(getUShort(&assembled[currentPoint]), fnLevel[threadId], threadId, 0);
            targetSymbol=getVariableSymbol(getUShort(&assembled[fnAddress]), fnLevel[threadId]+1, threadId, 0);
#else
            srcSymbol=getVariableSymbol(getUShort(&assembled[currentPoint]), fnLevel, 0);
            targetSymbol=getVariableSymbol(getUShort(&assembled[fnAddress]), fnLevel+1, 0);
#endif
            targetSymbol->state=ALIAS;
            targetSymbol->alias=srcSymbol->id;
        }
        if (i<callerNumArgs) currentPoint+=sizeof(unsigned short);
        if (i<fnNumArgs) fnAddress+=sizeof(unsigned short);
    }
    *functionAddress=fnAddress;
    return currentPoint;
}

/**
 * Loop iteration
 */
#ifdef HOST_INTERPRETER
static unsigned int handleFor(char * assembled, unsigned int currentPoint, unsigned int length, int threadId) {
#else
static unsigned int handleFor(char * assembled, unsigned int currentPoint, unsigned int length) {
#endif
    unsigned short loopIncrementerId=getUShort(&assembled[currentPoint]);
    currentPoint+=sizeof(unsigned short);
    unsigned short loopVariantId=getUShort(&assembled[currentPoint]);
    currentPoint+=sizeof(unsigned short);
#ifdef HOST_INTERPRETER
    struct symbol_node* incrementVarSymbol=getVariableSymbol(loopIncrementerId, fnLevel[threadId], threadId, 1);
    struct symbol_node* variantVarSymbol=getVariableSymbol(loopVariantId, fnLevel[threadId], threadId, 1);
    struct value_defn expressionVal=getExpressionValue(assembled, &currentPoint, length, threadId);
#else
    struct symbol_node* incrementVarSymbol=getVariableSymbol(loopIncrementerId, fnLevel, 1);
    struct symbol_node* variantVarSymbol=getVariableSymbol(loopVariantId, fnLevel, 1);
    struct value_defn expressionVal=getExpressionValue(assembled, &currentPoint, length);
#endif
    unsigned short blockLen=getUShort(&assembled[currentPoint]);
    currentPoint+=sizeof(unsigned short);

    char * ptr;
    int singleSize, arrSize=1, i, headersize;
    unsigned char numDims;
    cpy(&ptr, expressionVal.data, sizeof(char*));
    cpy(&numDims, ptr, sizeof(unsigned char));
    numDims=numDims & 0xF;
    for (i=0; i<numDims; i++) {
        cpy(&singleSize, &ptr[1+(i*sizeof(unsigned int))], sizeof(unsigned int));
        arrSize*=singleSize;
    }
    headersize=sizeof(unsigned char) + (sizeof(unsigned int) * numDims);
    struct value_defn varVal=getVariableValue(incrementVarSymbol, -1);
    int incrementVal=getInt(varVal.data);
    if (incrementVal < arrSize) {
        struct value_defn nextElement;
        nextElement.type=expressionVal.type;
        cpy(&nextElement.data, ptr+((incrementVal*sizeof(int)) + headersize), sizeof(int));
        setVariableValue(variantVarSymbol, nextElement, -1);
        return currentPoint;
    }
    currentPoint+=(blockLen+sizeof(unsigned short)+sizeof(unsigned char));
    return currentPoint;
}

/**
 * Conditional, with or without else block
 */
#ifdef HOST_INTERPRETER
static unsigned int handleIf(char * assembled, unsigned int currentPoint, unsigned int length, int threadId) {
    int conditionalResult=determine_logical_expression(assembled, &currentPoint, length, threadId);
#else
static unsigned int handleIf(char * assembled, unsigned int currentPoint, unsigned int length) {
    int conditionalResult=determine_logical_expression(assembled, &currentPoint, length);
#endif
    if (conditionalResult) return currentPoint+sizeof(unsigned short);
    unsigned short blockLen=getUShort(&assembled[currentPoint]);
    return currentPoint+sizeof(unsigned short)+blockLen;
}