Просмотр исходного кода

Fix for x86 and amd64 continuations (#3182)

Dunati 9 лет назад
Родитель
Сommit
15fedcada9
5 измененных файлов с 27 добавлено и 11 удалено
  1. 6 4
      mono/mini/exceptions-amd64.c
  2. 5 5
      mono/mini/exceptions-x86.c
  3. 6 1
      mono/mini/mini-amd64.c
  4. 9 1
      mono/mini/mini.h
  5. 1 0
      mono/mini/tasklets.c

+ 6 - 4
mono/mini/exceptions-amd64.c

@@ -1152,13 +1152,15 @@ mono_tasklets_arch_restore (void)
 	amd64_movsl (code);
 
 	/* now restore the registers from the LMF */
-	NOT_IMPLEMENTED;
 	amd64_mov_reg_membase (code, AMD64_RCX, cont_reg, MONO_STRUCT_OFFSET (MonoContinuation, lmf), 8);
+	amd64_mov_reg_membase (code, AMD64_RBP, AMD64_RCX, MONO_STRUCT_OFFSET (MonoLMF, rbp), 8);
 	amd64_mov_reg_membase (code, AMD64_RSP, AMD64_RCX, MONO_STRUCT_OFFSET (MonoLMF, rsp), 8);
 
-	/* restore the lmf chain */
-	/*x86_mov_reg_membase (code, X86_ECX, X86_ESP, 12, 4);
-	x86_mov_membase_reg (code, X86_ECX, 0, X86_EDX, 4);*/
+#ifdef WIN32
+	amd64_mov_reg_reg (code, AMD64_R14, AMD64_ARG_REG3, 8);
+#else
+	amd64_mov_reg_reg (code, AMD64_R12, AMD64_ARG_REG3, 8);
+#endif
 
 	/* state is already in rax */
 	amd64_jump_membase (code, cont_reg, MONO_STRUCT_OFFSET (MonoContinuation, return_ip));

+ 5 - 5
mono/mini/exceptions-x86.c

@@ -1145,8 +1145,10 @@ mono_tasklets_arch_restore (void)
 	/* the signature is: restore (MonoContinuation *cont, int state, MonoLMF **lmf_addr) */
 	/* put cont in edx */
 	x86_mov_reg_membase (code, X86_EDX, X86_ESP, 4, 4);
-        /* state in eax, so it's setup as the return value */
-        x86_mov_reg_membase (code, X86_EAX, X86_ESP, 8, 4);
+	/* state in eax, so it's setup as the return value */
+	x86_mov_reg_membase (code, X86_EAX, X86_ESP, 8, 4);
+	/* lmf_addr in ebx */
+	x86_mov_reg_membase(code, X86_EBX, X86_ESP, 0x0C, 4);
 
 	/* setup the copy of the stack */
 	x86_mov_reg_membase (code, X86_ECX, X86_EDX, MONO_STRUCT_OFFSET (MonoContinuation, stack_used_size), 4);
@@ -1159,10 +1161,8 @@ mono_tasklets_arch_restore (void)
 
 	/* now restore the registers from the LMF */
 	x86_mov_reg_membase (code, X86_ECX, X86_EDX, MONO_STRUCT_OFFSET (MonoContinuation, lmf), 4);
-	x86_mov_reg_membase (code, X86_EBX, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, ebx), 4);
 	x86_mov_reg_membase (code, X86_EBP, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, ebp), 4);
-	x86_mov_reg_membase (code, X86_ESI, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, esi), 4);
-	x86_mov_reg_membase (code, X86_EDI, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, edi), 4);
+	x86_mov_reg_membase (code, X86_ESP, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, esp), 4);
 
 	/* restore the lmf chain */
 	/*x86_mov_reg_membase (code, X86_ECX, X86_ESP, 12, 4);

+ 6 - 1
mono/mini/mini-amd64.c

@@ -7148,7 +7148,12 @@ mono_arch_emit_epilog (MonoCompile *cfg)
 	for (i = 0; i < AMD64_NREG; ++i) {
 		if (AMD64_IS_CALLEE_SAVED_REG (i) && (cfg->arch.saved_iregs & (1 << i))) {
 			/* Restore only used_int_regs, not arch.saved_iregs */
-			if (cfg->used_int_regs & (1 << i)) {
+#if defined(MONO_SUPPORT_TASKLETS)
+			int restore_reg=1;
+#else
+			int restore_reg=(cfg->used_int_regs & (1 << i));
+#endif
+			if (restore_reg) {
 				amd64_mov_reg_membase (code, i, cfg->frame_reg, save_area_offset, 8);
 				mono_emit_unwind_op_same_value (cfg, code, i);
 				async_exc_point (code);

+ 9 - 1
mono/mini/mini.h

@@ -76,8 +76,16 @@
 #define MINI_DEBUG(level,limit,code) do {if (G_UNLIKELY ((level) >= (limit))) code} while (0)
 #endif
 
-#if !defined(DISABLE_TASKLETS) && defined(MONO_ARCH_SUPPORT_TASKLETS) && defined(__GNUC__)
+#if !defined(DISABLE_TASKLETS) && defined(MONO_ARCH_SUPPORT_TASKLETS)
+#if defined(__GNUC__)
 #define MONO_SUPPORT_TASKLETS 1
+#elif defined(HOST_WIN32)
+#define MONO_SUPPORT_TASKLETS 1
+// Replace some gnu intrinsics needed for tasklets with MSVC equivalents.
+#define __builtin_extract_return_addr(x) x
+#define __builtin_return_address(x) _ReturnAddress()
+#define __builtin_frame_address(x) _AddressOfReturnAddress()
+#endif
 #endif
 
 #if ENABLE_LLVM

+ 1 - 0
mono/mini/tasklets.c

@@ -54,6 +54,7 @@ continuation_mark_frame (MonoContinuation *cont)
 
 	/* get to the frame that called Mark () */
 	memset (&rji, 0, sizeof (rji));
+	memset (&ctx, 0, sizeof (ctx));
 	do {
 		ji = mono_find_jit_info (cont->domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, NULL);
 		if (!ji || ji == (gpointer)-1) {