@@ -92,8 +92,6 @@ struct FrameClauseArgs {
9292	 * frame further down the stack. 
9393	 */ 
9494	const  guint16  * end_at_ip ;
95- 	/* When exiting this clause we also exit the frame */ 
96- 	int  exit_clause ;
9795	/* Frame that is executing this clause */ 
9896	InterpFrame  * exec_frame ;
9997};
@@ -429,6 +427,14 @@ interp_free_context (gpointer ctx)
429427	g_free  (context );
430428}
431429
430+ /* Continue unwinding if there is an exception that needs to be handled in an AOTed frame above us */ 
431+ static  void 
432+ check_pending_unwind  (ThreadContext  * context )
433+ {
434+ 	if  (context -> has_resume_state  &&  !context -> handler_frame )
435+ 		mono_llvm_cpp_throw_exception  ();
436+ }
437+ 
432438void 
433439mono_interp_error_cleanup  (MonoError *  error )
434440{
@@ -2118,6 +2124,8 @@ interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject
21182124
21192125	context -> stack_pointer  =  (guchar * )sp ;
21202126
2127+ 	check_pending_unwind  (context );
2128+ 
21212129	if  (context -> has_resume_state ) {
21222130		/* 
21232131		 * This can happen on wasm where native frames cannot be skipped during EH. 
@@ -2220,10 +2228,12 @@ interp_entry (InterpEntryData *data)
22202228	if  (rmethod -> needs_thread_attach )
22212229		mono_threads_detach_coop  (orig_domain , & attach_cookie );
22222230
2231+ 	check_pending_unwind  (context );
2232+ 
22232233	if  (mono_llvm_only ) {
22242234		if  (context -> has_resume_state )
22252235			/* The exception will be handled in a frame above us */ 
2226- 			mono_llvm_reraise_exception  (( MonoException * ) mono_gchandle_get_target_internal  ( context -> exc_gchandle ) );
2236+ 			mono_llvm_cpp_throw_exception  ( );
22272237	} else  {
22282238		g_assert  (!context -> has_resume_state );
22292239	}
@@ -2641,9 +2651,20 @@ do_jit_call (ThreadContext *context, stackval *ret_sp, stackval *sp, InterpFrame
26412651			 * This happens when interp_entry calls mono_llvm_reraise_exception (). 
26422652			 */ 
26432653			return ;
2644- 		MonoObject  * obj  =  mono_llvm_load_exception  ();
2654+ 		MonoJitTlsData  * jit_tls  =  mono_get_jit_tls  ();
2655+ 		if  (jit_tls -> resume_state .il_state ) {
2656+ 			/* 
2657+ 			 * This c++ exception is going to be caught by an AOTed frame above us. 
2658+ 			 * We can't rethrow here, since that will skip the cleanup of the 
2659+ 			 * interpreter stack space etc. So instruct the interpreter to unwind. 
2660+ 			 */ 
2661+ 			context -> has_resume_state  =  TRUE;
2662+ 			context -> handler_frame  =  NULL ;
2663+ 			return ;
2664+ 		}
2665+ 		MonoObject  * obj  =  mini_llvmonly_load_exception  ();
26452666		g_assert  (obj );
2646- 		mono_llvm_clear_exception  ();
2667+ 		mini_llvmonly_clear_exception  ();
26472668		mono_error_set_exception_instance  (error , (MonoException * )obj );
26482669		return ;
26492670	}
@@ -2958,6 +2979,8 @@ interp_entry_from_trampoline (gpointer ccontext_untyped, gpointer rmethod_untype
29582979	if  (rmethod -> needs_thread_attach )
29592980		mono_threads_detach_coop  (orig_domain , & attach_cookie );
29602981
2982+ 	check_pending_unwind  (context );
2983+ 
29612984	/* Write back the return value */ 
29622985	/* 'frame' is still valid */ 
29632986	mono_arch_set_native_call_context_ret  (ccontext , & frame , sig , retp );
@@ -2996,8 +3019,10 @@ interp_compile_interp_method (MonoMethod *method, MonoError *error)
29963019	InterpMethod  * imethod  =  mono_interp_get_imethod  (method , error );
29973020	return_val_if_nok  (error , NULL );
29983021
2999- 	mono_interp_transform_method  (imethod , get_context  (), error );
3000- 	return_val_if_nok  (error , NULL );
3022+ 	if  (!imethod -> transformed ) {
3023+ 		mono_interp_transform_method  (imethod , get_context  (), error );
3024+ 		return_val_if_nok  (error , NULL );
3025+ 	}
30013026
30023027	return  imethod -> jinfo ;
30033028}
@@ -7269,6 +7294,8 @@ interp_parse_options (const char *options)
72697294 * interp_set_resume_state: 
72707295 * 
72717296 *   Set the state the interpeter will continue to execute from after execution returns to the interpreter. 
7297+  * If INTERP_FRAME is NULL, that means the exception is caught in an AOTed frame and the interpreter needs to 
7298+  * unwind back to AOT code. 
72727299 */ 
72737300static  void 
72747301interp_set_resume_state  (MonoJitTlsData  * jit_tls , MonoObject  * ex , MonoJitExceptionInfo  * ei , MonoInterpFrameHandle  interp_frame , gpointer  handler_ip )
@@ -7286,8 +7313,10 @@ interp_set_resume_state (MonoJitTlsData *jit_tls, MonoObject *ex, MonoJitExcepti
72867313		mono_gchandle_free_internal  (context -> exc_gchandle );
72877314	context -> exc_gchandle  =  mono_gchandle_new_internal  ((MonoObject * )ex , FALSE );
72887315	/* Ditto */ 
7289- 	if  (ei )
7290- 		* (MonoObject * * )(frame_locals  (context - > handler_frame ) +  ei - > exvar_offset ) =  ex ;
7316+ 	if  (context -> handler_frame ) {
7317+ 		if  (ei )
7318+ 			* (MonoObject * * )(frame_locals  (context - > handler_frame ) +  ei - > exvar_offset ) =  ex ;
7319+ 	}
72917320	context -> handler_ip  =  (const  guint16 * )handler_ip ;
72927321}
72937322
@@ -7323,7 +7352,6 @@ interp_run_finally (StackFrameInfo *frame, int clause_index, gpointer handler_ip
73237352	memset  (& clause_args , 0 , sizeof  (FrameClauseArgs ));
73247353	clause_args .start_with_ip  =  (const  guint16 * )handler_ip ;
73257354	clause_args .end_at_ip  =  (const  guint16 * )handler_ip_end ;
7326- 	clause_args .exit_clause  =  clause_index ;
73277355	clause_args .exec_frame  =  iframe ;
73287356
73297357	state_ip  =  iframe - > state .ip ;
@@ -7339,6 +7367,9 @@ interp_run_finally (StackFrameInfo *frame, int clause_index, gpointer handler_ip
73397367
73407368	iframe - > next_free  =  next_free ;
73417369	iframe - > state .ip  =  state_ip ;
7370+ 
7371+ 	check_pending_unwind  (context );
7372+ 
73427373	if  (context - > has_resume_state ) {
73437374		return  TRUE;
73447375	} else  {
@@ -7390,32 +7421,41 @@ interp_run_filter (StackFrameInfo *frame, MonoException *ex, int clause_index, g
73907421
73917422	context - > stack_pointer  =  (guchar * )child_frame .stack ;
73927423
7424+ 	check_pending_unwind  (context );
7425+ 
73937426	/* ENDFILTER stores the result into child_frame->retval */ 
73947427	return  retval .data .i  ? TRUE : FALSE;
73957428}
73967429
7430+ /* Returns TRUE if there is a pending exception */ 
73977431static  gboolean 
7398- interp_run_finally_with_il_state  (gpointer  il_state_ptr , int  clause_index , gpointer  handler_ip , gpointer  handler_ip_end )
7432+ interp_run_clause_with_il_state  (gpointer  il_state_ptr , int  clause_index , gpointer  handler_ip , gpointer  handler_ip_end ,
7433+ 								 MonoObject  * ex , gboolean  * filtered , MonoExceptionEnum  clause_type )
73997434{
74007435	MonoMethodILState  * il_state  =  (MonoMethodILState * )il_state_ptr ;
74017436	MonoMethodSignature  * sig ;
74027437	ThreadContext  * context  =  get_context  ();
7438+ 	stackval  * orig_sp ;
74037439	stackval  * sp , * sp_args ;
74047440	InterpMethod  * imethod ;
74057441	FrameClauseArgs  clause_args ;
74067442	ERROR_DECL  (error );
74077443
7408- 	// FIXME: Optimize this ? Its only used during EH 
7409- 
74107444	sig  =  mono_method_signature_internal  (il_state -> method );
74117445	g_assert  (sig );
74127446
74137447	imethod  =  mono_interp_get_imethod  (il_state - > method , error );
74147448	mono_error_assert_ok  (error );
74157449
7416- 	sp_args  =  sp  =  (stackval * )context - > stack_pointer ;
7450+ 	orig_sp  =  sp_args  =  sp  =  (stackval * )context - > stack_pointer ;
7451+ 
7452+ 	gpointer  ret_addr  =  NULL;
74177453
74187454	int  findex  =  0 ;
7455+ 	if  (sig - > ret - > type  !=  MONO_TYPE_VOID ) {
7456+ 		ret_addr  =  il_state - > data  [findex ];
7457+ 		findex  + + ;
7458+ 	}
74197459	if  (sig - > hasthis ) {
74207460		if  (il_state - > data  [findex ])
74217461			sp_args -> data .p  =  * (gpointer * )il_state - > data  [findex ];
@@ -7451,32 +7491,41 @@ interp_run_finally_with_il_state (gpointer il_state_ptr, int clause_index, gpoin
74517491	if  (header - > num_locals )
74527492		memset  (frame_locals  (& frame ) +  imethod - > local_offsets  [0 ], 0 , imethod - > locals_size );
74537493	/* Copy locals from il_state */ 
7454- 	int  locals_start  =  sig -> hasthis   +   sig - > param_count ;
7494+ 	int  locals_start  =  findex ;
74557495	for  (int  i  =  0 ; i  <  header - > num_locals ; ++ i ) {
74567496		if  (il_state -> data  [locals_start  +  i ])
74577497			stackval_from_data  (header -> locals  [i ], (stackval * )(frame_locals  (& frame ) +  imethod - > local_offsets  [i ]), il_state - > data  [locals_start  +  i ], FALSE );
74587498	}
74597499
74607500	memset  (& clause_args , 0 , sizeof  (FrameClauseArgs ));
74617501	clause_args .start_with_ip  =  (const  guint16 * )handler_ip ;
7462- 	clause_args .end_at_ip  =  (const  guint16 * )handler_ip_end ;
7463- 	clause_args .exit_clause  =  clause_index ;
7502+ 	if  (clause_type  ==  MONO_EXCEPTION_CLAUSE_NONE  ||  clause_type  ==  MONO_EXCEPTION_CLAUSE_FILTER )
7503+ 		clause_args .end_at_ip  =  (const  guint16 * )clause_args .start_with_ip  +  0xffffff ;
7504+ 	else 
7505+ 		clause_args .end_at_ip  =  (const  guint16 * )handler_ip_end ;
74647506	clause_args .exec_frame  =  & frame ;
74657507
7466- 	// this informs MINT_ENDFINALLY to return to EH 
7467- 	* (guint16 * * )(frame_locals  (& frame ) +  imethod - > clause_data_offsets  [clause_index ]) =  NULL;
7508+ 	if  (clause_type  ==  MONO_EXCEPTION_CLAUSE_NONE  ||  clause_type  ==  MONO_EXCEPTION_CLAUSE_FILTER )
7509+ 		* (MonoObject * * )(frame_locals  (& frame ) +  imethod - > jinfo - > clauses  [clause_index ].exvar_offset ) =  ex ;
7510+ 	else 
7511+ 		// this informs MINT_ENDFINALLY to return to EH 
7512+ 		* (guint16 * * )(frame_locals  (& frame ) +  imethod - > clause_data_offsets  [clause_index ]) =  NULL;
7513+ 
7514+ 	/* Set in mono_handle_exception () */ 
7515+ 	context -> has_resume_state  =  FALSE;
74687516
74697517	interp_exec_method  (& frame , context , & clause_args );
74707518
74717519	/* Write back args */ 
74727520	sp_args  =  sp ;
74737521	findex  =  0 ;
7522+ 	if  (sig -> ret -> type  !=  MONO_TYPE_VOID )
7523+ 		findex  ++ ;
74747524	if  (sig -> hasthis ) {
74757525		// FIXME: This 
74767526		sp_args ++ ;
74777527		findex  ++ ;
74787528	}
7479- 	findex  =  sig -> hasthis  ? 1  : 0 ;
74807529	for  (int  i  =  0 ; i  <  sig - > param_count ; ++ i ) {
74817530		if  (il_state -> data  [findex ]) {
74827531			int  size  =  stackval_to_data  (sig -> params  [i ], sp_args , il_state - > data  [findex ], FALSE );
@@ -7494,11 +7543,19 @@ interp_run_finally_with_il_state (gpointer il_state_ptr, int clause_index, gpoin
74947543	}
74957544	mono_metadata_free_mh  (header );
74967545
7497- 	// FIXME: Restore stack ? 
7498- 	if  (context -> has_resume_state )
7499- 		return  TRUE;
7500- 	else 
7501- 		return  FALSE;
7546+ 	if  (clause_type  ==  MONO_EXCEPTION_CLAUSE_NONE  &&  ret_addr ) {
7547+ 		stackval_to_data  (sig -> ret , frame .retval , ret_addr , FALSE);
7548+ 	} else  if  (clause_type  ==  MONO_EXCEPTION_CLAUSE_FILTER ) {
7549+ 		g_assert  (filtered );
7550+ 		* filtered  =  frame .retval - > data .i ;
7551+ 	}
7552+ 
7553+ 	memset  (orig_sp , 0 , (guint8 * )context - > stack_pointer  -  (guint8 * )orig_sp );
7554+ 	context - > stack_pointer  =  (guchar * )orig_sp ;
7555+ 
7556+ 	check_pending_unwind  (context );
7557+ 
7558+ 	return  context - > has_resume_state ;
75027559}
75037560
75047561typedef  struct  {
0 commit comments