mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[XRay] Use TSC delta encoding for custom/typed events
Summary: This change updates the version number for FDR logs to 5, and update the trace processing to support changes in the custom event records. In the runtime, since we're already writing down the record preamble to handle CPU migrations and TSC wraparound, we can use the same TSC delta encoding in the custom event and typed event records that we use in function event records. We do the same change to typed events (which were unsupported before this change in the trace processing) which now show up in the trace. Future changes should increase our testing coverage to make custom and typed events as first class entities in the FDR mode log processing tools. This change is also a good example of how we end up supporting new record types in the FDR mode implementation. This shows the places where new record types are added and supported. Depends on D54139. Reviewers: mboerger Subscribers: hiraditya, arphaman, jfb, llvm-commits Differential Revision: https://reviews.llvm.org/D54140 llvm-svn: 346293
This commit is contained in:
parent
6656cc18c1
commit
d9e9a38395
@ -54,6 +54,8 @@ public:
|
||||
Error visit(NewBufferRecord &) override;
|
||||
Error visit(EndBufferRecord &) override;
|
||||
Error visit(FunctionRecord &) override;
|
||||
Error visit(CustomEventRecordV5 &) override;
|
||||
Error visit(TypedEventRecord &) override;
|
||||
|
||||
/// The flush() function will clear out the current state of the visitor, to
|
||||
/// allow for explicitly flushing a block's records to the currently
|
||||
|
@ -50,6 +50,8 @@ public:
|
||||
Error visit(NewBufferRecord &) override;
|
||||
Error visit(EndBufferRecord &) override;
|
||||
Error visit(FunctionRecord &) override;
|
||||
Error visit(CustomEventRecordV5 &) override;
|
||||
Error visit(TypedEventRecord &) override;
|
||||
|
||||
void reset() { CurrentState = State::Start; }
|
||||
};
|
||||
|
@ -33,6 +33,7 @@ public:
|
||||
NewCPUId,
|
||||
TSCWrap,
|
||||
CustomEvent,
|
||||
TypedEvent,
|
||||
Function,
|
||||
CallArg,
|
||||
EndOfBuffer,
|
||||
@ -58,6 +59,8 @@ public:
|
||||
Error visit(NewBufferRecord &) override;
|
||||
Error visit(EndBufferRecord &) override;
|
||||
Error visit(FunctionRecord &) override;
|
||||
Error visit(CustomEventRecordV5 &) override;
|
||||
Error visit(TypedEventRecord &) override;
|
||||
|
||||
Error verify();
|
||||
void reset();
|
||||
|
@ -66,6 +66,7 @@ public:
|
||||
PIDEntry,
|
||||
NewBuffer,
|
||||
EndOfBuffer,
|
||||
TypedEvent,
|
||||
};
|
||||
|
||||
Type type() const override { return Type::Metadata; }
|
||||
@ -174,6 +175,52 @@ public:
|
||||
Error apply(RecordVisitor &V) override;
|
||||
};
|
||||
|
||||
class CustomEventRecordV5 : public MetadataRecord {
|
||||
int32_t Size = 0;
|
||||
int32_t Delta = 0;
|
||||
std::string Data{};
|
||||
friend class RecordInitializer;
|
||||
|
||||
public:
|
||||
CustomEventRecordV5() = default;
|
||||
explicit CustomEventRecordV5(int32_t S, int32_t D, std::string P)
|
||||
: MetadataRecord(), Size(S), Delta(D), Data(std::move(P)) {}
|
||||
|
||||
MetadataType metadataType() const override {
|
||||
return MetadataType::CustomEvent;
|
||||
}
|
||||
|
||||
int32_t size() const { return Size; }
|
||||
int32_t delta() const { return Delta; }
|
||||
StringRef data() const { return Data; }
|
||||
|
||||
Error apply(RecordVisitor &V) override;
|
||||
};
|
||||
|
||||
class TypedEventRecord : public MetadataRecord {
|
||||
int32_t Size = 0;
|
||||
int32_t Delta = 0;
|
||||
uint16_t EventType = 0;
|
||||
std::string Data{};
|
||||
friend class RecordInitializer;
|
||||
|
||||
public:
|
||||
TypedEventRecord() = default;
|
||||
explicit TypedEventRecord(int32_t S, int32_t D, uint16_t E, std::string P)
|
||||
: MetadataRecord(), Size(S), Delta(D), Data(std::move(P)) {}
|
||||
|
||||
MetadataType metadataType() const override {
|
||||
return MetadataType::TypedEvent;
|
||||
}
|
||||
|
||||
int32_t size() const { return Size; }
|
||||
int32_t delta() const { return Delta; }
|
||||
uint16_t eventType() const { return EventType; }
|
||||
StringRef data() const { return Data; }
|
||||
|
||||
Error apply(RecordVisitor &V) override;
|
||||
};
|
||||
|
||||
class CallArgRecord : public MetadataRecord {
|
||||
uint64_t Arg;
|
||||
friend class RecordInitializer;
|
||||
@ -269,6 +316,8 @@ public:
|
||||
virtual Error visit(NewBufferRecord &) = 0;
|
||||
virtual Error visit(EndBufferRecord &) = 0;
|
||||
virtual Error visit(FunctionRecord &) = 0;
|
||||
virtual Error visit(CustomEventRecordV5 &) = 0;
|
||||
virtual Error visit(TypedEventRecord &) = 0;
|
||||
};
|
||||
|
||||
class RecordInitializer : public RecordVisitor {
|
||||
@ -277,7 +326,7 @@ class RecordInitializer : public RecordVisitor {
|
||||
uint16_t Version;
|
||||
|
||||
public:
|
||||
static constexpr uint16_t DefaultVersion = 4u;
|
||||
static constexpr uint16_t DefaultVersion = 5u;
|
||||
|
||||
explicit RecordInitializer(DataExtractor &DE, uint32_t &OP, uint16_t V)
|
||||
: RecordVisitor(), E(DE), OffsetPtr(OP), Version(V) {}
|
||||
@ -295,6 +344,8 @@ public:
|
||||
Error visit(NewBufferRecord &) override;
|
||||
Error visit(EndBufferRecord &) override;
|
||||
Error visit(FunctionRecord &) override;
|
||||
Error visit(CustomEventRecordV5 &) override;
|
||||
Error visit(TypedEventRecord &) override;
|
||||
};
|
||||
|
||||
} // namespace xray
|
||||
|
@ -49,6 +49,8 @@ public:
|
||||
Error visit(NewBufferRecord &) override;
|
||||
Error visit(EndBufferRecord &) override;
|
||||
Error visit(FunctionRecord &) override;
|
||||
Error visit(CustomEventRecordV5 &) override;
|
||||
Error visit(TypedEventRecord &) override;
|
||||
|
||||
// Must be called after all the records have been processed, to handle the
|
||||
// most recent record generated.
|
||||
|
@ -43,6 +43,8 @@ public:
|
||||
Error visit(NewBufferRecord &) override;
|
||||
Error visit(EndBufferRecord &) override;
|
||||
Error visit(FunctionRecord &) override;
|
||||
Error visit(CustomEventRecordV5 &) override;
|
||||
Error visit(TypedEventRecord &) override;
|
||||
|
||||
private:
|
||||
support::endian::Writer OS;
|
||||
|
@ -40,6 +40,8 @@ public:
|
||||
Error visit(NewBufferRecord &) override;
|
||||
Error visit(EndBufferRecord &) override;
|
||||
Error visit(FunctionRecord &) override;
|
||||
Error visit(CustomEventRecordV5 &) override;
|
||||
Error visit(TypedEventRecord &) override;
|
||||
};
|
||||
|
||||
} // namespace xray
|
||||
|
@ -39,6 +39,16 @@ Error BlockIndexer::visit(CustomEventRecord &R) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error BlockIndexer::visit(CustomEventRecordV5 &R) {
|
||||
CurrentBlock.Records.push_back(&R);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error BlockIndexer::visit(TypedEventRecord &R) {
|
||||
CurrentBlock.Records.push_back(&R);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error BlockIndexer::visit(CallArgRecord &R) {
|
||||
CurrentBlock.Records.push_back(&R);
|
||||
return Error::success();
|
||||
|
@ -68,6 +68,24 @@ Error BlockPrinter::visit(CustomEventRecord &R) {
|
||||
return E;
|
||||
}
|
||||
|
||||
Error BlockPrinter::visit(CustomEventRecordV5 &R) {
|
||||
if (CurrentState == State::Metadata)
|
||||
OS << "\n";
|
||||
CurrentState = State::CustomEvent;
|
||||
OS << "* ";
|
||||
auto E = RP.visit(R);
|
||||
return E;
|
||||
}
|
||||
|
||||
Error BlockPrinter::visit(TypedEventRecord &R) {
|
||||
if (CurrentState == State::Metadata)
|
||||
OS << "\n";
|
||||
CurrentState = State::CustomEvent;
|
||||
OS << "* ";
|
||||
auto E = RP.visit(R);
|
||||
return E;
|
||||
}
|
||||
|
||||
// Function call printing.
|
||||
Error BlockPrinter::visit(FunctionRecord &R) {
|
||||
if (CurrentState == State::Metadata)
|
||||
|
@ -43,6 +43,8 @@ StringRef recordToString(BlockVerifier::State R) {
|
||||
return "CallArg";
|
||||
case BlockVerifier::State::EndOfBuffer:
|
||||
return "EndOfBuffer";
|
||||
case BlockVerifier::State::TypedEvent:
|
||||
return "TypedEvent";
|
||||
case BlockVerifier::State::StateMax:
|
||||
case BlockVerifier::State::Unknown:
|
||||
return "Unknown";
|
||||
@ -75,27 +77,34 @@ Error BlockVerifier::transition(State To) {
|
||||
{State::NewCPUId,
|
||||
{mask(State::NewCPUId) | mask(State::TSCWrap) |
|
||||
mask(State::CustomEvent) | mask(State::Function) |
|
||||
mask(State::EndOfBuffer)}},
|
||||
mask(State::EndOfBuffer) | mask(State::TypedEvent)}},
|
||||
|
||||
{State::TSCWrap,
|
||||
{mask(State::TSCWrap) | mask(State::NewCPUId) |
|
||||
mask(State::CustomEvent) | mask(State::Function) |
|
||||
mask(State::EndOfBuffer)}},
|
||||
mask(State::EndOfBuffer) | mask(State::TypedEvent)}},
|
||||
|
||||
{State::CustomEvent,
|
||||
{mask(State::CustomEvent) | mask(State::TSCWrap) |
|
||||
mask(State::NewCPUId) | mask(State::Function) |
|
||||
mask(State::EndOfBuffer)}},
|
||||
mask(State::EndOfBuffer) | mask(State::TypedEvent)}},
|
||||
|
||||
{State::TypedEvent,
|
||||
{mask(State::TypedEvent) | mask(State::TSCWrap) |
|
||||
mask(State::NewCPUId) | mask(State::Function) |
|
||||
mask(State::EndOfBuffer) | mask(State::CustomEvent)}},
|
||||
|
||||
{State::Function,
|
||||
{mask(State::Function) | mask(State::TSCWrap) |
|
||||
mask(State::NewCPUId) | mask(State::CustomEvent) |
|
||||
mask(State::CallArg) | mask(State::EndOfBuffer)}},
|
||||
mask(State::CallArg) | mask(State::EndOfBuffer) |
|
||||
mask(State::TypedEvent)}},
|
||||
|
||||
{State::CallArg,
|
||||
{mask(State::CallArg) | mask(State::Function) |
|
||||
mask(State::TSCWrap) | mask(State::NewCPUId) |
|
||||
mask(State::CustomEvent) | mask(State::EndOfBuffer)}},
|
||||
mask(State::CustomEvent) | mask(State::EndOfBuffer) |
|
||||
mask(State::TypedEvent)}},
|
||||
|
||||
{State::EndOfBuffer, {}}}};
|
||||
|
||||
@ -145,6 +154,14 @@ Error BlockVerifier::visit(CustomEventRecord &) {
|
||||
return transition(State::CustomEvent);
|
||||
}
|
||||
|
||||
Error BlockVerifier::visit(CustomEventRecordV5 &) {
|
||||
return transition(State::CustomEvent);
|
||||
}
|
||||
|
||||
Error BlockVerifier::visit(TypedEventRecord &) {
|
||||
return transition(State::TypedEvent);
|
||||
}
|
||||
|
||||
Error BlockVerifier::visit(CallArgRecord &) {
|
||||
return transition(State::CallArg);
|
||||
}
|
||||
@ -169,6 +186,7 @@ Error BlockVerifier::verify() {
|
||||
case State::EndOfBuffer:
|
||||
case State::NewCPUId:
|
||||
case State::CustomEvent:
|
||||
case State::TypedEvent:
|
||||
case State::Function:
|
||||
case State::CallArg:
|
||||
case State::TSCWrap:
|
||||
|
@ -53,14 +53,15 @@ metadataRecordType(const XRayFileHeader &Header, uint8_t T) {
|
||||
case MetadataRecordKinds::WalltimeMarkerKind:
|
||||
return make_unique<WallclockRecord>();
|
||||
case MetadataRecordKinds::CustomEventMarkerKind:
|
||||
if (Header.Version >= 5)
|
||||
return make_unique<CustomEventRecordV5>();
|
||||
return make_unique<CustomEventRecord>();
|
||||
case MetadataRecordKinds::CallArgumentKind:
|
||||
return make_unique<CallArgRecord>();
|
||||
case MetadataRecordKinds::BufferExtentsKind:
|
||||
return make_unique<BufferExtents>();
|
||||
case MetadataRecordKinds::TypedEventMarkerKind:
|
||||
return createStringError(std::make_error_code(std::errc::invalid_argument),
|
||||
"Encountered an unsupported TypedEventMarker.");
|
||||
return make_unique<TypedEventRecord>();
|
||||
case MetadataRecordKinds::PidKind:
|
||||
return make_unique<PIDRecord>();
|
||||
case MetadataRecordKinds::EnumEndMarker:
|
||||
|
@ -26,6 +26,8 @@ Error PIDRecord::apply(RecordVisitor &V) { return V.visit(*this); }
|
||||
Error NewBufferRecord::apply(RecordVisitor &V) { return V.visit(*this); }
|
||||
Error EndBufferRecord::apply(RecordVisitor &V) { return V.visit(*this); }
|
||||
Error FunctionRecord::apply(RecordVisitor &V) { return V.visit(*this); }
|
||||
Error CustomEventRecordV5::apply(RecordVisitor &V) { return V.visit(*this); }
|
||||
Error TypedEventRecord::apply(RecordVisitor &V) { return V.visit(*this); }
|
||||
|
||||
} // namespace xray
|
||||
} // namespace llvm
|
||||
|
@ -52,6 +52,39 @@ Error TraceExpander::visit(CustomEventRecord &R) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error TraceExpander::visit(CustomEventRecordV5 &R) {
|
||||
resetCurrentRecord();
|
||||
if (!IgnoringRecords) {
|
||||
BaseTSC += R.delta();
|
||||
CurrentRecord.TSC = BaseTSC;
|
||||
CurrentRecord.CPU = CPUId;
|
||||
CurrentRecord.PId = PID;
|
||||
CurrentRecord.TId = TID;
|
||||
CurrentRecord.Type = RecordTypes::CUSTOM_EVENT;
|
||||
std::copy(R.data().begin(), R.data().end(),
|
||||
std::back_inserter(CurrentRecord.Data));
|
||||
BuildingRecord = true;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error TraceExpander::visit(TypedEventRecord &R) {
|
||||
resetCurrentRecord();
|
||||
if (!IgnoringRecords) {
|
||||
BaseTSC += R.delta();
|
||||
CurrentRecord.TSC = BaseTSC;
|
||||
CurrentRecord.CPU = CPUId;
|
||||
CurrentRecord.PId = PID;
|
||||
CurrentRecord.TId = TID;
|
||||
CurrentRecord.RecordType = R.eventType();
|
||||
CurrentRecord.Type = RecordTypes::TYPED_EVENT;
|
||||
std::copy(R.data().begin(), R.data().end(),
|
||||
std::back_inserter(CurrentRecord.Data));
|
||||
BuildingRecord = true;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error TraceExpander::visit(CallArgRecord &R) {
|
||||
CurrentRecord.CallArgs.push_back(R.arg());
|
||||
CurrentRecord.Type = RecordTypes::ENTER_ARG;
|
||||
|
@ -102,6 +102,24 @@ Error FDRTraceWriter::visit(CustomEventRecord &R) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error FDRTraceWriter::visit(CustomEventRecordV5 &R) {
|
||||
if (auto E = writeMetadata<5u>(OS, R.size(), R.delta()))
|
||||
return E;
|
||||
auto D = R.data();
|
||||
ArrayRef<char> Bytes(D.data(), D.size());
|
||||
OS.write(Bytes);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error FDRTraceWriter::visit(TypedEventRecord &R) {
|
||||
if (auto E = writeMetadata<7u>(OS, R.size(), R.delta(), R.eventType()))
|
||||
return E;
|
||||
auto D = R.data();
|
||||
ArrayRef<char> Bytes(D.data(), D.size());
|
||||
OS.write(Bytes);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error FDRTraceWriter::visit(CallArgRecord &R) {
|
||||
return writeMetadata<6u>(OS, R.arg());
|
||||
}
|
||||
|
@ -63,10 +63,6 @@ Expected<XRayFileHeader> readBinaryFormatHeader(DataExtractor &HeaderExtractor,
|
||||
// Manually advance the offset pointer 16 bytes, after getting a raw memcpy
|
||||
// from the underlying data.
|
||||
OffsetPtr += 16;
|
||||
if (FileHeader.Version < 1 || FileHeader.Version > 4)
|
||||
return createStringError(std::make_error_code(std::errc::invalid_argument),
|
||||
"Unsupported XRay file version: %d at offset %d",
|
||||
FileHeader.Version, OffsetPtr);
|
||||
return std::move(FileHeader);
|
||||
}
|
||||
|
||||
|
@ -151,6 +151,105 @@ Error RecordInitializer::visit(CustomEventRecord &R) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error RecordInitializer::visit(CustomEventRecordV5 &R) {
|
||||
if (!E.isValidOffsetForDataOfSize(OffsetPtr,
|
||||
MetadataRecord::kMetadataBodySize))
|
||||
return createStringError(std::make_error_code(std::errc::bad_address),
|
||||
"Invalid offset for a custom event record (%d).",
|
||||
OffsetPtr);
|
||||
|
||||
auto BeginOffset = OffsetPtr;
|
||||
auto PreReadOffset = OffsetPtr;
|
||||
|
||||
R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t));
|
||||
if (PreReadOffset == OffsetPtr)
|
||||
return createStringError(
|
||||
std::make_error_code(std::errc::invalid_argument),
|
||||
"Cannot read a custom event record size field offset %d.", OffsetPtr);
|
||||
|
||||
PreReadOffset = OffsetPtr;
|
||||
R.Delta = E.getSigned(&OffsetPtr, sizeof(int32_t));
|
||||
if (PreReadOffset == OffsetPtr)
|
||||
return createStringError(
|
||||
std::make_error_code(std::errc::invalid_argument),
|
||||
"Cannot read a custom event record TSC delta field at offset %d.",
|
||||
OffsetPtr);
|
||||
|
||||
assert(OffsetPtr > BeginOffset &&
|
||||
OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
|
||||
OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
|
||||
|
||||
// Next we read in a fixed chunk of data from the given offset.
|
||||
if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size))
|
||||
return createStringError(
|
||||
std::make_error_code(std::errc::bad_address),
|
||||
"Cannot read %d bytes of custom event data from offset %d.", R.Size,
|
||||
OffsetPtr);
|
||||
|
||||
std::vector<uint8_t> Buffer;
|
||||
Buffer.resize(R.Size);
|
||||
if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data())
|
||||
return createStringError(
|
||||
std::make_error_code(std::errc::invalid_argument),
|
||||
"Failed reading data into buffer of size %d at offset %d.", R.Size,
|
||||
OffsetPtr);
|
||||
R.Data.assign(Buffer.begin(), Buffer.end());
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error RecordInitializer::visit(TypedEventRecord &R) {
|
||||
if (!E.isValidOffsetForDataOfSize(OffsetPtr,
|
||||
MetadataRecord::kMetadataBodySize))
|
||||
return createStringError(std::make_error_code(std::errc::bad_address),
|
||||
"Invalid offset for a typed event record (%d).",
|
||||
OffsetPtr);
|
||||
|
||||
auto BeginOffset = OffsetPtr;
|
||||
auto PreReadOffset = OffsetPtr;
|
||||
|
||||
R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t));
|
||||
if (PreReadOffset == OffsetPtr)
|
||||
return createStringError(
|
||||
std::make_error_code(std::errc::invalid_argument),
|
||||
"Cannot read a typed event record size field offset %d.", OffsetPtr);
|
||||
|
||||
PreReadOffset = OffsetPtr;
|
||||
R.Delta = E.getSigned(&OffsetPtr, sizeof(int32_t));
|
||||
if (PreReadOffset == OffsetPtr)
|
||||
return createStringError(
|
||||
std::make_error_code(std::errc::invalid_argument),
|
||||
"Cannot read a typed event record TSC delta field at offset %d.",
|
||||
OffsetPtr);
|
||||
|
||||
PreReadOffset = OffsetPtr;
|
||||
R.EventType = E.getU16(&OffsetPtr);
|
||||
if (PreReadOffset == OffsetPtr)
|
||||
return createStringError(
|
||||
std::make_error_code(std::errc::invalid_argument),
|
||||
"Cannot read a typed event record type field at offset %d.", OffsetPtr);
|
||||
|
||||
assert(OffsetPtr > BeginOffset &&
|
||||
OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
|
||||
OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
|
||||
|
||||
// Next we read in a fixed chunk of data from the given offset.
|
||||
if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size))
|
||||
return createStringError(
|
||||
std::make_error_code(std::errc::bad_address),
|
||||
"Cannot read %d bytes of custom event data from offset %d.", R.Size,
|
||||
OffsetPtr);
|
||||
|
||||
std::vector<uint8_t> Buffer;
|
||||
Buffer.resize(R.Size);
|
||||
if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data())
|
||||
return createStringError(
|
||||
std::make_error_code(std::errc::invalid_argument),
|
||||
"Failed reading data into buffer of size %d at offset %d.", R.Size,
|
||||
OffsetPtr);
|
||||
R.Data.assign(Buffer.begin(), Buffer.end());
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error RecordInitializer::visit(CallArgRecord &R) {
|
||||
if (!E.isValidOffsetForDataOfSize(OffsetPtr,
|
||||
MetadataRecord::kMetadataBodySize))
|
||||
|
@ -42,6 +42,21 @@ Error RecordPrinter::visit(CustomEventRecord &R) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error RecordPrinter::visit(CustomEventRecordV5 &R) {
|
||||
OS << formatv("<Custom Event: delta = +{0}, size = {1}, data = '{2}'>",
|
||||
R.delta(), R.size(), R.data())
|
||||
<< Delim;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error RecordPrinter::visit(TypedEventRecord &R) {
|
||||
OS << formatv(
|
||||
"<Typed Event: delta = +{0}, type = {1}, size = {2}, data = '{3}'",
|
||||
R.delta(), R.eventType(), R.size(), R.data())
|
||||
<< Delim;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error RecordPrinter::visit(CallArgRecord &R) {
|
||||
OS << formatv("<Call Argument: data = {0} (hex = {0:x})>", R.arg()) << Delim;
|
||||
return Error::success();
|
||||
|
@ -247,6 +247,17 @@ Error loadNaiveFormatLog(StringRef Data, bool IsLittleEndian,
|
||||
/// ThreadBuffer: BufferExtents NewBuffer WallClockTime Pid NewCPUId
|
||||
/// FunctionSequence
|
||||
/// EOB: *deprecated*
|
||||
///
|
||||
/// In Version 4, we make the following changes:
|
||||
///
|
||||
/// CustomEventRecord now includes the CPU data.
|
||||
///
|
||||
/// In Version 5, we make the following changes:
|
||||
///
|
||||
/// CustomEventRecord and TypedEventRecord now use TSC delta encoding similar to
|
||||
/// what FunctionRecord instances use, and we no longer need to include the CPU
|
||||
/// id in the CustomEventRecord.
|
||||
///
|
||||
Error loadFDRLog(StringRef Data, bool IsLittleEndian,
|
||||
XRayFileHeader &FileHeader, std::vector<XRayRecord> &Records) {
|
||||
|
||||
@ -435,7 +446,7 @@ Expected<Trace> llvm::xray::loadTrace(const DataExtractor &DE, bool Sort) {
|
||||
}
|
||||
break;
|
||||
case FLIGHT_DATA_RECORDER_FORMAT:
|
||||
if (Version >= 1 && Version <= 4) {
|
||||
if (Version >= 1 && Version <= 5) {
|
||||
if (auto E = loadFDRLog(DE.getData(), DE.isLittleEndian(), T.FileHeader,
|
||||
T.Records))
|
||||
return std::move(E);
|
||||
|
@ -34,6 +34,8 @@ TEST(XRayFDRTest, BuilderAndBlockIndexer) {
|
||||
.add<PIDRecord>(1)
|
||||
.add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
|
||||
.add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
|
||||
.add<CustomEventRecordV5>(1, 4, "XRAY")
|
||||
.add<TypedEventRecord>(1, 4, 2, "XRAY")
|
||||
.consume();
|
||||
auto Block1 = LogBuilder()
|
||||
.add<BufferExtents>(100)
|
||||
@ -42,6 +44,8 @@ TEST(XRayFDRTest, BuilderAndBlockIndexer) {
|
||||
.add<PIDRecord>(1)
|
||||
.add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
|
||||
.add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
|
||||
.add<CustomEventRecordV5>(1, 4, "XRAY")
|
||||
.add<TypedEventRecord>(1, 4, 2, "XRAY")
|
||||
.consume();
|
||||
auto Block2 = LogBuilder()
|
||||
.add<BufferExtents>(100)
|
||||
@ -50,6 +54,8 @@ TEST(XRayFDRTest, BuilderAndBlockIndexer) {
|
||||
.add<PIDRecord>(1)
|
||||
.add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
|
||||
.add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
|
||||
.add<CustomEventRecordV5>(1, 4, "XRAY")
|
||||
.add<TypedEventRecord>(1, 4, 2, "XRAY")
|
||||
.consume();
|
||||
BlockIndexer::Index Index;
|
||||
BlockIndexer Indexer(Index);
|
||||
@ -92,6 +98,8 @@ TEST(XRayFDRTest, IndexAndVerifyBlocks) {
|
||||
.add<NewCPUIDRecord>(1, 2)
|
||||
.add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
|
||||
.add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
|
||||
.add<CustomEventRecordV5>(1, 4, "XRAY")
|
||||
.add<TypedEventRecord>(1, 4, 2, "XRAY")
|
||||
.consume();
|
||||
auto Block1 = LogBuilder()
|
||||
.add<BufferExtents>(64)
|
||||
@ -101,6 +109,8 @@ TEST(XRayFDRTest, IndexAndVerifyBlocks) {
|
||||
.add<NewCPUIDRecord>(1, 2)
|
||||
.add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
|
||||
.add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
|
||||
.add<CustomEventRecordV5>(1, 4, "XRAY")
|
||||
.add<TypedEventRecord>(1, 4, 2, "XRAY")
|
||||
.consume();
|
||||
auto Block2 = LogBuilder()
|
||||
.add<BufferExtents>(64)
|
||||
@ -110,6 +120,8 @@ TEST(XRayFDRTest, IndexAndVerifyBlocks) {
|
||||
.add<NewCPUIDRecord>(1, 2)
|
||||
.add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
|
||||
.add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
|
||||
.add<CustomEventRecordV5>(1, 4, "XRAY")
|
||||
.add<TypedEventRecord>(1, 4, 2, "XRAY")
|
||||
.consume();
|
||||
|
||||
// First, index the records in different blocks.
|
||||
|
Loading…
x
Reference in New Issue
Block a user