Discussion:
vex: r3337 - in /trunk: priv/ pub/
(too old to reply)
s***@valgrind.org
2017-03-29 16:13:36 UTC
Permalink
Raw Message
Author: sewardj
Date: Wed Mar 29 17:13:35 2017
New Revision: 3337

Log:
Add a mechanism for hinting to the core disassembler loop, that the
just-disassembled instruction is very verbose. This allows dynamic changes to
the maximum number of guest instructions allowed in the current IRSB.
Fixes #375839.


Modified:
trunk/priv/guest_amd64_toIR.c
trunk/priv/guest_arm64_toIR.c
trunk/priv/guest_arm_toIR.c
trunk/priv/guest_generic_bb_to_IR.c
trunk/priv/guest_generic_bb_to_IR.h
trunk/priv/guest_mips_toIR.c
trunk/priv/guest_ppc_toIR.c
trunk/priv/guest_s390_toIR.c
trunk/priv/guest_tilegx_toIR.c
trunk/priv/guest_x86_toIR.c
trunk/pub/libvex.h

Modified: trunk/priv/guest_amd64_toIR.c
==============================================================================
--- trunk/priv/guest_amd64_toIR.c (original)
+++ trunk/priv/guest_amd64_toIR.c Wed Mar 29 17:13:35 2017
@@ -29616,6 +29616,7 @@
if (have66noF2noF3(pfx)) {
delta = dis_FMA( vbi, pfx, delta, opc );
*uses_vvvv = True;
+ dres->hint = Dis_HintVerbose;
goto decode_success;
}
break;
@@ -31744,13 +31745,18 @@
/* else fall though; dis_PCMPxSTRx failed to decode it */
}
break;
+
case 0x5C ... 0x5F:
case 0x68 ... 0x6F:
case 0x78 ... 0x7F:
+ /* FIXME: list the instructions decoded here */
if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
Long delta0 = delta;
delta = dis_FMA4( pfx, delta, opc, uses_vvvv, vbi );
- if (delta > delta0) goto decode_success;
+ if (delta > delta0) {
+ dres->hint = Dis_HintVerbose;
+ goto decode_success;
+ }
/* else fall though; dis_FMA4 failed to decode it */
}
break;
@@ -31863,6 +31869,7 @@
dres.len = 0;
dres.continueAt = 0;
dres.jk_StopHere = Ijk_INVALID;
+ dres.hint = Dis_HintNone;
*expect_CAS = False;

vassert(guest_RIP_next_assumed == 0);

Modified: trunk/priv/guest_arm64_toIR.c
==============================================================================
--- trunk/priv/guest_arm64_toIR.c (original)
+++ trunk/priv/guest_arm64_toIR.c Wed Mar 29 17:13:35 2017
@@ -14305,6 +14305,7 @@
dres->len = 4;
dres->continueAt = 0;
dres->jk_StopHere = Ijk_INVALID;
+ dres->hint = Dis_HintNone;

/* At least this is simple on ARM64: insns are all 4 bytes long, and
4-aligned. So just fish the whole thing out of memory right now

Modified: trunk/priv/guest_arm_toIR.c
==============================================================================
--- trunk/priv/guest_arm_toIR.c (original)
+++ trunk/priv/guest_arm_toIR.c Wed Mar 29 17:13:35 2017
@@ -16099,6 +16099,7 @@
dres.len = 4;
dres.continueAt = 0;
dres.jk_StopHere = Ijk_INVALID;
+ dres.hint = Dis_HintNone;

/* Set default actions for post-insn handling of writes to r15, if
required. */
@@ -18986,6 +18987,7 @@
dres.len = 2;
dres.continueAt = 0;
dres.jk_StopHere = Ijk_INVALID;
+ dres.hint = Dis_HintNone;

/* Set default actions for post-insn handling of writes to r15, if
required. */

Modified: trunk/priv/guest_generic_bb_to_IR.c
==============================================================================
--- trunk/priv/guest_generic_bb_to_IR.c (original)
+++ trunk/priv/guest_generic_bb_to_IR.c Wed Mar 29 17:13:35 2017
@@ -237,6 +237,13 @@
vassert((offB_GUEST_IP % 8) == 0);
}

+ /* Although we will try to disassemble up to vex_control.guest_max_insns
+ insns into the block, the individual insn assemblers may hint to us that a
+ disassembled instruction is verbose. In that case we will lower the limit
+ so as to ensure that the JIT doesn't run out of space. See bug 375839 for
+ the motivating example. */
+ Int guest_max_insns_really = vex_control.guest_max_insns;
+
/* Start a new, empty extent. */
vge->n_used = 1;
vge->base[0] = guest_IP_bbstart;
@@ -284,7 +291,7 @@

