Value ValueMap::find_insert(Value x) { const intx hash = x->hash(); if (hash != 0) { // 0 hash means: exclude from value numbering NOT_PRODUCT(_number_of_finds++); for (ValueMapEntry* entry = entry_at(entry_index(hash, size())); entry != NULL; entry = entry->next()) { if (entry->hash() == hash) { Value f = entry->value(); if (!is_killed(f) && f->is_equal(x)) { NOT_PRODUCT(_number_of_hits++); TRACE_VALUE_NUMBERING(tty->print_cr("Value Numbering: %s %c%d equal to %c%d (size %d, entries %d, nesting-diff %d)", x->name(), x->type()->tchar(), x->id(), f->type()->tchar(), f->id(), size(), entry_count(), nesting() - entry->nesting())); if (entry->nesting() != nesting() && f->as_Constant() == NULL) { // non-constant values of of another block must be pinned, // otherwise it is possible that they are not evaluated f->pin(Instruction::PinGlobalValueNumbering); } assert(x->type()->tag() == f->type()->tag(), "should have same type"); return f; } } } // x not found, so insert it if (entry_count() >= size_threshold()) { increase_table_size(); } int idx = entry_index(hash, size()); _entries.at_put(idx, new ValueMapEntry(hash, x, nesting(), entry_at(idx))); _entry_count++; TRACE_VALUE_NUMBERING(tty->print_cr("Value Numbering: insert %s %c%d (size %d, entries %d, nesting %d)", x->name(), x->type()->tchar(), x->id(), size(), entry_count(), nesting())); } return x; }
//***************************************************************************** // //***************************************************************************** void CPU_HandleDynaRecOnBranch( bool backwards, bool trace_already_enabled ) { DAEDALUS_PROFILE( "CPU_HandleDynaRecOnBranch" ); bool start_of_trace( false ); if( backwards ) { start_of_trace = true; } bool change_core( false ); DAED_LOG( DEBUG_DYNAREC_CACHE, "CPU_HandleDynaRecOnBranch" ); while( gCPUState.GetStuffToDo() == 0 && gCPUState.Delay == NO_DELAY ) { DAEDALUS_ASSERT( gCPUState.Delay == NO_DELAY, "Why are we entering with a delay slot active?" ); #ifdef DAEDALUS_ENABLE_DYNAREC_PROFILE u32 entry_count( gCPUState.CPUControl[C0_COUNT]._u32 ); // Just used DYNAREC_PROFILE_ENTEREXIT #endif u32 entry_address( gCPUState.CurrentPC ); #ifdef DAEDALUS_DEBUG_DYNAREC CFragment * p_fragment( gFragmentCache.LookupFragment( entry_address ) ); #else CFragment * p_fragment( gFragmentCache.LookupFragmentQ( entry_address ) ); #endif if( p_fragment != NULL ) { #ifdef DAEDALUS_PROFILE_EXECUTION gFragmentLookupSuccess++; #endif // Check if another trace is active and we're about to enter if( gTraceRecorder.IsTraceActive() ) { gTraceRecorder.StopTrace( gCPUState.CurrentPC ); CPU_CreateAndAddFragment(); // We need to change the core when exiting change_core = true; } p_fragment->Execute(); DYNAREC_PROFILE_ENTEREXIT( entry_address, gCPUState.CurrentPC, gCPUState.CPUControl[C0_COUNT]._u32 - entry_count ); start_of_trace = true; } else { #ifdef DAEDALUS_PROFILE_EXECUTION gFragmentLookupFailure++; #endif if( start_of_trace ) { start_of_trace = false; if( !gTraceRecorder.IsTraceActive() ) { if (gResetFragmentCache) { #ifdef DAEDALUS_ENABLE_OS_HOOKS //Don't reset the cache if there is no fragment except OSHLE function stubs if (gFragmentCache.GetCacheSize() >= gNumOfOSFunctions) #else if(true) #endif { gFragmentCache.Clear(); gHotTraceCountMap.clear(); // Makes sense to clear this now, to get accurate usage stats #ifdef DAEDALUS_ENABLE_OS_HOOKS Patch_PatchAll(); #endif } #ifdef DAEDALUS_DEBUG_CONSOLE else { DBGConsole_Msg(0, "Safely skipped one flush"); } #endif gResetFragmentCache = false; } if( gFragmentCache.GetCacheSize() > gMaxFragmentCacheSize) { gFragmentCache.Clear(); gHotTraceCountMap.clear(); // Makes sense to clear this now, to get accurate usage stats #ifdef DAEDALUS_ENABLE_OS_HOOKS Patch_PatchAll(); #endif } // If there is no fragment for this target, start tracing u32 trace_count( ++gHotTraceCountMap[ gCPUState.CurrentPC ] ); if( gHotTraceCountMap.size() >= gMaxHotTraceMapSize ) { DBGConsole_Msg( 0, "Hot trace cache hit %d, dumping", gHotTraceCountMap.size() ); gHotTraceCountMap.clear(); gFragmentCache.Clear(); #ifdef DAEDALUS_ENABLE_OS_HOOKS Patch_PatchAll(); #endif } else if( trace_count == gHotTraceThreshold ) { //DBGConsole_Msg( 0, "Identified hot trace at [R%08x]! (size is %d)", gCPUState.CurrentPC, gHotTraceCountMap.size() ); gTraceRecorder.StartTrace( gCPUState.CurrentPC ); if(!trace_already_enabled) { change_core = true; } DAED_LOG( DEBUG_DYNAREC_CACHE, "StartTrace( %08x )", gCPUState.CurrentPC ); } #ifdef DAEDALUS_DEBUG_DYNAREC else if( trace_count > gHotTraceThreshold ) { if(gAbortedTraceReasons.find( gCPUState.CurrentPC ) != gAbortedTraceReasons.end() ) { u32 reason( gAbortedTraceReasons[ gCPUState.CurrentPC ] ); use( reason ); //DBGConsole_Msg( 0, "Hot trace at [R%08x] has count of %d! (reason is %x) size %d", gCPUState.CurrentPC, trace_count, reason, gHotTraceCountMap.size( ) ); DAED_LOG( DEBUG_DYNAREC_CACHE, "Hot trace at %08x has count of %d! (reason is %x) size %d", gCPUState.CurrentPC, trace_count, reason, gHotTraceCountMap.size( ) ); } else { DAED_LOG( DEBUG_DYNAREC_CACHE, "Hot trace at %08x has count of %d! (reason is UNKNOWN!)", gCPUState.CurrentPC, trace_count ); } } #endif //DAEDALUS_DEBUG_DYNAREC } } else { DAED_LOG( DEBUG_DYNAREC_CACHE, "Not start of trace" ); } break; } } if(change_core) { CPU_SelectCore(); } }