forked from mirror/openmw-tes3mp
don't create a new virtual machine for each script and frame
This commit is contained in:
parent
a133920eb0
commit
80691250ec
7 changed files with 77 additions and 71 deletions
|
@ -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…
Reference in a new issue