/* Process instructions. */
while (True) {
- vassert(n_instrs < vex_control.guest_max_insns);
+ vassert(n_instrs < guest_max_insns_really);

/* Regardless of what chase_into_ok says, is chasing permissible
at all right now? Set resteerOKfn accordingly. */
@@ -383,6 +390,23 @@
if (n_cond_resteers_allowed == 0)
vassert(dres.whatNext != Dis_ResteerC);

+ /* If the disassembly function passed us a hint, take note of it. */
+ if (LIKELY(dres.hint == Dis_HintNone)) {
+ /* Do nothing */
+ } else {
+ vassert(dres.hint == Dis_HintVerbose);
+ /* The current insn is known to be verbose. Lower the max insns limit
+ if necessary so as to avoid running the JIT out of space in the
+ event that we've encountered the start of a long sequence of them.
+ This is expected to be a very rare event. In any case the remaining
+ limit (30 insns) is still so high that most blocks will terminate
+ anyway before then. So this is very unlikely to give a perf hit in
+ practice. See bug 375839 for the motivating example. */
+ if (guest_max_insns_really > 30) {
+ guest_max_insns_really = 30;
+ }
+ }
+
/* Fill in the insn-mark length field. */
vassert(first_stmt_idx >= 0 && first_stmt_idx < irsb->stmts_used);
imark = irsb->stmts[first_stmt_idx];
@@ -435,7 +459,7 @@
case Dis_Continue:
vassert(dres.continueAt == 0);
vassert(dres.jk_StopHere == Ijk_INVALID);
- if (n_instrs < vex_control.guest_max_insns) {
+ if (n_instrs < guest_max_insns_really) {
/* keep going */
} else {
/* We have to stop. See comment above re irsb field

Modified: trunk/priv/guest_generic_bb_to_IR.h
==============================================================================
--- trunk/priv/guest_generic_bb_to_IR.h (original)
+++ trunk/priv/guest_generic_bb_to_IR.h Wed Mar 29 17:13:35 2017
@@ -76,10 +76,16 @@
Dis_ResteerC: (speculatively, of course) followed a
conditional branch; continue at 'continueAt'
*/
- enum { Dis_StopHere, Dis_Continue,
+ enum { Dis_StopHere=0x10, Dis_Continue,
Dis_ResteerU, Dis_ResteerC } whatNext;

- /* For Dis_StopHere, we need to end the block and create a
+ /* Any other hints that we should feed back to the disassembler?
+ Dis_HintNone: no hint
+ Dis_HintVerbose: this insn potentially generates a lot of code
+ */
+ enum { Dis_HintNone=0x20, Dis_HintVerbose } hint;
+
+ /* For whatNext==Dis_StopHere, we need to end the block and create a
transfer to whatever the NIA is. That will have presumably
been set by the IR generated for this insn. So we need to
know the jump kind to use. Should Ijk_INVALID in other Dis_
@@ -89,7 +95,6 @@
/* For Dis_Resteer, this is the guest address we should continue
at. Otherwise ignored (should be zero). */
Addr continueAt;
-
}

DisResult;

Modified: trunk/priv/guest_mips_toIR.c
==============================================================================
--- trunk/priv/guest_mips_toIR.c (original)
+++ trunk/priv/guest_mips_toIR.c Wed Mar 29 17:13:35 2017
@@ -12132,6 +12132,7 @@
dres.len = 0;
dres.continueAt = 0;
dres.jk_StopHere = Ijk_INVALID;
+ dres.hint = Dis_HintNone;

delay_slot_branch = likely_delay_slot = delay_slot_jump = False;


Modified: trunk/priv/guest_ppc_toIR.c
==============================================================================
--- trunk/priv/guest_ppc_toIR.c (original)
+++ trunk/priv/guest_ppc_toIR.c Wed Mar 29 17:13:35 2017
@@ -27406,6 +27406,7 @@
dres.len = 0;
dres.continueAt = 0;
dres.jk_StopHere = Ijk_INVALID;
+ dres.hint = Dis_HintNone;

/* At least this is simple on PPC32: insns are all 4 bytes long, and
4-aligned. So just fish the whole thing out of memory right now
@@ -29112,6 +29113,7 @@
dres.whatNext = Dis_StopHere;
dres.jk_StopHere = Ijk_NoDecode;
dres.continueAt = 0;
+ dres.hint = Dis_HintNone;
return dres;
}


Modified: trunk/priv/guest_s390_toIR.c
==============================================================================
--- trunk/priv/guest_s390_toIR.c (original)
+++ trunk/priv/guest_s390_toIR.c Wed Mar 29 17:13:35 2017
@@ -16832,6 +16832,7 @@
dres.len = insn_length;
dres.continueAt = 0;
dres.jk_StopHere = Ijk_INVALID;
+ dres.hint = Dis_HintNone;

/* fixs390: consider chasing of conditional jumps */


Modified: trunk/priv/guest_tilegx_toIR.c
==============================================================================
--- trunk/priv/guest_tilegx_toIR.c (original)
+++ trunk/priv/guest_tilegx_toIR.c Wed Mar 29 17:13:35 2017
@@ -323,6 +323,7 @@
dres.len = 0;
dres.continueAt = 0;
dres.jk_StopHere = Ijk_INVALID;
+ dres.hint = Dis_HintNone;

/* Verify the code addr is 8-byte aligned. */
vassert((((Addr)code) & 7) == 0);

Modified: trunk/priv/guest_x86_toIR.c
==============================================================================
--- trunk/priv/guest_x86_toIR.c (original)
+++ trunk/priv/guest_x86_toIR.c Wed Mar 29 17:13:35 2017
@@ -8114,6 +8114,7 @@
dres.whatNext = Dis_Continue;
dres.len = 0;
dres.continueAt = 0;
+ dres.hint = Dis_HintNone;
dres.jk_StopHere = Ijk_INVALID;

*expect_CAS = False;

Modified: trunk/pub/libvex.h
==============================================================================
--- trunk/pub/libvex.h (original)
+++ trunk/pub/libvex.h Wed Mar 29 17:13:35 2017
@@ -475,7 +475,7 @@
Default=120. A setting of zero disables unrolling. */
Int iropt_unroll_thresh;
/* What's the maximum basic block length the front end(s) allow?
- BBs longer than this are split up. Default=50 (guest
+ BBs longer than this are split up. Default=60 (guest
insns). */
Int guest_max_insns;
/* How aggressive should front ends be in following

Loading...