Before this change, pop-ing a vt from the stack was done in 2 opcodes, a MINT_POP (decrementing the stack) and the weird MINT_VTRESULT (decrementing the vtstack). However, optimizations could have removed both the initial loading of the value type on the stack as well as the MINT_POP, leaving MINT_VTRESULT underflowing the vtstack. Fix this and cleanup the code by pop-ing a value type from the stack in a single instruction.
Co-authored-by: BrzVlad <BrzVlad@users.noreply.github.com>
ip++;
MINT_IN_BREAK;
}
+ MINT_IN_CASE(MINT_POP_VT) {
+ int i32 = READ32 (ip + 1);
+ vt_sp -= ALIGN_TO (i32, MINT_VT_ALIGNMENT);
+ sp--;
+ ip += 3;
+ MINT_IN_BREAK;
+ }
MINT_IN_CASE(MINT_POP1) {
sp [-2] = sp [-1];
sp--;
OPDEF(MINT_DUP, "dup", 1, Pop1, Push2, MintOpNoArgs)
OPDEF(MINT_DUP_VT, "dup.vt", 3, Pop1, Push2, MintOpInt)
OPDEF(MINT_POP, "pop", 1, Pop1, Push0, MintOpNoArgs)
+OPDEF(MINT_POP_VT, "pop.vt", 3, Pop1, Push0, MintOpNoArgs)
OPDEF(MINT_POP1, "pop1", 1, Pop2, Push1, MintOpNoArgs)
OPDEF(MINT_RET, "ret", 1, Pop1, Push0, MintOpNoArgs)
}
case CEE_POP:
CHECK_STACK(td, 1);
- SIMPLE_OP(td, MINT_POP);
if (td->sp [-1].type == STACK_TYPE_VT) {
int size = mono_class_value_size (td->sp [-1].klass, NULL);
size = ALIGN_TO (size, MINT_VT_ALIGNMENT);
- interp_add_ins (td, MINT_VTRESULT);
- td->last_ins->data [0] = 0;
- WRITE32_INS (td->last_ins, 1, &size);
+ interp_add_ins (td, MINT_POP_VT);
+ WRITE32_INS (td->last_ins, 0, &size);
td->vt_sp -= size;
+ td->ip++;
+ } else {
+ SIMPLE_OP(td, MINT_POP);
}
--td->sp;
break;
sp [-i].ins = NULL;
memset (sp, 0, sizeof (StackContentInfo));
sp++;
- } else if (ins->opcode == MINT_POP) {
+ } else if (ins->opcode == MINT_POP || ins->opcode == MINT_POP_VT) {
sp--;
if (sp->ins) {
// The top of the stack is not used by any instructions. Kill both the