操作数栈管理相关的字节码指令如下表所示。
0x57 |
pop |
将栈顶数值弹出 (数值不能是long或double类型的) |
0x58 |
pop2 |
将栈顶的一个(long或double类型的)或两个数值弹出(其它) |
0x59 |
dup |
复制栈顶数值并将复制值压入栈顶 |
0x5a |
dup_x1 |
复制栈顶数值并将两个复制值压入栈顶 |
0x5b |
dup_x2 |
复制栈顶数值并将三个(或两个)复制值压入栈顶 |
0x5c |
dup2 |
复制栈顶一个(long或double类型的)或两个(其它)数值并将复制值压入栈顶 |
0x5d |
dup2_x1 |
dup_x1 指令的双倍版本 |
0x5e |
dup2_x2 |
dup_x2 指令的双倍版本 |
0x5f |
swap |
将栈最顶端的两个数值互换(数值不能是long或double类型的) |
字节码指令对应的模板定义如下:
def(Bytecodes::_pop , ____|____|____|____, vtos, vtos, pop , _ ); def(Bytecodes::_pop2 , ____|____|____|____, vtos, vtos, pop2 , _ ); def(Bytecodes::_dup , ____|____|____|____, vtos, vtos, dup , _ ); def(Bytecodes::_dup_x1 , ____|____|____|____, vtos, vtos, dup_x1 , _ ); def(Bytecodes::_dup_x2 , ____|____|____|____, vtos, vtos, dup_x2 , _ ); def(Bytecodes::_dup2 , ____|____|____|____, vtos, vtos, dup2 , _ ); def(Bytecodes::_dup2_x1 , ____|____|____|____, vtos, vtos, dup2_x1 , _ ); def(Bytecodes::_dup2_x2 , ____|____|____|____, vtos, vtos, dup2_x2 , _ ); def(Bytecodes::_swap , ____|____|____|____, vtos, vtos, swap , _ );
pop指令将栈顶数值弹出。对应的汇编代码如下:
add $0x8,%rsp
pop2指令将栈顶数值弹出。对应的汇编代码如下:
add $0x10,%rsp
dup指令复制栈顶数值并将复制值压入栈顶。对应的汇编代码如下:
mov (%rsp),%rax push %rax
swap指令将栈最顶端的两个数值互换(数值不能是long或double类型的)。对应的汇编代码如下:
mov 0x8(%rsp),%rcx mov (%rsp),%rax mov %rcx,(%rsp) mov %rax,0x8(%rsp)
指令的执行逻辑比较简单,这里不再过多介绍。
推荐阅读:
第2篇-JVM虚拟机这样来调用Java主类的main()方法
第13篇-通过InterpreterCodelet存储机器指令片段
第20篇-加载与存储指令之ldc与_fast_aldc指令(2)
第21篇-加载与存储指令之iload、_fast_iload等(3)