bsnes_state_save.zip
Makes sense. You want to ultimately get the thread to some deeply nested point, maybe a few function calls deep, but you can't easily just put it there from the start. So you start it at the beginning and feed it doctored inputs for the sole purpose of getting it to that deeply nested point, not caring at all what you have to feed it or what else it does, since you've ensured that whatever it does won't have any ill effects. Then when it's there, it yields and you then restore all the data state to the proper values.henke37 wrote:Yes, it does start at CPU::run. But the trick here is that when loading, we feed it the data that causes it to move to the right sync call. We ignore what it does with the data, it is just a trick to get it into the right position. Once the thread is swapped out, the data in the thread is completely ignored and overwritten with data from the save state(remapped as needed).
Say a new variable is added to a function; what will this be set to when restoring an old save state? For that matter, what if a function is removed entirely but an old save state was saved while in this function? The problem here is that highly volatile aspects of the implementation are captured in the save state, requiring that the implementation be frozen or states be broken constantly.henke37 wrote:Also, you claim that the memory layout may be different at each time. So what? How do you think exceptions with their unrolling of the stack is supposed to work? (Rhetorical question) It is smart enough to understand the stack frames, so why can't the threading library understand them?
Exceptions work because the compiler regenerates the information every time you recompile, and exceptions don't save state across runs of a program. It only has to deal with the current program, which it has current tables for.
Maintainability. For every version of the program, you must be able to load states from previous versions, down to every last detail, converting state to the new format as necessary. Function removed in new version? Well, you'll have to figure out how to convert the old state within that function into the equivalent where that function doesn't even exist.henke37 wrote:And seriously, if we understand the stack frames, what prevents us from parsing them, saving the data in a portable format and later pre filing the stack with the data and then "returning" to the function?
"But, the same issues apply to file format compatibility!" you say. Yes, but the layout of a file can be independently maintained from the organization of the functions and local variables, so changes to a file format can be kept to a minimum. Saving stack frame contents tightly couples the two, making changes frequent and unplanned.
First, let's imagine a spherical program. Seriously, this kind of abstraction might be possible in Java, but forget about something like cothreads in the first place on that straight-jacket language.henke37 wrote:Yes, it is portable, the data on the stack is after all just the function's local variables, the return address and the arguments to the function. That data does not change. Sure, the format of the data can be different, but it is still the same values, just in different formats.
Sure, the actual binary format is very platform, compilator and build setting specific. But the data that is stored is not.