llvm.org GIT mirror llvm / d6aeff8
[XRay][tools] Support tail-call exits before we write them in the runtime Summary: This change adds support for explicit tail-exit records to be written by the XRay runtime. This lets us differentiate the tail exit records/events in the log, and allows us to treat those exit events especially in the future. For now we allow printing those out in YAML (and reading them in). Reviewers: kpw, pelikan Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D37964 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313514 91177308-0d34-0410-b5e6-96231b3b80d8 Dean Michael Berris 2 years ago
9 changed file(s) with 26 addition(s) and 12 deletion(s). Raw diff Collapse all Expand all
164164 +---------------+--------------+-----------------------------------------------+
165165 | Exit | ``1`` | Typical function exit. |
166166 +---------------+--------------+-----------------------------------------------+
167 | Tail_Exit | ``2`` | An exit from a function due to Tail call |
167 | Tail_Exit | ``2`` | An exit from a function due to tail call |
168168 | | | optimization. |
169169 +---------------+--------------+-----------------------------------------------+
170170 | Entry_Args | ``3`` | A function entry that records arguments. |
5252 /// This may or may not correspond to actual record types in the raw trace (as
5353 /// the loader implementation may synthesize this information in the process of
5454 /// of loading).
55 enum class RecordTypes { ENTER, EXIT };
55 enum class RecordTypes { ENTER, EXIT, TAIL_EXIT };
5656
5757 struct XRayRecord {
5858 /// The type of record.
5353 static void enumeration(IO &IO, xray::RecordTypes &Type) {
5454 IO.enumCase(Type, "function-enter", xray::RecordTypes::ENTER);
5555 IO.enumCase(Type, "function-exit", xray::RecordTypes::EXIT);
56 IO.enumCase(Type, "function-tail-exit", xray::RecordTypes::TAIL_EXIT);
5657 }
5758 };
5859
4747 FileHeader.NonstopTSC = Bitfield & 1uL << 1;
4848 FileHeader.CycleFrequency = HeaderExtractor.getU64(&OffsetPtr);
4949 std::memcpy(&FileHeader.FreeFormData, Data.bytes_begin() + OffsetPtr, 16);
50 if (FileHeader.Version != 1)
50 if (FileHeader.Version != 1 && FileHeader.Version != 2)
5151 return make_error(
5252 Twine("Unsupported XRay file version: ") + Twine(FileHeader.Version),
5353 std::make_error_code(std::errc::invalid_argument));
9292 break;
9393 case 1:
9494 Record.Type = RecordTypes::EXIT;
95 break;
96 case 2:
97 Record.Type = RecordTypes::TAIL_EXIT;
9598 break;
9699 default:
97100 return make_error(
319322 Record.Type = RecordTypes::ENTER;
320323 break;
321324 case static_cast(RecordTypes::EXIT):
322 case 2: // TAIL_EXIT is not yet defined in RecordTypes.
323325 Record.Type = RecordTypes::EXIT;
326 break;
327 case static_cast(RecordTypes::TAIL_EXIT):
328 Record.Type = RecordTypes::TAIL_EXIT;
324329 break;
325330 default:
326331 // Cast to an unsigned integer to not interpret the record type as a char.
442447 // Having iterated over everything we've been given, we've either consumed
443448 // everything and ended up in the end state, or were told to skip the rest.
444449 bool Finished = State.Expects == FDRState::Token::SCAN_TO_END_OF_THREAD_BUF &&
445 State.CurrentBufferSize == State.CurrentBufferConsumed;
450 State.CurrentBufferSize == State.CurrentBufferConsumed;
446451 if (State.Expects != FDRState::Token::NEW_BUFFER_RECORD_OR_EOF && !Finished)
447452 return make_error(
448453 Twine("Encountered EOF with unexpected state expectation ") +
533538 enum BinaryFormatType { NAIVE_FORMAT = 0, FLIGHT_DATA_RECORDER_FORMAT = 1 };
534539
535540 Trace T;
536 if (Version == 1 && Type == NAIVE_FORMAT) {
537 if (auto E =
538 loadNaiveFormatLog(Data, T.FileHeader, T.Records))
541 if (Type == NAIVE_FORMAT && (Version == 1 || Version == 2)) {
542 if (auto E = loadNaiveFormatLog(Data, T.FileHeader, T.Records))
539543 return std::move(E);
540544 } else if (Version == 1 && Type == FLIGHT_DATA_RECORDER_FORMAT) {
541545 if (auto E = loadFDRLog(Data, T.FileHeader, T.Records))
1515 ; CHECK-NEXT: - { type: 0, func-id: 2, function: '2', cpu: 5, thread: 5, kind: function-exit, tsc: 7238225556407467 }
1616 ; CHECK-NEXT: - { type: 0, func-id: 4, function: '4', cpu: 5, thread: 5, kind: function-enter, tsc: 7238225556407492 }
1717 ; CHECK-NEXT: - { type: 0, func-id: 5, function: '5', cpu: 5, thread: 5, kind: function-enter, tsc: 7238225556407517 }
18 ; CHECK-NEXT: - { type: 0, func-id: 5, function: '5', cpu: 5, thread: 5, kind: function-exit, tsc: 7238225556407542 }
18 ; CHECK-NEXT: - { type: 0, func-id: 5, function: '5', cpu: 5, thread: 5, kind: function-tail-exit, tsc: 7238225556407542 }
1919 ; CHECK-NEXT: - { type: 0, func-id: 268435455, function: '268435455', cpu: 5, thread: 5, kind: function-enter, tsc: 7238225556407552 }
2020 ; CHECK-NEXT: - { type: 0, func-id: 268435455, function: '268435455', cpu: 5, thread: 5, kind: function-exit, tsc: 7238225556407562 }
2121 ; CHECK-NEXT: - { type: 0, func-id: 6, function: '6', cpu: 6, thread: 5, kind: function-enter, tsc: 7238225556407682 }
149149 ThreadStack.emplace_back(Record.FuncId, Record.TSC);
150150 break;
151151 }
152 case RecordTypes::EXIT: {
152 case RecordTypes::EXIT:
153 case RecordTypes::TAIL_EXIT: {
153154 if (ThreadStack.empty())
154155 return false;
155156
418419 case RecordTypes::EXIT:
419420 Stream << "exit";
420421 break;
422 case RecordTypes::TAIL_EXIT:
423 Stream << "tail-exit";
424 break;
421425 }
422426 }
423427 };
127127 case RecordTypes::EXIT:
128128 Writer.write(uint8_t{1});
129129 break;
130 case RecordTypes::TAIL_EXIT:
131 Writer.write(uint8_t{2});
132 break;
130133 }
131134 Writer.write(R.FuncId);
132135 Writer.write(R.TSC);
213213 ThreadStack.push_back({Record.FuncId, Record.TSC});
214214 break;
215215 }
216 case RecordTypes::EXIT: {
216 case RecordTypes::EXIT:
217 case RecordTypes::TAIL_EXIT: {
217218 // FIXME: Refactor this and the account subcommand to reduce code
218219 // duplication
219220 if (ThreadStack.size() == 0 || ThreadStack.back().FuncId != Record.FuncId) {
351351 }
352352 return AccountRecordStatus::OK;
353353 }
354 case RecordTypes::EXIT: {
354 case RecordTypes::EXIT:
355 case RecordTypes::TAIL_EXIT: {
355356 bool wasLastRecordExit = state->wasLastRecordExit;
356357 state->wasLastRecordExit = true;
357358 // The exit case is more interesting, since we want to be able to deduce