@@ -22,8 +22,12 @@ my $TYPE_MHL := 'Ljava/lang/invoke/MethodHandles$Lookup;';
22
22
my $ TYPE_CLASS := ' Ljava/lang/Class;' ;
23
23
my $ TYPE_LONG := ' Ljava/lang/Long;' ;
24
24
my $ TYPE_DOUBLE := ' Ljava/lang/Double;' ;
25
+ my $ TYPE_EH := ' Lorg/perl6/nqp/runtime/ExceptionHandling;' ;
25
26
my $ TYPE_EX_LEX := ' Lorg/perl6/nqp/runtime/LexoticException;' ;
26
27
my $ TYPE_EX_UNWIND := ' Lorg/perl6/nqp/runtime/UnwindException;' ;
28
+ my $ TYPE_EX_CONT := ' Lorg/perl6/nqp/runtime/ControlException;' ;
29
+ my $ TYPE_EX_RT := ' Ljava/lang/RuntimeException;' ;
30
+ my $ TYPE_THROWABLE := ' Ljava/lang/Throwable;' ;
27
31
28
32
# Exception handler categories.
29
33
my $ EX_CAT_CATCH := 1 ;
@@ -2755,7 +2759,7 @@ class QAST::CompilerJAST {
2755
2759
# Stash lexical names.
2756
2760
$ * CODEREFS . set_lexical_names($ node . cuid, | $ block . lexical_names_by_type());
2757
2761
2758
- # Emit prelude. This crates and stashes the CallFrame.
2762
+ # Emit prelude. This creates and stashes the CallFrame.
2759
2763
$ * JMETH . add_local(' cf' , $ TYPE_CF );
2760
2764
$ * JMETH . append (JAST::Instruction. new ( : op(' new' ), $ TYPE_CF ));
2761
2765
$ * JMETH . append (JAST::Instruction. new ( : op(' dup' ) ));
@@ -2895,17 +2899,30 @@ class QAST::CompilerJAST {
2895
2899
$ il . append (JAST::Instruction. new ( : op(' invokestatic' ), $ TYPE_OPS ,
2896
2900
' return_' ~ typechar($ body . type), ' Void' , jtype($ body . type), $ TYPE_CF ));
2897
2901
2898
- # Keep the thread state in sync. Note, JVM doesn't do finally
2899
- # natively, so we just emit this in a catch as well as at the
2900
- # end before exit.
2901
- my $ unwind := JAST::InstructionList. new ();
2902
- for ($ il , $ unwind ) {
2903
- $ _ . append (JAST::Instruction. new ( : op(' aload' ), ' cf' ));
2904
- $ _ . append (JAST::Instruction. new ( : op(' invokevirtual' ),
2905
- $ TYPE_CF , ' leave' , ' Void' ));
2906
- }
2907
- $ unwind . append (JAST::Instruction. new ( : op(' athrow' ) ));
2908
- $ * JMETH . append (JAST::TryCatch. new ( : try($ il ), : catch($ unwind ), : type(' ' ) ));
2902
+ # Emit the postlude. We catch any exceptions. Control ones are
2903
+ # rethrown, after calling CallFrame.leave. Others are passed on to
2904
+ # dieInternal. Finally, if there's no exception, we also need to
2905
+ # call CallFrame.leave.
2906
+ $ il . append (JAST::Instruction. new ( : op(' aload' ), ' cf' ));
2907
+ $ il . append (JAST::Instruction. new ( : op(' invokevirtual' ),
2908
+ $ TYPE_CF , ' leave' , ' Void' ));
2909
+ my $ posthan := JAST::InstructionList. new ();
2910
+ my $ nclab := JAST::Label. new ( : name(' non_cont_ex' ) );
2911
+ $ posthan . append (JAST::Instruction. new ( : op(' dup' ) ));
2912
+ $ posthan . append (JAST::Instruction. new ( : op(' instanceof' ), $ TYPE_EX_CONT ));
2913
+ $ posthan . append (JAST::Instruction. new ( : op(' ifeq' ), $ nclab ));
2914
+ $ posthan . append (JAST::Instruction. new ( : op(' aload' ), ' cf' ));
2915
+ $ posthan . append (JAST::Instruction. new ( : op(' invokevirtual' ),
2916
+ $ TYPE_CF , ' leave' , ' Void' ));
2917
+ $ posthan . append (JAST::Instruction. new ( : op(' athrow' ) ));
2918
+ $ posthan . append ($ nclab );
2919
+ $ posthan . append (JAST::Instruction. new ( : op(' aload_1' ) ));
2920
+ $ posthan . append (JAST::Instruction. new ( : op(' swap' ) ));
2921
+ $ posthan . append (JAST::Instruction. new ( : op(' invokestatic' ),
2922
+ $ TYPE_EH , ' dieInternal' , $ TYPE_EX_RT , $ TYPE_TC , $ TYPE_THROWABLE ));
2923
+ $ posthan . append (JAST::Instruction. new ( : op(' athrow' ) ));
2924
+ $ * JMETH . append (JAST::TryCatch. new ( : try($ il ), : catch($ posthan ),
2925
+ : type($ TYPE_THROWABLE ) ));
2909
2926
$ * JMETH . append (JAST::Instruction. new ( : op(' return' ) ));
2910
2927
2911
2928
# Finalize method and add it to the class.
0 commit comments