wallace added inline comments.
================ Comment at: lldb/include/lldb/Target/TraceHTR.h:272 + /// The map of block IDs to \a HTRBlock. + std::unordered_map<size_t, HTRBlock> const &GetBlockDefs() const; + ---------------- jj10306 wrote: > wallace wrote: > > As this is const, the only way to use this unordered_map is to do look ups, > > then let's better hide the implementation detail that is an unordered map > > and create this method instead > > > > const HTRBlock &GetBlockById(size_t id); > > > > that way we can later change unordered_map for anything else without > > affecting any callers > Makes sense. How should the case when an `id` that the layer doesn't contain > is passed in? I would like to use `llvm::Optional` here but it's not possible > to have an Optional reference (i.e. `Optional<& const HTRBlock>`). I was > thinking about creating different methods: > > `bool ContainsBlock(size_t id) const` for checking if the layer contains an ID > `HTRBlock const & GetBlockById(size_t id) const` for retrieving a reference > to a block in the layer > but this still doesn't solve the issue of if a caller calls `GetBlockId` with > an invalid ID. > > Another option would be to change `GetBlockId` to return `Optional<HTRBlock>` > instead of a reference, but this would result in an unnecessary copy, when > all we really need is an const reference. Optional<const HTRBlock &> should work like a charm. You can't put the & before the const AFAIK. People normally read the & backwards as in "reference to <const HTRBlock>" ================ Comment at: lldb/include/lldb/Target/TraceHTR.h:339 + /// The file that the exported HTR data will be written to. + void Export(Stream &s, TraceExportFormat export_format, std::string outfile); + ---------------- jj10306 wrote: > wallace wrote: > > better return an llvm::Error that will contain the error message, if any. > > The CommandObject that invokes this method can then get the error and dump > > it if necessary. So, don't pass any streams here > I based this method off of `TraceCursor::DumpInstructions` which takes in a > Stream & to output its success/error messages to. This method > (`TraceHTR::Export`) prints a message to the console on success (not only > failure) so I'm not sure how the success message could be propagated back up > to the caller. I agree that using `llvm::Error` here would make sense if we > were only printing if an Error occurred, but since we print on success I'm > not sure if we should use llvm::Error over passing the Stream. It's different, because DumpInstructions is supposed to dump information in the stream, but in this case Export is printing to a file. So what if someone wants to invoke Export but not from a command? e.g. from a python script. You are making this case a little bit more complicated. You can just return llvm::success() and let the caller print anything to Stream if available. In any case, it's standard in lldb to not print anything if the operation is a success ================ Comment at: lldb/source/Target/TraceHTR.cpp:152 + valid_cursor = cursor.Next(); + s.Printf("%s\n", toString(std::move(err)).c_str()); + } else { ---------------- jj10306 wrote: > wallace wrote: > > this Printf is too noisy. You don't really need that. Just remove it and > > instead of invoking cursor.GetError(), invoke cursor.IsError() after > > rebasing the code > Initially I wasn't planning on displaying the error, but then I was getting > runtime errors because I wasn't doing anything with the error. As a result, I > decided to display the error and looked at how > `TraceCursor::DumpInstructions` does it: `s << toString(std::move(err));`. > I believe if an `isError()` method existed then I would not have this issue > about not checking/using the error and I could just use the `isError()` > method to check for the presence of an error without actually retrieving the > error object. yes my bad =P After rebasing you should be able to use IsError() :) Sorry for the hiccup ================ Comment at: lldb/source/Target/TraceHTR.cpp:197 +HTRBlock IHTRLayer::MergeUnits(size_t start_unit_index, size_t num_units) { + assert(num_units > 0); + llvm::Optional<HTRBlockMetadata> merged_metadata = llvm::None; ---------------- jj10306 wrote: > wallace wrote: > > remove this assert, the code wouldn't break if num_units is 0 > If `num_units` is 0 then the loop body would never execute and thus > `merged_metadata` would be `None` at the time of return. This would be > problematic since we return `*merged_metadata`. Ahh, true. Then also mention in the documentation that num_units must be >= 1, otherwise someone might think that could somehow get an empty HTRBlock >< ================ Comment at: lldb/source/Target/TraceHTR.cpp:439-440 + + // Can't use ConstString here because no toJSON implementation exists for + // ConstString + llvm::Optional<std::string> most_freq_func = ---------------- jj10306 wrote: > wallace wrote: > > this comment doens't make sense, as you are instead passing display_name to > > the json object > I was trying to indicate that `GetMostFrequentlyCalledFunction` returns a > `std::string` instead of `ConstString` because eventually the `ConsString` > function name will need to be converted to `std::string` in order to be > serialized, but I will remove this comment and just change the function to > return `ConstString` and then do the conversion in the ternary that defines > `display_name`. you shouldn't change a generic API just to ease a single instance of a usage. Better return a ConstString, or even better, a llvm::StringRef, which can point to anything. ConstString has a method to get a StringRef out of it. StringRef::str() gets you a std::string if you need it, or you can use StringRef::data() to get the const char *, which helps you avoid one copy. ================ Comment at: lldb/test/API/commands/trace/TestTraceExport.py:60 + error=True) + ---------------- jj10306 wrote: > wallace wrote: > > Add a new test in which you run this algorithm on a program with a few > > levels of function calls, and check that the output trace makes sense. > > Don't check for individual load addresses, but instead check for the > > appearance of the methods and blocks that you expect. > Yes, this makes sense. Is the way to do this by loading the JSON file's > contents into memory in the test and doing assertions on that structure? yes, that should be fine. You can also precompile a non-trivial a.out file and include it here, if you want the code to be fully deterministic. If you make it non-trivial enough, we should be able to reuse for other intel pt tests as well CHANGES SINCE LAST ACTION https://reviews.llvm.org/D105741/new/ https://reviews.llvm.org/D105741 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits