Skip to content

Commit dd14e48

Browse files
committed
simx86: stop using e_querymark to stop codegen (except prejit)
Only stop if 1. there's a jump op generated, or 2. we're in single step mode (SINGLEBLOCK or TF), or 3. we encounter a compatible block we can jump into other code is going to be invalidated in DoClose(), we're just going to bulldoze over it here. SPEC_PREJIT should avoid overwriting, but instead of using a gap, I let it give up, by not calling Close() and resetting CurrIMeta, thereby throwing away the prejitted code, instead of generating an early tailcode.
1 parent 7af5712 commit dd14e48

File tree

1 file changed

+54
-47
lines changed

1 file changed

+54
-47
lines changed

src/base/emu-i386/simx86/interp.c

Lines changed: 54 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
564548
static 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

583590
static 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

Comments
 (0)