|
|
Say I have the classes Graphics, Keyboard, Math, and Sys. Each declares statics.
When I run a program that uses these classes in the VM emulator, analyzing the static segment (RAM 16..256) shows that the VM emulator allocates the static segments alphabetically. That is RAM[16..16+x] is allocated for Graphics' statics, RAM[16+x..16+x+y] is allocated for Keyboard's statics etc.
The curious thing is that Sys' statics seem to break this convention and are instead allocated to RAM[16..16+z].
Thus if for example, Graphics sets static_0 to 1000, and then Sys sets static_0 to 2000, the contents of RAM[16] will reflect the most recent write of 2000.
I've tried looking at the VM emulator's source code, but I cannot pinpoint why this happens.
|
Administrator
|
I can't reproduce this behavior on my system.
Please email me an archive (zip, rar, tar.gz) of a directory that exhibits this behavior and instructions on what I need to do to see the collision occur. What OS are you running?
Have you tried setting a breakpoint on RAM[16] to confirm when the incorrect value is being written there?
--Mark
|
|
Hi
I've written a small program (attached) that reproduces this behaviour. It has seven classes: A, B, C, D, E, F, Main, and Sys. All the classes except for Main declare five statics.
In the barebones Sys class, a call to Sys.init() initializes each of the classes' statics by calling their respective init() functions. A's statics are initalized to the values 1,2,3,4,5. B's statics to the values 11,12,13,14,15. C's statics to the values 21,22,23,24,25. And so on. Sys.init() then initializes Sys's statics to the values 61,62,63,64,65. After which it proceeds to call Main.main() (which in this code does nothing).
In the image attached, you can see that instead of seeing A's statics of 1,2,3,4,5 in RAM[16..21] you instead see Sys's statics of 61,62,63,64,65. Also noteworthy is that there are no values in RAM[46..51] where you would expect to see Sys's statics.
cadet1620 wrote
Have you tried setting a breakpoint on RAM[16] to confirm when the incorrect value is being written there?
When I step through the code, I can clearly see the values 1,2,3,4,5 written to RAM[16..21] when A.init() is called, and then subsequently overwtitten to 61,62,63,64,65 when Sys.init() begins initializing its own statics.
testStatics.rar
|
Administrator
|
I can reproduce this with your code.
Truly strange is that Sys starts out with the correct static segment. I manually editied
push constant 123
pop static 0
as the first two instructions in Sys.vm and the 123 was correctly written to RAM[46] and it displays in the "Static" list correctly. After returning from the call "A.init 0" , A's statics show in the "Static" list and if you change static 0 it changes RAM[16].
I'm not Java programmer, but poking around in the source, it looks like the dirty deed is done in this code:
.../VMEmulator/CPU.java
456: public void returnFromFunction() throws ProgramException {
...
508: // sets the static segment range
if (stackFrames.size() > 0) {
setStaticRange(callStack.getTopFunction());
} else {
staticSegment.setStartAddress(Definitions.VAR_START_ADDRESS);
staticSegment.setEnabledRange(Definitions.VAR_START_ADDRESS,
Definitions.VAR_END_ADDRESS - 1,
true);
}
Sys.init() begins with an empty stack (SP=256) When a function called by Sys.init() returns, stackFrames.size() is 0 so the else is executed and Sys gets the entire static variable area, 16..255, as its static segment.
callStack.getTopFunction() returns "" if there is no top function. My guess is that the stackFrames.size() > 0 is safety code that's checking the wrong stack. I think the code ahould be something like
// sets the static segment range
final String topFunction = callStack.getTopFunction();
if (topFunction.length() > 0) {
setStaticRange(topFunction);
} else {
I haven't been able to successfully build the code so somebody who knows Java will need to fix it.
--Mark
|
|
I see, thanks for looking into this!
Based on what you explained about the empty stack problem, I was able to (not elegantly) work around the problem by having a function in Sys called 'initializeMyStatics'. Instead of directly initializing them in Sys.init(), they are initialized by a call to 'initializeMyStatics()'. It's ugly but it works.
Thanks for the detective work.
|
Administrator
|
I did the same thing in my debugging. I moved the static inits from Sys.init() to Sys.runProgram()
I'm curious. What are you using statics for in Sys.init?
--Mark
|
|
I want to ensure that the heap overflow error message (a string) is pre-allocated. That way it is guaranteed to always display. (Instead of being allocated at runtime leading to an endless chain if indeed the heap has overflown). Having the static in Sys is most convenient as Sys.error resides there.
|
Administrator
|
I did this by using 3 Output.printChar() calls to avoid the "ERR" string. My Output.printInt() doesn't do a Memory.alloc() so the ERR# message can always be displayed.
--Mark
|
|
Ah I see, clever!
In the future I intend to print out full descriptions for the error messages (not just the codes) to make them more user friendly. So getting this static fiasco sorted out works out well.
|
Administrator
|
The downside to that is that you will have those messages that are never normally used always taking up heap space, and worse, the code to create them will be using up ROM space.
Have you compiled your chapter 9 "game" with your compiler and translated it with your OS and VM Translator an run it on the CPU Emulator? I'ts quite awesome when it all comes together.
--Mark
|
|
Though I finished the course work quite a while ago, I haven't made a game in Jack yet. I have however succeeded in compiling a small 'Hello World' program that successfully runs on both my standalone VM and CPU emulators. Bigger programs such as Gavin's demos run on my VM emulator, but not my CPU emulator due to their size (in combination with my OS file sizes). However, I know they can run on the CPU emulator once I figure out the Virtual Memory thing.
I'm prioritizing ease of use and richness over compact code. Memory is cheap these days and I don't want it to be a consideration when someone is writing code for my version of the Hack computer.
cadet1620 wrote
It's quite awesome when it all comes together.
It is. But after seeing the 'Hello World' run on the CPU emulator, I'm not quite yet satisfied. I'm in the process of building the Hack computer on an FPGA. When that works, and the architecture is running successfully on dedicated hardware, I will be truly satisfied! For now, the emulators are invaluable in detecting bugs and shortcomings that would be impossibly hard to narrow down in a physical implementation.
|
|