If possible, avoid shorts, bytes, and compressed byte code. Most CPUs work with 32 and 64 bit numbers, and they will convert bytes/shorts to 32 bits usually, which takes time (your compiler may do this regardless, depending on optimization, but anyhow it keeps your VM smaller and cleaner). Also, your VM would need to support every permutation of action (add a byte to an int, a int to a short, etc). Also, compressing an instruction into a 32 bit or 64 bit space is adverse to performance. Memory is plentiful enough (both RAM and cache) that you should not bother with this unless you are targeting an embedded device or something.
Use enums for your op codes, and a switch statement (depends on compiler). If you use enums and a switch, the compiler can generate a jump table because it knows the enum will always be in a certain range. Much better performance than a bunch of if/else statements.
It is possible to write a VM that only uses floating point numbers, if you want to keep the VM as small and simple as possible. This means casting the floats for things like addressing, but otherwise I think it might perform well.