From aed32933656dd5d1690716c85a2fd72697c2e181 Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Wed, 23 Nov 2005 04:25:07 +0000 Subject: [PATCH] Use a very fast in-line allocator. This improves its performance by up to 10% on a P4. git-svn-id: svn://svn.valgrind.org/vex/trunk@1469 --- VEX/priv/main/vex_main.c | 30 ++++++-- VEX/priv/main/vex_util.c | 160 ++++++++++++++++++++++++++------------- VEX/priv/main/vex_util.h | 4 +- VEX/pub/libvex.h | 25 +++++- 4 files changed, 158 insertions(+), 61 deletions(-) diff --git a/VEX/priv/main/vex_main.c b/VEX/priv/main/vex_main.c index 085093e581..26cdcc2f08 100644 --- a/VEX/priv/main/vex_main.c +++ b/VEX/priv/main/vex_main.c @@ -263,8 +263,8 @@ VexTranslateResult LibVEX_Translate ( vex_traceflags = traceflags; vassert(vex_initdone); - vexClearTEMP(); - + vexSetAllocModeTEMP_and_clear(); + vexAllocSanityCheck(); /* First off, check that the guest and host insn sets are supported. */ @@ -406,6 +406,8 @@ VexTranslateResult LibVEX_Translate ( vassert(archinfo_guest->subarch == archinfo_host->subarch); } + vexAllocSanityCheck(); + if (vex_traceflags & VEX_TRACE_FE) vex_printf("\n------------------------" " Front end " @@ -423,9 +425,11 @@ VexTranslateResult LibVEX_Translate ( offB_TISTART, offB_TILEN ); + vexAllocSanityCheck(); + if (irbb == NULL) { /* Access failure. */ - vexClearTEMP(); + vexSetAllocModeTEMP_and_clear(); vex_traceflags = 0; return VexTransAccessFail; } @@ -455,6 +459,8 @@ VexTranslateResult LibVEX_Translate ( sanityCheckIRBB( irbb, "initial IR", False/*can be non-flat*/, guest_word_type ); + vexAllocSanityCheck(); + /* Clean it up, hopefully a lot. */ irbb = do_iropt_BB ( irbb, specHelper, preciseMemExnsFn, guest_bytes_addr ); @@ -469,11 +475,15 @@ VexTranslateResult LibVEX_Translate ( vex_printf("\n"); } + vexAllocSanityCheck(); + /* Get the thing instrumented. */ if (instrument1) irbb = (*instrument1)(irbb, guest_layout, guest_bytes_addr_noredir, guest_extents, guest_word_type, host_word_type); + vexAllocSanityCheck(); + if (instrument2) irbb = (*instrument2)(irbb, guest_layout, guest_bytes_addr_noredir, guest_extents, @@ -500,6 +510,8 @@ VexTranslateResult LibVEX_Translate ( True/*must be flat*/, guest_word_type ); } + vexAllocSanityCheck(); + if (vex_traceflags & VEX_TRACE_OPT2) { vex_printf("\n------------------------" " After post-instr IR optimisation " @@ -512,6 +524,8 @@ VexTranslateResult LibVEX_Translate ( do_deadcode_BB( irbb ); do_treebuild_BB( irbb ); + vexAllocSanityCheck(); + if (vex_traceflags & VEX_TRACE_TREES) { vex_printf("\n------------------------" " After tree-building " @@ -531,6 +545,8 @@ VexTranslateResult LibVEX_Translate ( vcode = iselBB ( irbb, archinfo_host ); + vexAllocSanityCheck(); + if (vex_traceflags & VEX_TRACE_VCODE) vex_printf("\n"); @@ -550,6 +566,8 @@ VexTranslateResult LibVEX_Translate ( genSpill, genReload, guest_sizeB, ppInstr, ppReg ); + vexAllocSanityCheck(); + if (vex_traceflags & VEX_TRACE_RCODE) { vex_printf("\n------------------------" " Register-allocated code " @@ -589,7 +607,7 @@ VexTranslateResult LibVEX_Translate ( vex_printf("\n\n"); } if (out_used + j > host_bytes_size) { - vexClearTEMP(); + vexSetAllocModeTEMP_and_clear(); vex_traceflags = 0; return VexTransOutputFull; } @@ -601,7 +619,9 @@ VexTranslateResult LibVEX_Translate ( } *host_bytes_used = out_used; - vexClearTEMP(); + vexAllocSanityCheck(); + + vexSetAllocModeTEMP_and_clear(); vex_traceflags = 0; return VexTransOK; diff --git a/VEX/priv/main/vex_util.c b/VEX/priv/main/vex_util.c index 370e582a2d..0436e8ffa8 100644 --- a/VEX/priv/main/vex_util.c +++ b/VEX/priv/main/vex_util.c @@ -64,28 +64,94 @@ */ #define N_TEMPORARY_BYTES 2400000 -static Char temporary[N_TEMPORARY_BYTES]; -static Int temporary_used = 0; +static HChar temporary[N_TEMPORARY_BYTES]; +static HChar* temporary_first = &temporary[0]; +static HChar* temporary_curr = &temporary[0]; +static HChar* temporary_last = &temporary[N_TEMPORARY_BYTES-1]; -#define N_PERMANENT_BYTES 1000 +static ULong temporary_bytes_allocd_TOT = 0; -static Char permanent[N_TEMPORARY_BYTES]; -static Int permanent_used = 0; +#define N_PERMANENT_BYTES 1000 +static HChar permanent[N_TEMPORARY_BYTES]; +static HChar* permanent_first = &permanent[0]; +static HChar* permanent_curr = &permanent[0]; +static HChar* permanent_last = &permanent[N_TEMPORARY_BYTES-1]; -/* Gather statistics. */ -static Int temporary_bytes_allocd = 0; -static Int temporary_count_allocs = 0; +static VexAllocMode mode = VexAllocModeTEMP; -static ULong temporary_bytes_allocd_TOT = 0; -static ULong temporary_count_allocs_TOT = 0; +void vexAllocSanityCheck ( void ) +{ + vassert(temporary_first == &temporary[0]); + vassert(temporary_last == &temporary[N_TEMPORARY_BYTES-1]); + vassert(permanent_first == &permanent[0]); + vassert(permanent_last == &permanent[N_TEMPORARY_BYTES-1]); + vassert(temporary_first <= temporary_curr); + vassert(temporary_curr <= temporary_last); + vassert(permanent_first <= permanent_curr); + vassert(permanent_curr <= permanent_last); + vassert(private_LibVEX_alloc_first <= private_LibVEX_alloc_curr); + vassert(private_LibVEX_alloc_curr <= private_LibVEX_alloc_last); + if (mode == VexAllocModeTEMP){ + vassert(private_LibVEX_alloc_first == temporary_first); + vassert(private_LibVEX_alloc_last == temporary_last); + } + else + if (mode == VexAllocModePERM) { + vassert(private_LibVEX_alloc_first == permanent_first); + vassert(private_LibVEX_alloc_last == permanent_last); + } + else + vassert(0); + +# define IS_WORD_ALIGNED(p) (0 == (((HWord)p) & (sizeof(HWord)-1))) + vassert(sizeof(HWord) == 4 || sizeof(HWord) == 8); + vassert(IS_WORD_ALIGNED(temporary_first)); + vassert(IS_WORD_ALIGNED(temporary_curr)); + vassert(IS_WORD_ALIGNED(temporary_last+1)); + vassert(IS_WORD_ALIGNED(permanent_first)); + vassert(IS_WORD_ALIGNED(permanent_curr)); + vassert(IS_WORD_ALIGNED(permanent_last+1)); + vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_first)); + vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_curr)); + vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_last+1)); +# undef IS_WORD_ALIGNED +} /* The current allocation mode. */ -static VexAllocMode mode = VexAllocModeTEMP; - void vexSetAllocMode ( VexAllocMode m ) { + vexAllocSanityCheck(); + + /* Save away the current allocation point .. */ + if (mode == VexAllocModeTEMP){ + temporary_curr = private_LibVEX_alloc_curr; + } + else + if (mode == VexAllocModePERM) { + permanent_curr = private_LibVEX_alloc_curr; + } + else + vassert(0); + + /* Did that screw anything up? */ + vexAllocSanityCheck(); + + if (m == VexAllocModeTEMP){ + private_LibVEX_alloc_first = temporary_first; + private_LibVEX_alloc_curr = temporary_curr; + private_LibVEX_alloc_last = temporary_last; + } + else + if (m == VexAllocModePERM) { + private_LibVEX_alloc_first = permanent_first; + private_LibVEX_alloc_curr = permanent_curr; + private_LibVEX_alloc_last = permanent_last; + } + else + vassert(0); + mode = m; } @@ -94,48 +160,39 @@ VexAllocMode vexGetAllocMode ( void ) return mode; } -/* Exported to library client. */ +/* Visible to library client, unfortunately. */ -void* LibVEX_Alloc ( Int nbytes ) +HChar* private_LibVEX_alloc_first = &temporary[0]; +HChar* private_LibVEX_alloc_curr = &temporary[0]; +HChar* private_LibVEX_alloc_last = &temporary[N_TEMPORARY_BYTES-1]; + +__attribute__((noreturn)) +void private_LibVEX_alloc_OOM(void) { - /* 3 or 7 depending on host word size. */ -# define ALIGN (sizeof(void*)-1) - vassert(vex_initdone); - vassert(nbytes >= 0); - if (0 && vex_valgrind_support) { - /* ugly hack -- do not remove */ - //extern void* malloc ( int ); - //return malloc(nbytes); - return NULL; - } else { - nbytes = (nbytes + ALIGN) & ~ALIGN; - if (mode == VexAllocModeTEMP) { - if (temporary_used + nbytes > N_TEMPORARY_BYTES) - vpanic("VEX temporary storage exhausted.\n" - "Increase N_TEMPORARY_BYTES and recompile."); - temporary_count_allocs++; - temporary_bytes_allocd += nbytes; - temporary_used += nbytes; - return (void*)(&temporary[temporary_used - nbytes]); - } else { - if (permanent_used + nbytes > N_PERMANENT_BYTES) - vpanic("VEX permanent storage exhausted.\n" - "Increase N_PERMANENT_BYTES and recompile."); - permanent_used += nbytes; - return (void*)(&permanent[permanent_used - nbytes]); - } - } -# undef ALIGN + HChar* pool = "???"; + if (private_LibVEX_alloc_first == &temporary[0]) pool = "TEMP"; + if (private_LibVEX_alloc_first == &permanent[0]) pool = "PERM"; + vex_printf("VEX temporary storage exhausted.\n"); + vex_printf("Pool = %s, start %p curr %p end %p (size %d)\n", + pool, + private_LibVEX_alloc_first, + private_LibVEX_alloc_curr, + private_LibVEX_alloc_last, + private_LibVEX_alloc_last - private_LibVEX_alloc_first); + vpanic("VEX temporary storage exhausted.\n" + "Increase N_{TEMPORARY,PERMANENT}_BYTES and recompile."); } -void vexClearTEMP ( void ) +void vexSetAllocModeTEMP_and_clear ( void ) { /* vassert(vex_initdone); */ /* causes infinite assert loops */ - temporary_bytes_allocd_TOT += (ULong)temporary_bytes_allocd; - temporary_count_allocs_TOT += (ULong)temporary_count_allocs; - temporary_used = 0; - temporary_bytes_allocd = 0; - temporary_count_allocs = 0; + temporary_bytes_allocd_TOT + += (ULong)( private_LibVEX_alloc_curr - private_LibVEX_alloc_first); + + mode = VexAllocModeTEMP; + temporary_curr = &temporary[0]; + private_LibVEX_alloc_curr = &temporary[0]; + vexAllocSanityCheck(); } @@ -143,11 +200,8 @@ void vexClearTEMP ( void ) void LibVEX_ShowAllocStats ( void ) { - vex_printf("vex storage: P %d, T total %lld (%lld), T curr %d (%d)\n", - permanent_used, - (Long)temporary_bytes_allocd_TOT, - (Long)temporary_count_allocs_TOT, - temporary_bytes_allocd, temporary_count_allocs ); + vex_printf("vex storage: T total %lld bytes allocated\n", + (Long)temporary_bytes_allocd_TOT ); } diff --git a/VEX/priv/main/vex_util.h b/VEX/priv/main/vex_util.h index afe94c8727..6ec1e7a9cf 100644 --- a/VEX/priv/main/vex_util.h +++ b/VEX/priv/main/vex_util.h @@ -101,9 +101,9 @@ typedef extern void vexSetAllocMode ( VexAllocMode ); extern VexAllocMode vexGetAllocMode ( void ); +extern void vexAllocSanityCheck ( void ); -extern void vexClearTEMP ( void ); - +extern void vexSetAllocModeTEMP_and_clear ( void ); #endif /* ndef __VEX_UTIL_H */ diff --git a/VEX/pub/libvex.h b/VEX/pub/libvex.h index 361981b5db..5541dbd86e 100644 --- a/VEX/pub/libvex.h +++ b/VEX/pub/libvex.h @@ -168,7 +168,30 @@ extern const HChar* LibVEX_Version ( void ); LibVEX_Translate. The storage allocated will only stay alive until translation of the current basic block is complete. */ -extern void* LibVEX_Alloc ( Int nbytes ); +extern HChar* private_LibVEX_alloc_first; +extern HChar* private_LibVEX_alloc_curr; +extern HChar* private_LibVEX_alloc_last; +extern void private_LibVEX_alloc_OOM(void) __attribute__((noreturn)); + +static inline void* LibVEX_Alloc ( Int nbytes ) +{ +#if 0 + /* Nasty debugging hack, do not use. */ + return malloc(nbytes); +#else + HChar* curr; + HChar* next; + Int ALIGN; + ALIGN = sizeof(void*)-1; + nbytes = (nbytes + ALIGN) & ~ALIGN; + curr = private_LibVEX_alloc_curr; + next = curr + nbytes; + if (next >= private_LibVEX_alloc_last) + private_LibVEX_alloc_OOM(); + private_LibVEX_alloc_curr = next; + return curr; +#endif +} /* Show Vex allocation statistics. */ extern void LibVEX_ShowAllocStats ( void ); -- 2.47.2