As noted in https://docs.oracle.com/javase/specs/jvms/se14/html/jvms-2.html#jvms-2.11.1, encoding operand types into opcodes comes at a cost:
Given the Java Virtual Machine's one-byte opcode size, encoding types into opcodes places pressure on the design of its instruction set. If each typed instruction supported all of the Java Virtual Machine's run-time data types, there would be more instructions than could be represented in a byte.
Thus, it seems one should only do this for instructions where type information of the operands is required or enables optimizations. For example, differentiation between iadd
and fadd
is required because addition for integers and floats is implemented differently. And I don't know exactly why there are different instructions for loading a boolean
and an int
from an array (baload
and iaload
, respectively), but I can at least imagine some performance reasons.
However, why are there different instructions for storing an int
(istore
) and a float
(fstore
) into a local variable? Shouldn't they be implemented in absolutely the same way?
This answer https://stackoverflow.com/a/2638143 says typed instructions are required for the bytecode verifier. But is this really necessary? In a method, all data flows from the method's parameters (for which the types are known) and from class fields (for which the types are also known) to other class fields and to the return value. Thus, since the types for inputs and outputs are known, can't we reconstruct any missing types for the instructions? In fact, isn't this what the bytecode verifier does anyway, since it has to check the types, i.e., it must know which types are expected?
In short: What would break if we were to combine istore
and fstore
into a single instruction? Would performance or portability suffer? Would bytecode verification stop working?