[PATCH] D146169: Non-debuginfo JITLink perf jitdump support

Lang Hames via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun Mar 19 20:27:21 PDT 2023


lhames added a comment.

This looks great -- thanks very much @pchintalapudi!

I love that you've gone for the full cross-process implementation -- that's amazing. Have you tested it in a cross-process setup with `llvm-jitlink-executor`? Is it really working out-of-process already?

I have a few requests, mostly cosmetic (though the licensing info should go in before this lands), but other than that LGTM.



================
Comment at: llvm/include/llvm/ExecutionEngine/Orc/PerfSupportPlugin.h:1
+//===--- PerfSupportPlugin.h -- Utils for perf support ---*- C++ -*-===//
+//
----------------
Should be padded out to 80 cols with dashes either side of the name/description. 


================
Comment at: llvm/include/llvm/ExecutionEngine/Orc/PerfSupportPlugin.h:39-44
+  Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
+    return Error::success();
+  }
+
+  void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
+                                   ResourceKey SrcKey) override {}
----------------
Do the perf JIT APIs support unloading code? If so these should have a `// TODO` to fill them in later. (I don't think they're needed for the initial commit).


================
Comment at: llvm/include/llvm/ExecutionEngine/Orc/PerfSupportPlugin.h:135-140
+  static size_t size(const PerfJITRecordPrefix &Val) {
+    auto tup = std::make_tuple(static_cast<uint32_t>(Val.Id), Val.TotalSize,
+                               Val.Timestamp);
+    return SPSSerializationTraits<SPSPerfJITRecordPrefix, ImplTupleType>::size(
+        tup);
+  }
----------------
In SimplePackedSerialization argument lists and tuples are guaranteed to have the same serialization, so there's a convenience method on the SPS tuple list that you can use here:
```
static size_t size(const PerfJITRecordPrefix &Val) {
  return SPSPerfJITRecordPrefix::AsArgList::size(
    static_cast<uint32_t>(Val.Id), Val.TotalSize, Val.Timestamp);
}
```


