void InlineCacheRegistry::print_stats(STATE) { SYNC(state); int total = 0; std::vector<int> sizes(cTrackedICHits + 1); int overflow = 0; for(CacheHash::iterator hi = caches_.begin(); hi != caches_.end(); ++hi) { for(CacheVector::iterator vi = hi->second.begin(); vi != hi->second.end(); ++vi) { InlineCache* ic = *vi; int seen = ic->classes_seen(); if(ic->seen_classes_overflow() > 0) { total++; overflow++; } else if(seen > 0) { total++; sizes[seen]++; } } } std::cerr << "IC Stats:\n"; for(int i = 1; i < cTrackedICHits + 1; i++) { std::cerr << " " << i << ": " << sizes[i] << " " << ratio(sizes[i], total) << "%\n"; } std::cerr << cTrackedICHits << "+: " << overflow << " " << ratio(overflow, total) << "%\n"; // print out the mega-morphic ones std::cerr << "\nMegamorphic call sites:\n"; for(CacheHash::iterator hi = caches_.begin(); hi != caches_.end(); ++hi) { for(CacheVector::iterator vi = hi->second.begin(); vi != hi->second.end(); ++vi) { InlineCache* ic = *vi; if(ic->seen_classes_overflow() > 0) { ic->print(state, std::cerr); std::cerr << "location: "; ic->print_location(state, std::cerr); std::cerr << "\n\n"; } } } }
void InlineCacheRegistry::print_stats(STATE) { int total = 0; std::vector<int> sizes(cTrackedICHits + 1); int overflow = 0; for(CacheHash::iterator hi = caches_.begin(); hi != caches_.end(); ++hi) { for(CacheVector::iterator vi = hi->second.begin(); vi != hi->second.end(); ++vi) { InlineCache* ic = *vi; int seen = ic->classes_seen(); if(ic->seen_classes_overflow() > 0) { total++; overflow++; } else if(seen > 0) { total++; sizes[seen]++; } } } std::cerr << "IC Stats:\n"; for(int i = 1; i < cTrackedICHits + 1; i++) { std::cerr << " " << i << ": " << sizes[i] << " " << ratio(sizes[i], total) << "%\n"; } std::cerr << cTrackedICHits << "+: " << overflow << " " << ratio(overflow, total) << "%\n"; // Stats that take the number of hits into account std::vector<int> hits(cTrackedICHits + 1); int overflow_hits = 0; int total_hits = 0; for(CacheHash::iterator hi = caches_.begin(); hi != caches_.end(); ++hi) { for(CacheVector::iterator vi = hi->second.begin(); vi != hi->second.end(); ++vi) { InlineCache* ic = *vi; int seen = ic->classes_seen(); if(ic->seen_classes_overflow() > 0) { int these_hits = (ic->total_hits() + ic->seen_classes_overflow()); overflow_hits += these_hits; total_hits += these_hits; } else if(seen > 0) { hits[seen] += ic->total_hits(); total_hits += ic->total_hits(); } } } std::cerr << "Hits per classes tracked: (" << total_hits << ")\n"; for(int i = 1; i < cTrackedICHits + 1; i++) { std::cerr << " " << i << ": " << hits[i] << " " << ratio(hits[i], total_hits) << "%\n"; } std::cerr << cTrackedICHits << "+: " << overflow_hits << " " << ratio(overflow_hits, total_hits) << "%\n"; // print out the mega-morphic ones std::cerr << "\nMegamorphic call sites:\n"; for(CacheHash::iterator hi = caches_.begin(); hi != caches_.end(); ++hi) { for(CacheVector::iterator vi = hi->second.begin(); vi != hi->second.end(); ++vi) { InlineCache* ic = *vi; if(ic->seen_classes_overflow() > 0) { ic->print(state, std::cerr); std::cerr << "location: "; ic->print_location(state, std::cerr); std::cerr << "\n\n"; } } } }
void MachineCode::initialize_caches(STATE, CompiledCode* original, int sends) { number_of_caches_ = sends; caches = new InlineCache[sends]; int which = 0; bool allow_private = false; bool is_super = false; for(size_t ip = 0; ip < total;) { opcode op = opcodes[ip]; switch(op) { case InstructionSequence::insn_invoke_primitive: { Symbol* name = try_as<Symbol>(original->literals()->at(opcodes[ip + 1])); if(!name) { name = state->symbol("__unknown__"); } InvokePrimitive invoker = Primitives::get_invoke_stub(state, name); opcodes[ip + 1] = reinterpret_cast<intptr_t>(invoker); update_addresses(ip, 1); break; } case InstructionSequence::insn_allow_private: allow_private = true; break; case InstructionSequence::insn_push_const_fast: case InstructionSequence::insn_find_const_fast: original->literals()->put(state, opcodes[ip + 2], GlobalCacheEntry::empty(state)); break; case InstructionSequence::insn_send_super_stack_with_block: case InstructionSequence::insn_send_super_stack_with_splat: case InstructionSequence::insn_zsuper: is_super = true; // fall through case InstructionSequence::insn_check_serial: case InstructionSequence::insn_check_serial_private: case InstructionSequence::insn_call_custom: case InstructionSequence::insn_send_method: case InstructionSequence::insn_send_stack: case InstructionSequence::insn_send_stack_with_block: case InstructionSequence::insn_send_stack_with_splat: case InstructionSequence::insn_meta_send_call: case InstructionSequence::insn_meta_send_op_plus: case InstructionSequence::insn_meta_send_op_minus: case InstructionSequence::insn_meta_send_op_equal: case InstructionSequence::insn_meta_send_op_tequal: case InstructionSequence::insn_meta_send_op_lt: case InstructionSequence::insn_meta_send_op_gt: case InstructionSequence::insn_meta_to_s: { assert(which < sends); InlineCache* cache = &caches[which++]; cache->set_location(ip, this); Symbol* name = try_as<Symbol>(original->literals()->at(opcodes[ip + 1])); if(!name) { name = state->symbol("__unknown__"); } cache->set_name(name); if(op == InstructionSequence::insn_call_custom) { cache->set_call_custom(); } else { if(allow_private) cache->set_is_private(); if(is_super) cache->set_is_super(); if(op == InstructionSequence::insn_send_method) { cache->set_is_vcall(); } } state->shared().ic_registry()->add_cache(state, name, cache); opcodes[ip + 1] = reinterpret_cast<intptr_t>(cache); update_addresses(ip, 1); is_super = false; allow_private = false; } } ip += InstructionSequence::instruction_width(op); } }