Przeglądaj źródła

x64: Use external unwinding for lua_yield().

Mike Pall 14 lat temu
rodzic
commit
642ae06916
2 zmienionych plików z 18 dodań i 11 usunięć
  1. 4 0
      src/lj_api.c
  2. 14 11
      src/lj_err.c

+ 4 - 0
src/lj_api.c

@@ -1107,9 +1107,13 @@ LUA_API int lua_yield(lua_State *L, int nresults)
       top[2].fr.tp.ftsz = (int)((char *)(top+3)-(char *)L->base)+FRAME_CONT;
       top[2].fr.tp.ftsz = (int)((char *)(top+3)-(char *)L->base)+FRAME_CONT;
       L->top = L->base = top+3;
       L->top = L->base = top+3;
     }
     }
+#if LJ_TARGET_X64
+    lj_err_throw(L, LUA_YIELD);
+#else
     L->cframe = NULL;
     L->cframe = NULL;
     L->status = LUA_YIELD;
     L->status = LUA_YIELD;
     lj_vm_unwind_c(cf, LUA_YIELD);
     lj_vm_unwind_c(cf, LUA_YIELD);
+#endif
   }
   }
   lj_err_msg(L, LJ_ERR_CYIELD);
   lj_err_msg(L, LJ_ERR_CYIELD);
   return 0;  /* unreachable */
   return 0;  /* unreachable */

+ 14 - 11
src/lj_err.c

@@ -502,11 +502,14 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode)
       frame = frame_prevd(frame);
       frame = frame_prevd(frame);
       break;
       break;
     case FRAME_PCALL:  /* FF pcall() frame. */
     case FRAME_PCALL:  /* FF pcall() frame. */
-      if (errcode)
-	hook_leave(G(L));
-      /* fallthrough */
     case FRAME_PCALLH:  /* FF pcall() frame inside hook. */
     case FRAME_PCALLH:  /* FF pcall() frame inside hook. */
       if (errcode) {
       if (errcode) {
+	if (errcode == LUA_YIELD) {
+	  frame = frame_prevd(frame);
+	  break;
+	}
+	if (frame_typep(frame) == FRAME_PCALL)
+	  hook_leave(G(L));
 	L->cframe = cf;
 	L->cframe = cf;
 	L->base = frame_prevd(frame) + 1;
 	L->base = frame_prevd(frame) + 1;
 	unwindstack(L, L->base);
 	unwindstack(L, L->base);
@@ -660,28 +663,28 @@ LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec,
   void *cf, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch)
   void *cf, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch)
 {
 {
   lua_State *L = cframe_L(cf);
   lua_State *L = cframe_L(cf);
+  int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ?
+		LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN;
   if ((rec->ExceptionFlags & 6)) {  /* EH_UNWINDING|EH_EXIT_UNWIND */
   if ((rec->ExceptionFlags & 6)) {  /* EH_UNWINDING|EH_EXIT_UNWIND */
-    err_unwind(L, cf, 1);  /* Unwind internal frames. */
+    /* Unwind internal frames. */
+    err_unwind(L, cf, errcode);
   } else {
   } else {
     void *cf2 = err_unwind(L, cf, 0);
     void *cf2 = err_unwind(L, cf, 0);
     if (cf2) {  /* We catch it, so start unwinding the upper frames. */
     if (cf2) {  /* We catch it, so start unwinding the upper frames. */
-      int errcode;
-      if (LJ_EXCODE_CHECK(rec->ExceptionCode)) {
-	errcode = LJ_EXCODE_ERRCODE(rec->ExceptionCode);
-      } else if (rec->ExceptionCode == LJ_MSVC_EXCODE) {
+      if (rec->ExceptionCode == LJ_MSVC_EXCODE) {
 #ifdef _MSC_VER
 #ifdef _MSC_VER
 	__DestructExceptionObject(rec, 1);
 	__DestructExceptionObject(rec, 1);
 #endif
 #endif
 	setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP));
 	setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP));
-	errcode = LUA_ERRRUN;
-      } else {  /* Don't catch access violations etc. */
+      } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) {
+	/* Don't catch access violations etc. */
 	return ExceptionContinueSearch;
 	return ExceptionContinueSearch;
       }
       }
       /* Unwind the stack and call all handlers for all lower C frames
       /* Unwind the stack and call all handlers for all lower C frames
       ** (including ourselves) again with EH_UNWINDING set. Then set
       ** (including ourselves) again with EH_UNWINDING set. Then set
       ** rsp = cf, rax = errcode and jump to the specified target.
       ** rsp = cf, rax = errcode and jump to the specified target.
       */
       */
-      RtlUnwindEx(cf, (void *)(cframe_unwind_ff(cf2) ?
+      RtlUnwindEx(cf, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ?
 			       lj_vm_unwind_ff_eh :
 			       lj_vm_unwind_ff_eh :
 			       lj_vm_unwind_c_eh),
 			       lj_vm_unwind_c_eh),
 		  rec, (void *)errcode, ctx, dispatch->HistoryTable);
 		  rec, (void *)errcode, ctx, dispatch->HistoryTable);