================
Comment at: llvm/include/llvm/ExecutionEngine/Orc/PerfSupportPlugin.h:142-152
+    ImplTupleType Tup;
+    if (SPSSerializationTraits<SPSPerfJITRecordPrefix,
+                               ImplTupleType>::deserialize(IB, Tup)) {
+      Val.Id = static_cast<PerfJITRecordType>(std::move(std::get<0>(Tup)));
+      Val.TotalSize = std::move(std::get<1>(Tup));
+      Val.Timestamp = std::move(std::get<2>(Tup));
+      return true;
----------------
Likewise here:
```
static bool deserialize(SPSInputBuffer &IB, PerfJITRecordPrefix &Val) {
    uint32_t Id;
    if (SPSPerfJITRecordPrefix::AsArgList::deserialize(IB, Id, Val.TotalSize, Val.Timestamp)) {
      Val.Id = Id;
      return true;
    }
    return false;
}
```



================
Comment at: llvm/include/llvm/ExecutionEngine/Orc/PerfSupportPlugin.h:153-157
+  static bool serialize(SPSOutputBuffer &OB, const PerfJITRecordPrefix &Val) {
+    return SPSSerializationTraits<SPSPerfJITRecordPrefix, ImplTupleType>::
+        serialize(OB, std::make_tuple(static_cast<uint32_t>(Val.Id),
+                                      Val.TotalSize, Val.Timestamp));
+  }
----------------
And here:
```
static bool serialize(SPSOutputBuffer &OB, const PerfJITRecordPrefix &Val) {
  return SPSPerfJITRecordPrefix:AsArgList::
        serialize(OB, static_cast<uint32_t>(Val.Id), Val.TotalSize, Val.Timestamp);
}
```



================
Comment at: llvm/include/llvm/ExecutionEngine/Orc/PerfSupportPlugin.h:165
+template <>
+class SPSSerializationTraits<SPSPerfJITCodeLoadRecord, PerfJITCodeLoadRecord> {
+public:
----------------
Same advice as above here -- the methods below can probably be shortened by using `SPSPerfJITCodeLoadRecord::AsArgList`.


================
Comment at: llvm/include/llvm/ExecutionEngine/Orc/PerfSupportPlugin.h:207
+template <>
+class SPSSerializationTraits<SPSPerfJITDebugEntry, PerfJITDebugEntry> {
+public:
----------------
More potential `AsArgList` simplifications here.


================
Comment at: llvm/include/llvm/ExecutionEngine/Orc/PerfSupportPlugin.h:242
+template <>
+class SPSSerializationTraits<SPSPerfJITDebugInfoRecord,
+                             PerfJITDebugInfoRecord> {
----------------
More potential AsArgList simplifications here.


================
Comment at: llvm/include/llvm/ExecutionEngine/Orc/PerfSupportPlugin.h:278
+template <>
+class SPSSerializationTraits<SPSPerfJITCodeUnwindingInfoRecord,
+                             PerfJITCodeUnwindingInfoRecord> {
----------------
More potential AsArgList simplifications here.


================
Comment at: llvm/include/llvm/ExecutionEngine/Orc/PerfSupportPlugin.h:324
+template <>
+class SPSSerializationTraits<SPSPerfJITRecordBatch, PerfJITRecordBatch> {
+public:
----------------
More potential AsArgList simplifications here.


================
Comment at: llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.h:1
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
----------------
Looks like this is missing the file name / description line.
```
//===------- JITLoaderPerf.h - Register profiler objects ------*- C++ -*-===//
```


================
Comment at: llvm/lib/ExecutionEngine/Orc/PerfSupportPlugin.cpp:1
+#include "llvm/ExecutionEngine/Orc/PerfSupportPlugin.h"
+
----------------
Needs LLVM licensing header.


================
Comment at: llvm/lib/ExecutionEngine/Orc/PerfSupportPlugin.cpp:22
+
+std::string serialize(LinkGraph &G) {
+  std::string out;
----------------
There's already a `LinkGraph::dump(raw_ostream&)` method. Could that be used instead of this?

Alternatively if the former is dumping too verbosely could we clean it up? Or add this to `LinkGraph` as `dumpCompact`?


================
Comment at: llvm/lib/ExecutionEngine/Orc/PerfSupportPlugin.cpp:47-86
+std::string createX64EHFrameHeader(Section &EHFrame,
+                                   support::endianness endianness,
+                                   bool absolute) {
+  uint8_t Version = 1;
+  uint8_t EhFramePtrEnc = 0;
+  if (absolute) {
+    EhFramePtrEnc |= dwarf::DW_EH_PE_sdata8 | dwarf::DW_EH_PE_absptr;
----------------
This shoul


================
Comment at: llvm/lib/ExecutionEngine/Orc/PerfSupportPlugin.cpp:82-83
+  } else {
+    memcpy(HeaderContent.data() + 4, &EHFrameRelocation,
+           sizeof(EHFrameRelocation));
+  }
----------------
It looks like the header is a known size -- you might be better off using a BinaryStreamWriter here.


================
Comment at: llvm/lib/ExecutionEngine/Orc/PerfSupportPlugin.cpp:100-113
+static inline uint64_t perf_get_timestamp() {
+#ifdef __linux__
+  struct timespec ts;
+  int ret;
+
+  ret = clock_gettime(CLOCK_MONOTONIC, &ts);
+  if (ret)
----------------
This is being used to get the timestamp in the host process. Should we be timestamping the deserialized records on the executor side instead?


================
Comment at: llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.cpp:1
+#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.h"
+
----------------
Needs LLVM licensing header.

We should also have a file-level TODO to move this into the ORC runtime once we can.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D146169/new/

https://reviews.llvm.org/D146169



More information about the llvm-commits mailing list