void ProfileDataContainer::switchStorageToAshmem(int ashmemfd) { int regionSize = ashmem_get_size_region(ashmemfd); if (regionSize < 0) { int err = errno; ALOGW("Failed to get ashmem region size from fd %d, err %d %s", ashmemfd, err, strerror(err)); return; } if (regionSize < static_cast<int>(sizeof(ProfileData))) { ALOGW("Ashmem region is too small! Received %d, required %u", regionSize, static_cast<unsigned int>(sizeof(ProfileData))); return; } ProfileData* newData = reinterpret_cast<ProfileData*>( mmap(NULL, sizeof(ProfileData), PROT_READ | PROT_WRITE, MAP_SHARED, ashmemfd, 0)); if (newData == MAP_FAILED) { int err = errno; ALOGW("Failed to move profile data to ashmem fd %d, error = %d", ashmemfd, err); return; } newData->mergeWith(*mData); freeData(); mData = newData; mIsMapped = true; }
void methodDataOopDesc::print_data_on(outputStream* st) { ResourceMark rm; ProfileData* data = first_data(); for ( ; is_valid(data); data = next_data(data)) { st->print("%d", dp_to_di(data->dp())); st->fill_to(6); data->print_data_on(st); } st->print_cr("--- Extra data:"); DataLayout* dp = extra_data_base(); DataLayout* end = extra_data_limit(); for (; dp < end; dp = next_extra(dp)) { // No need for "OrderAccess::load_acquire" ops, // since the data structure is monotonic. if (dp->tag() == DataLayout::no_tag) continue; if (dp->tag() == DataLayout::bit_data_tag) { data = new BitData(dp); } else { assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo"); data = new ArgInfoData(dp); dp = end; // ArgInfoData is at the end of extra data section. } st->print("%d", dp_to_di(data->dp())); st->fill_to(6); data->print_data_on(st); } }
// Give each of the data entries a chance to perform specific // data initialization. void methodDataOopDesc::post_initialize(BytecodeStream* stream) { ResourceMark rm; ProfileData* data; for (data = first_data(); is_valid(data); data = next_data(data)) { stream->set_start(data->bci()); stream->next(); data->post_initialize(stream, this); } }
void BytecodePrinter::bytecode_epilog(int bci, outputStream* st) { MethodData* mdo = method()->method_data(); if (mdo != NULL) { ProfileData* data = mdo->bci_to_data(bci); if (data != NULL) { st->print(" %d", mdo->dp_to_di(data->dp())); st->fill_to(6); data->print_data_on(st); } } }
// Translate a bci to its corresponding data, or NULL. ProfileData* methodDataOopDesc::bci_to_data(int bci) { ProfileData* data = data_before(bci); for ( ; is_valid(data); data = next_data(data)) { if (data->bci() == bci) { set_hint_di(dp_to_di(data->dp())); return data; } else if (data->bci() > bci) { break; } } return bci_to_extra_data(bci, false); }
void methodDataKlass::oop_follow_contents(oop obj) { assert (obj->is_methodData(), "object must be method data"); methodDataOop m = methodDataOop(obj); obj->follow_header(); MarkSweep::mark_and_push(m->adr_method()); ResourceMark rm; for (ProfileData* data = m->first_data(); m->is_valid(data); data = m->next_data(data)) { data->follow_contents(); } }
void ciMethodData::set_return_type(int bci, ciKlass* k) { VM_ENTRY_MARK; MethodData* mdo = get_MethodData(); if (mdo != NULL) { ProfileData* data = mdo->bci_to_data(bci); if (data->is_CallTypeData()) { data->as_CallTypeData()->set_return_type(k->get_Klass()); } else { assert(data->is_VirtualCallTypeData(), "no arguments!"); data->as_VirtualCallTypeData()->set_return_type(k->get_Klass()); } } }
int methodDataKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { assert(obj->is_methodData(), "should be method data"); methodDataOop m = methodDataOop(obj); PSParallelCompact::adjust_pointer(m->adr_method()); ResourceMark rm; ProfileData* data; for (data = m->first_data(); m->is_valid(data); data = m->next_data(data)) { data->update_pointers(); } return m->object_size(); }
void BytecodePrinter::bytecode_epilog(int bci) { #ifndef CORE methodDataOop mdo = method()->method_data(); if (mdo != NULL) { ProfileData* data = mdo->bci_to_data(bci); if (data != NULL) { tty->print(" %d", mdo->dp_to_di(data->dp())); tty->fill_to(6); data->print_data_on(tty); } } #endif }
/// readEdge - Take the value from a profile counter and assign it to an edge. void ProfileMetadataLoaderPass::readEdge(unsigned ReadCount, ProfileData &PB, ProfileData::Edge e, ArrayRef<unsigned> Counters) { if (ReadCount >= Counters.size()) return; unsigned weight = Counters[ReadCount]; assert(weight != ProfileDataLoader::Uncounted); PB.addEdgeWeight(e, weight); DEBUG(dbgs() << "-- Read Edge Counter for " << e << " (# "<< (ReadCount) << "): " << PB.getEdgeWeight(e) << "\n"); }
void methodDataKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { assert (obj->is_methodData(), "object must be method data"); methodDataOop m = methodDataOop(obj); obj->follow_header(cm); PSParallelCompact::mark_and_push(cm, m->adr_method()); ResourceMark rm; for (ProfileData* data = m->first_data(); m->is_valid(data); data = m->next_data(data)) { data->follow_contents(cm); } }
int methodDataKlass::oop_adjust_pointers(oop obj) { assert(obj->is_methodData(), "should be method data"); methodDataOop m = methodDataOop(obj); // Get size before changing pointers // Don't call size() or oop_size() since that is a virtual call. int size = m->object_size(); obj->adjust_header(); MarkSweep::adjust_pointer(m->adr_method()); ResourceMark rm; ProfileData* data; for (data = m->first_data(); m->is_valid(data); data = m->next_data(data)) { data->adjust_pointers(); } return size; }
int methodDataKlass::oop_oop_iterate(oop obj, OopClosure* blk) { assert (obj->is_methodData(), "object must be method data"); methodDataOop m = methodDataOop(obj); // Get size before changing pointers // Don't call size() or oop_size() since that is a virtual call. int size = m->object_size(); obj->oop_iterate_header(blk); blk->do_oop(m->adr_method()); ResourceMark rm; for (ProfileData* data = m->first_data(); m->is_valid(data); data = m->next_data(data)) { data->oop_iterate(blk); } return size; }
/// matchEdges - Link every profile counter with an edge. unsigned ProfileMetadataLoaderPass::matchEdges(Module &M, ProfileData &PB, ArrayRef<unsigned> Counters) { if (Counters.size() == 0) return 0; unsigned ReadCount = 0; for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { if (F->isDeclaration()) continue; DEBUG(dbgs() << "Loading edges in '" << F->getName() << "'\n"); readEdge(ReadCount++, PB, PB.getEdge(0, &F->getEntryBlock()), Counters); for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { TerminatorInst *TI = BB->getTerminator(); for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) { readEdge(ReadCount++, PB, PB.getEdge(BB,TI->getSuccessor(s)), Counters); } } } return ReadCount; }
void methodDataOopDesc::print_data_on(outputStream* st) { ResourceMark rm; ProfileData* data = first_data(); for ( ; is_valid(data); data = next_data(data)) { st->print("%d", dp_to_di(data->dp())); st->fill_to(6); data->print_data_on(st); } DataLayout* dp = extra_data_base(); DataLayout* end = extra_data_limit(); for (; dp < end; dp = next_extra(dp)) { // No need for "OrderAccess::load_acquire" ops, // since the data structure is monotonic. if (dp->tag() == DataLayout::no_tag) break; if (dp == extra_data_base()) st->print_cr("--- Extra data:"); data = new BitData(dp); st->print("%d", dp_to_di(data->dp())); st->fill_to(6); data->print_data_on(st); } }
void _printData(char *dest, const ProfileData &a_data, float a_topercent) { float totalTicksAvg = a_data.totalTicksAvg(); const TimeUnit *selfUnit = GetTimeUnit(a_data.selfTicks.avg); const TimeUnit *totalUnit = GetTimeUnit(totalTicksAvg); snprintf(dest, OUTPUT_WIDTH_DATA + TRAILING, " %*.1f %*.0f %-2s %*.0f%% %*.0f %-2s %*.0f%%", OUTPUT_WIDTH_HIT, a_data.entryCount.avg, OUTPUT_WIDTH_TIME, a_data.selfTicks.avg * selfUnit->invTickFreq, selfUnit->suffix, OUTPUT_WIDTH_PERC, a_data.selfTicks.avg * a_topercent, OUTPUT_WIDTH_TIME, totalTicksAvg * totalUnit->invTickFreq, totalUnit->suffix, OUTPUT_WIDTH_PERC, totalTicksAvg * a_topercent); }
/// setBranchWeightMetadata - Translate the counter values associated with each /// edge into branch weights for each conditional branch (a branch with 2 or /// more desinations). void ProfileMetadataLoaderPass::setBranchWeightMetadata(Module &M, ProfileData &PB) { for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { if (F->isDeclaration()) continue; DEBUG(dbgs() << "Setting branch metadata in '" << F->getName() << "'\n"); for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { TerminatorInst *TI = BB->getTerminator(); unsigned NumSuccessors = TI->getNumSuccessors(); // If there is only one successor then we can not set a branch // probability as the target is certain. if (NumSuccessors < 2) continue; // Load the weights of all edges leading from this terminator. DEBUG(dbgs() << "-- Terminator with " << NumSuccessors << " successors:\n"); SmallVector<uint32_t, 4> Weights(NumSuccessors); for (unsigned s = 0 ; s < NumSuccessors ; ++s) { ProfileData::Edge edge = PB.getEdge(BB, TI->getSuccessor(s)); Weights[s] = (uint32_t)PB.getEdgeWeight(edge); DEBUG(dbgs() << "---- Edge '" << edge << "' has weight " << Weights[s] << "\n"); } // Set branch weight metadata. This will set branch probabilities of // 100%/0% if that is true of the dynamic execution. // BranchProbabilityInfo can account for this when it loads this metadata // (it gives the unexectuted branch a weight of 1 for the purposes of // probability calculations). MDBuilder MDB(TI->getContext()); MDNode *Node = MDB.createBranchWeights(Weights); TI->setMetadata(LLVMContext::MD_prof, Node); NumTermsAnnotated++; } } }
// Translate a bci to its corresponding data index (di). address methodDataOopDesc::bci_to_dp(int bci) { ResourceMark rm; ProfileData* data = data_before(bci); ProfileData* prev = NULL; for ( ; is_valid(data); data = next_data(data)) { if (data->bci() >= bci) { if (data->bci() == bci) set_hint_di(dp_to_di(data->dp())); else if (prev != NULL) set_hint_di(dp_to_di(prev->dp())); return data->dp(); } prev = data; } return (address)limit_data_position(); }
void StackTrace::trace(ProfileData &data){ CaptureStackBackTrace(0, backtraceSize, backtrace, &hash); auto stk = data.stacks.find(hash); if (stk != data.stacks.end()) { idx = stk->second; return; }; HANDLE process = GetCurrentProcess(); const int MAXSYMBOLNAME = 128 - sizeof(IMAGEHLP_SYMBOL); char symbol64_buf[sizeof(IMAGEHLP_SYMBOL) + MAXSYMBOLNAME] = { 0 }; IMAGEHLP_SYMBOL *symbol = reinterpret_cast<IMAGEHLP_SYMBOL*>(symbol64_buf); symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); symbol->MaxNameLength = MAXSYMBOLNAME - 1; IMAGEHLP_MODULE module; module.SizeOfStruct = sizeof(IMAGEHLP_MODULE); for (size_t i = backtraceSize - 1; i > 0; --i){ int fileidx = 0; int linenum = 0; int symidx = 0; int modidx = 0; if (backtrace[i]){ // Output stack frame symbols if available. if (SymGetSymFromAddr(process, (DWORD64)backtrace[i], 0, symbol)){ std::string symbol_name = symbol->Name; if (strncmp("mallocHook<", symbol->Name, 11) == 0) { symbol_name = "malloc"; } if (strncmp("freeHook<", symbol->Name, 9) == 0) { symbol_name = "free"; } symidx = data.intern(symbol_name); if (SymGetModuleInfo(process, (DWORD64)backtrace[i], &module)) { modidx = data.intern(module.ModuleName); } // Output filename + line info if available. IMAGEHLP_LINE lineSymbol = { 0 }; lineSymbol.SizeOfStruct = sizeof(IMAGEHLP_LINE); DWORD displacement; if (SymGetLineFromAddr(process, (DWORD64)backtrace[i], &displacement, &lineSymbol)){ fileidx = data.intern(lineSymbol.FileName); linenum = lineSymbol.LineNumber; } } fprintf(data.output, "i %lx %lx", symbol->Address, modidx); if (symidx || fileidx) { fprintf(data.output, " %lx", symidx); if (fileidx) fprintf(data.output, " %lx %lx", fileidx, linenum); } fprintf(data.output, "\n"); } else{ continue; } } idx = data.instGraph.index((intptr_t*)backtrace, data.output); data.stacks.insert(std::make_pair(hash, idx)); }
void ciMethodData::dump_replay_data(outputStream* out) { ResourceMark rm; MethodData* mdo = get_MethodData(); Method* method = mdo->method(); Klass* holder = method->method_holder(); out->print("ciMethodData %s %s %s %d %d", holder->name()->as_quoted_ascii(), method->name()->as_quoted_ascii(), method->signature()->as_quoted_ascii(), _state, current_mileage()); // dump the contents of the MDO header as raw data unsigned char* orig = (unsigned char*)&_orig; int length = sizeof(_orig); out->print(" orig %d", length); for (int i = 0; i < length; i++) { out->print(" %d", orig[i]); } // dump the MDO data as raw data int elements = (data_size() + extra_data_size()) / sizeof(intptr_t); out->print(" data %d", elements); for (int i = 0; i < elements; i++) { // We could use INTPTR_FORMAT here but that's a zero justified // which makes comparing it with the SA version of this output // harder. #ifdef _LP64 out->print(" 0x%" FORMAT64_MODIFIER "x", data()[i]); #else out->print(" 0x%x", data()[i]); #endif } // The MDO contained oop references as ciObjects, so scan for those // and emit pairs of offset and klass name so that they can be // reconstructed at runtime. The first round counts the number of // oop references and the second actually emits them. ciParametersTypeData* parameters = parameters_type_data(); for (int count = 0, round = 0; round < 2; round++) { if (round == 1) out->print(" oops %d", count); ProfileData* pdata = first_data(); for ( ; is_valid(pdata); pdata = next_data(pdata)) { if (pdata->is_VirtualCallData()) { ciVirtualCallData* vdata = (ciVirtualCallData*)pdata; dump_replay_data_receiver_type_helper<ciVirtualCallData>(out, round, count, vdata); if (pdata->is_VirtualCallTypeData()) { ciVirtualCallTypeData* call_type_data = (ciVirtualCallTypeData*)pdata; dump_replay_data_call_type_helper<ciVirtualCallTypeData>(out, round, count, call_type_data); } } else if (pdata->is_ReceiverTypeData()) { ciReceiverTypeData* vdata = (ciReceiverTypeData*)pdata; dump_replay_data_receiver_type_helper<ciReceiverTypeData>(out, round, count, vdata); } else if (pdata->is_CallTypeData()) { ciCallTypeData* call_type_data = (ciCallTypeData*)pdata; dump_replay_data_call_type_helper<ciCallTypeData>(out, round, count, call_type_data); } } if (parameters != NULL) { for (int i = 0; i < parameters->number_of_parameters(); i++) { dump_replay_data_type_helper(out, round, count, parameters, ParametersTypeData::type_offset(i), parameters->valid_parameter_type(i)); } } } for (int count = 0, round = 0; round < 2; round++) { if (round == 1) out->print(" methods %d", count); dump_replay_data_extra_data_helper(out, round, count); } out->cr(); }