I'm trying to implement in C an integer java virtual machine taking as example the IJVM described by Andrew Tanenbaum in "Structured Computer Organization" -> IVJM . Until now I was able to execute some instruction such as GOTO, IFEQ, IADD, etc. by adjusting the right value of the program counter or/and pushing/popping values or constants (from pool area) onto stack, I've created the stack as a global array. My intentions is to call some methods and pass the parameters to it (onto stack), but I have a blocking point regarding how to implement local variable frame for each function. I know that the method area first contains two shorts (2 byte numbers), the first one signifying the number of arguments the method expects, and the second one being the local variable area size. The local variable area size helps me a lot, but:
- -> the local variable should be located also in the array used for stack (operands)?
- -> the main function doesn't have a local variable area size, how to prevent overlapping with values pushed into stack?
- -> what is the best approach to implement the local variable frame?
CodePudding user response:
the local variable should be located also in the array used for stack (operands)?
From your link:
- Local Variable Frame: The beginning of the frame will have the parameters (a.k.a. arguments) of the method/procedure, with the local variables following.
- Operand Stack: Will be right above the local variable stack frame.
Therefore, these two stacks are within a global Java stack, one following the other.
Nevertheless, the local variable should not be located within the array part used for the stack (operands).
the main function doesn't have a local variable area size, how to prevent overlapping with values pushed into stack?
The stack grows only in one direction and then shrinks respectively, according to the processing of bytecodes. It can overflow or underflow but overlapping is hard, i.e. only produced by an incorrect implementation of bytecodes (IJVM Assembly), exception handling, method returning. When a method is called a new stack frame is put onto the stack, i.e. return info (I don't know how return info is handled in IJVM but there must be away to remove a stack frame from the stack. Usually, it is a pointer to the beginning of the previous stack frame) and place for the arguments and local variables. From then on the stack grows/shrinks above the local variables according to the executed bytecodes. The same applies for the main method.
There is an implementation at https://github.com/HongyuHe/IJVM. It contains the following stack visualization:
| ...... |
|operation stack above | [...]<- sp
| old_lv |
| old_pc |
| var[2] |
| var[1] |
| var[0] |
| ...... |
| arg[2] |
| arg[1] |
| arg[0] |
| link_ptr | [...]<- lv
| ...... | [2]
| ...... | [1]
| MAIN_FRAM | [0]
what is the best approach to implement the local variable frame?
Pointer to the Java stack where the local variables are located of type stack element. (Be aware that depending on your particular VM spec some primitive types might use up more than one stack element.) The bytecodes refer to local variables via an index. Therefore, it can simply be used as an array.