@@ -27,6 +27,7 @@ import {
2727 traceEip , nullCheckValidation ,
2828 abortAtJittedLoopBodies , traceNullCheckOptimizations ,
2929 nullCheckCaching , traceBackBranches ,
30+ maxCallHandlerReturnAddresses ,
3031
3132 mostRecentOptions ,
3233
@@ -345,12 +346,13 @@ export function generateWasmBody (
345346 case MintOpcode . MINT_CALL_HANDLER_S :
346347 if ( ! emit_branch ( builder , ip , frame , opcode ) )
347348 ip = abort ;
348- else
349+ else {
349350 // Technically incorrect, but the instructions following this one may not be executed
350351 // since we might have skipped over them.
351352 // FIXME: Identify when we should actually set the conditionally executed flag, perhaps
352353 // by doing a simple static flow analysis based on the displacements. Update heuristic too!
353354 isConditionallyExecuted = true ;
355+ }
354356 break ;
355357
356358 case MintOpcode . MINT_CKNULL : {
@@ -923,13 +925,41 @@ export function generateWasmBody (
923925 isLowValueOpcode = true ;
924926 break ;
925927
926- case MintOpcode . MINT_ENDFINALLY :
927- // This one might make sense to partially implement, but the jump target
928- // is computed at runtime which would make it hard to figure out where
929- // we need to put branch targets. Not worth just doing a conditional
930- // bailout since finally blocks always run
931- ip = abort ;
928+ case MintOpcode . MINT_ENDFINALLY : {
929+ if (
930+ ( builder . callHandlerReturnAddresses . length > 0 ) &&
931+ ( builder . callHandlerReturnAddresses . length <= maxCallHandlerReturnAddresses )
932+ ) {
933+ // console.log(`endfinally @0x${(<any>ip).toString(16)}. return addresses:`, builder.callHandlerReturnAddresses.map(ra => (<any>ra).toString(16)));
934+ // FIXME: Clean this codegen up
935+ // Load ret_ip
936+ const clauseIndex = getArgU16 ( ip , 1 ) ,
937+ clauseDataOffset = get_imethod_clause_data_offset ( frame , clauseIndex ) ;
938+ builder . local ( "pLocals" ) ;
939+ builder . appendU8 ( WasmOpcode . i32_load ) ;
940+ builder . appendMemarg ( clauseDataOffset , 0 ) ;
941+ // Stash it in a variable because we're going to need to use it multiple times
942+ builder . local ( "math_lhs32" , WasmOpcode . set_local ) ;
943+ // Do a bunch of trivial comparisons to see if ret_ip is one of our expected return addresses,
944+ // and if it is, generate a branch back to the dispatcher at the top
945+ for ( let r = 0 ; r < builder . callHandlerReturnAddresses . length ; r ++ ) {
946+ const ra = builder . callHandlerReturnAddresses [ r ] ;
947+ builder . local ( "math_lhs32" ) ;
948+ builder . ptr_const ( ra ) ;
949+ builder . appendU8 ( WasmOpcode . i32_eq ) ;
950+ builder . block ( WasmValtype . void , WasmOpcode . if_ ) ;
951+ builder . cfg . branch ( ra , ra < ip , true ) ;
952+ builder . endBlock ( ) ;
953+ }
954+ // If none of the comparisons succeeded we won't have branched anywhere, so bail out
955+ // This shouldn't happen during non-exception-handling execution unless the trace doesn't
956+ // contain the CALL_HANDLER that led here
957+ append_bailout ( builder , ip , BailoutReason . UnexpectedRetIp ) ;
958+ } else {
959+ ip = abort ;
960+ }
932961 break ;
962+ }
933963
934964 case MintOpcode . MINT_RETHROW :
935965 case MintOpcode . MINT_PROF_EXIT :
@@ -2444,7 +2474,8 @@ function append_call_handler_store_ret_ip (
24442474 builder . appendU8 ( WasmOpcode . i32_store ) ;
24452475 builder . appendMemarg ( clauseDataOffset , 0 ) ; // FIXME: 32-bit alignment?
24462476
2447- // console.log(`call_handler clauseDataOffset=0x${clauseDataOffset.toString(16)} retIp=0x${retIp.toString(16)}`);
2477+ // console.log(`call_handler @0x${(<any>ip).toString(16)} retIp=0x${retIp.toString(16)}`);
2478+ builder . callHandlerReturnAddresses . push ( retIp ) ;
24482479}
24492480
24502481function emit_branch (
@@ -2496,10 +2527,14 @@ function emit_branch (
24962527 counters . backBranchesEmitted ++ ;
24972528 return true ;
24982529 } else {
2499- if ( ( traceBackBranches > 0 ) || ( builder . cfg . trace > 0 ) )
2500- console . log ( `back branch target 0x${ destination . toString ( 16 ) } not found in list ` +
2530+ if ( destination < builder . cfg . entryIp ) {
2531+ if ( ( traceBackBranches > 1 ) || ( builder . cfg . trace > 1 ) )
2532+ console . log ( `${ info [ 0 ] } target 0x${ destination . toString ( 16 ) } before start of trace` ) ;
2533+ } else if ( ( traceBackBranches > 0 ) || ( builder . cfg . trace > 0 ) )
2534+ console . log ( `0x${ ( < any > ip ) . toString ( 16 ) } ${ info [ 0 ] } target 0x${ destination . toString ( 16 ) } not found in list ` +
25012535 builder . backBranchOffsets . map ( bbo => "0x" + ( < any > bbo ) . toString ( 16 ) ) . join ( ", " )
25022536 ) ;
2537+
25032538 cwraps . mono_jiterp_boost_back_branch_target ( destination ) ;
25042539 // FIXME: Should there be a safepoint here?
25052540 append_bailout ( builder , destination , BailoutReason . BackwardBranch ) ;
@@ -2586,8 +2621,11 @@ function emit_branch (
25862621 builder . cfg . branch ( destination , true , true ) ;
25872622 counters . backBranchesEmitted ++ ;
25882623 } else {
2589- if ( ( traceBackBranches > 0 ) || ( builder . cfg . trace > 0 ) )
2590- console . log ( `back branch target 0x${ destination . toString ( 16 ) } not found in list ` +
2624+ if ( destination < builder . cfg . entryIp ) {
2625+ if ( ( traceBackBranches > 1 ) || ( builder . cfg . trace > 1 ) )
2626+ console . log ( `${ info [ 0 ] } target 0x${ destination . toString ( 16 ) } before start of trace` ) ;
2627+ } else if ( ( traceBackBranches > 0 ) || ( builder . cfg . trace > 0 ) )
2628+ console . log ( `0x${ ( < any > ip ) . toString ( 16 ) } ${ info [ 0 ] } target 0x${ destination . toString ( 16 ) } not found in list ` +
25912629 builder . backBranchOffsets . map ( bbo => "0x" + ( < any > bbo ) . toString ( 16 ) ) . join ( ", " )
25922630 ) ;
25932631 // We didn't find a loop to branch to, so bail out
0 commit comments