Skip to content

Commit 12b1843

Browse files
authored
Merge pull request #66377 from mikeash/section-scan-signposts
[Runtime] Add tracing for section scans.
2 parents 2b8a397 + 110f428 commit 12b1843

File tree

11 files changed

+273
-5
lines changed

11 files changed

+273
-5
lines changed

stdlib/cmake/modules/AddSwiftStdlib.cmake

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,10 @@ function(_add_target_variant_c_compile_flags)
417417
list(APPEND result "-DSWIFT_STDLIB_ENABLE_UNICODE_DATA")
418418
endif()
419419

420+
if(SWIFT_STDLIB_TRACING)
421+
list(APPEND result "-DSWIFT_STDLIB_TRACING")
422+
endif()
423+
420424
if(SWIFT_STDLIB_CONCURRENCY_TRACING)
421425
list(APPEND result "-DSWIFT_STDLIB_CONCURRENCY_TRACING")
422426
endif()
@@ -897,7 +901,7 @@ function(add_swift_target_library_single target name)
897901

898902
# Define availability macros.
899903
foreach(def ${SWIFT_STDLIB_AVAILABILITY_DEFINITIONS})
900-
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS "-Xfrontend" "-define-availability" "-Xfrontend" "${def}")
904+
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS "-Xfrontend" "-define-availability" "-Xfrontend" "${def}")
901905
endforeach()
902906

903907
# Enable -target-min-inlining-version

