Browse Source

Pass MULTRES or negated error code in RD to lj_vm_exit_interp.

Fixes overwrite of saved r12 after trace exit.
Mike Pall 15 years ago
parent
commit
6038866f7d
6 changed files with 1675 additions and 1692 deletions
  1. 549 549
      src/buildvm_x64.h
  2. 517 517
      src/buildvm_x64win.h
  3. 5 5
      src/buildvm_x86.dasc
  4. 587 586
      src/buildvm_x86.h
  5. 7 21
      src/lj_asm.c
  6. 10 14
      src/lj_trace.c

File diff suppressed because it is too large
+ 549 - 549
src/buildvm_x64.h


File diff suppressed because it is too large
+ 517 - 517
src/buildvm_x64win.h


+ 5 - 5
src/buildvm_x86.dasc

@@ -2623,7 +2623,7 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
   |.endif
   |  lea FCARG1, [DISPATCH+GG_DISP2J]
   |  call extern lj_trace_exit@8	// (jit_State *J, ExitState *ex)
-  |  // Error code returned in eax (RD).
+  |  // MULTRES or negated error code returned in eax (RD).
   |  mov RAa, L:RB->cframe
   |  and RAa, CFRAME_RAWMASK
   |.if X64WIN
@@ -2638,14 +2638,12 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
   |  mov PC, [RAa+CFRAME_OFS_PC]	// Get SAVE_PC.
   |.if X64
   |  jmp >1
-  |.else
-  |  test RD, RD; jnz >2		// Check for error from exit.
   |.endif
 #endif
   |->vm_exit_interp:
+  |  // RD = MULTRES or negated error code, BASE, PC and DISPATCH set.
 #if LJ_HASJIT
   |.if X64
-  |  xor RD, RD
   |  // Restore additional callee-save registers only used in compiled code.
   |.if X64WIN
   |  lea RAa, [rsp+9*16+4*8]
@@ -2669,8 +2667,9 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
   |.endif
   |  mov r13, TMPa
   |  mov r12, TMPQ
-  |  test RD, RD; jnz >2		// Check for error from exit.
   |.endif
+  |  test RD, RD; js >2			// Check for error from exit.
+  |  mov MULTRES, RD
   |  mov LFUNC:KBASE, [BASE-8]
   |  mov KBASE, LFUNC:KBASE->pc
   |  mov KBASE, [KBASE+PC2PROTO(k)]
@@ -2679,6 +2678,7 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
   |  ins_next
   |
   |2:  // Rethrow error from the right C frame.
+  |  neg RD
   |  mov FCARG1, L:RB
   |  mov FCARG2, RD
   |  call extern lj_err_throw@8		// (lua_State *L, int errcode)

File diff suppressed because it is too large
+ 587 - 586
src/buildvm_x86.h


+ 7 - 21
src/lj_asm.c

@@ -3253,16 +3253,6 @@ static void asm_head_side(ASMState *as)
 
 /* -- Tail of trace ------------------------------------------------------- */
 
