Merge patch from JeremyF:
56-chained-accounting
Fix accounting for chained blocks, by only counting real unchain
events, rather than the unchains used to establish the initial call to
VG_(patch_me) at the jump site.
Also a minor cleanup of the jump delta calculation in synth_jcond_lit.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1340 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_dispatch.S b/coregrind/vg_dispatch.S
index 08ae86b..60d0310 100644
--- a/coregrind/vg_dispatch.S
+++ b/coregrind/vg_dispatch.S
@@ -181,13 +181,24 @@
jmp run_innerloop_exit
-/* This is the translation chainer, our run-time linker, if you like.
-
- This enters with %eax pointing to next eip we want. If
- we've already compiled that eip (ie, get a fast hit), we
- backpatch the call instruction with a jump, and jump there.
- Otherwise, we do a slow hit/compile through the normal path
- (and get to do a backpatch next time through).
+/*
+ This is the translation chainer, our run-time linker, if you like.
+
+ VG_(patch_me) patches the call instruction in the jump site
+ with a jump to the generated code for the branch target. %eax
+ contains the original program's EIP - if we get a hit in
+ tt_fast, then the call is patched into a jump; otherwise it
+ simply drops back into the dispatch loop for normal
+ processing.
+
+ The callsite is expected to look like:
+ call VG_(patch_me)
+ it will be transformed into
+ jmp $TARGETADDR
+
+ The environment we're expecting on entry is:
+ %eax = branch target address (original code EIP)
+ *(%esp) = just after call
*/
.globl VG_(patch_me)
VG_(patch_me):
diff --git a/coregrind/vg_from_ucode.c b/coregrind/vg_from_ucode.c
index 645988c..5085b43 100644
--- a/coregrind/vg_from_ucode.c
+++ b/coregrind/vg_from_ucode.c
@@ -1053,6 +1053,17 @@
return (*cp == 0xE9); /* 0xE9 -- jmp */
}
+static
+Bool is_fresh_jumpsite(UChar *cp)
+{
+ return
+ cp[0] == 0x0F && /* UD2 */
+ cp[1] == 0x0B &&
+ cp[2] == 0x0F && /* UD2 */
+ cp[3] == 0x0B &&
+ cp[4] == 0x90; /* NOP */
+}
+
/* Predicate used in sanity checks elsewhere - returns true if all
jump-sites are calls to VG_(patch_me) */
Bool VG_(is_unchained_jumpsite)(Addr a)
@@ -1098,12 +1109,14 @@
if (VG_(is_unchained_jumpsite)(a))
return; /* don't write unnecessarily */
+ if (!is_fresh_jumpsite(cp))
+ VG_(bb_dechain_count)++; /* update stats */
+
*cp++ = 0xE8; /* call */
*cp++ = (delta >> 0) & 0xff;
*cp++ = (delta >> 8) & 0xff;
*cp++ = (delta >> 16) & 0xff;
*cp++ = (delta >> 24) & 0xff;
- VG_(bb_dechain_count)++; /* update stats */
}
/* This doesn't actually generate a call to VG_(patch_me), but
@@ -1569,11 +1582,10 @@
mov $0x4000d190,%eax // 5
mov %eax, VGOFF_(m_eip)(%ebp) // 3
call 0x40050f9a <vgPlain_patch_me> // 5
- $01 // 1
1: mov $0x4000d042,%eax
call 0x40050f9a <vgPlain_patch_me>
*/
- delta = 5+3+5+1 -1;
+ delta = 5+3+5;
} else
delta = 5+1;