#include "NewPlacement.hpp" #include "HeapAllocatorGlobal.hpp" #include "core/scriptsection.h" using namespace obj; ScriptSection* gScriptSection = NULL; struct script_data_head { tp::alni refc = 0; tp::alni store_adress = 0; }; void set_script_head_store_adress(Script* in, tp::alni address) { ((script_data_head*)in - 1)->store_adress = address; } tp::alni get_script_head_store_adress(Script* in) { return ((script_data_head*)in - 1)->store_adress; } Script* ScriptSection::createScript() { auto sdhead = (script_data_head*)tp::HeapAllocGlobal::allocate(sizeof(script_data_head) + sizeof(Script)); auto out = (Script*)(sdhead + 1); if (!sdhead) { return NULL; } sdhead->refc = 1; sdhead->store_adress = -1; mScripts.pushBack(out); new (out) Script(); out->mReadable = obj::StringObject::create(""); obj::NDO->refinc(out->mReadable); return out; } void ScriptSection::delete_script(Script* script) { script->~Script(); obj::NDO->destroy(script->mReadable); tp::HeapAllocGlobal::deallocate((((script_data_head*)script) - 1)); } void ScriptSection::reference_script(Script* script) { (((script_data_head*)script) - 1)->refc++; } void ScriptSection::abandonScript(Script* script) { if ((((script_data_head*)script) - 1)->refc > 1) { (((script_data_head*)script) - 1)->refc--; } else { // ISSUE : on delete list structure is outdated // FIXME : use pool alloc with ref count // forwarding to global destruction //delete_script(script); } } void ScriptSection::changeScript(Script** current_script, Script** new_script) { abandonScript(*current_script); reference_script(*new_script); *current_script = *new_script; } tp::alni ScriptSection::get_script_file_adress(Script* in) { return get_script_head_store_adress(in); } tp::alni ScriptSection::save_script_table_to_file_size(ScriptSection* self, Archiver& file) { tp::alni size = 0; size += 5; // header size += sizeof(tp::alni); // scripts length for (auto iter : self->mScripts) { set_script_head_store_adress(iter.data(), file.adress + size); size += sizeof(tp::alni); // scripts string obj ref size += sizeof(tp::alni); // constants length for (auto const_obj : iter->mBytecode.mConstants) { size += sizeof(tp::alni); // constant object addres } // instructions size += iter->mBytecode.mInstructions.saveSize(); } size += sizeof(tp::alni); // objects mem offset size += 5; // header return size; } void ScriptSection::save_script_table_to_file(ScriptSection* self, Archiver& file) { // header file.write_bytes("/scr/", 5); // scripts length tp::alni scripts_count = self->mScripts.length(); file.write(&scripts_count); for (auto iter : self->mScripts) { // scripts string obj ref auto obj_addres = obj::NDO->save(file, iter->mReadable); file.write(&obj_addres); // constants length tp::alni consts_count = iter->mBytecode.mConstants.size(); file.write(&consts_count); for (auto const_obj : iter->mBytecode.mConstants) { // constant object addres auto obj_addres = obj::NDO->save(file, const_obj.data()); file.write(&obj_addres); } // mInstructions iter->mBytecode.mInstructions.save(file); } // header file.write_bytes("/scr/", 5); tp::alni objects_mem_offset = file.avl_adress; file.write(&objects_mem_offset); } void load_constants(ScriptSection* self, Archiver& file, tp::alni start_addr) { auto addres = file.adress; file.adress = start_addr; file.adress += 5; // header tp::alni scripts_count; file.read(&scripts_count); for (tp::alni i = 0; i < scripts_count; i++) { auto script = self->get_scritp_from_file_adress(file.adress); // script text tp::alni str_addr; file.read(&str_addr); script->mReadable = NDO_CAST(obj::StringObject, obj::NDO->load(file, str_addr)); file.adress += sizeof(tp::alni); // constants length for (auto const_obj : script->mBytecode.mConstants) { tp::alni consts_addr; file.read(&consts_addr); const_obj.data() = obj::NDO->load(file, consts_addr); } // instructions file.adress += script->mBytecode.mInstructions.saveSize(); } file.adress = addres; } void ScriptSection::load_script_table_from_file(ScriptSection* self, Archiver& file) { for (auto iter : self->mScripts) { set_script_head_store_adress(iter.data(), -1); } auto section_start_addr = file.adress; // header file.adress += 5; // scripts length tp::alni scripts_count; file.read(&scripts_count); for (tp::alni i = 0; i < scripts_count; i++) { auto new_script = self->createScript(); set_script_head_store_adress(new_script, file.adress); // scripts text file.adress += sizeof(tp::alni); // constants length tp::alni consts_count; file.read(&consts_count); new_script->mBytecode.mConstants.reserve(consts_count); for (tp::alni j = 0; j < consts_count; j++) { // constant object addres tp::alni consts_addr; file.read(&consts_addr); // skiping //new_script->mBytecode.mConstants[j] = obj::NDO->load(file, consts_addr); } // mInstructions new_script->mBytecode.mInstructions.load(file); } load_constants(self, file, section_start_addr); // header file.adress += 5; tp::alni objects_mem_offset; file.read(&objects_mem_offset); file.adress = objects_mem_offset; } Script* ScriptSection::get_scritp_from_file_adress(tp::alni file_adress) { for (auto iter : mScripts) { if (get_script_head_store_adress(iter.data()) == file_adress) { return iter.data(); } } return NULL; } ScriptSection::~ScriptSection() { for (auto iter : mScripts) { delete_script(iter.data()); } } obj::save_load_callbacks ScriptSection::slcb_script_section = { .self = gScriptSection, .pre_save = (obj::pre_save_callback*)ScriptSection::save_script_table_to_file, .size = (obj::slcb_size_callback*)ScriptSection::save_script_table_to_file_size, .pre_load = (obj::pre_load_callback*)ScriptSection::load_script_table_from_file, .post_save = NULL, .post_load = NULL, }; void ScriptSection::initialize() { ASSERT(!gScriptSection); gScriptSection = new ScriptSection(); ASSERT(obj::NDO && "Forgot to initialize objects?"); slcb_script_section.self = gScriptSection; obj::NDO->add_sl_callbacks(&slcb_script_section); } void ScriptSection::uninitialize() { ASSERT(gScriptSection); delete gScriptSection; } ScriptSection* ScriptSection::globalHandle() { return gScriptSection; }