]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add a mechanism for hinting to the core disassembler loop, that the
authorJulian Seward <jseward@acm.org>
Wed, 29 Mar 2017 16:13:35 +0000 (16:13 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 29 Mar 2017 16:13:35 +0000 (16:13 +0000)
just-disassembled instruction is very verbose.  This allows dynamic changes to
the maximum number of guest instructions allowed in the current IRSB.
Fixes #375839.

git-svn-id: svn://svn.valgrind.org/vex/trunk@3337

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

index da06a87218c1aa904c70fd134225f61897d10ae2..46dd4601802d8cc8abc53711dfbffc769807ce9b 100644 (file)
@@ -29616,6 +29616,7 @@ Long dis_ESC_0F38__VEX (
       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 @@ Long dis_ESC_0F3A__VEX (
          /* 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 @@ DisResult disInstr_AMD64_WRK (
    dres.len         = 0;
    dres.continueAt  = 0;
    dres.jk_StopHere = Ijk_INVALID;
+   dres.hint        = Dis_HintNone;
    *expect_CAS = False;
 
    vassert(guest_RIP_next_assumed == 0);
index 8e91291ddba3dcd20471688b7d31db9e79716cb0..088af554d46d4fb4d0c3a4cea76f060ed729bf39 100644 (file)
@@ -14305,6 +14305,7 @@ Bool disInstr_ARM64_WRK (
    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
index 2cb3ac3a7e908d69b40d201f04514592f0e6fb9a..b9e1be27fbec8f89fea3265f7e24bf2500780685 100644 (file)
@@ -16099,6 +16099,7 @@ DisResult disInstr_ARM_WRK (
    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 @@ DisResult disInstr_THUMB_WRK (
    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. */
index 779f8ae451262c4a4ede0e4b62c95a3fb9364557..fb3ffb513625ea070ebcca875080f7a90cbfc10c 100644 (file)
@@ -237,6 +237,13 @@ IRSB* bb_to_IR (
       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 @@ IRSB* bb_to_IR (
 
    /* 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 @@ IRSB* bb_to_IR (
       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 @@ IRSB* bb_to_IR (
          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
index 78a5a870dd05368c927ab1b30be3d645aeb5e250..2c90db3d2bca2ba4b4be191be8ac6aeecf251f6f 100644 (file)
@@ -76,10 +76,16 @@ typedef
          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 @@ typedef
       /* For Dis_Resteer, this is the guest address we should continue
          at.  Otherwise ignored (should be zero). */
       Addr   continueAt;
-
    }
 
    DisResult;
index 77cd1f29e4d24acaed47fdc3d4074df58d62a7d8..38f375e6fc5f452b49fd73e99c19862775247e50 100644 (file)
@@ -12132,6 +12132,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
    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;
 
index 6fede61aec4228ea582245e091d5ea988e5d8fd5..d9d9255d4f9a53cf9ad3459c2fac373c8cd433b6 100644 (file)
@@ -27406,6 +27406,7 @@ DisResult disInstr_PPC_WRK (
    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 @@ DisResult disInstr_PPC ( IRSB*        irsb_IN,
       dres.whatNext    = Dis_StopHere;
       dres.jk_StopHere = Ijk_NoDecode;
       dres.continueAt   = 0;
+      dres.hint        = Dis_HintNone;
       return dres;
    }
 
index c5b97b406fe76633f6475e341caca95506ec2195..a7bcacc5aff493e92c0e6627bbfb11dd7ceae6d7 100644 (file)
@@ -16832,6 +16832,7 @@ disInstr_S390_WRK(const UChar *insn)
    dres.len        = insn_length;
    dres.continueAt = 0;
    dres.jk_StopHere = Ijk_INVALID;
+   dres.hint        = Dis_HintNone;
 
    /* fixs390: consider chasing of conditional jumps */
 
index f13c7ad71f53f65d60380bd7e545737de50fc50a..93e1297cbb9b5404bc5317feec69a637f7913d13 100644 (file)
@@ -323,6 +323,7 @@ static DisResult disInstr_TILEGX_WRK ( Bool(*resteerOkFn) (void *, Addr),
   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);
index d2cdb6a02435f0792f085d6b5df4e36d99e38bc4..23ed055d7e20bc9d5437c7776e831e51e7c03a77 100644 (file)
@@ -8114,6 +8114,7 @@ DisResult disInstr_X86_WRK (
    dres.whatNext    = Dis_Continue;
    dres.len         = 0;
    dres.continueAt  = 0;
+   dres.hint        = Dis_HintNone;
    dres.jk_StopHere = Ijk_INVALID;
 
    *expect_CAS = False;
index 855bc64f770153fa0839cac7a4e50b5a83f88c2e..fdb772fee0d241fb2e67105b7f89c919bfb74920 100644 (file)
@@ -475,7 +475,7 @@ typedef
          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