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; } }
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; } }
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; } } }
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 ¤tIndex = 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; } }