don't create a new virtual machine for each script and frame

actorid
Marc Zinnschlag 14 years ago
parent a133920eb0
commit 80691250ec

@ -223,11 +223,11 @@ namespace MWGui
try try
{ {
ConsoleInterpreterContext interpreterContext (*this, mEnvironment, MWWorld::Ptr()); ConsoleInterpreterContext interpreterContext (*this, mEnvironment, MWWorld::Ptr());
Interpreter::Interpreter interpreter (interpreterContext); Interpreter::Interpreter interpreter;
MWScript::installOpcodes (interpreter); MWScript::installOpcodes (interpreter);
std::vector<Interpreter::Type_Code> code; std::vector<Interpreter::Type_Code> code;
output.getCode (code); output.getCode (code);
interpreter.run (&code[0], code.size()); interpreter.run (&code[0], code.size(), interpreterContext);
} }
catch (const std::exception& error) catch (const std::exception& error)
{ {

@ -12,8 +12,6 @@
#include <components/compiler/scanner.hpp> #include <components/compiler/scanner.hpp>
#include <components/compiler/context.hpp> #include <components/compiler/context.hpp>
#include <components/interpreter/interpreter.hpp>
#include "extensions.hpp" #include "extensions.hpp"
namespace MWScript namespace MWScript
@ -21,7 +19,8 @@ namespace MWScript
ScriptManager::ScriptManager (const ESMS::ESMStore& store, bool verbose, ScriptManager::ScriptManager (const ESMS::ESMStore& store, bool verbose,
Compiler::Context& compilerContext) Compiler::Context& compilerContext)
: mErrorHandler (std::cerr), mStore (store), mVerbose (verbose), : mErrorHandler (std::cerr), mStore (store), mVerbose (verbose),
mCompilerContext (compilerContext), mParser (mErrorHandler, mCompilerContext) mCompilerContext (compilerContext), mParser (mErrorHandler, mCompilerContext),
mOpcodesInstalled (false)
{} {}
bool ScriptManager::compile (const std::string& name) bool ScriptManager::compile (const std::string& name)
@ -99,9 +98,13 @@ namespace MWScript
if (!iter->second.empty()) if (!iter->second.empty())
try try
{ {
Interpreter::Interpreter interpreter (interpreterContext); if (!mOpcodesInstalled)
installOpcodes (interpreter); {
interpreter.run (&iter->second[0], iter->second.size()); installOpcodes (mInterpreter);
mOpcodesInstalled = true;
}
mInterpreter.run (&iter->second[0], iter->second.size(), interpreterContext);
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {

@ -8,6 +8,7 @@
#include <components/compiler/streamerrorhandler.hpp> #include <components/compiler/streamerrorhandler.hpp>
#include <components/compiler/fileparser.hpp> #include <components/compiler/fileparser.hpp>
#include <components/interpreter/interpreter.hpp>
#include <components/interpreter/types.hpp> #include <components/interpreter/types.hpp>
namespace ESMS namespace ESMS
@ -35,6 +36,8 @@ namespace MWScript
bool mVerbose; bool mVerbose;
Compiler::Context& mCompilerContext; Compiler::Context& mCompilerContext;
Compiler::FileParser mParser; Compiler::FileParser mParser;
Interpreter::Interpreter mInterpreter;
bool mOpcodesInstalled;
std::map<std::string, std::vector<Interpreter::Type_Code> > mScripts; std::map<std::string, std::vector<Interpreter::Type_Code> > mScripts;

@ -134,8 +134,7 @@ namespace Interpreter
throw std::runtime_error (error.str()); throw std::runtime_error (error.str());
} }
Interpreter::Interpreter (Context& context) Interpreter::Interpreter()
: mRuntime (context)
{} {}
Interpreter::~Interpreter() Interpreter::~Interpreter()
@ -195,11 +194,11 @@ namespace Interpreter
mSegment5.insert (std::make_pair (code, opcode)); mSegment5.insert (std::make_pair (code, opcode));
} }
void Interpreter::run (const Type_Code *code, int codeSize) void Interpreter::run (const Type_Code *code, int codeSize, Context& context)
{ {
assert (codeSize>=4); assert (codeSize>=4);
mRuntime.configure (code, codeSize); mRuntime.configure (code, codeSize, context);
int opcodes = static_cast<int> (code[0]); int opcodes = static_cast<int> (code[0]);

@ -21,23 +21,23 @@ namespace Interpreter
std::map<int, Opcode1 *> mSegment3; std::map<int, Opcode1 *> mSegment3;
std::map<int, Opcode2 *> mSegment4; std::map<int, Opcode2 *> mSegment4;
std::map<int, Opcode0 *> mSegment5; std::map<int, Opcode0 *> mSegment5;
// not implemented // not implemented
Interpreter (const Interpreter&); Interpreter (const Interpreter&);
Interpreter& operator= (const Interpreter&); Interpreter& operator= (const Interpreter&);
void execute (Type_Code code); void execute (Type_Code code);
void abortUnknownCode (int segment, int opcode); void abortUnknownCode (int segment, int opcode);
void abortUnknownSegment (Type_Code code); void abortUnknownSegment (Type_Code code);
public: public:
Interpreter (Context& context); Interpreter();
~Interpreter(); ~Interpreter();
void installSegment0 (int code, Opcode1 *opcode); void installSegment0 (int code, Opcode1 *opcode);
///< ownership of \a opcode is transferred to *this. ///< ownership of \a opcode is transferred to *this.
@ -55,10 +55,9 @@ namespace Interpreter
void installSegment5 (int code, Opcode0 *opcode); void installSegment5 (int code, Opcode0 *opcode);
///< ownership of \a opcode is transferred to *this. ///< ownership of \a opcode is transferred to *this.
void run (const Type_Code *code, int codeSize); void run (const Type_Code *code, int codeSize, Context& context);
}; };
} }
#endif #endif

