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"); }
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, ¤tPoint, length, threadId); #else toPassValues[i]=getExpressionValue(assembled, ¤tPoint, 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, ¤tPoint, 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, ¤tPoint, 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, ¤tPoint, length, threadId); #else static unsigned int handleIf(char * assembled, unsigned int currentPoint, unsigned int length) { int conditionalResult=determine_logical_expression(assembled, ¤tPoint, length); #endif if (conditionalResult) return currentPoint+sizeof(unsigned short); unsigned short blockLen=getUShort(&assembled[currentPoint]); return currentPoint+sizeof(unsigned short)+blockLen; }