Index: vm/port/include/lil.h =================================================================== --- vm/port/include/lil.h (revision 569233) +++ vm/port/include/lil.h (working copy) @@ -522,7 +522,10 @@ 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; + virtual void hse() {} + virtual void hsd() {} }; @@ -556,7 +559,10 @@ 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 *) {} + void hse() {} + void hsd() {} }; 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_Print, LIT_HSE, LIT_HSD, LIT_PopM2N_NoExp }; struct LilInstruction { @@ -782,10 +782,21 @@ if (!lil_parse_operand(src, va, &(i->u.call.target))) return NULL; break; case 'h': // handles - i->tag = LIT_Handles; - if (!lil_parse_kw(src, "handles")) return NULL; - if (!lil_parse_kw(src, "=")) return NULL; - if (!lil_parse_operand(src, va, &(i->u.handles))) return NULL; + if ((*src)[1]=='a') { + i->tag = LIT_Handles; + if (!lil_parse_kw(src, "handles")) return NULL; + if (!lil_parse_kw(src, "=")) return NULL; + if (!lil_parse_operand(src, va, &(i->u.handles))) return NULL; + } + if ((*src)[1]=='s' && ((*src)[2])=='e') { + i->tag = LIT_HSE; + if (!lil_parse_kw(src, "hse")) return NULL; + } + if ((*src)[1]=='s' && ((*src)[2])=='d') { + i->tag = LIT_HSD; + if (!lil_parse_kw(src, "hsd")) return NULL; + } + break; case 'i': // =, in2out, inc if (num((*src)[1]) || (*src)[1]=='%') goto asgn; @@ -883,9 +894,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,9 +1388,18 @@ 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; + case LIT_HSE: + case LIT_HSD: + break; default: ASSERT(0, "Unknown instruction tag"); } } @@ -1746,9 +1775,18 @@ 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; + case LIT_HSE: + v->hse(); + break; + case LIT_HSD: + v->hsd(); + break; default: ASSERT(0, "Unknown instruction tag"); } } @@ -2053,12 +2091,16 @@ 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: if (!lil_is_valid_operand(cs, c, &i->u.print.arg)) ERR("invalid argument to print"); break; + case LIT_HSE: + case LIT_HSD: + break; default: ERR("unknown instruction"); } @@ -2405,11 +2447,20 @@ 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); fprintf(out, "\n"); break; + case LIT_HSE: + fprintf(out, "hse\n"); + break; + case LIT_HSD: + fprintf(out, "hsd\n"); + break; default: ASSERT(0, "Unknown instruction tag"); }; 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 } @@ -858,6 +887,15 @@ if (!info->short_jumps) info->size += 3*js+4*jcs; } + void hse() { + info->size += 25; + } + + void hsd() { + info->size += 35; + } + + private: tl::MemoryPool* mem; LilCodeStub* cs; @@ -1422,10 +1460,52 @@ *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 } + void hse() { + int32 disable_count_offset = (unsigned) &(((HyThread_public *) (0))->disable_count); + *buf = m2n_gen_hts_to_register(*buf, &eax_opnd); + *buf = alu(*buf, sub_opc, M_Base_Opnd(eax_reg, disable_count_offset), Imm_Opnd(1)); + } + + void hsd() { + int32 disable_count_offset = (unsigned) &(((HyThread_public *) (0))->disable_count); + int32 request_offset = (unsigned) &(((HyThread_public *) (0))->request); + + *buf = m2n_gen_hts_to_register(*buf, &eax_opnd); + + *buf = alu(*buf, add_opc, M_Base_Opnd(eax_reg, disable_count_offset), Imm_Opnd(1)); + + // (((HyThread_public *)thread)->request) + *buf = alu(*buf, cmp_opc, M_Base_Opnd(eax_reg, request_offset), Imm_Opnd(0)); + *buf = branch8(*buf, Condition_E, Imm_Opnd(0x0D + 6)); + + // ((HyThread_public *)thread)->disable_count == 1) + *buf = alu(*buf, cmp_opc, M_Base_Opnd(eax_reg, disable_count_offset), Imm_Opnd(1)); + *buf = branch8(*buf, Condition_NE, Imm_Opnd(0x06 + 7)); + // hythread_safe_point_other(thread); + + // TODO: optimize push-pop before hythread_safe_point_other + *buf = push(*buf, eax_opnd); + *buf = push(*buf, ebx_opnd); + *buf = push(*buf, ecx_opnd); + *buf = push(*buf, edx_opnd); + *buf = ::call(*buf, (char*)hythread_safe_point_other); + *buf = pop(*buf, edx_opnd); + *buf = pop(*buf, ecx_opnd); + *buf = pop(*buf, ebx_opnd); + *buf = pop(*buf, eax_opnd); + } + + tl::MemoryPool* mem; char** buf; LilCguLabelAddresses la_tab; 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) @@ -21,6 +21,7 @@ #include "open/types.h" #include "open/hythread.h" +#include "open/thread_helpers.h" #include "m2n.h" #include "m2n_ia32_internal.h" @@ -170,16 +171,41 @@ return 22; } + +// ashipile: fast TLS get generator char* m2n_gen_ts_to_register(char* buf, R_Opnd* reg) { + unsigned offset = + (unsigned) &(((HyThread_public *) (0))->thread_local_storage[0]); + +// Trap for the debugger +// buf = int3(buf); + if (reg!=&eax_opnd) buf = push(buf, eax_opnd); - buf = push(buf, ecx_opnd); - buf = push(buf, edx_opnd); - buf = call(buf, (char *)get_thread_ptr); - buf = pop(buf, edx_opnd); - buf = pop(buf, ecx_opnd); + + // get hythr tls in eax + buf = gen_hythread_self_helper(buf); + + // get vm_thread TLS from hythr + buf = mov(buf, *reg, M_Base_Opnd(eax_reg, offset)); + assert(buf); + if (reg!=&eax_opnd) { + buf = pop(buf, eax_opnd); + } + return buf; +} + +char* m2n_gen_hts_to_register(char* buf, R_Opnd* reg) +{ + if (reg!=&eax_opnd) + buf = push(buf, eax_opnd); + + // get hythr tls in eax + buf = gen_hythread_self_helper(buf); + + if (reg!=&eax_opnd) { buf = mov(buf, *reg, eax_opnd); buf = pop(buf, eax_opnd); } @@ -316,6 +342,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) @@ -47,6 +47,8 @@ unsigned m2n_ts_to_register_size(); char* m2n_gen_ts_to_register(char* buf, R_Opnd* reg); +char* m2n_gen_hts_to_register(char* buf, R_Opnd* reg); + // Generate code to push an M2nFrame onto the stack. // It assumes that num_callee_saves registers have already been saved and the rest have been preserved, that the saved registers are immediately // below the return address, and that esp points to the last one saved. The order for callee saves is ebp, ebx, esi, edi. @@ -68,6 +70,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) @@ -326,10 +326,14 @@ } //***** Part 4: Enable GC - cs = lil_parse_onto_end(cs, +/* + cs = lil_parse_onto_end(cs, "out platform::void;" "call %0i;", hythread_suspend_enable); +*/ + cs = lil_parse_onto_end(cs, + "hse;"); assert(cs); //***** Part 5: Set up arguments @@ -413,10 +417,15 @@ assert(cs); //***** Part 8: Disable GC +/* cs = lil_parse_onto_end(cs, "out platform::void;" "call %0i;", hythread_suspend_disable); +*/ + cs = lil_parse_onto_end(cs, + "hsd;"); + assert(cs); // Exception offsets @@ -508,7 +517,7 @@ assert(cs); } cs = lil_parse_onto_end(cs, - "pop_m2n;" + "pop_noexp_m2n;" "ret;"); assert(cs);