@ -7,50 +7,51 @@
namespace Interpreter namespace Interpreter
{ {
Runtime::Runtime (Context& context) : mContext (context), mCode (0), mPC (0) {} Runtime::Runtime() : mContext (0), mCode (0), mPC (0) {}
int Runtime::getPC() const int Runtime::getPC() const
{ {
return mPC; return mPC;
} }
int Runtime::getIntegerLiteral (int index) const int Runtime::getIntegerLiteral (int index) const
{ {
assert (index>=0 && index<static_cast<int> (mCode[1])); assert (index>=0 && index<static_cast<int> (mCode[1]));
const Type_Code *literalBlock = mCode + 4 + mCode[0]; const Type_Code *literalBlock = mCode + 4 + mCode[0];
return *reinterpret_cast<const int *> (&literalBlock[index]); return *reinterpret_cast<const int *> (&literalBlock[index]);
} }
float Runtime::getFloatLiteral (int index) const float Runtime::getFloatLiteral (int index) const
{ {
assert (index>=0 && index<static_cast<int> (mCode[2])); assert (index>=0 && index<static_cast<int> (mCode[2]));
const Type_Code *literalBlock = mCode + 4 + mCode[0] + mCode[1]; const Type_Code *literalBlock = mCode + 4 + mCode[0] + mCode[1];
return *reinterpret_cast<const float *> (&literalBlock[index]); return *reinterpret_cast<const float *> (&literalBlock[index]);
} }
std::string Runtime::getStringLiteral (int index) const std::string Runtime::getStringLiteral (int index) const
{ {
assert (index>=0 && index<static_cast<int> (mCode[3])); assert (index>=0 && index<static_cast<int> (mCode[3]));
const char *literalBlock = const char *literalBlock =
reinterpret_cast<const char *> (mCode + 4 + mCode[0] + mCode[1] + mCode[2]); reinterpret_cast<const char *> (mCode + 4 + mCode[0] + mCode[1] + mCode[2]);
for (; index; --index) for (; index; --index)
{ {
literalBlock += std::strlen (literalBlock) + 1; literalBlock += std::strlen (literalBlock) + 1;
} }
return literalBlock; return literalBlock;
} }
void Runtime::configure (const Interpreter::Type_Code *code, int codeSize) void Runtime::configure (const Interpreter::Type_Code *code, int codeSize, Context& context)
{ {
clear(); clear();
mContext = &context;
mCode = code; mCode = code;
mCodeSize = codeSize; mCodeSize = codeSize;
mPC = 0; mPC = 0;
@ -58,54 +59,55 @@ namespace Interpreter
void Runtime::clear() void Runtime::clear()
{ {
mContext = 0;
mCode = 0; mCode = 0;
mCodeSize = 0; mCodeSize = 0;
mStack.clear(); mStack.clear();
} }
void Runtime::setPC (int PC) void Runtime::setPC (int PC)
{ {
mPC = PC; mPC = PC;
} }
void Runtime::push (const Data& data) void Runtime::push (const Data& data)
{ {
mStack.push_back (data); mStack.push_back (data);
} }
void Runtime::push (Type_Integer value) void Runtime::push (Type_Integer value)
{ {
Data data; Data data;
data.mInteger = value; data.mInteger = value;
push (data); push (data);
} }
void Runtime::push (Type_Float value) void Runtime::push (Type_Float value)
{ {
Data data; Data data;
data.mFloat = value; data.mFloat = value;
push (data); push (data);
} }
void Runtime::pop() void Runtime::pop()
{ {
if (mStack.empty()) if (mStack.empty())
throw std::runtime_error ("stack underflow"); throw std::runtime_error ("stack underflow");
mStack.resize (mStack.size()-1); mStack.resize (mStack.size()-1);
} }
Data& Runtime::operator[] (int Index) Data& Runtime::operator[] (int Index)
{ {
if (Index<0 || Index>=static_cast<int> (mStack.size())) if (Index<0 || Index>=static_cast<int> (mStack.size()))
throw std::runtime_error ("stack index out of range"); throw std::runtime_error ("stack index out of range");
return mStack[mStack.size()-Index-1]; return mStack[mStack.size()-Index-1];
} }
Context& Runtime::getContext() Context& Runtime::getContext()
{ {
return mContext; assert (mContext);
return *mContext;
} }
} }

@ -11,52 +11,52 @@ namespace Interpreter
class Context; class Context;
/// Runtime data and engine interface /// Runtime data and engine interface
class Runtime class Runtime
{ {
Context& mContext; Context *mContext;
const Type_Code *mCode; const Type_Code *mCode;
int mCodeSize; int mCodeSize;
int mPC; int mPC;
std::vector<Data> mStack; std::vector<Data> mStack;
public: public:
Runtime (Context& context); Runtime ();
int getPC() const; int getPC() const;
///< return program counter. ///< return program counter.
int getIntegerLiteral (int index) const; int getIntegerLiteral (int index) const;
float getFloatLiteral (int index) const; float getFloatLiteral (int index) const;
std::string getStringLiteral (int index) const; std::string getStringLiteral (int index) const;
void configure (const Type_Code *code, int codeSize); void configure (const Type_Code *code, int codeSize, Context& context);
///< \a context and \a code must exist as least until either configure, clear or ///< \a context and \a code must exist as least until either configure, clear or
/// the destructor is called. \a codeSize is given in 32-bit words. /// the destructor is called. \a codeSize is given in 32-bit words.
void clear(); void clear();
void setPC (int PC); void setPC (int PC);
///< set program counter. ///< set program counter.
void push (const Data& data); void push (const Data& data);
///< push data on stack ///< push data on stack
void push (Type_Integer value); void push (Type_Integer value);
///< push integer data on stack. ///< push integer data on stack.
void push (Type_Float value); void push (Type_Float value);
///< push float data on stack. ///< push float data on stack.
void pop(); void pop();
///< pop stack ///< pop stack
Data& operator[] (int Index); Data& operator[] (int Index);
///< Access stack member, counted from the top. ///< Access stack member, counted from the top.
Context& getContext(); Context& getContext();
}; };
} }

Loading…
Cancel
Save