Search code examples
jvmbytecodejava-bytecode-asmvm-implementation

How to load different primitive datas to the operand stack


JVM has two instructions: bipush (operand value should be between Byte.MIN_VALUE and Byte.MAX_VALUE.) and sipush (operand value should be between Short.MIN_VALUE and Short.MAX_VALUE). Correspondingly, the MethodVisitor in the ASM provide the API to manipulate these two instructions:

      public void visitIntInsn(int opcode, int operand)

Therefore, how to visit other non-byte(short) primitives in the ASM? For example, the primitive long, double, int, boolean, and float data? It looks strange these data are wrapped as Long, Double, Integer.


Solution

  • Booleans are just ints at the JVM level. Push 0 for false and 1 for true. You don't need bipush for that, you can just use iconst_0 and iconst_1.

    Bytes, shorts, chars, and ints are all also just ints at the JVM level. There is no concept of short primitive types in bytecode, only truncatation functions (i2c and co).

    If you want to push the int value 111, you would use bipush 111. If you want to push 1111, you would use sipush 1111. If you want to push 111111, you would use ldc 111111. They're all just ints at the bytecode level.

    For floats, doubles, and longs, you'll have to in most cases use the ldc* family of instructions. For the special case of 0 or 1 constants, you can instead use lconst_0, dconst_1, etc.

    You can create ldc instructions in ASM using the aptly named MethodVisitor.visitLdcInsn.

    Note that ldc requires space in the constant pool, which is limited to 65534 slots. However, it's big enough that you'll never run out under practical circumstances. If you really want to, you can push larger primitive values without using the constant pool by using math to construct the values.

    For example, int 111111 can be generated by iconst_3 bipush 15 ishl sipush 12807 iadd. Enjarify has code to do this for every primative type, even doubles, though they usually take many more instructions to represent for obvious reasons. However, if you're using ASM, you're probably not doing anything unusual and complicated enough to require this approach.