|
From: <sv...@va...> - 2005-12-13 20:54:15
|
Author: njn
Date: 2005-12-13 20:54:11 +0000 (Tue, 13 Dec 2005)
New Revision: 5333
Log:
Commit r5331 (vg_SP_update_pass improvement) from the trunk. A couple of
other minor commits from the trunk got dragged in too.
Modified:
branches/COMPVBITS/coregrind/m_translate.c
branches/COMPVBITS/coregrind/m_transtab.c
Modified: branches/COMPVBITS/coregrind/m_translate.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/COMPVBITS/coregrind/m_translate.c 2005-12-13 20:23:38 UTC (r=
ev 5332)
+++ branches/COMPVBITS/coregrind/m_translate.c 2005-12-13 20:54:11 UTC (r=
ev 5333)
@@ -49,7 +49,35 @@
#include "pub_core_translate.h"
#include "pub_core_transtab.h"
=20
+/*------------------------------------------------------------*/
+/*--- Stats ---*/
+/*------------------------------------------------------------*/
=20
+static UInt n_SP_updates_fast =3D 0;
+static UInt n_SP_updates_generic_known =3D 0;
+static UInt n_SP_updates_generic_unknown =3D 0;
+
+void VG_(print_translation_stats) ( void )
+{
+ Char buf[6];
+ UInt n_SP_updates =3D n_SP_updates_fast + n_SP_updates_generic_known
+ + n_SP_updates_generic_unknown;
+ VG_(percentify)(n_SP_updates_fast, n_SP_updates, 1, 6, buf);
+ VG_(message)(Vg_DebugMsg,
+ "translate: fast SP updates identified: %,u (%s)",
+ n_SP_updates_fast, buf );
+
+ VG_(percentify)(n_SP_updates_generic_known, n_SP_updates, 1, 6, buf);
+ VG_(message)(Vg_DebugMsg,
+ "translate: generic_known SP updates identified: %,u (%s)",
+ n_SP_updates_generic_known, buf );
+
+ VG_(percentify)(n_SP_updates_generic_unknown, n_SP_updates, 1, 6, buf=
);
+ VG_(message)(Vg_DebugMsg,
+ "translate: generic_unknown SP updates identified: %,u (%s)",
+ n_SP_updates_generic_unknown, buf );
+}
+
/*------------------------------------------------------------*/
/*--- %SP-update pass ---*/
/*------------------------------------------------------------*/
@@ -70,24 +98,99 @@
VG_(tdict).track_die_mem_stack );
}
=20
-/* NOTE: this comment is out of date */
+// - The SP aliases are held in an array which is used as a circular buf=
fer.
+// This misses very few constant updates of SP (ie. < 0.1%) while usin=
g a
+// small, constant structure that will also never fill up and cause
+// execution to abort.
+// - Unused slots have a .temp value of 'IRTemp_INVALID'.
+// - 'next_SP_alias_slot' is the index where the next alias will be stor=
ed.
+// - If the buffer fills, we circle around and start over-writing
+// non-IRTemp_INVALID values. This is rare, and the overwriting of a
+// value that would have subsequently be used is even rarer.
+// - Every slot below next_SP_alias_slot holds a non-IRTemp_INVALID valu=
e.
+// The rest either all won't (if we haven't yet circled around) or all
+// will (if we have circled around).
=20
-/* For tools that want to know about %ESP changes, this pass adds
+typedef=20
+ struct {
+ IRTemp temp;
+ Long delta;
+ }
+ SP_Alias;
+
+// With 32 slots the buffer fills very rarely -- eg. once in a run of GC=
C.
+// And I've tested with smaller values and the wrap-around case works ok=
.
+#define N_ALIASES 32
+static SP_Alias SP_aliases[N_ALIASES];
+static Int next_SP_alias_slot =3D 0;
+
+static void clear_SP_aliases(void)
+{
+ Int i;
+ for (i =3D 0; i < N_ALIASES; i++) {
+ SP_aliases[i].temp =3D IRTemp_INVALID;
+ SP_aliases[i].delta =3D 0;
+ }
+ next_SP_alias_slot =3D 0;
+}
+
+static void add_SP_alias(IRTemp temp, Long delta)
+{
+ vg_assert(temp !=3D IRTemp_INVALID);
+ SP_aliases[ next_SP_alias_slot ].temp =3D temp;
+ SP_aliases[ next_SP_alias_slot ].delta =3D delta;
+ next_SP_alias_slot++;
+ if (N_ALIASES =3D=3D next_SP_alias_slot) next_SP_alias_slot =3D 0;
+}
+
+static Bool get_SP_delta(IRTemp temp, ULong* delta)
+{
+ Int i; // i must be signed!
+ vg_assert(IRTemp_INVALID !=3D temp);
+ // Search backwards between current buffer position and the start.
+ for (i =3D next_SP_alias_slot-1; i >=3D 0; i--) {
+ if (temp =3D=3D SP_aliases[i].temp) {
+ *delta =3D SP_aliases[i].delta;
+ return True;
+ }
+ }
+ // Search backwards between the end and the current buffer position.
+ for (i =3D N_ALIASES-1; i >=3D next_SP_alias_slot; i--) {
+ if (temp =3D=3D SP_aliases[i].temp) {
+ *delta =3D SP_aliases[i].delta;
+ return True;
+ }
+ }
+ return False;
+}
+
+static void update_SP_aliases(Long delta)
+{
+ Int i;
+ for (i =3D 0; i < N_ALIASES; i++) {
+ if (SP_aliases[i].temp =3D=3D IRTemp_INVALID) {
+ return;
+ }
+ SP_aliases[i].delta +=3D delta;
+ }
+}
+
+
+/* For tools that want to know about SP changes, this pass adds
in the appropriate hooks. We have to do it after the tool's
- instrumentation, so the tool doesn't have to worry about the CCALLs
+ instrumentation, so the tool doesn't have to worry about the C calls
it adds in, and we must do it before register allocation because
- spilled temps make it much harder to work out the %esp deltas.
- Thus we have it as an extra phase between the two.=20
- =20
- We look for "GETL %ESP, t_ESP", then track ADDs and SUBs of
- literal values to t_ESP, and the total delta of the ADDs/SUBs. Then =
if
- "PUTL t_ESP, %ESP" happens, we call the helper with the known delta. =
We
- also cope with "MOVL t_ESP, tX", making tX the new t_ESP. If any oth=
er
- instruction clobbers t_ESP, we don't track it anymore, and fall back =
to
- the delta-is-unknown case. That case is also used when the delta is =
not
- a nice small amount, or an unknown amount.
+ spilled temps make it much harder to work out the SP deltas.
+ This it is done with Vex's "second instrumentation" pass.
+
+ Basically, we look for GET(SP)/PUT(SP) pairs and track constant
+ increments/decrements of SP between them. (This requires tracking on=
e or
+ more "aliases", which are not exact aliases but instead are tempregs
+ whose value is equal to the SP's plus or minus a known constant.)
+ If all the changes to SP leading up to a PUT(SP) are by known, small
+ constants, we can do a specific call to eg. new_mem_stack_4, otherwis=
e
+ we fall back to the case that handles an unknown SP change.
*/
-
static
IRBB* vg_SP_update_pass ( IRBB* bb_in,=20
VexGuestLayout* layout,=20
@@ -101,9 +204,8 @@
IRStmt* st;
IRExpr* e;
IRArray* descr;
- IRTemp curr;
IRType typeof_SP;
- Long delta;
+ Long delta, con;
=20
/* Set up BB */
IRBB* bb =3D emptyIRBB();
@@ -111,7 +213,6 @@
bb->next =3D dopyIRExpr(bb_in->next);
bb->jumpkind =3D bb_in->jumpkind;
=20
- curr =3D IRTemp_INVALID;
delta =3D 0;
=20
sizeof_SP =3D layout->sizeof_SP;
@@ -128,9 +229,10 @@
(sizeof_SP=3D=3D4 ? (Long)(Int)(con->Ico.U32) =
\
: (Long)(con->Ico.U64))
=20
-# define DO(kind, syze) =
\
+// XXX: convert this to a function
+# define DO(kind, syze, tmpp) =
\
do { =
\
- if (!VG_(tdict).track_##kind##_mem_stack_##syze) \
+ if (!VG_(tdict).track_##kind##_mem_stack_##syze) =
\
goto generic; =
\
=
\
/* I don't know if it's really necessary to say that the */ =
\
@@ -139,7 +241,7 @@
1/*regparms*/, =
\
"track_" #kind "_mem_stack_" #syze, =
\
VG_(tdict).track_##kind##_mem_stack_##syze, =
\
- mkIRExprVec_1(IRExpr_Tmp(curr)) =
\
+ mkIRExprVec_1(IRExpr_Tmp(tmpp)) =
\
); =
\
dcall->nFxState =3D 1; =
\
dcall->fxState[0].fx =3D Ifx_Read; =
\
@@ -147,13 +249,18 @@
dcall->fxState[0].size =3D layout->sizeof_SP; =
\
=
\
addStmtToIRBB( bb, IRStmt_Dirty(dcall) ); =
\
+ =
\
+ update_SP_aliases(-delta); =
\
+ =
\
+ n_SP_updates_fast++; =
\
+ =
\
} while (0)
=20
+ clear_SP_aliases();
+
for (i =3D 0; i < bb_in->stmts_used; i++) {
=20
st =3D bb_in->stmts[i];
- if (!st)
- continue;
=20
/* t =3D Get(sp): curr =3D t, delta =3D 0 */
if (st->tag !=3D Ist_Tmp) goto case2;
@@ -161,8 +268,7 @@
if (e->tag !=3D Iex_Get) goto case2;
if (e->Iex.Get.offset !=3D offset_SP) goto case2;
if (e->Iex.Get.ty !=3D typeof_SP) goto case2;
- curr =3D st->Ist.Tmp.tmp;
- delta =3D 0;
+ add_SP_alias(st->Ist.Tmp.tmp, 0);
addStmtToIRBB( bb, st );
continue;
=20
@@ -172,14 +278,15 @@
e =3D st->Ist.Tmp.data;
if (e->tag !=3D Iex_Binop) goto case3;
if (e->Iex.Binop.arg1->tag !=3D Iex_Tmp) goto case3;
- if (e->Iex.Binop.arg1->Iex.Tmp.tmp !=3D curr) goto case3;
+ if (!get_SP_delta(e->Iex.Binop.arg1->Iex.Tmp.tmp, &delta)) goto ca=
se3;
if (e->Iex.Binop.arg2->tag !=3D Iex_Const) goto case3;
if (!IS_ADD_OR_SUB(e->Iex.Binop.op)) goto case3;
- curr =3D st->Ist.Tmp.tmp;
- if (IS_ADD(e->Iex.Binop.op))
- delta +=3D GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
- else
- delta -=3D GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
+ con =3D GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
+ if (IS_ADD(e->Iex.Binop.op)) {
+ add_SP_alias(st->Ist.Tmp.tmp, delta + con);
+ } else {
+ add_SP_alias(st->Ist.Tmp.tmp, delta - con);
+ }
addStmtToIRBB( bb, st );
continue;
=20
@@ -188,8 +295,8 @@
if (st->tag !=3D Ist_Tmp) goto case4;
e =3D st->Ist.Tmp.data;
if (e->tag !=3D Iex_Tmp) goto case4;
- if (e->Iex.Tmp.tmp !=3D curr) goto case4;
- curr =3D st->Ist.Tmp.tmp;
+ if (!get_SP_delta(e->Iex.Tmp.tmp, &delta)) goto case4;
+ add_SP_alias(st->Ist.Tmp.tmp, delta);
addStmtToIRBB( bb, st );
continue;
=20
@@ -198,23 +305,31 @@
if (st->tag !=3D Ist_Put) goto case5;
if (st->Ist.Put.offset !=3D offset_SP) goto case5;
if (st->Ist.Put.data->tag !=3D Iex_Tmp) goto case5;
- if (st->Ist.Put.data->Iex.Tmp.tmp =3D=3D curr) {
+ if (get_SP_delta(st->Ist.Put.data->Iex.Tmp.tmp, &delta)) {
+ IRTemp tttmp =3D st->Ist.Put.data->Iex.Tmp.tmp;
switch (delta) {
- case 0: addStmtToIRBB(bb,st); delta =3D 0; co=
ntinue;
- case 4: DO(die, 4); addStmtToIRBB(bb,st); delta =3D 0; co=
ntinue;
- case -4: DO(new, 4); addStmtToIRBB(bb,st); delta =3D 0; co=
ntinue;
- case 8: DO(die, 8); addStmtToIRBB(bb,st); delta =3D 0; co=
ntinue;
- case -8: DO(new, 8); addStmtToIRBB(bb,st); delta =3D 0; co=
ntinue;
- case 12: DO(die, 12); addStmtToIRBB(bb,st); delta =3D 0; co=
ntinue;
- case -12: DO(new, 12); addStmtToIRBB(bb,st); delta =3D 0; co=
ntinue;
- case 16: DO(die, 16); addStmtToIRBB(bb,st); delta =3D 0; co=
ntinue;
- case -16: DO(new, 16); addStmtToIRBB(bb,st); delta =3D 0; co=
ntinue;
- case 32: DO(die, 32); addStmtToIRBB(bb,st); delta =3D 0; co=
ntinue;
- case -32: DO(new, 32); addStmtToIRBB(bb,st); delta =3D 0; co=
ntinue;
- default: goto generic;
+ case 0: addStmtToIRBB(bb,st); continue=
;
+ case 4: DO(die, 4, tttmp); addStmtToIRBB(bb,st); continue=
;
+ case -4: DO(new, 4, tttmp); addStmtToIRBB(bb,st); continue=
;
+ case 8: DO(die, 8, tttmp); addStmtToIRBB(bb,st); continue=
;
+ case -8: DO(new, 8, tttmp); addStmtToIRBB(bb,st); continue=
;
+ case 12: DO(die, 12, tttmp); addStmtToIRBB(bb,st); continue=
;
+ case -12: DO(new, 12, tttmp); addStmtToIRBB(bb,st); continue=
;
+ case 16: DO(die, 16, tttmp); addStmtToIRBB(bb,st); continue=
;
+ case -16: DO(new, 16, tttmp); addStmtToIRBB(bb,st); continue=
;
+ case 32: DO(die, 32, tttmp); addStmtToIRBB(bb,st); continue=
;
+ case -32: DO(new, 32, tttmp); addStmtToIRBB(bb,st); continue=
;
+ default: =20
+ n_SP_updates_generic_known++;
+ goto generic;
}
} else {
IRTemp old_SP;
+ n_SP_updates_generic_unknown++;
+
+ // Nb: if all is well, this generic case will typically be
+ // called something like every 1000th SP update. If it's more =
than
+ // that, the above code may be missing some cases.
generic:
/* Pass both the old and new SP values to this helper. */
old_SP =3D newIRTemp(bb->tyenv, typeof_SP);
@@ -232,8 +347,8 @@
=20
addStmtToIRBB( bb, st );
=20
- curr =3D st->Ist.Put.data->Iex.Tmp.tmp;
- delta =3D 0;
+ clear_SP_aliases();
+ add_SP_alias(st->Ist.Put.data->Iex.Tmp.tmp, 0);
continue;
}
=20
@@ -272,7 +387,6 @@
=20
}
=20
-
/*------------------------------------------------------------*/
/*--- Main entry point for the JITter. ---*/
/*------------------------------------------------------------*/
@@ -384,7 +498,8 @@
=20
/* This stops Vex from chasing into function entry points that we wish
to redirect. Chasing across them obviously defeats the redirect
- mechanism, with bad effects for Memcheck and possibly others.
+ mechanism, with bad effects for Memcheck, Addrcheck, and possibly
+ others.
=20
Also, we must stop Vex chasing into blocks for which we might want
to self checking.
Modified: branches/COMPVBITS/coregrind/m_transtab.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/COMPVBITS/coregrind/m_transtab.c 2005-12-13 20:23:38 UTC (re=
v 5332)
+++ branches/COMPVBITS/coregrind/m_transtab.c 2005-12-13 20:54:11 UTC (re=
v 5333)
@@ -1295,16 +1295,16 @@
n_fast_updates, n_fast_flushes );
=20
VG_(message)(Vg_DebugMsg,
- "translate: new %,lld "
+ " transtab: new %,lld "
"(%,llu -> %,llu; ratio %,llu:10) [%,llu scs]",
n_in_count, n_in_osize, n_in_tsize,
safe_idiv(10*n_in_tsize, n_in_osize),
n_in_sc_count);
VG_(message)(Vg_DebugMsg,
- "translate: dumped %,llu (%,llu -> ?" "?)",
+ " transtab: dumped %,llu (%,llu -> ?" "?)",
n_dump_count, n_dump_osize );
VG_(message)(Vg_DebugMsg,
- "translate: discarded %,llu (%,llu -> ?" "?)",
+ " transtab: discarded %,llu (%,llu -> ?" "?)",
n_disc_count, n_disc_osize );
=20
if (0) {
|