}
OCache;
-static OCache ocache;
-static UWord ocache_event_ctr = 0;
+static OCache* ocache = NULL;
+static UWord ocache_event_ctr = 0;
static void init_ocacheL2 ( void ); /* fwds */
static void init_OCache ( void )
{
UWord line, set;
+ tl_assert(MC_(clo_mc_level) >= 3);
+ tl_assert(ocache == NULL);
+ ocache = VG_(am_shadow_alloc)(sizeof(OCache));
+ if (ocache == NULL) {
+ VG_(out_of_memory_NORETURN)( "memcheck:allocate the OCache",
+ sizeof(OCache) );
+ }
+ tl_assert(ocache != NULL);
for (set = 0; set < OC_N_SETS; set++) {
for (line = 0; line < OC_LINES_PER_SET; line++) {
- ocache.set[set].line[line].tag = 1/*invalid*/;
+ ocache->set[set].line[line].tag = 1/*invalid*/;
}
}
init_ocacheL2();
/* we already tried line == 0; skip therefore. */
for (line = 1; line < OC_LINES_PER_SET; line++) {
- if (ocache.set[setno].line[line].tag == tag) {
+ if (ocache->set[setno].line[line].tag == tag) {
if (line == 1) {
stats_ocacheL1_found_at_1++;
} else {
}
if (UNLIKELY(0 == (ocache_event_ctr++
& ((1<<OC_MOVE_FORWARDS_EVERY_BITS)-1)))) {
- moveLineForwards( &ocache.set[setno], line );
+ moveLineForwards( &ocache->set[setno], line );
line--;
}
- return &ocache.set[setno].line[line];
+ return &ocache->set[setno].line[line];
}
}
tl_assert(line > 0);
/* First, move the to-be-ejected line to the L2 cache. */
- victim = &ocache.set[setno].line[line];
+ victim = &ocache->set[setno].line[line];
c = classify_OCacheLine(victim);
switch (c) {
case 'e':
inL2 = ocacheL2_find_tag( tag );
if (inL2) {
/* We're in luck. It's in the L2. */
- ocache.set[setno].line[line] = *inL2;
+ ocache->set[setno].line[line] = *inL2;
} else {
/* Missed at both levels of the cache hierarchy. We have to
declare it as full of zeroes (unknown origins). */
stats__ocacheL2_misses++;
- zeroise_OCacheLine( &ocache.set[setno].line[line], tag );
+ zeroise_OCacheLine( &ocache->set[setno].line[line], tag );
}
/* Move it one forwards */
- moveLineForwards( &ocache.set[setno], line );
+ moveLineForwards( &ocache->set[setno], line );
line--;
- return &ocache.set[setno].line[line];
+ return &ocache->set[setno].line[line];
}
static INLINE OCacheLine* find_OCacheLine ( Addr a )
tl_assert(0 == (tag & (4 * OC_W32S_PER_LINE - 1)));
}
- if (LIKELY(ocache.set[setno].line[0].tag == tag)) {
- return &ocache.set[setno].line[0];
+ if (LIKELY(ocache->set[setno].line[0].tag == tag)) {
+ return &ocache->set[setno].line[0];
}
return find_OCacheLine_SLOW( a );
# endif
VG_(track_new_mem_stack) ( mc_new_mem_stack );
}
+
+ /* This origin tracking cache is huge (~100M), so only initialise
+ if we need it. */
+ if (MC_(clo_mc_level) >= 3) {
+ init_OCache();
+ tl_assert(ocache != NULL);
+ tl_assert(ocacheL2 != NULL);
+ } else {
+ tl_assert(ocache == NULL);
+ tl_assert(ocacheL2 == NULL);
+ }
}
static void print_SM_info(char* type, int n_SMs)
VG_(message)(Vg_DebugMsg,
" niacache: %,12lu refs %,12lu misses",
stats__nia_cache_queries, stats__nia_cache_misses);
+ } else {
+ tl_assert(ocache == NULL);
+ tl_assert(ocacheL2 == NULL);
}
}
// BYTES_PER_SEC_VBIT_NODE must be a power of two.
tl_assert(-1 != VG_(log2)(BYTES_PER_SEC_VBIT_NODE));
- init_OCache();
+ /* This is small. Always initialise it. */
init_nia_to_ecu_cache();
+ /* We can't initialise ocache/ocacheL2 yet, since we don't know if
+ we need to, since the command line args haven't been processed
+ yet. Hence defer it to mc_post_clo_init. */
+ tl_assert(ocache == NULL);
+ tl_assert(ocacheL2 == NULL);
+
/* Check some important stuff. See extensive comments above
re UNALIGNED_OR_HIGH for background. */
# if VG_WORDSIZE == 4