[interp] Add separate opcode for pop vt (#36760)
authormonojenkins <jo.shields+jenkins@xamarin.com>
Wed, 20 May 2020 21:35:59 +0000 (17:35 -0400)
committerGitHub <noreply@github.com>
Wed, 20 May 2020 21:35:59 +0000 (00:35 +0300)
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>
src/mono/mono/mini/interp/interp.c
src/mono/mono/mini/interp/mintops.def
src/mono/mono/mini/interp/transform.c

index 35de785..6fb7279 100644 (file)
@@ -3567,6 +3567,13 @@ main_loop:
                        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--;
index d3dd6cc..f3cbbb5 100644 (file)
@@ -16,6 +16,7 @@ OPDEF(MINT_LDNULL, "ldnull", 1, Pop0, Push1, MintOpNoArgs)
 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)
index 5d78ab5..70d866e 100644 (file)
@@ -3740,14 +3740,15 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
                }
                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;
@@ -7347,7 +7348,7 @@ retry:
                                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