This question is sort of the opposite of this existing one: What is the role of operand stack in JVM?
That question asks why the JVM does not operate directly on the local variables. I'm wondering, since we have the stack anyway, why not operate only on the stack and forego the local variables entirely?
I guess it would need a few more instructions to manipulate the stack (much like advanced RPN calculators do), but how does one know whether that tradeoff would be worth it? Is this design rationale recorded somewhere?
The specification is light on rationale (https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-2.html#jvms-2.6.1), but I suspect that's because the specification is the wrong document for it, and maybe there's an annotated specification somewhere like with Ada?
Is this design rationale recorded somewhere?
I doubt that you will find a satisfying answer to this question.
When people began working on what is now known as Java around 30 years ago this wasn't a big commitee and some elaborate process . It was a small group of people working tightly together and explicitly formed to work autonomously without the bureaucracy that was stalling other Sun projects". The process was therefore probably more: someone proposed something to the group, there was some discussion and then it was decided without much writing down of rationales.
Source for the "small group": https://en.wikipedia.org/wiki/Java_(software_platform)#History
Some thoughts on the other points you've made:
I guess it would need a few more instructions to manipulate the stack (much like advanced RPN calculators do)
Without local variables you would have to replace iload
, aload
and some more variants with ipick
, apick
and similar variants that pick a value from some offset from the top of the operand stack and push it on top of the operand stack.
Similarly you would need to replace istore
, astore
and some more variants with ireplace
, areplace
and similar variants that pop a value from the operand stack and replace the value at some offset of the top of the operand stack with the popped value.
The main difference between the existing instructions and the proposed instructions would be that the existing instructions always use the same offset for a specific local variable while the proposed instructions would have to use different offsets for a specific local variable depending on how much values have been pushed to the operand stack.
but how does one know whether that tradeoff would be worth it?
IMHO not using local variables would make Java byte code harder to work with (for example when doing Verification of class Files) without reaping any benefits.
Note that at runtime there are no separate memory spaces for local variables and the operand stack. Conceptually the JVM uses one Frame per method invocation and this frame contains the local variables and the operand stack.