I understand iload takes in integers -1 to 5, but how can you extend to higher numbers using a bipush instruction? How is the specific integer being stored with the bytecode?
-
Your question is very unclear, whether you're asking about pushing the values of local variables onto the stack when you have more than 4 local variables to choose from (`iload`), or pushing literals with `bipush`. – chrylis -cautiouslyoptimistic- May 04 '18 at 05:33
-
I'm really asking about both. Is iload_1 loading the integer one? – Tim May 04 '18 at 06:00
-
`iload_1` pushes the `int` in local variable #1 (the second one, since it's zero-based) onto the stack. – chrylis -cautiouslyoptimistic- May 04 '18 at 06:26
-
My mistake, I was getting the instructions mixed. When you are using istore, and you are storing more than 4 variables, how does it handle the size? I figured the variable field is a fixed array. – Tim May 04 '18 at 19:54
-
The size of what? – chrylis -cautiouslyoptimistic- May 04 '18 at 23:01
-
The fixed size of the variable field. – Tim May 05 '18 at 01:15
-
What is a "variable field"? – chrylis -cautiouslyoptimistic- May 05 '18 at 13:07
-
Variable field is how Hotspot VM stores local variables within each frame. – Tim May 17 '18 at 00:48
2 Answers
There's several different instructions that can be used to push an integer constant.
The smallest is the iconst_* instructions. These are only a single byte, because the value is encoded in the opcode itself. iconst_1, iconst_2, etc. are different opcodes. iconst_5 for example would be encoded as the byte 08.
Note: iload is a completely unrelated instruction used for loading the value of a local variable. You must have been thinking of iconst_*.
Next is bipush, which can push a constant between -128 and 127. This instruction is two bytes long - the first byte is the opcode, and the second byte is a signed 8 bit integer. You can even use it to push constants in the range -1 to 5, although doing so would take up more space in the classfile than necessary. For example, bipush 5 would be encoded as 10 05. (0x10 is the opcode for bipush)
Next is sipush, which is the same except that it stores a 16 bit constant instead of an 8 bit constant, and hence the instruction is three bytes long. The opcode for sipush is 0x11, so sipush 5 would be encoded as the three byte sequence 11 00 05.
You might wonder how integer constants which don't fit in 16 bits are stored. In this case, the compiler creates entries in a separate section of the classfile called the constant pool, and then uses the ldc or ldc_w instruction to refer to the constant pool entry.
- 37,781
- 10
- 100
- 107
-
So how is a bytecode implemented in the interpreter if it's holding an instruction and a value? I thought each bytecode is an int8_t. – Tim May 04 '18 at 05:58
-
@Tim Each *opcode* is one byte. Depending on their definitions, operations can be followed by operands. – chrylis -cautiouslyoptimistic- May 04 '18 at 06:27
-
Since it's one byte, how are there two values, integer and bipush instruction? – Tim May 04 '18 at 07:24
-
I think you're looking for section 2.11 of the JVMS, which deals with instruction representation. In particular, it uses the obvious order: the opcode, immediately followed by operands in order, big-endian (as all Java representations). In the case of bipush, this would be the byte 0x10 followed by the literal value.
- 75,269
- 21
- 115
- 152