R runner(SimpleInterpreter *p, void *func, size_t paramsCount) {
     switch (paramsCount) {
         case 0:
             return nativeCaller<R>(func);
         case 1:
             return Collector<0, 1, R, decltype(make_tuple())>::run(p, func, make_tuple());
         case 2:
             return Collector<0, 2, R, decltype(make_tuple())>::run(p, func, make_tuple());
         case 3:
             return Collector<0, 3, R, decltype(make_tuple())>::run(p, func, make_tuple());
         case 4:
             return Collector<0, 4, R, decltype(make_tuple())>::run(p, func, make_tuple());
         default:
             throw InterpretationError("Non-jit native caller can't process " + to_string(paramsCount) + " function parameters. Call AmJit insted");
     }
 }
 static R run(SimpleInterpreter *inter, void* f, T a) {
     auto p = inter->loadVariable(index);
     switch (p._type) {
         case VT_DOUBLE:
             return Collector<index + 1, size, R, decltype(tuple_cat(a, make_tuple(p.getDoubleValue())))>::
                     run(inter, f, tuple_cat(a, make_tuple(p.getDoubleValue())));
         case VT_INT:
             return Collector<index + 1, size, R, decltype(tuple_cat(a, make_tuple(p.getIntValue())))>::
                     run(inter, f, tuple_cat(a, make_tuple(p.getIntValue())));
         case VT_STRING:
             return Collector<index + 1, size, R, decltype(tuple_cat(a, make_tuple(p.getStringValue())))>::
                     run(inter, f, tuple_cat(a, make_tuple(p.getStringValue())));
         default:
             throw InterpretationError("Unknown type of " + to_string(index) + " function parameter");
     }
 }
        void callNative(uint16_t id) {
            const Signature *signature;
            const std::string *name;
            void *nativeFunctionAddress = (void *) nativeById(id, &signature, &name);
            if (!nativeFunctionAddress) {
                throw InterpretationError("Native function not found");
            }

            size_t paramsCount = signature->size() - 1;
            VarType returnType = signature->at(0).first;
            if (paramsCount <= 4) {
                callNativeFunctionViaTemplateMagic(nativeFunctionAddress, paramsCount, returnType);
            } else {
                callNativeFunctionViaAsmJit(nativeFunctionAddress, signature, returnType);
            }
        }
示例#4
0
void Pattern::apply(Tree *pTree) const
{
	// do interpretation
	text::TokenSequence &text = *pTree->refText();
	Interpreter &interp = const_cast<Pattern *>(this)->interp;
	interp.setCutoffValue(cutoffValue * (long long)text.size());
	interp.swapVariable(varName, &text);
	boost::int32_t errorPc = interp.interpret(0);
	if (errorPc > 0) {
		interp.swapVariable(varName, &text);
		throw InterpretationError((boost::format("PC = %d, ErrorCode = %d") % errorPc % (100 + interp.getError().code)).str());
	}
	else {
		interp.swapVariable(varName, &text);
	}
}
 void SimpleInterpreter::callNativeFunctionViaTemplateMagic(void* f, size_t params, VarType returnType) {
     switch (returnType) {
         case VT_VOID:
             runner<void>(this, f, params);
             break;
         case VT_DOUBLE:
             pushVariable(runner<double>(this, f, params));
             break;
         case VT_INT:
             pushVariable(runner<signedIntType>(this, f, params));
             break;
         case VT_STRING:
             pushVariable(runner<char const*>(this, f, params));
             break;
         default:
             throw InterpretationError("Wrong native function return type");
     }
 }
        void storeVariable(unsignedIntType contextID, unsignedIntType id) {
            while (vars.size() <= contextID){
                vars.push_back(vector<Variables>());
            }
            while(callsCounter.size() <= contextID) {
                callsCounter.push_back(0);
            }

            vector<Variables> &currentRecursiveScope = vars[contextID];
            while (currentRecursiveScope.size() <= callsCounter[contextID]) {
                currentRecursiveScope.push_back(Variables());
            }

            Variables &local_vars = currentRecursiveScope[callsCounter[contextID]];
            while (local_vars.size() <= id) {
                local_vars.push_back(TypedVariable(VT_INT));
            }
            if (local_vars.size() > MAX_VARS_COUNT) {
                throw InterpretationError("Too many variables");
            }
            local_vars[id] = popVariable();
        }
    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;
        }
    }