mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-09-10 12:02:53 +02:00
Don't run stack frame destructors when deserializing libretro save states
This commit is contained in:
parent
4ada800de3
commit
33153783e8
3 changed files with 18 additions and 10 deletions
|
@ -299,6 +299,9 @@ namespace mkxp_sandbox {
|
|||
inline wasm_ptr_t get_stack_pointer() const noexcept {
|
||||
return stack_ptr;
|
||||
}
|
||||
inline void forget() noexcept {
|
||||
destructor = nullptr;
|
||||
}
|
||||
private:
|
||||
void *coroutine;
|
||||
void (*destructor)(void *coroutine);
|
||||
|
@ -308,14 +311,10 @@ namespace mkxp_sandbox {
|
|||
struct fiber {
|
||||
friend struct binding_base;
|
||||
fiber(key_t key) : key(key), stack_index(0) {};
|
||||
inline const std::vector<struct stack_frame> &get_stack() const noexcept {
|
||||
return stack;
|
||||
}
|
||||
public:
|
||||
const key_t key;
|
||||
wasm_size_t stack_index;
|
||||
std::vector<struct deser_stack_frame> deser_stack;
|
||||
private:
|
||||
std::vector<struct stack_frame> stack;
|
||||
};
|
||||
|
||||
|
|
|
@ -97,7 +97,10 @@ namespace mkxp_sandbox {
|
|||
{
|
||||
struct mkxp_sandbox::bindings::stack_frame_guard<T> frame = bindings->bind<T>();
|
||||
auto result = frame()();
|
||||
if (frame().is_complete()) return result;
|
||||
if (frame().is_complete()) {
|
||||
assert(!yielding);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (yielding) {
|
||||
yielding = false;
|
||||
|
|
16
src/core.cpp
16
src/core.cpp
|
@ -1741,15 +1741,15 @@ extern "C" RETRO_API bool retro_serialize(void *data, size_t len) {
|
|||
if (!sandbox_serialize(fiber.stack_index, data, max_size)) return false;
|
||||
|
||||
// Write the number of frames in the fiber
|
||||
if (!sandbox_serialize(std::max((wasm_size_t)fiber.get_stack().size(), (wasm_size_t)fiber.deser_stack.size()), data, max_size)) return false;
|
||||
if (!sandbox_serialize(std::max((wasm_size_t)fiber.stack.size(), (wasm_size_t)fiber.deser_stack.size()), data, max_size)) return false;
|
||||
|
||||
// Write the stack pointer and state of each frame
|
||||
for (const auto &frame : fiber.get_stack()) {
|
||||
for (const auto &frame : fiber.stack) {
|
||||
if (!sandbox_serialize(frame.get_stack_pointer(), data, max_size)) return false;
|
||||
if (!sandbox_serialize((int32_t)frame, data, max_size)) return false;
|
||||
}
|
||||
if (fiber.deser_stack.size() > fiber.get_stack().size()) {
|
||||
for (auto it = fiber.deser_stack.begin() + fiber.get_stack().size(); it != fiber.deser_stack.end(); ++it) {
|
||||
if (fiber.deser_stack.size() > fiber.stack.size()) {
|
||||
for (auto it = fiber.deser_stack.begin() + fiber.stack.size(); it != fiber.deser_stack.end(); ++it) {
|
||||
if (!sandbox_serialize(it->stack_ptr, data, max_size)) return false;
|
||||
if (!sandbox_serialize(it->state, data, max_size)) return false;
|
||||
}
|
||||
|
@ -1911,6 +1911,12 @@ extern "C" RETRO_API bool retro_unserialize(const void *data, size_t len) {
|
|||
wasm_size_t num_fibers;
|
||||
if (!sandbox_deserialize(num_fibers, data, max_size)) DESER_FAIL;
|
||||
|
||||
for (auto &fiber : sb()->fiber_list) {
|
||||
for (auto &frame : fiber.stack) {
|
||||
// Make sure the destructors of the existing stack frames don't run when we call `sb()->fiber_list.clear()` a few lines from now
|
||||
frame.forget();
|
||||
}
|
||||
}
|
||||
sb()->fiber_map.clear();
|
||||
sb()->fiber_list.clear();
|
||||
sb()->fiber_map.reserve(num_fibers);
|
||||
|
@ -2019,7 +2025,7 @@ extern "C" RETRO_API bool retro_unserialize(const void *data, size_t len) {
|
|||
if (typenum > SANDBOX_NUM_TYPENUMS) DESER_OBJECTS_END_FAIL;
|
||||
|
||||
bool should_be_disposed;
|
||||
if (!sandbox_deserialize(should_be_disposed, data, max_size)) return false;
|
||||
if (!sandbox_deserialize(should_be_disposed, data, max_size)) DESER_OBJECTS_END_FAIL;
|
||||
|
||||
// Destroy and recreate objects that don't match the type in the save state, or are currently disposed but not disposed in the save state
|
||||
auto &object = sb()->objects[object_key - 1];
|
||||
|
|
Loading…
Add table
Reference in a new issue