Index: vm/port/include/lil.h =================================================================== --- vm/port/include/lil.h (revision 569233) +++ vm/port/include/lil.h (working copy) @@ -522,6 +522,7 @@ virtual void push_m2n(Method_Handle method, frame_type current_frame_type, bool handles) = 0; virtual void m2n_save_all() = 0; virtual void pop_m2n() = 0; + virtual void pop_m2n_noexp() = 0; virtual void print(char *, LilOperand *) = 0; }; @@ -556,6 +557,7 @@ void push_m2n(Method_Handle UNREF method, frame_type UNREF current_frame_type, bool UNREF handles) {} void m2n_save_all() {} void pop_m2n() {} + void pop_m2n_noexp() {} void print(char *, LilOperand *) {} }; Index: vm/port/src/lil/lil.cpp =================================================================== --- vm/port/src/lil/lil.cpp (revision 569233) +++ vm/port/src/lil/lil.cpp (working copy) @@ -62,7 +62,7 @@ enum LilInstructionTag { LIT_Label, LIT_Locals, LIT_StdPlaces, LIT_Alloc, LIT_Asgn, LIT_Ts, LIT_Handles, LIT_Ld, LIT_St, LIT_Inc, LIT_Cas, LIT_J, LIT_Jc, LIT_Out, LIT_In2Out, LIT_Call, LIT_Ret, - LIT_PushM2N, LIT_M2NSaveAll, LIT_PopM2N, LIT_Print + LIT_PushM2N, LIT_M2NSaveAll, LIT_PopM2N, LIT_PopM2N_NoExp, LIT_Print }; struct LilInstruction { @@ -883,9 +883,18 @@ } } else if ((*src)[1]=='o') { - // pop_m2n - i->tag = LIT_PopM2N; - if (!lil_parse_kw(src, "pop_m2n")) return NULL; + if ((*src)[4]=='n') { + // pop_m2n + i->tag = LIT_PopM2N_NoExp; + if (!lil_parse_kw(src, "pop_noexp_m2n")) return NULL; + } + if ((*src)[4]=='m') { + // pop_m2n + i->tag = LIT_PopM2N; + if (!lil_parse_kw(src, "pop_m2n")) return NULL; + + } + } else { // print @@ -1368,6 +1377,12 @@ c->num_std_places = 0; c->out_sig = NULL; break; + case LIT_PopM2N_NoExp: + c->m2n = LMS_NoM2n; + c->amt_alloced = 0; + c->num_std_places = 0; + c->out_sig = NULL; + break; case LIT_Print: // nothing to do here break; @@ -1746,6 +1761,9 @@ case LIT_PopM2N: v->pop_m2n(); break; + case LIT_PopM2N_NoExp: + v->pop_m2n_noexp(); + break; case LIT_Print: v->print(i->u.print.str, &i->u.print.arg); break; @@ -2053,6 +2071,7 @@ if (c->m2n==LMS_NoM2n) ERR("m2n save all not dominated by push m2n"); break; case LIT_PopM2N: + case LIT_PopM2N_NoExp: if (c->m2n==LMS_NoM2n) ERR("pop m2n not dominated by push"); break; case LIT_Print: @@ -2405,6 +2424,9 @@ case LIT_PopM2N: fprintf(out, "pop_m2n"); break; + case LIT_PopM2N_NoExp: + fprintf(out, "pop_noexp_m2n"); + break; case LIT_Print: fprintf(out, "print %p, ", i->u.print.str); lil_print_operand(out, &i->u.print.arg); Index: vm/port/src/lil/ia32/pim/lil_code_generator_ia32.cpp =================================================================== --- vm/port/src/lil/ia32/pim/lil_code_generator_ia32.cpp (revision 569233) +++ vm/port/src/lil/ia32/pim/lil_code_generator_ia32.cpp (working copy) @@ -834,6 +834,35 @@ info->size += m2n_pop_m2n_size(lil_ic_get_m2n_state(ctxt.ctxt)==LMS_Handles, 4, num, ii->u.pop_m2n); } + void pop_m2n_noexp() + { + m2n_ops++; + unsigned num = m2n_base(&ctxt); + switch (lil_ic_get_ret_type(ctxt.ctxt)) { + case LT_Void: + case LT_F4: + case LT_F8: + ii->u.pop_m2n = 0; + break; + case LT_G8: + ii->u.pop_m2n = 2; + break; + case LT_G1: + case LT_G2: + case LT_G4: + case LT_Ref: + case LT_PInt: + ii->u.pop_m2n = 1; + break; + default: ASSERT(0, "Unknown LIL type"); + } + info->size += m2n_pop_m2n_size(lil_ic_get_m2n_state(ctxt.ctxt)==LMS_Handles, 4, num, ii->u.pop_m2n); + + // A bit more for inlining + info->size += 20; + } + + void print(char *, LilOperand *) { // not implemented on ia32 } @@ -1422,6 +1451,12 @@ *buf = m2n_gen_pop_m2n(*buf, lil_ic_get_m2n_state(ctxt.ctxt)==LMS_Handles, ctxt.info->num_callee_saves, m2n_base(&ctxt), ii->u.pop_m2n); } + void pop_m2n_noexp() + { + *buf = m2n_gen_pop_m2n_noexp(*buf, lil_ic_get_m2n_state(ctxt.ctxt)==LMS_Handles, ctxt.info->num_callee_saves, m2n_base(&ctxt), ii->u.pop_m2n); + } + + void print(char *, LilOperand *) { // not implemented on ia32 } Index: vm/port/src/lil/ia32/pim/m2n_ia32.cpp =================================================================== --- vm/port/src/lil/ia32/pim/m2n_ia32.cpp (revision 569233) +++ vm/port/src/lil/ia32/pim/m2n_ia32.cpp (working copy) @@ -316,6 +316,68 @@ return buf; } +char* m2n_gen_pop_m2n_noexp(char* buf, bool handles, unsigned num_callee_saves, unsigned extra_on_stack, unsigned preserve_ret) +{ + if (preserve_ret > 0) { + // Save return value + buf = push(buf, eax_opnd); + if (preserve_ret > 1) { + buf = push(buf, edx_opnd); + } + } + + int32 lastframe_offset = (unsigned) &(((VM_thread *) (0))->last_m2n_frame); + int32 localobj_offset = (unsigned) &(((M2nFrame *) (0))->local_object_handles); + +// buf = int3(buf); + + buf = m2n_gen_ts_to_register(buf, &eax_opnd); + buf = mov(buf, eax_opnd, M_Base_Opnd(eax_reg, lastframe_offset)); + buf = mov(buf, eax_opnd, M_Base_Opnd(eax_reg, localobj_offset)); + buf = push(buf, eax_opnd); + + if (handles) { + // There are handles located on the stack + buf = call(buf, (char*)free_local_object_handles2); + } else { + buf = call(buf, (char*)free_local_object_handles3); + } + buf = pop(buf, eax_opnd); + + + if (preserve_ret > 0) { + // Restore return value + if (preserve_ret > 1) { + buf = pop(buf, edx_opnd); + } + buf = pop(buf, eax_opnd); + } + + // pop "garbage" from the stack + if (extra_on_stack) { + Imm_Opnd imm(extra_on_stack); + buf = alu(buf, add_opc, esp_opnd, imm); + } + + // Unlink the M2nFrame from the list of the current thread + buf = pop(buf, esi_opnd); + buf = pop(buf, ebx_opnd); + buf = mov(buf, M_Base_Opnd(ebx_reg, +0), esi_opnd); + buf = alu(buf, add_opc, esp_opnd, Imm_Opnd(+16)); + + // TODO: check if there is no need to restore callee saved registers + // JUSTIFICATION: m2n frame is popped as a result of "normal" + // (opposite to destuctive) stack unwinding + // Restore callee saved general registers + if (num_callee_saves<4) buf = pop(buf, edi_opnd); + if (num_callee_saves<3) buf = pop(buf, esi_opnd); + if (num_callee_saves<2) buf = pop(buf, ebx_opnd); + if (num_callee_saves<1) buf = pop(buf, ebp_opnd); + + return buf; +} + + // returns pointer to the registers used for jvmti PopFrame Registers* get_pop_frame_registers(M2nFrame* m2nf) { return m2nf->pop_regs; Index: vm/port/src/lil/ia32/pim/m2n_ia32_internal.h =================================================================== --- vm/port/src/lil/ia32/pim/m2n_ia32_internal.h (revision 569233) +++ vm/port/src/lil/ia32/pim/m2n_ia32_internal.h (working copy) @@ -68,6 +68,7 @@ // handles: as for push_m2n, frees the handles if true. unsigned m2n_pop_m2n_size(bool handles, unsigned num_callee_saves, unsigned extra_on_stack, unsigned preserve_ret); char* m2n_gen_pop_m2n(char* buf, bool handles, unsigned num_callee_saves, unsigned extra_on_stack, unsigned preserve_ret); +char* m2n_gen_pop_m2n_noexp(char* buf, bool handles, unsigned num_callee_saves, unsigned extra_on_stack, unsigned preserve_ret); ////////////////////////////////////////////////////////////////////////// // Implementation details Index: vm/vmcore/src/jit/compile.cpp =================================================================== --- vm/vmcore/src/jit/compile.cpp (revision 569233) +++ vm/vmcore/src/jit/compile.cpp (working copy) @@ -508,7 +508,7 @@ assert(cs); } cs = lil_parse_onto_end(cs, - "pop_m2n;" + "pop_noexp_m2n;" "ret;"); assert(cs);