-/* Set MULTRES in C frame. */
-static void asm_tail_multres(ASMState *as, BCReg mres)
-{
-  /* We don't know spadj yet, so get the C frame from L->cframe. */
-  emit_movmroi(as, RID_RET, CFRAME_OFS_MULTRES, mres);
-  emit_gri(as, XG_ARITHi(XOg_AND), RID_RET|REX_64, CFRAME_RAWMASK);
-  emit_rmro(as, XO_MOV, RID_RET|REX_64, RID_RET, offsetof(lua_State, cframe));
-  emit_getgl(as, RID_RET, jit_L);
-}
-
 /* Link to another trace. */
 static void asm_tail_link(ASMState *as)
 {
@@ -3276,6 +3266,7 @@ static void asm_tail_link(ASMState *as)
   if (as->T->link == TRACE_INTERP) {
     /* Setup fixed registers for exit to interpreter. */
     const BCIns *pc = snap_pc(as->T->snapmap[snap->mapofs + snap->nent]);
+    int32_t mres;
     if (bc_op(*pc) == BC_JLOOP) {  /* NYI: find a better way to do this. */
       BCIns *retpc = &as->J->trace[bc_d(*pc)]->startins;
       if (bc_isret(bc_op(*retpc)))
@@ -3283,19 +3274,14 @@ static void asm_tail_link(ASMState *as)
     }
     emit_loada(as, RID_DISPATCH, J2GG(as->J)->dispatch);
     emit_loada(as, RID_PC, pc);
+    mres = (int32_t)(snap->nslots - baseslot - bc_a(*pc));
     switch (bc_op(*pc)) {
-    case BC_CALLM: case BC_CALLMT:
-      asm_tail_multres(as, snap->nslots - baseslot - 1 - bc_a(*pc) - bc_c(*pc));
-      break;
-    case BC_RETM:
-      asm_tail_multres(as, snap->nslots - baseslot - bc_a(*pc) - bc_d(*pc));
-      break;
-    case BC_TSETM:
-      asm_tail_multres(as, snap->nslots - baseslot - bc_a(*pc));
-      break;
-    default:
-      break;
+    case BC_CALLM: case BC_CALLMT: mres -= (int32_t)(1 + bc_c(*pc)); break;
+    case BC_RETM: mres -= (int32_t)bc_d(*pc); break;
+    case BC_TSETM: break;
+    default: mres = 0; break;
     }
+    emit_loadi(as, RID_RET, mres);  /* Return MULTRES or 0. */
   } else if (baseslot) {
     /* Save modified BASE for linking to trace with higher start frame. */
     emit_setgl(as, RID_BASE, jit_base);

+ 10 - 14
src/lj_trace.c

@@ -671,7 +671,7 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
   exd.exptr = exptr;
   errcode = lj_vm_cpcall(L, NULL, &exd, trace_exit_cp);
   if (errcode)
-    return errcode;
+    return -errcode;  /* Return negated error code. */
 
   lj_vmevent_send(L, TEXIT,
     ExitState *ex = (ExitState *)exptr;
@@ -694,8 +694,7 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
   pc = exd.pc;
   trace_hotside(J, pc);
   cf = cframe_raw(L->cframe);
-  switch (bc_op(*pc)) {
-  case BC_JLOOP: {
+  if (bc_op(*pc) == BC_JLOOP) {
     BCIns *retpc = &J->trace[bc_d(*pc)]->startins;
     if (bc_isret(bc_op(*retpc))) {
       if (J->state == LJ_TRACE_RECORD) {
@@ -706,22 +705,19 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
 	pc = retpc;
       }
     }
-    break;
-    }
+  }
+  setcframe_pc(cf, pc);
+  /* Return MULTRES or 0. */
+  switch (bc_op(*pc)) {
   case BC_CALLM: case BC_CALLMT:
-    cframe_multres(cf) = (BCReg)(L->top - L->base) - bc_a(*pc) - bc_c(*pc);
-    break;
+    return (int)((BCReg)(L->top - L->base) - bc_a(*pc) - bc_c(*pc));
   case BC_RETM:
-    cframe_multres(cf) = (BCReg)(L->top - L->base) + 1 - bc_a(*pc) - bc_d(*pc);
-    break;
+    return (int)((BCReg)(L->top - L->base) + 1 - bc_a(*pc) - bc_d(*pc));
   case BC_TSETM:
-    cframe_multres(cf) = (BCReg)(L->top - L->base) + 1 - bc_a(*pc);
-    break;
+    return (int)((BCReg)(L->top - L->base) + 1 - bc_a(*pc));
   default:
-    break;
+    return 0;
   }
-  setcframe_pc(cf, pc);
-  return 0;
 }
 
 #endif

Some files were not shown because too many files changed in this diff