@@ -98,44 +98,42 @@ static TNode *DoClose(unsigned int PC, unsigned int Interp_LONG_CS, int mode,
9898 int flags )
9999{
100100 unsigned int P0 = InstrMeta [0 ].npc ;
101- TNode * G , * nextG = NULL ;
101+ TNode * G , * nextG ;
102+ int linknext ;
102103
103- assert (CurrIMeta >= 0 );
104- /* If the code doesn't terminate with a jump/loop instruction
105- * it still lacks the tail code; add it here */
106- IMeta * GL = & InstrMeta [CurrIMeta ];
107- if (GL -> gen [GL -> ngen - 1 ].op < JMP_TAILCODE ) {
108- /* almost always we get here because e_querymark() in
109- interp_post() found code. If there is no overlap
110- and the node is compatible we can generate a jump
111- to it and link as well */
112- nextG = FindTree (PC );
113- if (nextG && nextG -> mode == mode &&
114- nextG -> cs == Interp_LONG_CS )
115- JMPGen (JMP_LINK , mode , PC );
116- else
117- JMPGen (JMP_TAILCODE , mode , PC );
118- }
119-
120- assert (PC > P0 );
104+ assert (CurrIMeta >= 0 && PC > P0 );
121105 if (e_querymark (P0 , PC - P0 )) {
106+ /* with SPEC_PREJIT give up if we'd overwrite
107+ existing code */
108+ if (flags & F_SPRJ ) {
109+ CurrIMeta = -1 ;
110+ return NULL ;
111+ }
122112 InvalidateNodeRange (P0 , PC - P0 , NULL );
123113 if (!e_querymprotrange_full (P0 , PC - P0 )) {
124114 unsigned int abeg , aend ;
125115
126116 /* in case of prejit, the page content could
127117 * be altered, so we better re-jit */
128- if (flags & (F_PREJ | F_SPRJ ))
118+ if (flags & F_PREJ ) {
119+ CurrIMeta = -1 ;
129120 return NULL ;
121+ }
130122 abeg = P0 & _PAGE_MASK ;
131123 aend = PC & _PAGE_MASK ;
132124 /* re-populate cache */
133125 for (; abeg <= aend ; abeg += PAGE_SIZE )
134126 Fetch (abeg );
135127 }
136128 }
129+
130+ IMeta * GL = & InstrMeta [CurrIMeta ];
131+ linknext = GL -> gen [GL -> ngen - 1 ].op == JMP_LINK && !(flags & F_SPRJ );
137132 G = Close (PC , Interp_LONG_CS , mode , flags );
138- if (nextG )
133+ if (linknext &&
134+ (nextG = FindTree (PC )) &&
135+ nextG -> mode == mode &&
136+ nextG -> cs == Interp_LONG_CS )
139137 NodeLinker (G , nextG );
140138 return G ;
141139}
@@ -464,23 +462,13 @@ static unsigned int FindExecCode(unsigned int PC)
464462 else if (debug_level ('e' )> 2 )
465463 e_printf ("** Found compiled code at %08x\n" ,PC );
466464 }
467- else if (e_querymark (PC , 1 )) {
468- /* slow path */
469- InvalidateNodeRange (PC , 1 , NULL );
470- }
471465 /* future proofing: _Interp86() can't fail now in non-prejit mode
472466 but if it ever does, retry */
473467 while (!G ) {
474468 if (CEmuStat & (CeS_PREJIT_RM | CeS_PREJIT_PM )) {
475469 TheCPU .err = EXCP_GOBACK ;
476470 return PC ;
477471 }
478- #if 0
479- /* this obviously can't happen with current code, but
480- * slows down execution under debug a lot */
481- if (debug_level ('e' ) && e_querymark (PC , 1 ))
482- error ("simx86: code nodes clashed at %x\n" , PC );
483- #endif
484472 if (debug_level ('e' )>=9 )
485473 dbug_printf ("\n%s" ,e_print_regs (LONG_CS ));
486474 PC = _Interp86 (PC , LONG_CS , TheCPU .cs , TheCPU .mode , 0 );
@@ -557,27 +545,46 @@ void Interp86(void)
557545 TheCPU .eip = PC - LONG_CS ;
558546}
559547
560- /* safety gap should be definitely longer than 1 instruction to not
561- * overwrite something unintentionally */
562- #define SAFE_PRJ_GAP 16
563-
564548static int interp_post (unsigned int PC , unsigned int Interp_LONG_CS ,
565549 const int mode , int flags )
566550{
567- int ret = 0 ;
568- int gap = ( flags & F_SPRJ ) ? SAFE_PRJ_GAP : 1 ;
569- assert ( CurrIMeta >= 0 ) ;
551+ TNode * nextG ;
552+ assert ( CurrIMeta >= 0 ) ;
553+ InstrMeta [ 0 ]. flags |= flags ;
570554
555+ IMeta * GL = & InstrMeta [CurrIMeta ];
556+ if (GL -> gen [GL -> ngen - 1 ].op >= JMP_TAILCODE )
557+ return 1 ;
558+
559+ #ifndef SINGLEBLOCK
560+ if (mode & MSSTP ) {
561+ assert (mode & MTRAP );
562+ #endif
563+ /* The code doesn't terminate with a jump/loop instruction
564+ * it still lacks the tail code; add it here */
565+ JMPGen (JMP_TAILCODE , mode , PC );
566+ return 1 ;
571567#ifndef SINGLEBLOCK
572- IMeta * GL = & InstrMeta [CurrIMeta ];
573- if ((mode & MSSTP ) ||
574- GL -> gen [GL -> ngen - 1 ].op >= JMP_TAILCODE ||
575- e_querymark (PC , gap ))
568+ }
569+
570+ /* if we encounter a compatible block, we can jump and link to
571+ it without needing to overwrite it */
572+ if ((nextG = FindTree (PC )) &&
573+ nextG -> mode == mode &&
574+ nextG -> cs == Interp_LONG_CS ) {
575+ JMPGen (JMP_LINK , mode , PC );
576+ return 1 ;
577+ }
576578#endif
577- ret = 1 ;
578- InstrMeta [0 ].flags |= flags ;
579579
580- return ret ;
580+ #ifdef SPEC_PREJIT
581+ /* let SPEC_PREJIT give up via DoClose if it overwrites */
582+ if ((flags & F_SPRJ ) && e_querymark (PC - 1 , 1 ))
583+ return 1 ;
584+ #endif
585+
586+ /* else we continue interpreting code */
587+ return 0 ;
581588}
582589
583590static void sprj_deep (TNode * G , unsigned PC , unsigned int Interp_LONG_CS ,
@@ -589,9 +596,9 @@ static void sprj_deep(TNode *G, unsigned PC, unsigned int Interp_LONG_CS,
589596 while (G -> clink_t .link && !(G -> flags & F_LJMP )) {
590597 TNode * oldG = G ;
591598 PC = G -> clink_t .target ;
592- if (e_querymark (PC , SAFE_PRJ_GAP )) break ;
593599 PC = _Interp86 (PC , Interp_LONG_CS , ocs , basemode , flags );
594600 G = DoClose (PC , Interp_LONG_CS , basemode , flags );
601+ if (!G ) break ;
595602 i ++ ;
596603 NodesPrejitted ++ ;
597604 NodeLinker (oldG , G );
@@ -2791,7 +2798,7 @@ static void prejit_run(TNode *G)
27912798 ds = e_emu_disasm (EMU_BASE32 (PC ),basemode & MBIGCS ,ocs );
27922799 e_printf ("prejit at %s\n" , ds );
27932800 }
2794- if (e_querymark (PC , SAFE_PRJ_GAP ))
2801+ if (e_querymark (PC , 1 ))
27952802 return ;
27962803#if PROFILE
27972804 SpecPrejits ++ ;
0 commit comments