stdlib/cmake/modules/StdlibOptions.cmake

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,11 +221,18 @@ set(SWIFT_STDLIB_ENABLE_LTO OFF CACHE STRING "Build Swift stdlib with LTO. One
221221
option only affects the standard library and runtime, not tools.")
222222

223223
if("${SWIFT_HOST_VARIANT_SDK}" IN_LIST SWIFT_DARWIN_PLATFORMS)
224+
set(SWIFT_STDLIB_TRACING_default TRUE)
224225
set(SWIFT_STDLIB_CONCURRENCY_TRACING_default TRUE)
225226
else()
227+
set(SWIFT_STDLIB_TRACING_default FALSE)
226228
set(SWIFT_STDLIB_CONCURRENCY_TRACING_default FALSE)
227229
endif()
228230

231+
option(SWIFT_STDLIB_TRACING
232+
"Enable tracing in the runtime; assumes the presence of os_log(3)
233+
and the os_signpost(3) API."
234+
"${SWIFT_STDLIB_TRACING_default}")
235+
229236
option(SWIFT_STDLIB_CONCURRENCY_TRACING
230237
"Enable concurrency tracing in the runtime; assumes the presence of os_log(3)
231238
and the os_signpost(3) API."

stdlib/public/runtime/AccessibleFunction.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/Runtime/AccessibleFunction.h"
2222
#include "swift/Runtime/Concurrent.h"
2323
#include "swift/Runtime/Metadata.h"
24+
#include "Tracing.h"
2425

2526
#include <cstdint>
2627
#include <new>
@@ -120,12 +121,14 @@ void swift::addImageAccessibleFunctionsBlockCallback(
120121

121122
static const AccessibleFunctionRecord *
122123
_searchForFunctionRecord(AccessibleFunctionsState &S, llvm::StringRef name) {
124+
auto traceState = runtime::trace::accessible_function_scan_begin(name);
125+
123126
for (const auto &section : S.SectionsToScan.snapshot()) {
124127
for (auto &record : section) {
125128
auto recordName =
126129
swift::Demangle::makeSymbolicMangledNameStringRef(record.Name.get());
127130
if (recordName == name)
128-
return &record;
131+
return traceState.end(&record);
129132
}
130133
}
131134
return nullptr;

stdlib/public/runtime/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ set(swift_runtime_sources
7676
SwiftDtoa.cpp
7777
SwiftTLSContext.cpp
7878
ThreadingError.cpp
79+
Tracing.cpp
7980
AccessibleFunction.cpp
8081
Win32.cpp)
8182

stdlib/public/runtime/Demangle.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,9 @@ swift::_swift_buildDemanglingForMetadata(const Metadata *type,
822822
auto metatype = static_cast<const MetatypeMetadata *>(type);
823823
auto instance = _swift_buildDemanglingForMetadata(metatype->InstanceType,
824824
Dem);
825+
if (!instance)
826+
return nullptr;
827+
825828
auto typeNode = Dem.createNode(Node::Kind::Type);
826829
typeNode->addChild(instance, Dem);
827830
auto node = Dem.createNode(Node::Kind::Metatype);

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "../CompatibilityOverride/CompatibilityOverride.h"
1818
#include "ImageInspection.h"
1919
#include "Private.h"
20+
#include "Tracing.h"
2021
#include "swift/ABI/TypeIdentity.h"
2122
#include "swift/Basic/Lazy.h"
2223
#include "swift/Demangling/Demangler.h"
@@ -742,11 +743,13 @@ _searchTypeMetadataRecords(TypeMetadataPrivateState &T,
742743
return nullptr;
743744
#endif
744745

746+
auto traceState = runtime::trace::metadata_scan_begin(node);
747+
745748
for (auto &section : T.SectionsToScan.snapshot()) {
746749
for (const auto &record : section) {
747750
if (auto context = record.getContextDescriptor()) {
748751
if (_contextDescriptorMatchesMangling(context, node)) {
749-
return context;
752+
return traceState.end(context);
750753
}
751754
}
752755
}
@@ -970,11 +973,13 @@ void swift::swift_registerProtocols(const ProtocolRecord *begin,
970973
static const ProtocolDescriptor *
971974
_searchProtocolRecords(ProtocolMetadataPrivateState &C,
972975
NodePointer node) {
976+
auto traceState = runtime::trace::protocol_scan_begin(node);
977+
973978
for (auto &section : C.SectionsToScan.snapshot()) {
974979
for (const auto &record : section) {
975980
if (auto protocol = record.Protocol.getPointer()) {
976981
if (_contextDescriptorMatchesMangling(protocol, node))
977-
return protocol;
982+
return traceState.end(protocol);
978983
}
979984
}
980985
}

stdlib/public/runtime/ProtocolConformance.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "../CompatibilityOverride/CompatibilityOverride.h"
3131
#include "ImageInspection.h"
3232
#include "Private.h"
33+
#include "Tracing.h"
3334

3435
#include <new>
3536
#include <vector>
@@ -1089,6 +1090,9 @@ swift_conformsToProtocolMaybeInstantiateSuperclasses(
10891090
}
10901091
};
10911092

1093+
auto traceState =
1094+
runtime::trace::protocol_conformance_scan_begin(type, protocol);
1095+
10921096
auto snapshot = C.SectionsToScan.snapshot();
10931097
if (C.scanSectionsBackwards) {
10941098
for (auto &section : llvm::reverse(snapshot))
@@ -1125,6 +1129,8 @@ swift_conformsToProtocolMaybeInstantiateSuperclasses(
11251129
}
11261130
noteFinalMetadataState(superclassIterator.state);
11271131

1132+
traceState.end(foundWitness);
1133+
11281134
// If it's for a superclass or if we didn't find anything, then add an
11291135
// authoritative entry for this type.
11301136
if (foundType != type)
@@ -1170,13 +1176,15 @@ swift_conformsToProtocolImpl(const Metadata *const type,
11701176

11711177
const ContextDescriptor *
11721178
swift::_searchConformancesByMangledTypeName(Demangle::NodePointer node) {
1179+
auto traceState = runtime::trace::protocol_conformance_scan_begin(node);
1180+
11731181
auto &C = Conformances.get();
11741182

11751183
for (auto &section : C.SectionsToScan.snapshot()) {
11761184
for (const auto &record : section) {
11771185
if (auto ntd = record->getTypeDescriptor()) {
11781186
if (_contextDescriptorMatchesMangling(ntd, node))
1179-
return ntd;
1187+
return traceState.end(ntd);
11801188
}
11811189
}
11821190
}

stdlib/public/runtime/Tracing.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//===--- Tracing.cpp - Support code for runtime tracing ------------*- C++ -*-//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// Support code for tracing events in the Swift runtime
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#include "Tracing.h"
18+
19+
#if SWIFT_STDLIB_TRACING
20+
21+
#define SWIFT_LOG_SUBSYSTEM "com.apple.swift"
22+
#define SWIFT_LOG_SECTION_SCAN_CATEGORY "SectionScan"
23+
24+
namespace swift {
25+
namespace runtime {
26+
namespace trace {
27+
28+
os_log_t ScanLog;
29+
swift::once_t LogsToken;
30+
31+
void setupLogs(void *unused) {
32+
ScanLog = os_log_create(SWIFT_LOG_SUBSYSTEM, SWIFT_LOG_SECTION_SCAN_CATEGORY);
33+
}
34+
35+
} // namespace trace
36+
} // namespace runtime
37+
} // namespace swift
38+
39+
#endif

stdlib/public/runtime/Tracing.h

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
//===--- Tracing.h - Support code for runtime tracing --------------*- C++ -*-//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// Support code for tracing events in the Swift runtime
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_TRACING_H
18+
#define SWIFT_TRACING_H
19+
20+
#include "llvm/ADT/StringRef.h"
21+
#include "swift/ABI/Metadata.h"
22+
#include "swift/Demangling/Demangler.h"
23+
24+
#if SWIFT_STDLIB_TRACING
25+
#include <os/signpost.h>
26+
27+
#include "swift/Runtime/HeapObject.h"
28+
29+
#define SWIFT_LOG_SECTION_SCAN "section_scan"
30+
31+
namespace swift {
32+
namespace runtime {
33+
namespace trace {
34+
35+
extern os_log_t ScanLog;
36+
extern swift::once_t LogsToken;
37+
38+
void setupLogs(void *unused);
39+
40+
// Every function does ENSURE_LOGS() before making any os_signpost calls, so
41+
// we can skip availability checking on all the individual calls.
42+
#pragma clang diagnostic push
43+
#pragma clang diagnostic ignored "-Wunguarded-availability"
44+
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
45+
46+
// Check a representative os_signpost function for NULL rather than doing a
47+
// standard availability check, for better performance if the check doesn't get
48+
// optimized out.
49+
#define ENSURE_LOG(log) \
50+
do { \
51+
if (!SWIFT_RUNTIME_WEAK_CHECK(os_signpost_enabled)) \
52+
return {}; \
53+
swift::once(LogsToken, setupLogs, nullptr); \
54+
} while (0)
55+
56+
/// A struct that captures the state of a scan tracing signpost. When the scan
57+
/// is complete, call end() with the result of the scan. If the state struct
58+
/// goes out of scope without calling end(), then it will automatically do the
59+
/// equivalent of end(nullptr).
60+
struct ScanTraceState {
61+
os_signpost_id_t signpostID;
62+
63+
bool ended = false;
64+
65+
template <typename T>
66+
T *end(T *result) {
67+
ended = true;
68+
os_signpost_interval_end(ScanLog, signpostID, SWIFT_LOG_SECTION_SCAN,
69+
"result=%p", result);
70+
return result;
71+
}
72+
73+
~ScanTraceState() {
74+
if (!ended)
75+
end((void *)nullptr);
76+
}
77+
};
78+
79+
static inline ScanTraceState
80+
accessible_function_scan_begin(llvm::StringRef name) {
81+
ENSURE_LOG(ScanLog);
82+
83+
auto id = os_signpost_id_generate(ScanLog);
84+
os_signpost_interval_begin(ScanLog, id, SWIFT_LOG_SECTION_SCAN,
85+
"accessible function scan for '%.*s'",
86+
(int)name.size(), name.data());
87+
return {id};
88+
}
89+
90+
static inline ScanTraceState metadata_scan_begin(Demangle::NodePointer node) {
91+
ENSURE_LOG(ScanLog);
92+
93+
auto id = os_signpost_id_generate(ScanLog);
94+
os_signpost_interval_begin(ScanLog, id, SWIFT_LOG_SECTION_SCAN,
95+
"metadata scan for %s",
96+
node ? nodeToString(node).c_str() : "<null>");
97+
return {id};
98+
}
99+
100+
static inline ScanTraceState
101+
protocol_conformance_scan_begin(Demangle::NodePointer node) {
102+
ENSURE_LOG(ScanLog);
103+
104+
auto id = os_signpost_id_generate(ScanLog);
105+
os_signpost_interval_begin(ScanLog, id, SWIFT_LOG_SECTION_SCAN,
106+
"protocol conformance scan for %s",
107+
node ? nodeToString(node).c_str() : "<null>");
108+
return {id};
109+
}
110+
111+
static inline ScanTraceState
112+
protocol_conformance_scan_begin(const Metadata *type,
113+
const ProtocolDescriptor *protocol) {
114+
ENSURE_LOG(ScanLog);
115+
116+
auto id = os_signpost_id_generate(ScanLog);
117+
118+
// Check for enablement separately to avoid the potentially expensive
119+
// swift_getTypeName call when tracing is not enabled.
120+
if (os_signpost_enabled(ScanLog)) {
121+
auto typeName = swift_getTypeName(type, /*qualified*/ true);
122+
auto protoName = protocol ? protocol->Name.get() : "<null>";
123+
os_signpost_interval_begin(ScanLog, id, SWIFT_LOG_SECTION_SCAN,
124+
"protocol conformance scan for %.*s(%p): %s(%p)",
125+
(int)typeName.length, typeName.data, type,
126+
protoName, protocol);
127+
}
128+
return {id};
129+
}
130+
131+
static inline ScanTraceState protocol_scan_begin(Demangle::NodePointer node) {
132+
ENSURE_LOG(ScanLog);
133+
134+
auto id = os_signpost_id_generate(ScanLog);
135+
os_signpost_interval_begin(ScanLog, id, SWIFT_LOG_SECTION_SCAN,
136+
"protocol scan for '%s'",
137+
node ? nodeToString(node).c_str() : "<null>");
138+
return {id};
139+
}
140+
141+
#pragma clang diagnostic pop
142+
143+
} // namespace trace
144+
} // namespace runtime
145+
} // namespace swift
146+
147+
#else
148+
149+
namespace swift {
150+
namespace runtime {
151+
namespace trace {
152+
153+
struct ScanTraceState {
154+
template <typename T>
155+
T *end(T *result) {
156+
return result;
157+
}
158+
};
159+
160+
static inline ScanTraceState
161+
accessible_function_scan_begin(llvm::StringRef name) {
162+
return {};
163+
}
164+
165+
static inline ScanTraceState metadata_scan_begin(Demangle::NodePointer node) {
166+
return {};
167+
}
168+
169+
static inline ScanTraceState
170+
protocol_conformance_scan_begin(Demangle::NodePointer node) {
171+
return {};
172+
}
173+
174+
static inline ScanTraceState
175+
protocol_conformance_scan_begin(const Metadata *type,
176+
const ProtocolDescriptor *protocol) {
177+
return {};
178+
}
179+
180+
static inline ScanTraceState protocol_scan_begin(Demangle::NodePointer node) {
181+
return {};
182+
}
183+
184+
} // namespace trace
185+
} // namespace runtime
186+
} // namespace swift
187+
188+
#endif
189+
190+
#endif // SWIFT_TRACING_H

0 commit comments

Comments
 (0)