m_transtab.c revision e49d8e7dfd3a9c96feb9935b5920973dfc0b170a
1de4a1d01951937632098a6cda45859afa587a06fsewardj 2de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/ 3de4a1d01951937632098a6cda45859afa587a06fsewardj/*--- Management of the translation table and cache. ---*/ 4de4a1d01951937632098a6cda45859afa587a06fsewardj/*--- vg_transtab.c ---*/ 5de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/ 6de4a1d01951937632098a6cda45859afa587a06fsewardj 7de4a1d01951937632098a6cda45859afa587a06fsewardj/* 8de4a1d01951937632098a6cda45859afa587a06fsewardj This file is part of Valgrind, an x86 protected-mode emulator 9de4a1d01951937632098a6cda45859afa587a06fsewardj designed for debugging and profiling binaries on x86-Unixes. 10de4a1d01951937632098a6cda45859afa587a06fsewardj 11de4a1d01951937632098a6cda45859afa587a06fsewardj Copyright (C) 2000-2002 Julian Seward 12de4a1d01951937632098a6cda45859afa587a06fsewardj jseward@acm.org 13de4a1d01951937632098a6cda45859afa587a06fsewardj 14de4a1d01951937632098a6cda45859afa587a06fsewardj This program is free software; you can redistribute it and/or 15de4a1d01951937632098a6cda45859afa587a06fsewardj modify it under the terms of the GNU General Public License as 16de4a1d01951937632098a6cda45859afa587a06fsewardj published by the Free Software Foundation; either version 2 of the 17de4a1d01951937632098a6cda45859afa587a06fsewardj License, or (at your option) any later version. 18de4a1d01951937632098a6cda45859afa587a06fsewardj 19de4a1d01951937632098a6cda45859afa587a06fsewardj This program is distributed in the hope that it will be useful, but 20de4a1d01951937632098a6cda45859afa587a06fsewardj WITHOUT ANY WARRANTY; without even the implied warranty of 21de4a1d01951937632098a6cda45859afa587a06fsewardj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22de4a1d01951937632098a6cda45859afa587a06fsewardj General Public License for more details. 23de4a1d01951937632098a6cda45859afa587a06fsewardj 24de4a1d01951937632098a6cda45859afa587a06fsewardj You should have received a copy of the GNU General Public License 25de4a1d01951937632098a6cda45859afa587a06fsewardj along with this program; if not, write to the Free Software 26de4a1d01951937632098a6cda45859afa587a06fsewardj Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27de4a1d01951937632098a6cda45859afa587a06fsewardj 02111-1307, USA. 28de4a1d01951937632098a6cda45859afa587a06fsewardj 29e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn The GNU General Public License is contained in the file COPYING. 30de4a1d01951937632098a6cda45859afa587a06fsewardj*/ 31de4a1d01951937632098a6cda45859afa587a06fsewardj 32de4a1d01951937632098a6cda45859afa587a06fsewardj#include "vg_include.h" 33de4a1d01951937632098a6cda45859afa587a06fsewardj 3418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj/* #define DEBUG_TRANSTAB */ 3518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj 36de4a1d01951937632098a6cda45859afa587a06fsewardj 37de4a1d01951937632098a6cda45859afa587a06fsewardj/*------------------------------------------------------------*/ 38de4a1d01951937632098a6cda45859afa587a06fsewardj/*--- Management of the LRU-based translation table+cache. ---*/ 39de4a1d01951937632098a6cda45859afa587a06fsewardj/*------------------------------------------------------------*/ 40de4a1d01951937632098a6cda45859afa587a06fsewardj 41de4a1d01951937632098a6cda45859afa587a06fsewardj/* These sizes were set up so as to be able to debug large KDE 3 42de4a1d01951937632098a6cda45859afa587a06fsewardj applications (are there any small ones?) without excessive amounts 43de4a1d01951937632098a6cda45859afa587a06fsewardj of code retranslation. */ 44de4a1d01951937632098a6cda45859afa587a06fsewardj 45de4a1d01951937632098a6cda45859afa587a06fsewardj/* Size of the translation cache, in bytes. */ 4618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj#define VG_TC_SIZE /*1000000*/ /*16000000*/ 32000000 /*40000000*/ 47de4a1d01951937632098a6cda45859afa587a06fsewardj 48de4a1d01951937632098a6cda45859afa587a06fsewardj/* Do a LRU pass when the translation cache becomes this full. */ 49ec05564e60750787ac4db9e9254f74be357f307csewardj#define VG_TC_LIMIT_PERCENT 98 50de4a1d01951937632098a6cda45859afa587a06fsewardj 51de4a1d01951937632098a6cda45859afa587a06fsewardj/* When doing an LRU pass, reduce TC fullness to this level. */ 52de4a1d01951937632098a6cda45859afa587a06fsewardj#define VG_TC_TARGET_PERCENT 85 53de4a1d01951937632098a6cda45859afa587a06fsewardj 54de4a1d01951937632098a6cda45859afa587a06fsewardj/* Number of entries in the translation table. This must be a prime 55de4a1d01951937632098a6cda45859afa587a06fsewardj number in order to make the hashing work properly. */ 5618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj#define VG_TT_SIZE /*5281*/ /*100129*/ 200191 /*250829*/ 57de4a1d01951937632098a6cda45859afa587a06fsewardj 58de4a1d01951937632098a6cda45859afa587a06fsewardj/* Do an LRU pass when the translation table becomes this full. */ 59de4a1d01951937632098a6cda45859afa587a06fsewardj#define VG_TT_LIMIT_PERCENT /*67*/ 80 60de4a1d01951937632098a6cda45859afa587a06fsewardj 61de4a1d01951937632098a6cda45859afa587a06fsewardj/* When doing an LRU pass, reduce TT fullness to this level. */ 62de4a1d01951937632098a6cda45859afa587a06fsewardj#define VG_TT_TARGET_PERCENT /*60*/ 70 63de4a1d01951937632098a6cda45859afa587a06fsewardj 64de4a1d01951937632098a6cda45859afa587a06fsewardj/* The number of age steps we track. 0 means the current epoch, 65de4a1d01951937632098a6cda45859afa587a06fsewardj N_EPOCHS-1 means used the epoch N_EPOCHS-1 or more ago. */ 66ac68028393aef2bf9a7d48c98f293d3106a44ae1sewardj#define VG_N_EPOCHS /*2000*/ /*4000*/ 20000 67de4a1d01951937632098a6cda45859afa587a06fsewardj 6818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj/* This TT entry is empty. There is no associated TC storage. */ 69de4a1d01951937632098a6cda45859afa587a06fsewardj#define VG_TTE_EMPTY ((Addr)1) 7018d7513cc08bf982711c8a22b70d56af6aa87b33sewardj/* This TT entry has been deleted, in the sense that it does not 7118d7513cc08bf982711c8a22b70d56af6aa87b33sewardj contribute to the orig->trans mapping. However, the ex-translation 7218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj it points at still occupies space in TC. This slot cannot be 7318d7513cc08bf982711c8a22b70d56af6aa87b33sewardj re-used without doing an LRU pass. */ 74de4a1d01951937632098a6cda45859afa587a06fsewardj#define VG_TTE_DELETED ((Addr)3) 75de4a1d01951937632098a6cda45859afa587a06fsewardj 76de4a1d01951937632098a6cda45859afa587a06fsewardj/* The TC. This used to be statically allocated, but that forces many 77de4a1d01951937632098a6cda45859afa587a06fsewardj SecMap arrays to be pointlessly allocated at startup, bloating the 78de4a1d01951937632098a6cda45859afa587a06fsewardj process size by about 22M and making startup slow. So now we 79de4a1d01951937632098a6cda45859afa587a06fsewardj dynamically allocate it at startup time. 80de4a1d01951937632098a6cda45859afa587a06fsewardj was: static UChar vg_tc[VG_TC_SIZE]; 81de4a1d01951937632098a6cda45859afa587a06fsewardj*/ 82de4a1d01951937632098a6cda45859afa587a06fsewardjstatic UChar* vg_tc = NULL; 83de4a1d01951937632098a6cda45859afa587a06fsewardj 8418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj/* Count of bytes used in the TC. This includes those pointed to from 8518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj VG_TTE_DELETED entries. */ 86de4a1d01951937632098a6cda45859afa587a06fsewardjstatic Int vg_tc_used = 0; 87de4a1d01951937632098a6cda45859afa587a06fsewardj 88de4a1d01951937632098a6cda45859afa587a06fsewardj/* The TT. Like TC, for the same reason, is dynamically allocated at 89de4a1d01951937632098a6cda45859afa587a06fsewardj startup. 90de4a1d01951937632098a6cda45859afa587a06fsewardj was: static TTEntry vg_tt[VG_TT_SIZE]; 91de4a1d01951937632098a6cda45859afa587a06fsewardj*/ 92de4a1d01951937632098a6cda45859afa587a06fsewardjstatic TTEntry* vg_tt = NULL; 93de4a1d01951937632098a6cda45859afa587a06fsewardj 9418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj/* Count of non-empty TT entries. This includes deleted ones. */ 95de4a1d01951937632098a6cda45859afa587a06fsewardjstatic Int vg_tt_used = 0; 96de4a1d01951937632098a6cda45859afa587a06fsewardj 97de4a1d01951937632098a6cda45859afa587a06fsewardj/* Fast helper for the TT. A direct-mapped cache which holds a 98de4a1d01951937632098a6cda45859afa587a06fsewardj pointer to a TT entry which may or may not be the correct one, but 99de4a1d01951937632098a6cda45859afa587a06fsewardj which we hope usually is. This array is referred to directly from 100de4a1d01951937632098a6cda45859afa587a06fsewardj vg_dispatch.S. */ 101de4a1d01951937632098a6cda45859afa587a06fsewardjAddr VG_(tt_fast)[VG_TT_FAST_SIZE]; 102de4a1d01951937632098a6cda45859afa587a06fsewardj 103de4a1d01951937632098a6cda45859afa587a06fsewardj/* For reading/writing the misaligned TT-index word at immediately 104de4a1d01951937632098a6cda45859afa587a06fsewardj preceding every translation in TC. */ 1058aef1191a25d33b1173c2f05a27df7606f3ef535sewardj#if 0 1068aef1191a25d33b1173c2f05a27df7606f3ef535sewardj /* Big sigh. However reasonable this seems, there are those who 1078aef1191a25d33b1173c2f05a27df7606f3ef535sewardj set AC in %EFLAGS (Alignment Check) to 1, causing bus errors. A 1088aef1191a25d33b1173c2f05a27df7606f3ef535sewardj proper solution is for valgrind to properly virtualise AC, like 1098aef1191a25d33b1173c2f05a27df7606f3ef535sewardj the other flags (DOSZACP). The current cheap hack simply avoids 1108aef1191a25d33b1173c2f05a27df7606f3ef535sewardj all misaligned accesses, so valgrind doesn't fault even if AC is 1118aef1191a25d33b1173c2f05a27df7606f3ef535sewardj set. */ 1128aef1191a25d33b1173c2f05a27df7606f3ef535sewardj# define VG_READ_MISALIGNED_WORD(aaa) (*((UInt*)(aaa))) 1138aef1191a25d33b1173c2f05a27df7606f3ef535sewardj# define VG_WRITE_MISALIGNED_WORD(aaa,vvv) *((UInt*)(aaa)) = ((UInt)(vvv)) 1148aef1191a25d33b1173c2f05a27df7606f3ef535sewardj#else 1158aef1191a25d33b1173c2f05a27df7606f3ef535sewardj static __inline__ 1168aef1191a25d33b1173c2f05a27df7606f3ef535sewardj UInt VG_READ_MISALIGNED_WORD ( Addr aaa ) 1178aef1191a25d33b1173c2f05a27df7606f3ef535sewardj { 1188aef1191a25d33b1173c2f05a27df7606f3ef535sewardj UInt w = 0; 1198aef1191a25d33b1173c2f05a27df7606f3ef535sewardj UChar* p = (UChar*)aaa; 1208aef1191a25d33b1173c2f05a27df7606f3ef535sewardj w = 0xFF & ((UInt)(p[3])); 1218aef1191a25d33b1173c2f05a27df7606f3ef535sewardj w = (w << 8) | (0xFF & ((UInt)(p[2]))); 1228aef1191a25d33b1173c2f05a27df7606f3ef535sewardj w = (w << 8) | (0xFF & ((UInt)(p[1]))); 1238aef1191a25d33b1173c2f05a27df7606f3ef535sewardj w = (w << 8) | (0xFF & ((UInt)(p[0]))); 1248aef1191a25d33b1173c2f05a27df7606f3ef535sewardj return w; 1258aef1191a25d33b1173c2f05a27df7606f3ef535sewardj } 1268aef1191a25d33b1173c2f05a27df7606f3ef535sewardj 1278aef1191a25d33b1173c2f05a27df7606f3ef535sewardj static __inline__ 1288aef1191a25d33b1173c2f05a27df7606f3ef535sewardj void VG_WRITE_MISALIGNED_WORD ( Addr aaa, UInt vvv ) 1298aef1191a25d33b1173c2f05a27df7606f3ef535sewardj { 1308aef1191a25d33b1173c2f05a27df7606f3ef535sewardj UChar* p = (UChar*)aaa; 1318aef1191a25d33b1173c2f05a27df7606f3ef535sewardj p[0] = vvv & 0xFF; 1328aef1191a25d33b1173c2f05a27df7606f3ef535sewardj p[1] = (vvv >> 8) & 0xFF; 1338aef1191a25d33b1173c2f05a27df7606f3ef535sewardj p[2] = (vvv >> 16) & 0xFF; 1348aef1191a25d33b1173c2f05a27df7606f3ef535sewardj p[3] = (vvv >> 24) & 0xFF; 1358aef1191a25d33b1173c2f05a27df7606f3ef535sewardj } 1368aef1191a25d33b1173c2f05a27df7606f3ef535sewardj#endif 1378aef1191a25d33b1173c2f05a27df7606f3ef535sewardj 138de4a1d01951937632098a6cda45859afa587a06fsewardj 139de4a1d01951937632098a6cda45859afa587a06fsewardj/* Used for figuring out an age threshold for translations. */ 140de4a1d01951937632098a6cda45859afa587a06fsewardjstatic Int vg_bytes_in_epoch[VG_N_EPOCHS]; 141de4a1d01951937632098a6cda45859afa587a06fsewardjstatic Int vg_entries_in_epoch[VG_N_EPOCHS]; 142de4a1d01951937632098a6cda45859afa587a06fsewardj 143de4a1d01951937632098a6cda45859afa587a06fsewardj 144de4a1d01951937632098a6cda45859afa587a06fsewardj/* Just so these counts can be queried without making them globally 145de4a1d01951937632098a6cda45859afa587a06fsewardj visible. */ 146de4a1d01951937632098a6cda45859afa587a06fsewardjvoid VG_(get_tt_tc_used) ( UInt* tt_used, UInt* tc_used ) 147de4a1d01951937632098a6cda45859afa587a06fsewardj{ 148de4a1d01951937632098a6cda45859afa587a06fsewardj *tt_used = vg_tt_used; 149de4a1d01951937632098a6cda45859afa587a06fsewardj *tc_used = vg_tc_used; 150de4a1d01951937632098a6cda45859afa587a06fsewardj} 151de4a1d01951937632098a6cda45859afa587a06fsewardj 152de4a1d01951937632098a6cda45859afa587a06fsewardj 153de4a1d01951937632098a6cda45859afa587a06fsewardj/* Do the LRU thing on TT/TC, clearing them back to the target limits 154de4a1d01951937632098a6cda45859afa587a06fsewardj if they are over the threshold limits. 155de4a1d01951937632098a6cda45859afa587a06fsewardj*/ 156de4a1d01951937632098a6cda45859afa587a06fsewardjvoid VG_(maybe_do_lru_pass) ( void ) 157de4a1d01951937632098a6cda45859afa587a06fsewardj{ 158de4a1d01951937632098a6cda45859afa587a06fsewardj Int i, j, r, w, thresh, ttno; 159de4a1d01951937632098a6cda45859afa587a06fsewardj TTEntry* tte; 160de4a1d01951937632098a6cda45859afa587a06fsewardj 161215e7f01dd2a1c1baa18e1ddec99697f83edd717sewardj const Int tc_limit = (Int)(((double)VG_TC_SIZE * (double)VG_TC_LIMIT_PERCENT) 162215e7f01dd2a1c1baa18e1ddec99697f83edd717sewardj / (double)100.0); 163215e7f01dd2a1c1baa18e1ddec99697f83edd717sewardj const Int tt_limit = (Int)(((double)VG_TT_SIZE * (double)VG_TT_LIMIT_PERCENT) 164215e7f01dd2a1c1baa18e1ddec99697f83edd717sewardj / (double)100.0); 165215e7f01dd2a1c1baa18e1ddec99697f83edd717sewardj const Int tc_target = (Int)(((double)VG_TC_SIZE * (double)VG_TC_TARGET_PERCENT) 166215e7f01dd2a1c1baa18e1ddec99697f83edd717sewardj / (double)100.0); 167215e7f01dd2a1c1baa18e1ddec99697f83edd717sewardj const Int tt_target = (Int)(((double)VG_TT_SIZE * (double)VG_TT_TARGET_PERCENT) 168215e7f01dd2a1c1baa18e1ddec99697f83edd717sewardj / (double)100.0); 169de4a1d01951937632098a6cda45859afa587a06fsewardj 170de4a1d01951937632098a6cda45859afa587a06fsewardj /* Decide quickly if we need to do an LRU pass ? */ 171de4a1d01951937632098a6cda45859afa587a06fsewardj if (vg_tc_used <= tc_limit && vg_tt_used <= tt_limit) 172de4a1d01951937632098a6cda45859afa587a06fsewardj return; 173de4a1d01951937632098a6cda45859afa587a06fsewardj 17418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj# ifdef DEBUG_TRANSTAB 17518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj VG_(sanity_check_tc_tt)(); 17618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj# endif 17718d7513cc08bf982711c8a22b70d56af6aa87b33sewardj 178de4a1d01951937632098a6cda45859afa587a06fsewardj VGP_PUSHCC(VgpDoLRU); 179de4a1d01951937632098a6cda45859afa587a06fsewardj /* 180de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(printf)( 181de4a1d01951937632098a6cda45859afa587a06fsewardj "limits: tc_limit %d, tt_limit %d, tc_target %d, tt_target %d\n", 182de4a1d01951937632098a6cda45859afa587a06fsewardj tc_limit, tt_limit, tc_target, tt_target); 183de4a1d01951937632098a6cda45859afa587a06fsewardj */ 184de4a1d01951937632098a6cda45859afa587a06fsewardj 185de4a1d01951937632098a6cda45859afa587a06fsewardj if (VG_(clo_verbosity) > 2) 186de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(printf)(" pre-LRU: tc %d (target %d), tt %d (target %d)\n", 187de4a1d01951937632098a6cda45859afa587a06fsewardj vg_tc_used, tc_target, vg_tt_used, tt_target); 188de4a1d01951937632098a6cda45859afa587a06fsewardj 189de4a1d01951937632098a6cda45859afa587a06fsewardj /* Yes we do. Figure out what threshold age is required in order to 190de4a1d01951937632098a6cda45859afa587a06fsewardj shrink both the TC and TT occupancy below TC_TARGET_PERCENT and 191de4a1d01951937632098a6cda45859afa587a06fsewardj TT_TARGET_PERCENT respectively. */ 192de4a1d01951937632098a6cda45859afa587a06fsewardj 193de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(number_of_lrus)++; 194de4a1d01951937632098a6cda45859afa587a06fsewardj 195de4a1d01951937632098a6cda45859afa587a06fsewardj /* Count the number of TC bytes and TT entries in each epoch. */ 196de4a1d01951937632098a6cda45859afa587a06fsewardj for (i = 0; i < VG_N_EPOCHS; i++) 197de4a1d01951937632098a6cda45859afa587a06fsewardj vg_bytes_in_epoch[i] = vg_entries_in_epoch[i] = 0; 198de4a1d01951937632098a6cda45859afa587a06fsewardj 199de4a1d01951937632098a6cda45859afa587a06fsewardj for (i = 0; i < VG_TT_SIZE; i++) { 20018d7513cc08bf982711c8a22b70d56af6aa87b33sewardj if (vg_tt[i].orig_addr == VG_TTE_EMPTY 20118d7513cc08bf982711c8a22b70d56af6aa87b33sewardj || vg_tt[i].orig_addr == VG_TTE_DELETED) 20218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj continue; 203de4a1d01951937632098a6cda45859afa587a06fsewardj j = vg_tt[i].mru_epoch; 204de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(j <= VG_(current_epoch)); 205de4a1d01951937632098a6cda45859afa587a06fsewardj j = VG_(current_epoch) - j; 206de4a1d01951937632098a6cda45859afa587a06fsewardj if (j >= VG_N_EPOCHS) j = VG_N_EPOCHS-1; 207de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(0 <= j && j < VG_N_EPOCHS); 208de4a1d01951937632098a6cda45859afa587a06fsewardj /* Greater j now means older. */ 209de4a1d01951937632098a6cda45859afa587a06fsewardj vg_entries_in_epoch[j]++; 210de4a1d01951937632098a6cda45859afa587a06fsewardj vg_bytes_in_epoch[j] += 4+vg_tt[i].trans_size; 211de4a1d01951937632098a6cda45859afa587a06fsewardj } 212de4a1d01951937632098a6cda45859afa587a06fsewardj 213de4a1d01951937632098a6cda45859afa587a06fsewardj /* 214de4a1d01951937632098a6cda45859afa587a06fsewardj for (i = 0; i < VG_N_EPOCHS; i++) 215de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(printf)("epoch %d: ents %d, bytes %d\n", 216de4a1d01951937632098a6cda45859afa587a06fsewardj i, vg_entries_in_epoch[i], vg_bytes_in_epoch[i]); 217de4a1d01951937632098a6cda45859afa587a06fsewardj */ 218de4a1d01951937632098a6cda45859afa587a06fsewardj 219de4a1d01951937632098a6cda45859afa587a06fsewardj /* Cumulatise. Make vg_{bytes,entries}_in_epoch[n] contain the 220de4a1d01951937632098a6cda45859afa587a06fsewardj counts for itself and all younger epochs. */ 221de4a1d01951937632098a6cda45859afa587a06fsewardj for (i = 1; i < VG_N_EPOCHS; i++) { 222de4a1d01951937632098a6cda45859afa587a06fsewardj vg_entries_in_epoch[i] += vg_entries_in_epoch[i-1]; 223de4a1d01951937632098a6cda45859afa587a06fsewardj vg_bytes_in_epoch[i] += vg_bytes_in_epoch[i-1]; 224de4a1d01951937632098a6cda45859afa587a06fsewardj } 225de4a1d01951937632098a6cda45859afa587a06fsewardj 226de4a1d01951937632098a6cda45859afa587a06fsewardj for (thresh = 0; thresh < VG_N_EPOCHS; thresh++) { 227de4a1d01951937632098a6cda45859afa587a06fsewardj if (vg_entries_in_epoch[thresh] > tt_target 228de4a1d01951937632098a6cda45859afa587a06fsewardj || vg_bytes_in_epoch[thresh] >= tc_target) 229de4a1d01951937632098a6cda45859afa587a06fsewardj break; 230de4a1d01951937632098a6cda45859afa587a06fsewardj } 231de4a1d01951937632098a6cda45859afa587a06fsewardj 232de4a1d01951937632098a6cda45859afa587a06fsewardj if (VG_(clo_verbosity) > 2) 233de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(printf)( 234de4a1d01951937632098a6cda45859afa587a06fsewardj " LRU: discard translations %d or more epochs since last use\n", 235de4a1d01951937632098a6cda45859afa587a06fsewardj thresh 236de4a1d01951937632098a6cda45859afa587a06fsewardj ); 237de4a1d01951937632098a6cda45859afa587a06fsewardj 238de4a1d01951937632098a6cda45859afa587a06fsewardj thresh = VG_(current_epoch) - thresh; 239de4a1d01951937632098a6cda45859afa587a06fsewardj 240de4a1d01951937632098a6cda45859afa587a06fsewardj /* Ok, so we will hit our targets if we retain all entries most 241de4a1d01951937632098a6cda45859afa587a06fsewardj recently used at most thresh epochs ago. Traverse the TT and 242de4a1d01951937632098a6cda45859afa587a06fsewardj mark such entries as deleted. */ 243de4a1d01951937632098a6cda45859afa587a06fsewardj for (i = 0; i < VG_TT_SIZE; i++) { 24418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj if (vg_tt[i].orig_addr == VG_TTE_EMPTY 24518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj || vg_tt[i].orig_addr == VG_TTE_DELETED) 24618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj continue; 247de4a1d01951937632098a6cda45859afa587a06fsewardj if (vg_tt[i].mru_epoch <= thresh) { 248de4a1d01951937632098a6cda45859afa587a06fsewardj vg_tt[i].orig_addr = VG_TTE_DELETED; 249de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(this_epoch_out_count) ++; 250de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(this_epoch_out_osize) += vg_tt[i].orig_size; 251de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(this_epoch_out_tsize) += vg_tt[i].trans_size; 252de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(overall_out_count) ++; 253de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(overall_out_osize) += vg_tt[i].orig_size; 254de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(overall_out_tsize) += vg_tt[i].trans_size; 255de4a1d01951937632098a6cda45859afa587a06fsewardj } 256de4a1d01951937632098a6cda45859afa587a06fsewardj } 257de4a1d01951937632098a6cda45859afa587a06fsewardj 258de4a1d01951937632098a6cda45859afa587a06fsewardj /* Now compact the TC, sliding live entries downwards to fill spaces 259de4a1d01951937632098a6cda45859afa587a06fsewardj left by deleted entries. In this loop, r is the offset in TC of 260de4a1d01951937632098a6cda45859afa587a06fsewardj the current translation under consideration, and w is the next 261de4a1d01951937632098a6cda45859afa587a06fsewardj allocation point. */ 262de4a1d01951937632098a6cda45859afa587a06fsewardj r = w = 0; 263de4a1d01951937632098a6cda45859afa587a06fsewardj while (True) { 264de4a1d01951937632098a6cda45859afa587a06fsewardj if (r >= vg_tc_used) break; 265de4a1d01951937632098a6cda45859afa587a06fsewardj /* The first four bytes of every translation contain the index 266de4a1d01951937632098a6cda45859afa587a06fsewardj of its TT entry. The TT entry's .trans_addr field points at 267de4a1d01951937632098a6cda45859afa587a06fsewardj the start of the code proper, not at this 4-byte index, so 268de4a1d01951937632098a6cda45859afa587a06fsewardj that we don't constantly have to keep adding 4 in the main 269de4a1d01951937632098a6cda45859afa587a06fsewardj lookup/dispatch loop. */ 2708aef1191a25d33b1173c2f05a27df7606f3ef535sewardj 2718aef1191a25d33b1173c2f05a27df7606f3ef535sewardj ttno = VG_READ_MISALIGNED_WORD((Addr)(&vg_tc[r])); 272de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(ttno >= 0 && ttno < VG_TT_SIZE); 273de4a1d01951937632098a6cda45859afa587a06fsewardj tte = & vg_tt[ ttno ]; 274de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(tte->orig_addr != VG_TTE_EMPTY); 275de4a1d01951937632098a6cda45859afa587a06fsewardj if (tte->orig_addr != VG_TTE_DELETED) { 276de4a1d01951937632098a6cda45859afa587a06fsewardj /* We want to keep this one alive. */ 277de4a1d01951937632098a6cda45859afa587a06fsewardj /* Sanity check the pointer back to TC. */ 278de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(tte->trans_addr == (Addr)&vg_tc[r+4]); 279de4a1d01951937632098a6cda45859afa587a06fsewardj for (i = 0; i < 4+tte->trans_size; i++) 280de4a1d01951937632098a6cda45859afa587a06fsewardj vg_tc[w+i] = vg_tc[r+i]; 281de4a1d01951937632098a6cda45859afa587a06fsewardj tte->trans_addr = (Addr)&vg_tc[w+4]; 282de4a1d01951937632098a6cda45859afa587a06fsewardj w += 4+tte->trans_size; 28318d7513cc08bf982711c8a22b70d56af6aa87b33sewardj } else { 28418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj tte->orig_addr = VG_TTE_EMPTY; 28518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj vg_tt_used--; 286de4a1d01951937632098a6cda45859afa587a06fsewardj } 287de4a1d01951937632098a6cda45859afa587a06fsewardj r += 4+tte->trans_size; 288de4a1d01951937632098a6cda45859afa587a06fsewardj } 289de4a1d01951937632098a6cda45859afa587a06fsewardj /* should have traversed an exact number of translations, with no 290de4a1d01951937632098a6cda45859afa587a06fsewardj slop at the end. */ 291de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(w <= r); 292de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(r == vg_tc_used); 293de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(w <= r); 294de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(w <= tc_target); 295de4a1d01951937632098a6cda45859afa587a06fsewardj vg_tc_used = w; 296de4a1d01951937632098a6cda45859afa587a06fsewardj 29718d7513cc08bf982711c8a22b70d56af6aa87b33sewardj vg_assert(vg_tt_used >= 0); 29818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj vg_assert(vg_tt_used <= tt_target); 29918d7513cc08bf982711c8a22b70d56af6aa87b33sewardj 300de4a1d01951937632098a6cda45859afa587a06fsewardj /* Invalidate the fast cache, since it is now out of date. It will get 301de4a1d01951937632098a6cda45859afa587a06fsewardj reconstructed incrementally when the client resumes. */ 302de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(invalidate_tt_fast)(); 303de4a1d01951937632098a6cda45859afa587a06fsewardj 304de4a1d01951937632098a6cda45859afa587a06fsewardj if (VG_(clo_verbosity) > 2) 305de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(printf)("post-LRU: tc %d (target %d), tt %d (target %d)\n", 306de4a1d01951937632098a6cda45859afa587a06fsewardj vg_tc_used, tc_target, vg_tt_used, tt_target); 307de4a1d01951937632098a6cda45859afa587a06fsewardj 308de4a1d01951937632098a6cda45859afa587a06fsewardj if (VG_(clo_verbosity) > 1) 309de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(message)(Vg_UserMsg, 310de4a1d01951937632098a6cda45859afa587a06fsewardj "epoch %d (bb %luk): thresh %d, " 311de4a1d01951937632098a6cda45859afa587a06fsewardj "out %d (%dk -> %dk), new TT %d, TC %dk", 312de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(current_epoch), 313de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(bbs_done) / 1000, 314de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(current_epoch) - thresh, 315de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(this_epoch_out_count), 316de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(this_epoch_out_osize) / 1000, 317de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(this_epoch_out_tsize) / 1000, 318de4a1d01951937632098a6cda45859afa587a06fsewardj vg_tt_used, vg_tc_used / 1000 319de4a1d01951937632098a6cda45859afa587a06fsewardj ); 320de4a1d01951937632098a6cda45859afa587a06fsewardj 32118d7513cc08bf982711c8a22b70d56af6aa87b33sewardj# ifdef DEBUG_TRANSTAB 32218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj for (i = 0; i < VG_TT_SIZE; i++) 32318d7513cc08bf982711c8a22b70d56af6aa87b33sewardj vg_assert(vg_tt[i].orig_addr != VG_TTE_DELETED); 32418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj# endif 32518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj VG_(sanity_check_tc_tt)(); 326de4a1d01951937632098a6cda45859afa587a06fsewardj 327e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn VGP_POPCC(VgpDoLRU); 328de4a1d01951937632098a6cda45859afa587a06fsewardj} 329de4a1d01951937632098a6cda45859afa587a06fsewardj 330de4a1d01951937632098a6cda45859afa587a06fsewardj 331de4a1d01951937632098a6cda45859afa587a06fsewardj/* Do a sanity check on TT/TC. 332de4a1d01951937632098a6cda45859afa587a06fsewardj*/ 333de4a1d01951937632098a6cda45859afa587a06fsewardjvoid VG_(sanity_check_tc_tt) ( void ) 334de4a1d01951937632098a6cda45859afa587a06fsewardj{ 335de4a1d01951937632098a6cda45859afa587a06fsewardj Int i, counted_entries, counted_bytes; 336de4a1d01951937632098a6cda45859afa587a06fsewardj TTEntry* tte; 337de4a1d01951937632098a6cda45859afa587a06fsewardj counted_entries = 0; 338de4a1d01951937632098a6cda45859afa587a06fsewardj counted_bytes = 0; 339de4a1d01951937632098a6cda45859afa587a06fsewardj for (i = 0; i < VG_TT_SIZE; i++) { 340de4a1d01951937632098a6cda45859afa587a06fsewardj tte = &vg_tt[i]; 341de4a1d01951937632098a6cda45859afa587a06fsewardj if (tte->orig_addr == VG_TTE_EMPTY) continue; 342de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(tte->mru_epoch >= 0); 343de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(tte->mru_epoch <= VG_(current_epoch)); 344de4a1d01951937632098a6cda45859afa587a06fsewardj counted_entries++; 345de4a1d01951937632098a6cda45859afa587a06fsewardj counted_bytes += 4+tte->trans_size; 346de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(tte->trans_addr >= (Addr)&vg_tc[4]); 347de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(tte->trans_addr < (Addr)&vg_tc[vg_tc_used]); 348de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(VG_READ_MISALIGNED_WORD(tte->trans_addr-4) == i); 349de4a1d01951937632098a6cda45859afa587a06fsewardj } 350de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(counted_entries == vg_tt_used); 351de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(counted_bytes == vg_tc_used); 352de4a1d01951937632098a6cda45859afa587a06fsewardj} 353de4a1d01951937632098a6cda45859afa587a06fsewardj 354de4a1d01951937632098a6cda45859afa587a06fsewardj 355de4a1d01951937632098a6cda45859afa587a06fsewardj/* Add this already-filled-in entry to the TT. Assumes that the 356de4a1d01951937632098a6cda45859afa587a06fsewardj relevant code chunk has been placed in TC, along with a dummy back 357de4a1d01951937632098a6cda45859afa587a06fsewardj pointer, which is inserted here. 358de4a1d01951937632098a6cda45859afa587a06fsewardj*/ 359de4a1d01951937632098a6cda45859afa587a06fsewardjextern void VG_(add_to_trans_tab) ( TTEntry* tte ) 360de4a1d01951937632098a6cda45859afa587a06fsewardj{ 361de4a1d01951937632098a6cda45859afa587a06fsewardj Int i; 362de4a1d01951937632098a6cda45859afa587a06fsewardj /* 363de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(printf)("add_to_trans_tab(%d) %x %d %x %d\n", 364de4a1d01951937632098a6cda45859afa587a06fsewardj vg_tt_used, tte->orig_addr, tte->orig_size, 365de4a1d01951937632098a6cda45859afa587a06fsewardj tte->trans_addr, tte->trans_size); 366de4a1d01951937632098a6cda45859afa587a06fsewardj */ 367de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(tte->orig_addr != VG_TTE_DELETED 368de4a1d01951937632098a6cda45859afa587a06fsewardj && tte->orig_addr != VG_TTE_EMPTY); 369de4a1d01951937632098a6cda45859afa587a06fsewardj /* Hash to get initial probe point. */ 370de4a1d01951937632098a6cda45859afa587a06fsewardj i = ((UInt)(tte->orig_addr)) % VG_TT_SIZE; 371de4a1d01951937632098a6cda45859afa587a06fsewardj while (True) { 372de4a1d01951937632098a6cda45859afa587a06fsewardj if (vg_tt[i].orig_addr == tte->orig_addr) 373de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(panic)("add_to_trans_tab: duplicate"); 37418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj if (vg_tt[i].orig_addr == VG_TTE_EMPTY) { 375de4a1d01951937632098a6cda45859afa587a06fsewardj /* Put it here, and set the back pointer. */ 376de4a1d01951937632098a6cda45859afa587a06fsewardj vg_tt[i] = *tte; 377de4a1d01951937632098a6cda45859afa587a06fsewardj VG_WRITE_MISALIGNED_WORD(tte->trans_addr-4, i); 378de4a1d01951937632098a6cda45859afa587a06fsewardj vg_tt_used++; 379de4a1d01951937632098a6cda45859afa587a06fsewardj return; 380de4a1d01951937632098a6cda45859afa587a06fsewardj } 381de4a1d01951937632098a6cda45859afa587a06fsewardj i++; 382de4a1d01951937632098a6cda45859afa587a06fsewardj if (i == VG_TT_SIZE) i = 0; 383de4a1d01951937632098a6cda45859afa587a06fsewardj } 384de4a1d01951937632098a6cda45859afa587a06fsewardj} 385de4a1d01951937632098a6cda45859afa587a06fsewardj 386de4a1d01951937632098a6cda45859afa587a06fsewardj 387de4a1d01951937632098a6cda45859afa587a06fsewardj/* Copy a new translation's code into TC, leaving a 4-byte hole for 388de4a1d01951937632098a6cda45859afa587a06fsewardj the back pointer, and returning a pointer to the code proper (not 389de4a1d01951937632098a6cda45859afa587a06fsewardj the hole) in TC. 390de4a1d01951937632098a6cda45859afa587a06fsewardj*/ 391de4a1d01951937632098a6cda45859afa587a06fsewardjAddr VG_(copy_to_transcache) ( Addr trans_addr, Int trans_size ) 392de4a1d01951937632098a6cda45859afa587a06fsewardj{ 393de4a1d01951937632098a6cda45859afa587a06fsewardj Int i; 394de4a1d01951937632098a6cda45859afa587a06fsewardj Addr ret_addr; 395de4a1d01951937632098a6cda45859afa587a06fsewardj if (4+trans_size > VG_TC_SIZE-vg_tc_used) 396de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(panic)("copy_to_transcache: not enough free space?!"); 397de4a1d01951937632098a6cda45859afa587a06fsewardj /* Leave a hole for the back pointer to the TT entry. */ 398de4a1d01951937632098a6cda45859afa587a06fsewardj vg_tc_used += 4; 399de4a1d01951937632098a6cda45859afa587a06fsewardj ret_addr = (Addr)&vg_tc[vg_tc_used]; 400de4a1d01951937632098a6cda45859afa587a06fsewardj for (i = 0; i < trans_size; i++) 401de4a1d01951937632098a6cda45859afa587a06fsewardj vg_tc[vg_tc_used+i] = ((UChar*)trans_addr)[i]; 402de4a1d01951937632098a6cda45859afa587a06fsewardj vg_tc_used += trans_size; 403de4a1d01951937632098a6cda45859afa587a06fsewardj return ret_addr; 404de4a1d01951937632098a6cda45859afa587a06fsewardj} 405de4a1d01951937632098a6cda45859afa587a06fsewardj 406de4a1d01951937632098a6cda45859afa587a06fsewardj 407de4a1d01951937632098a6cda45859afa587a06fsewardj/* Invalidate the tt_fast cache, for whatever reason. Tricky. We 408de4a1d01951937632098a6cda45859afa587a06fsewardj have to find a TTE_EMPTY slot to point all entries at. */ 409de4a1d01951937632098a6cda45859afa587a06fsewardjvoid VG_(invalidate_tt_fast)( void ) 410de4a1d01951937632098a6cda45859afa587a06fsewardj{ 411de4a1d01951937632098a6cda45859afa587a06fsewardj Int i, j; 412de4a1d01951937632098a6cda45859afa587a06fsewardj for (i = 0; i < VG_TT_SIZE && vg_tt[i].orig_addr != VG_TTE_EMPTY; i++) 413de4a1d01951937632098a6cda45859afa587a06fsewardj ; 414de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(i < VG_TT_SIZE 415de4a1d01951937632098a6cda45859afa587a06fsewardj && vg_tt[i].orig_addr == VG_TTE_EMPTY); 416de4a1d01951937632098a6cda45859afa587a06fsewardj for (j = 0; j < VG_TT_FAST_SIZE; j++) 417de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(tt_fast)[j] = (Addr)&vg_tt[i]; 418de4a1d01951937632098a6cda45859afa587a06fsewardj} 419de4a1d01951937632098a6cda45859afa587a06fsewardj 420de4a1d01951937632098a6cda45859afa587a06fsewardj 421de4a1d01951937632098a6cda45859afa587a06fsewardj/* Search TT to find the translated address of the supplied original, 422de4a1d01951937632098a6cda45859afa587a06fsewardj or NULL if not found. This routine is used when we miss in 423de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(tt_fast). 424de4a1d01951937632098a6cda45859afa587a06fsewardj*/ 425de4a1d01951937632098a6cda45859afa587a06fsewardjstatic __inline__ TTEntry* search_trans_table ( Addr orig_addr ) 426de4a1d01951937632098a6cda45859afa587a06fsewardj{ 42718d7513cc08bf982711c8a22b70d56af6aa87b33sewardj //static Int queries = 0; 42818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj //static Int probes = 0; 429de4a1d01951937632098a6cda45859afa587a06fsewardj Int i; 430de4a1d01951937632098a6cda45859afa587a06fsewardj /* Hash to get initial probe point. */ 431de4a1d01951937632098a6cda45859afa587a06fsewardj // if (queries == 10000) { 432de4a1d01951937632098a6cda45859afa587a06fsewardj // VG_(printf)("%d queries, %d probes\n", queries, probes); 433de4a1d01951937632098a6cda45859afa587a06fsewardj // queries = probes = 0; 434de4a1d01951937632098a6cda45859afa587a06fsewardj //} 435de4a1d01951937632098a6cda45859afa587a06fsewardj //queries++; 436de4a1d01951937632098a6cda45859afa587a06fsewardj i = ((UInt)orig_addr) % VG_TT_SIZE; 437de4a1d01951937632098a6cda45859afa587a06fsewardj while (True) { 43818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj //probes++; 439de4a1d01951937632098a6cda45859afa587a06fsewardj if (vg_tt[i].orig_addr == orig_addr) 440de4a1d01951937632098a6cda45859afa587a06fsewardj return &vg_tt[i]; 441de4a1d01951937632098a6cda45859afa587a06fsewardj if (vg_tt[i].orig_addr == VG_TTE_EMPTY) 442de4a1d01951937632098a6cda45859afa587a06fsewardj return NULL; 443de4a1d01951937632098a6cda45859afa587a06fsewardj i++; 444de4a1d01951937632098a6cda45859afa587a06fsewardj if (i == VG_TT_SIZE) i = 0; 445de4a1d01951937632098a6cda45859afa587a06fsewardj } 446de4a1d01951937632098a6cda45859afa587a06fsewardj} 447de4a1d01951937632098a6cda45859afa587a06fsewardj 448de4a1d01951937632098a6cda45859afa587a06fsewardj 449de4a1d01951937632098a6cda45859afa587a06fsewardj/* Find the translation address for a given (original) code address. 450de4a1d01951937632098a6cda45859afa587a06fsewardj If found, update VG_(tt_fast) so subsequent lookups are fast. If 451de4a1d01951937632098a6cda45859afa587a06fsewardj no translation can be found, return zero. This routine is (the 452de4a1d01951937632098a6cda45859afa587a06fsewardj only one) called from vg_run_innerloop. */ 453de4a1d01951937632098a6cda45859afa587a06fsewardjAddr VG_(search_transtab) ( Addr original_addr ) 454de4a1d01951937632098a6cda45859afa587a06fsewardj{ 455de4a1d01951937632098a6cda45859afa587a06fsewardj TTEntry* tte; 456de4a1d01951937632098a6cda45859afa587a06fsewardj VGP_PUSHCC(VgpSlowFindT); 457de4a1d01951937632098a6cda45859afa587a06fsewardj tte = search_trans_table ( original_addr ); 458de4a1d01951937632098a6cda45859afa587a06fsewardj if (tte == NULL) { 459de4a1d01951937632098a6cda45859afa587a06fsewardj /* We didn't find it. vg_run_innerloop will have to request a 460de4a1d01951937632098a6cda45859afa587a06fsewardj translation. */ 461e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn VGP_POPCC(VgpSlowFindT); 462de4a1d01951937632098a6cda45859afa587a06fsewardj return (Addr)0; 463de4a1d01951937632098a6cda45859afa587a06fsewardj } else { 464de4a1d01951937632098a6cda45859afa587a06fsewardj /* Found it. Put the search result into the fast cache now. 465de4a1d01951937632098a6cda45859afa587a06fsewardj Also set the mru_epoch to mark this translation as used. */ 466de4a1d01951937632098a6cda45859afa587a06fsewardj UInt cno = (UInt)original_addr & VG_TT_FAST_MASK; 467de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(tt_fast)[cno] = (Addr)tte; 468de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(tt_fast_misses)++; 469de4a1d01951937632098a6cda45859afa587a06fsewardj tte->mru_epoch = VG_(current_epoch); 470e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn VGP_POPCC(VgpSlowFindT); 471de4a1d01951937632098a6cda45859afa587a06fsewardj return tte->trans_addr; 472de4a1d01951937632098a6cda45859afa587a06fsewardj } 473de4a1d01951937632098a6cda45859afa587a06fsewardj} 474de4a1d01951937632098a6cda45859afa587a06fsewardj 475de4a1d01951937632098a6cda45859afa587a06fsewardj 47618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj/* Invalidate translations of original code [start .. start + range - 1]. 47718d7513cc08bf982711c8a22b70d56af6aa87b33sewardj This is slow, so you *really* don't want to call it very often. 478de4a1d01951937632098a6cda45859afa587a06fsewardj*/ 47918d7513cc08bf982711c8a22b70d56af6aa87b33sewardjvoid VG_(invalidate_translations) ( Addr start, UInt range ) 480de4a1d01951937632098a6cda45859afa587a06fsewardj{ 48118d7513cc08bf982711c8a22b70d56af6aa87b33sewardj Addr i_start, i_end, o_start, o_end; 48218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj UInt out_count, out_osize, out_tsize; 48318d7513cc08bf982711c8a22b70d56af6aa87b33sewardj Int i; 484de4a1d01951937632098a6cda45859afa587a06fsewardj 48518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj# ifdef DEBUG_TRANSTAB 48618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj VG_(sanity_check_tc_tt)(); 487de4a1d01951937632098a6cda45859afa587a06fsewardj# endif 48818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj i_start = start; 48918d7513cc08bf982711c8a22b70d56af6aa87b33sewardj i_end = start + range - 1; 49018d7513cc08bf982711c8a22b70d56af6aa87b33sewardj out_count = out_osize = out_tsize = 0; 491de4a1d01951937632098a6cda45859afa587a06fsewardj 49218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj for (i = 0; i < VG_TT_SIZE; i++) { 49318d7513cc08bf982711c8a22b70d56af6aa87b33sewardj if (vg_tt[i].orig_addr == VG_TTE_EMPTY 49418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj || vg_tt[i].orig_addr == VG_TTE_DELETED) continue; 49518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj o_start = vg_tt[i].orig_addr; 49618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj o_end = o_start + vg_tt[i].orig_size - 1; 49718d7513cc08bf982711c8a22b70d56af6aa87b33sewardj if (o_end < i_start || o_start > i_end) 49818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj continue; 499e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn 500e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn if (VG_(needs).basic_block_discards) 501e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn SK_(discard_basic_block_info)( vg_tt[i].orig_addr, 502e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn vg_tt[i].orig_size ); 503e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn 50418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj vg_tt[i].orig_addr = VG_TTE_DELETED; 50518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj VG_(this_epoch_out_count) ++; 50618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj VG_(this_epoch_out_osize) += vg_tt[i].orig_size; 50718d7513cc08bf982711c8a22b70d56af6aa87b33sewardj VG_(this_epoch_out_tsize) += vg_tt[i].trans_size; 50818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj VG_(overall_out_count) ++; 50918d7513cc08bf982711c8a22b70d56af6aa87b33sewardj VG_(overall_out_osize) += vg_tt[i].orig_size; 51018d7513cc08bf982711c8a22b70d56af6aa87b33sewardj VG_(overall_out_tsize) += vg_tt[i].trans_size; 51118d7513cc08bf982711c8a22b70d56af6aa87b33sewardj out_count ++; 51218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj out_osize += vg_tt[i].orig_size; 51318d7513cc08bf982711c8a22b70d56af6aa87b33sewardj out_tsize += vg_tt[i].trans_size; 514de4a1d01951937632098a6cda45859afa587a06fsewardj } 515de4a1d01951937632098a6cda45859afa587a06fsewardj 51618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj if (out_count > 0) { 51718d7513cc08bf982711c8a22b70d56af6aa87b33sewardj VG_(invalidate_tt_fast)(); 51818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj VG_(sanity_check_tc_tt)(); 51918d7513cc08bf982711c8a22b70d56af6aa87b33sewardj# ifdef DEBUG_TRANSTAB 52018d7513cc08bf982711c8a22b70d56af6aa87b33sewardj { Addr aa; 52118d7513cc08bf982711c8a22b70d56af6aa87b33sewardj for (aa = i_start; aa <= i_end; aa++) 52218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj vg_assert(search_trans_table ( aa ) == NULL); 523de4a1d01951937632098a6cda45859afa587a06fsewardj } 52418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj# endif 525de4a1d01951937632098a6cda45859afa587a06fsewardj } 526de4a1d01951937632098a6cda45859afa587a06fsewardj 52718d7513cc08bf982711c8a22b70d56af6aa87b33sewardj if (1|| VG_(clo_verbosity) > 1) 52818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj VG_(message)(Vg_UserMsg, 52918d7513cc08bf982711c8a22b70d56af6aa87b33sewardj "discard %d (%d -> %d) translations in range %p .. %p", 53018d7513cc08bf982711c8a22b70d56af6aa87b33sewardj out_count, out_osize, out_tsize, i_start, i_end ); 531de4a1d01951937632098a6cda45859afa587a06fsewardj} 532de4a1d01951937632098a6cda45859afa587a06fsewardj 533de4a1d01951937632098a6cda45859afa587a06fsewardj 534de4a1d01951937632098a6cda45859afa587a06fsewardj/*------------------------------------------------------------*/ 535de4a1d01951937632098a6cda45859afa587a06fsewardj/*--- Initialisation. ---*/ 536de4a1d01951937632098a6cda45859afa587a06fsewardj/*------------------------------------------------------------*/ 537de4a1d01951937632098a6cda45859afa587a06fsewardj 53818d7513cc08bf982711c8a22b70d56af6aa87b33sewardjvoid VG_(init_tt_tc) ( void ) 539de4a1d01951937632098a6cda45859afa587a06fsewardj{ 540de4a1d01951937632098a6cda45859afa587a06fsewardj Int i; 541de4a1d01951937632098a6cda45859afa587a06fsewardj 542de4a1d01951937632098a6cda45859afa587a06fsewardj /* Allocate the translation table and translation cache. */ 543de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(vg_tc == NULL); 544e90479594359d19ca51884c7936073dd7bd7d9c6sewardj vg_tc = VG_(get_memory_from_mmap) ( VG_TC_SIZE * sizeof(UChar), 545e90479594359d19ca51884c7936073dd7bd7d9c6sewardj "trans-cache" ); 546de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(vg_tc != NULL); 547de4a1d01951937632098a6cda45859afa587a06fsewardj 548de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(vg_tt == NULL); 549e90479594359d19ca51884c7936073dd7bd7d9c6sewardj vg_tt = VG_(get_memory_from_mmap) ( VG_TT_SIZE * sizeof(TTEntry), 550e90479594359d19ca51884c7936073dd7bd7d9c6sewardj "trans-table" ); 551de4a1d01951937632098a6cda45859afa587a06fsewardj vg_assert(vg_tt != NULL); 552de4a1d01951937632098a6cda45859afa587a06fsewardj 553de4a1d01951937632098a6cda45859afa587a06fsewardj /* The main translation table is empty. */ 554de4a1d01951937632098a6cda45859afa587a06fsewardj vg_tt_used = 0; 555de4a1d01951937632098a6cda45859afa587a06fsewardj for (i = 0; i < VG_TT_SIZE; i++) { 556de4a1d01951937632098a6cda45859afa587a06fsewardj vg_tt[i].orig_addr = VG_TTE_EMPTY; 557de4a1d01951937632098a6cda45859afa587a06fsewardj } 558de4a1d01951937632098a6cda45859afa587a06fsewardj 559de4a1d01951937632098a6cda45859afa587a06fsewardj /* The translation table's fast cache is empty. Point all entries 560de4a1d01951937632098a6cda45859afa587a06fsewardj at the first TT entry, which is, of course, empty. */ 561de4a1d01951937632098a6cda45859afa587a06fsewardj for (i = 0; i < VG_TT_FAST_SIZE; i++) 562de4a1d01951937632098a6cda45859afa587a06fsewardj VG_(tt_fast)[i] = (Addr)(&vg_tt[0]); 563de4a1d01951937632098a6cda45859afa587a06fsewardj} 564de4a1d01951937632098a6cda45859afa587a06fsewardj 565de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/ 566de4a1d01951937632098a6cda45859afa587a06fsewardj/*--- end vg_transtab.c ---*/ 567de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/ 568