Ejemplo n.º 1
0
bool StackMachine::ifSatisfied(Instruction condition, vm_int_t value) {
    switch(condition) {
    case BC_IFICMPE:
        return value == 0L;
    case BC_IFICMPNE:
        return value != 0L;
    case BC_IFICMPL:
        return value < 0L;
    case BC_IFICMPLE:
        return value <= 0L;
    case BC_IFICMPG:
        return value > 0L;
    case BC_IFICMPGE:
        return value >= 0L;
    default:
        throwError("unsupported condition=" + string(bytecodeName(condition)));
        return false;
    }
}
Ejemplo n.º 2
0
void interpreter::process_func()
{
    for (size_t pos = 0; pos < func_->bytecode()->length();)
    {
        size_t length;
        const Instruction insn = func_->bytecode()->getInsn(pos);
        const char* name = bytecodeName(insn, &length);

        if (func_->has_local_context(pos))
            context_id_ = func_->local_context(pos);

        pos_ = pos + 1;
        
        return_ = false;
        process_insn(insn);
        if (return_)
        {
            return_ = false;
            break;
        }

        pos += length;
    }
}
Ejemplo n.º 3
0
void StackMachine::run() {
    while (true) {
        Instruction current_instruction = currentBytecode().getInsn(current_location_++);
        char const * v  = 0;
        switch (current_instruction) {
        case BC_DLOAD:
            push(currentBytecode().getDouble(current_location_));
            current_location_ += sizeof(double);
            break;
        case BC_DLOAD0:
            push(0.0);
            break;
        case BC_DLOAD1:
            push(1.0);
            break;
        case BC_ILOAD:
            push(currentBytecode().getInt64(current_location_));
            current_location_ += sizeof(vm_int_t);
            break;
        case BC_ILOAD0:
            push(vm_int_t(0L));
            break;
        case BC_ILOAD1:
            push(vm_int_t(1L));
            break;
        case BC_SLOAD:
            push(code_->constantById(getCurrent2BytesAndShiftLocation()).c_str());
            break;
        case BC_SLOAD0:
            push(__EMPTY_STRING);
            break;
        case BC_DADD:
            PUSH_BINARY_RESULT(double, std::plus<double>());
            break;
        case BC_DSUB:
            PUSH_BINARY_RESULT(double, std::minus<double>());
            break;
        case BC_DMUL:
            PUSH_BINARY_RESULT(double, std::multiplies<double>());
            break;
        case BC_DDIV:
            PUSH_BINARY_RESULT(double, std::divides<double>());
            break;
        case BC_IADD:
            PUSH_BINARY_RESULT(vm_int_t, std::plus<vm_int_t>());
            break;
        case BC_ISUB:
            PUSH_BINARY_RESULT(vm_int_t, std::minus<vm_int_t>());
            break;
        case BC_IMUL:
            PUSH_BINARY_RESULT(vm_int_t, std::multiplies<vm_int_t>());
            break;
        case BC_IDIV:
            PUSH_BINARY_RESULT(vm_int_t, std::divides<vm_int_t>());
            break;
        case BC_IMOD:
            PUSH_BINARY_RESULT(vm_int_t, std::modulus<vm_int_t>());
            break;
        case BC_IAOR:
            PUSH_BINARY_RESULT(vm_int_t, std::bit_or<vm_int_t>());
            break;
        case BC_IAAND:
            PUSH_BINARY_RESULT(vm_int_t, std::bit_and<vm_int_t>());
            break;
        case BC_IAXOR:
            PUSH_BINARY_RESULT(vm_int_t, std::bit_xor<vm_int_t>());
            break;
        case BC_DCMP:
            PUSH_BINARY_RESULT_(double, vm_int_t, cmp<double>);
            break;
        case BC_ICMP:
            PUSH_BINARY_RESULT(vm_int_t, cmp<vm_int_t>);
            break;
        case BC_DNEG:
            push(-popDouble());
            break;
        case BC_INEG:
            push(-popInt());
            break;
        case BC_IPRINT:
            os_ << popInt();
            os_.flush();
            break;
        case BC_DPRINT:
            os_ << popDouble();
            os_.flush();
            break;
        case BC_SPRINT:
            v = popString();
            os_ << (v == 0 ? "" : v);
            os_.flush();
            break;
        case BC_I2D:
            push((double) popInt());
            break;
        case BC_S2I:
            v = popString();
            try {
                push((vm_int_t) v);
            } catch (std::exception & e) {
                throwError("S2I conversion error: " + string(v));
            }
            break;
        case BC_D2I:
            push((vm_int_t) popDouble());
            break;
        case BC_POP:
            pop();
            break;
        case BC_LOADDVAR0:
            loadLocalVar<double>(0);
            break;
        case BC_LOADDVAR1:
            loadLocalVar<double>(1);
            break;
        case BC_LOADDVAR2:
            loadLocalVar<double>(2);
            break;
        case BC_LOADDVAR3:
            loadLocalVar<double>(3);
            break;
        case BC_LOADDVAR:
            loadLocalVar<double>(getCurrent2BytesAndShiftLocation());
            break;
        case BC_LOADIVAR0:
            loadLocalVar<vm_int_t>(0);
            break;
        case BC_LOADIVAR1:
            loadLocalVar<vm_int_t>(1);
            break;
        case BC_LOADIVAR2:
            loadLocalVar<vm_int_t>(2);
            break;
        case BC_LOADIVAR3:
            loadLocalVar<vm_int_t>(3);
            break;
        case BC_LOADIVAR:
            loadLocalVar<vm_int_t>(getCurrent2BytesAndShiftLocation());
            break;
        case BC_LOADSVAR0:
            loadLocalVar<vm_str_t>(0);
            break;
        case BC_LOADSVAR1:
            loadLocalVar<vm_str_t>(1);
            break;
        case BC_LOADSVAR2:
            loadLocalVar<vm_str_t>(2);
            break;
        case BC_LOADSVAR3:
            loadLocalVar<vm_str_t>(3);
            break;
        case BC_LOADSVAR:
            loadLocalVar<vm_str_t>(getCurrent2BytesAndShiftLocation());
            break;
        case BC_STOREDVAR0:
            storeLocalVar<double>(0);
            break;
        case BC_STOREDVAR1:
            storeLocalVar<double>(1);
            break;
        case BC_STOREDVAR2:
            storeLocalVar<double>(2);
            break;
        case BC_STOREDVAR3:
            storeLocalVar<double>(3);
            break;
        case BC_STOREDVAR:
            storeLocalVar<double>(getCurrent2BytesAndShiftLocation());
            break;
        case BC_STOREIVAR0:
            storeLocalVar<vm_int_t>(0);
            break;
        case BC_STOREIVAR1:
            storeLocalVar<vm_int_t>(1);
            break;
        case BC_STOREIVAR2:
            storeLocalVar<vm_int_t>(2);
            break;
        case BC_STOREIVAR3:
            storeLocalVar<vm_int_t>(3);
            break;
        case BC_STOREIVAR:
            storeLocalVar<vm_int_t>(getCurrent2BytesAndShiftLocation());
            break;
        case BC_STORESVAR0:
            storeLocalVar<vm_str_t>(0);
            break;
        case BC_STORESVAR1:
            storeLocalVar<vm_str_t>(1);
            break;
        case BC_STORESVAR2:
            storeLocalVar<vm_str_t>(2);
            break;
        case BC_STORESVAR3:
            storeLocalVar<vm_str_t>(3);
            break;
        case BC_STORESVAR:
            storeLocalVar<vm_str_t>(getCurrent2BytesAndShiftLocation());
            break;
        case BC_LOADCTXDVAR:
            processLoadContextVar<double>();
            break;
        case BC_LOADCTXIVAR:
            processLoadContextVar<vm_int_t>();
            break;
        case BC_LOADCTXSVAR:
            processLoadContextVar<vm_str_t>();
            break;
        case BC_STORECTXDVAR:
            processStoreContextVar<double>();
            break;
        case BC_STORECTXIVAR:
            processStoreContextVar<vm_int_t>();
            break;
        case BC_STORECTXSVAR:
            processStoreContextVar<vm_str_t>();
            break;
        case BC_JA:
            current_location_ = calculateTransitionAndShiftLocation();
            continue;
        case BC_IFICMPE:
        case BC_IFICMPNE:
        case BC_IFICMPL:
        case BC_IFICMPLE:
        case BC_IFICMPG:
        case BC_IFICMPGE: {
            index_t transition = calculateTransitionAndShiftLocation();

            vm_int_t a = popInt();
            vm_int_t b = popInt();

            if (ifSatisfied(current_instruction, cmp(a, b))) {
                current_location_= transition;
                continue;
            }
            break;
        }
        case BC_CALL:
            processCall(getCurrent2BytesAndShiftLocation());
            break;
        case BC_CALLNATIVE:
            processNativeCall(getCurrent2BytesAndShiftLocation());
            continue;
        case BC_RETURN:
            if (processReturn()) {
                return;
            }
            continue;
        default:
            throwError("unsupported insn=" + string(bytecodeName(current_instruction)));
            return;
        }
    }
}
Ejemplo n.º 4
0
    void SimpleInterpreter::run(ostream &out) {
        stack.resize(50);
        bytecodes.clear();
        indices.clear();
        vars.clear();
        bytecodes.push_back(bytecode);
        indices.push_back(0);
        contextID.push_back(0);
        callsCounter.push_back(0);
        SP = 0;

        while (!bytecodes.empty()) {
            indexType &currentIndex = indices.back();
            Bytecode &bytecode = *bytecodes.back();
            Instruction instruction = bytecode.getInsn(currentIndex);
            size_t instructionLength = bytecodeLength(instruction);
#ifdef LOG_INTERPRETER
            const char* bcName = bytecodeName(instruction, 0);
            cout << "index: " << currentIndex << ", instruction: " << bcName << endl;
#endif
            switch (instruction) {
                case BC_DLOAD: pushVariable(bytecode.getDouble(currentIndex + 1));
                    break;
                case BC_ILOAD: pushVariable(bytecode.getInt64(currentIndex + 1));
                    break;
                case BC_SLOAD: pushVariable(constantById(bytecode.getUInt16(currentIndex + 1)).c_str());
                    break;
                case BC_DLOAD0: pushVariable(0.0);
                    break;
                case BC_ILOAD0: pushVariable((signedIntType) 0);
                    break;
                case BC_SLOAD0: pushVariable("");
                    break;
                case BC_DLOAD1: pushVariable(1.0);
                    break;
                case BC_ILOAD1: pushVariable((signedIntType) 1);
                    break;
                case BC_DLOADM1: pushVariable(-1.0);
                    break;
                case BC_ILOADM1: pushVariable((signedIntType) - 1);
                    break;
                case BC_DADD: binary_operation(VT_DOUBLE, add<double>);
                    break;
                case BC_IADD: binary_operation(VT_INT, add < signedIntType > );
                    break;
                case BC_DSUB: binary_operation(VT_DOUBLE, sub<double>);
                    break;
                case BC_ISUB: binary_operation(VT_INT, sub < signedIntType > );
                    break;
                case BC_DMUL: binary_operation(VT_DOUBLE, mul<double>);
                    break;
                case BC_IMUL: binary_operation(VT_INT, mul < signedIntType > );
                    break;
                case BC_DDIV: binary_operation(VT_DOUBLE, _div<double>);
                    break;
                case BC_IDIV: binary_operation(VT_INT, _div < signedIntType > );
                    break;
                case BC_IMOD: binary_operation(VT_INT, mod < signedIntType > );
                    break;
                case BC_DNEG: unary_operation(VT_DOUBLE, neg<double>);
                    break;
                case BC_INEG: unary_operation(VT_INT, neg < signedIntType > );
                    break;
                case BC_IAOR: binary_operation(VT_INT, _or < signedIntType > );
                    break;
                case BC_IAAND: binary_operation(VT_INT, _and < signedIntType > );
                    break;
                case BC_IAXOR: binary_operation(VT_INT, _xor < signedIntType > );
                    break;
                case BC_IPRINT: out << popVariable().getIntValue();
                    out.flush();
                    break;
                case BC_DPRINT: out << popVariable().getDoubleValue();
                    out.flush();
                    break;
                case BC_SPRINT: out << popVariable().getStringValue();
                    out.flush();
                    break;
                case BC_SWAP: {
                    auto v1 = popVariable();
                    auto v2 = popVariable();
                    pushVariable(v1);
                    pushVariable(v2);
                    break;
                }
                case BC_STOREDVAR0:
                case BC_STOREIVAR0:
                case BC_STORESVAR0: storeVariable(0);
                    break;
                case BC_STOREDVAR1:
                case BC_STOREIVAR1:
                case BC_STORESVAR1: storeVariable(1);
                    break;
                case BC_STOREDVAR2:
                case BC_STOREIVAR2:
                case BC_STORESVAR2: storeVariable(2);
                    break;
                case BC_STOREDVAR3:
                case BC_STOREIVAR3:
                case BC_STORESVAR3: storeVariable(3);
                    break;
                case BC_LOADDVAR:
                case BC_LOADIVAR:
                case BC_LOADSVAR: pushVariable(loadVariable(bytecode.getUInt16(currentIndex + 1)));
                    break;
                case BC_LOADDVAR0:
                case BC_LOADIVAR0:
                case BC_LOADSVAR0: pushVariable(loadVariable(0));
                    break;
                case BC_LOADDVAR1:
                case BC_LOADIVAR1:
                case BC_LOADSVAR1: pushVariable(loadVariable(1));
                    break;
                case BC_LOADIVAR2:
                case BC_LOADSVAR2:
                case BC_LOADDVAR2: pushVariable(loadVariable(2));
                    break;
                case BC_LOADDVAR3:
                case BC_LOADIVAR3:
                case BC_LOADSVAR3: pushVariable(loadVariable(3));
                    break;
                case BC_STOREDVAR:
                case BC_STOREIVAR:
                case BC_STORESVAR: storeVariable(bytecode.getUInt16(currentIndex + 1));
                    break;
                case BC_LOADCTXDVAR:
                case BC_LOADCTXIVAR:
                case BC_LOADCTXSVAR: pushVariable(loadVariable(bytecode.getUInt16(currentIndex + 1), bytecode.getUInt16(currentIndex + 3)));
                    break;
                case BC_STORECTXDVAR:
                case BC_STORECTXIVAR:
                case BC_STORECTXSVAR: storeVariable(bytecode.getUInt16(currentIndex + 1), bytecode.getUInt16(currentIndex + 3));
                    break;
                case BC_DCMP: binary_operation<double, signedIntType>(VT_DOUBLE, _cmp<double>);
                    break;
                case BC_ICMP: binary_operation(VT_INT, _cmp < signedIntType > );
                    break;
                case BC_JA: {
                    currentIndex += bytecode.getInt16(currentIndex + 1) + 1;
                    continue;
                }
                case BC_IFICMPNE: {
                    if (!check_condition(_neq<signedIntType>))
                        break;
                    currentIndex += bytecode.getInt16(currentIndex + 1) + 1;
                    continue;
                }
                case BC_IFICMPE: {
                    if (!check_condition(_eq<signedIntType>))
                        break;
                    currentIndex += bytecode.getInt16(currentIndex + 1) + 1;
                    continue;
                }
                case BC_IFICMPG: {
                    if (!check_condition(_g<signedIntType>))
                        break;
                    currentIndex += bytecode.getInt16(currentIndex + 1) + 1;
                    continue;
                }
                case BC_IFICMPGE: {
                    if (!check_condition(_ge<signedIntType>))
                        break;
                    currentIndex += bytecode.getInt16(currentIndex + 1) + 1;
                    continue;
                }
                case BC_IFICMPL: {
                    if (!check_condition(_l<signedIntType>))
                        break;
                    currentIndex += bytecode.getInt16(currentIndex + 1) + 1;
                    continue;
                }
                case BC_IFICMPLE: {
                    if (!check_condition(_le<signedIntType>))
                        break;
                    currentIndex += bytecode.getInt16(currentIndex + 1) + 1;
                    continue;
                }
                case BC_STOP: {
                    indices.clear();
                    bytecodes.clear();
                    continue;
                }
                case BC_CALLNATIVE: {
                    callNative(bytecode.getUInt16(currentIndex + 1));
                    break;
                }
                case BC_CALL: {
                    TranslatedFunction *f = functionById(bytecode.getUInt16(currentIndex + 1));
                    bytecodes.push_back(static_cast<BytecodeFunction *>(f)->bytecode());
                    indices.push_back(0);
                    contextID.push_back(f->id());
                    detectCallWithFunctionID(contextID.back());
                    continue;
                }
                case BC_RETURN: {
                    indices.pop_back();
                    bytecodes.pop_back();
                    if (!indices.empty()) {
                        indices.back() += bytecodeLength(BC_CALL);
                    }
                    if (callsCounter[contextID.back()] > 0) {
                        callsCounter[contextID.back()]--;
                    }
                    contextID.pop_back();
                    continue;
                }
                case BC_I2D: pushVariable((double) popVariable().getIntValue());
                    break;
                case BC_D2I: pushVariable((signedIntType) popVariable().getDoubleValue());
                    break;
                case BC_S2I: pushVariable((signedIntType) popVariable().getStringValue());
                    break;
                case BC_BREAK: break;
                case BC_INVALID: throw InterpretationError("BC_Invalid instruction");
                default: throw InterpretationError(string("Unknown interpreting instruction: ") + bytecodeName(instruction, 0));
            }
            currentIndex += instructionLength;
        }
    }