RingRacers/libs/ACSVM/include/ACSVM/Thread.cpp
Sally Coolatta 26477941ed Attempt using ACSVM to implement
It's having trouble linking the dll on Windows currently
2022-10-03 01:23:58 -04:00

292 lines
7.4 KiB
C++

//-----------------------------------------------------------------------------
//
// Copyright (C) 2015-2017 David Hill
//
// See COPYING for license information.
//
//-----------------------------------------------------------------------------
//
// Thread classes.
//
//-----------------------------------------------------------------------------
#include "Thread.hpp"
#include "Array.hpp"
#include "BinaryIO.hpp"
#include "Environment.hpp"
#include "Module.hpp"
#include "Scope.hpp"
#include "Script.hpp"
#include "Serial.hpp"
#include <algorithm>
//----------------------------------------------------------------------------|
// Extern Functions |
//
namespace ACSVM
{
//
// Thread constructor
//
Thread::Thread(Environment *env_) :
env{env_},
link{this},
codePtr {nullptr},
module {nullptr},
scopeGbl{nullptr},
scopeHub{nullptr},
scopeMap{nullptr},
scopeMod{nullptr},
script {nullptr},
delay {0},
result {0}
{
}
//
// Thread destructor
//
Thread::~Thread()
{
}
//
// Thread::getInfo
//
ThreadInfo const *Thread::getInfo() const
{
return nullptr;
}
//
// Thread::loadState
//
void Thread::loadState(Serial &in)
{
std::size_t count, countFull;
in.readSign(Signature::Thread);
module = env->getModule(env->readModuleName(in));
codePtr = &module->codeV[ReadVLN<std::size_t>(in)];
scopeGbl = env->getGlobalScope(ReadVLN<Word>(in));
scopeHub = scopeGbl->getHubScope(ReadVLN<Word>(in));
scopeMap = scopeHub->getMapScope(ReadVLN<Word>(in));
scopeMod = scopeMap->getModuleScope(module);
script = env->readScript(in);
delay = ReadVLN<Word>(in);
result = ReadVLN<Word>(in);
count = ReadVLN<std::size_t>(in);
callStk.clear(); callStk.reserve(count + CallStkSize);
while(count--)
callStk.push(readCallFrame(in));
count = ReadVLN<std::size_t>(in);
dataStk.clear(); dataStk.reserve(count + DataStkSize);
while(count--)
dataStk.push(ReadVLN<Word>(in));
countFull = ReadVLN<std::size_t>(in);
count = ReadVLN<std::size_t>(in);
localArr.allocLoad(countFull, count);
for(auto itr = localArr.beginFull(), end = localArr.end(); itr != end; ++itr)
itr->loadState(in);
countFull = ReadVLN<std::size_t>(in);
count = ReadVLN<std::size_t>(in);
localReg.allocLoad(countFull, count);
for(auto itr = localReg.beginFull(), end = localReg.end(); itr != end; ++itr)
*itr = ReadVLN<Word>(in);
countFull = ReadVLN<std::size_t>(in);
count = ReadVLN<std::size_t>(in);
in.in->read(printBuf.getLoadBuf(countFull, count), countFull);
state.state = static_cast<ThreadState::State>(ReadVLN<int>(in));
state.data = ReadVLN<Word>(in);
state.type = ReadVLN<Word>(in);
in.readSign(~Signature::Thread);
}
//
// Thread::lockStrings
//
void Thread::lockStrings() const
{
for(auto &data : dataStk)
++env->getString(data)->lock;
for(auto arr = localArr.beginFull(), end = localArr.end(); arr != end; ++arr)
arr->lockStrings(env);
for(auto reg = localReg.beginFull(), end = localReg.end(); reg != end; ++reg)
++env->getString(*reg)->lock;
if(state == ThreadState::WaitScrS)
++env->getString(state.data)->lock;
}
//
// Thread::readCallFrame
//
CallFrame Thread::readCallFrame(Serial &in) const
{
CallFrame out;
out.module = env->getModule(env->readModuleName(in));
out.scopeMod = scopeMap->getModuleScope(out.module);
out.codePtr = &out.module->codeV[ReadVLN<std::size_t>(in)];
out.locArrC = ReadVLN<std::size_t>(in);
out.locRegC = ReadVLN<std::size_t>(in);
return out;
}
//
// Thread::refStrings
//
void Thread::refStrings() const
{
for(auto &data : dataStk)
env->getString(data)->ref = true;
for(auto arr = localArr.beginFull(), end = localArr.end(); arr != end; ++arr)
arr->refStrings(env);
for(auto reg = localReg.beginFull(), end = localReg.end(); reg != end; ++reg)
env->getString(*reg)->ref = true;
if(state == ThreadState::WaitScrS)
env->getString(state.data)->ref = true;
}
//
// Thread::saveState
//
void Thread::saveState(Serial &out) const
{
out.writeSign(Signature::Thread);
env->writeModuleName(out, module->name);
WriteVLN(out, codePtr - module->codeV.data());
WriteVLN(out, scopeGbl->id);
WriteVLN(out, scopeHub->id);
WriteVLN(out, scopeMap->id);
env->writeScript(out, script);
WriteVLN(out, delay);
WriteVLN(out, result);
WriteVLN(out, callStk.size());
for(auto &call : callStk)
writeCallFrame(out, call);
WriteVLN(out, dataStk.size());
for(auto &data : dataStk)
WriteVLN(out, data);
WriteVLN(out, localArr.sizeFull());
WriteVLN(out, localArr.size());
for(auto itr = localArr.beginFull(), end = localArr.end(); itr != end; ++itr)
itr->saveState(out);
WriteVLN(out, localReg.sizeFull());
WriteVLN(out, localReg.size());
for(auto itr = localReg.beginFull(), end = localReg.end(); itr != end; ++itr)
WriteVLN(out, *itr);
WriteVLN(out, printBuf.sizeFull());
WriteVLN(out, printBuf.size());
out.out->write(printBuf.dataFull(), printBuf.sizeFull());
WriteVLN<int>(out, state.state);
WriteVLN(out, state.data);
WriteVLN(out, state.type);
out.writeSign(~Signature::Thread);
}
//
// Thread::start
//
void Thread::start(Script *script_, MapScope *map, ThreadInfo const *,
Word const *argV, Word argC)
{
link.insert(&map->threadActive);
script = script_;
module = script->module;
codePtr = &module->codeV[script->codeIdx];
scopeMod = map->getModuleScope(module);
scopeMap = map;
scopeHub = scopeMap->hub;
scopeGbl = scopeHub->global;
callStk.reserve(CallStkSize);
dataStk.reserve(DataStkSize);
localArr.alloc(script->locArrC);
localReg.alloc(script->locRegC);
std::copy(argV, argV + std::min<Word>(argC, script->argC), &localReg[0]);
delay = 0;
result = 0;
state = ThreadState::Running;
}
//
// Thread::stop
//
void Thread::stop()
{
// Release execution resources.
callStk.clear();
dataStk.clear();
localArr.clear();
localReg.clear();
printBuf.clear();
// Set state.
state = ThreadState::Inactive;
}
//
// Thread::unlockStrings
//
void Thread::unlockStrings() const
{
for(auto &data : dataStk)
--env->getString(data)->lock;
for(auto arr = localArr.beginFull(), end = localArr.end(); arr != end; ++arr)
arr->unlockStrings(env);
for(auto reg = localReg.beginFull(), end = localReg.end(); reg != end; ++reg)
--env->getString(*reg)->lock;
if(state == ThreadState::WaitScrS)
--env->getString(state.data)->lock;
}
//
// Thread::writeCallFrame
//
void Thread::writeCallFrame(Serial &out, CallFrame const &in) const
{
env->writeModuleName(out, in.module->name);
WriteVLN(out, in.codePtr - in.module->codeV.data());
WriteVLN(out, in.locArrC);
WriteVLN(out, in.locRegC);
}
}
// EOF