Skip to content

Commit 4435a37

Browse files
authored
Merge pull request #41803 from ktoso/wip-abi-cleanup
[Distributed] Remove mangled names from API, move to RemoteCallTarget and pretty print it
2 parents 1f629f7 + 6caeecd commit 4435a37

21 files changed

+374
-128
lines changed

include/swift/Runtime/HeapObject.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,15 @@ swift_getTypeName(const Metadata *type, bool qualified);
11011101
/// -> (UnsafePointer<UInt8>, Int)
11021102
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
11031103
TypeNamePair
1104+
swift_getFunctionFullNameFromMangledName(
1105+
const char *mangledNameStart, uintptr_t mangledNameLength);
1106+
1107+
/// Return the human-readable full name of the mangled function name passed in.
1108+
/// func _getMangledTypeName(_ mangledName: UnsafePointer<UInt8>,
1109+
/// mangledNameLength: UInt)
1110+
/// -> (UnsafePointer<UInt8>, Int)
1111+
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
1112+
TypeNamePair
11041113
swift_getMangledTypeName(const Metadata *type);
11051114

11061115
} // end namespace swift

lib/SILGen/SILGenDistributed.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ using namespace Lowering;
4343
/// or the subsequent cast to VarDecl failed.
4444
static VarDecl* lookupProperty(NominalTypeDecl *decl, DeclName name) {
4545
assert(decl && "decl was null");
46-
auto &C = decl->getASTContext();
47-
4846
if (auto clazz = dyn_cast<ClassDecl>(decl)) {
4947
auto refs = decl->lookupDirect(name);
5048
if (refs.size() != 1)

lib/Sema/CodeSynthesisDistributedActor.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,6 @@ addDistributedActorCodableConformance(
564564
assert(proto->isSpecificProtocol(swift::KnownProtocolKind::Decodable) ||
565565
proto->isSpecificProtocol(swift::KnownProtocolKind::Encodable));
566566
auto &C = actor->getASTContext();
567-
auto DC = actor->getDeclContext();
568567
auto module = actor->getParentModule();
569568

570569
// === Only Distributed actors can gain this implicit conformance

lib/Sema/TypeCheckDistributed.cpp

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -311,21 +311,6 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements(
311311
if (checkAdHocRequirementAccessControl(decl, Proto, recordArgumentDecl))
312312
anyMissingAdHocRequirements = true;
313313

314-
// - recordErrorType
315-
auto recordErrorTypeDecl = C.getRecordErrorTypeOnDistributedInvocationEncoder(decl);
316-
if (!recordErrorTypeDecl) {
317-
auto identifier = C.Id_recordErrorType;
318-
decl->diagnose(
319-
diag::distributed_actor_system_conformance_missing_adhoc_requirement,
320-
decl->getDescriptiveKind(), decl->getName(), identifier);
321-
decl->diagnose(diag::note_distributed_actor_system_conformance_missing_adhoc_requirement,
322-
decl->getName(), identifier,
323-
"mutating func recordErrorType<Err: Error>(_ errorType: Err.Type) throws\n");
324-
anyMissingAdHocRequirements = true;
325-
}
326-
if (checkAdHocRequirementAccessControl(decl, Proto, recordErrorTypeDecl))
327-
anyMissingAdHocRequirements = true;
328-
329314
// - recordReturnType
330315
auto recordReturnTypeDecl = C.getRecordReturnTypeOnDistributedInvocationEncoder(decl);
331316
if (!recordReturnTypeDecl) {
@@ -736,13 +721,13 @@ GetDistributedRemoteCallTargetInitFunctionRequest::evaluate(
736721
if (params->size() != 1)
737722
return nullptr;
738723

739-
if (params->get(0)->getArgumentName() == C.getIdentifier("_mangledName"))
724+
// _ identifier
725+
if (params->get(0)->getArgumentName().empty())
740726
return ctor;
741727

742728
return nullptr;
743729
}
744730

745-
// TODO(distributed): make a Request for it?
746731
return nullptr;
747732
}
748733

stdlib/public/Distributed/DistributedActorSystem.swift

Lines changed: 56 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -172,23 +172,21 @@ extension DistributedActorSystem {
172172
/// latency sensitive-use-cases.
173173
public func executeDistributedTarget<Act, ResultHandler>(
174174
on actor: Act,
175-
mangledTargetName: String,
175+
target: RemoteCallTarget,
176176
invocationDecoder: inout InvocationDecoder,
177177
handler: ResultHandler
178178
) async throws where Act: DistributedActor,
179179
// Act.ID == ActorID, // FIXME(distributed): can we bring this back?
180180
ResultHandler: DistributedTargetInvocationResultHandler {
181-
// NOTE: this implementation is not the most efficient, nor final, version of this func
182-
// we end up demangling the name multiple times, perform more heap allocations than
183-
// we truly need to etc. We'll eventually move this implementation to a specialized one
184-
// avoiding these issues.
185-
guard mangledTargetName.count > 0 && mangledTargetName.first == "$" else {
186-
throw ExecuteDistributedTargetError(
187-
message: "Illegal mangledTargetName detected, must start with '$'")
188-
}
181+
// NOTE: Implementation could be made more efficient because we still risk
182+
// demangling a RemoteCallTarget identity (if it is a mangled name) multiple
183+
// times. We would prefer to store if it is a mangled name, demangle, and
184+
// always refer to that demangled repr perhaps? We do cache the resulting
185+
// pretty formatted name of the call target, but perhaps we can do better.
189186

190187
// Get the expected parameter count of the func
191-
let nameUTF8 = Array(mangledTargetName.utf8)
188+
let targetName = target.identifier
189+
let nameUTF8 = Array(targetName.utf8)
192190

193191
// Gen the generic environment (if any) associated with the target.
194192
let genericEnv = nameUTF8.withUnsafeBufferPointer { nameUTF8 in
@@ -207,7 +205,9 @@ extension DistributedActorSystem {
207205

208206
if let genericEnv = genericEnv {
209207
let subs = try invocationDecoder.decodeGenericSubstitutions()
210-
208+
for item in subs {
209+
print("SUB: \(item)")
210+
}
211211
if subs.isEmpty {
212212
throw ExecuteDistributedTargetError(
213213
message: "Cannot call generic method without generic argument substitutions")
@@ -224,7 +224,7 @@ extension DistributedActorSystem {
224224
genericArguments: substitutionsBuffer!)
225225
if numWitnessTables < 0 {
226226
throw ExecuteDistributedTargetError(
227-
message: "Generic substitutions \(subs) do not satisfy generic requirements of \(mangledTargetName)")
227+
message: "Generic substitutions \(subs) do not satisfy generic requirements of \(target) (\(targetName))")
228228
}
229229
}
230230

@@ -237,7 +237,7 @@ extension DistributedActorSystem {
237237
message: """
238238
Failed to decode distributed invocation target expected parameter count,
239239
error code: \(paramCount)
240-
mangled name: \(mangledTargetName)
240+
mangled name: \(targetName)
241241
""")
242242
}
243243

@@ -262,7 +262,7 @@ extension DistributedActorSystem {
262262
message: """
263263
Failed to decode the expected number of params of distributed invocation target, error code: \(decodedNum)
264264
(decoded: \(decodedNum), expected params: \(paramCount)
265-
mangled name: \(mangledTargetName)
265+
mangled name: \(targetName)
266266
""")
267267
}
268268

@@ -280,7 +280,7 @@ extension DistributedActorSystem {
280280
return UnsafeRawPointer(UnsafeMutablePointer<R>.allocate(capacity: 1))
281281
}
282282

283-
guard let returnTypeFromTypeInfo: Any.Type = _getReturnTypeInfo(mangledMethodName: mangledTargetName,
283+
guard let returnTypeFromTypeInfo: Any.Type = _getReturnTypeInfo(mangledMethodName: targetName,
284284
genericEnv: genericEnv,
285285
genericArguments: substitutionsBuffer) else {
286286
throw ExecuteDistributedTargetError(
@@ -307,7 +307,7 @@ extension DistributedActorSystem {
307307
// Execute the target!
308308
try await _executeDistributedTarget(
309309
on: actor,
310-
mangledTargetName, UInt(mangledTargetName.count),
310+
targetName, UInt(targetName.count),
311311
argumentDecoder: &invocationDecoder,
312312
argumentTypes: argumentTypesBuffer.baseAddress!._rawValue,
313313
resultBuffer: resultBuffer._rawValue,
@@ -326,6 +326,43 @@ extension DistributedActorSystem {
326326
}
327327
}
328328

329+
/// Represents a 'target' of a distributed call, such as a `distributed func` or
330+
/// `distributed` computed property. Identification schemes may vary between
331+
/// systems, and are subject to evolution.
332+
///
333+
/// Actor systems generally should treat the `identifier` as an opaque string,
334+
/// and pass it along to the remote system for in their `remoteCall`
335+
/// implementation. Alternative approaches are possible, where the identifiers
336+
/// are either compressed, cached, or represented in other ways, as long as the
337+
/// recipient system is able to determine which target was intended to be
338+
/// invoked.
339+
///
340+
/// The string representation will attempt to pretty print the target identifier,
341+
/// however its exact format is not specified and may change in future versions.
342+
@available(SwiftStdlib 5.7, *)
343+
public struct RemoteCallTarget: CustomStringConvertible {
344+
private let _identifier: String
345+
346+
public init(_ identifier: String) {
347+
self._identifier = identifier
348+
}
349+
350+
/// The underlying identifier of the target, returned as-is.
351+
public var identifier: String {
352+
return _identifier
353+
}
354+
355+
/// Attempts to pretty format the underlying target identifier.
356+
/// If unable to, returns the raw underlying identifier.
357+
public var description: String {
358+
if let name = _getFunctionFullNameFromMangledName(mangledName: _identifier) {
359+
return name
360+
} else {
361+
return "\(_identifier)"
362+
}
363+
}
364+
}
365+
329366
@available(SwiftStdlib 5.7, *)
330367
@_silgen_name("swift_distributed_execute_target")
331368
func _executeDistributedTarget<D: DistributedTargetInvocationDecoder>(
@@ -339,29 +376,6 @@ func _executeDistributedTarget<D: DistributedTargetInvocationDecoder>(
339376
numWitnessTables: UInt
340377
) async throws
341378

342-
// ==== ----------------------------------------------------------------------------------------------------------------
343-
// MARK: Support types
344-
/// A distributed 'target' can be a `distributed func` or `distributed` computed property.
345-
@available(SwiftStdlib 5.7, *)
346-
public struct RemoteCallTarget { // TODO: ship this around always; make printing nice
347-
let _mangledName: String // TODO: StaticString would be better here; no arc, codesize of cleanups
348-
349-
// Only intended to be created by the _Distributed library.
350-
// TODO(distributed): make this internal and only allow calling by the synthesized code?
351-
public init(_mangledName: String) {
352-
self._mangledName = _mangledName
353-
}
354-
355-
public var mangledName: String {
356-
_mangledName
357-
}
358-
359-
// <module>.Base.hello(hi:)
360-
public var fullName: String { // TODO: make description
361-
fatalError("NOT IMPLEMENTED YET: \(#function)")
362-
}
363-
}
364-
365379
/// Used to encode an invocation of a distributed target (method or computed property).
366380
///
367381
/// ## Forming an invocation
@@ -407,11 +421,9 @@ public protocol DistributedTargetInvocationEncoder {
407421
// mutating func recordArgument<Argument: SerializationRequirement>(_ argument: Argument) throws
408422
// TODO(distributed): offer recordArgument(label:type:)
409423

410-
// /// Ad-hoc requirement
411-
// ///
412-
// /// Record the error type of the distributed method.
413-
// /// This method will not be invoked if the target is not throwing.
414-
// mutating func recordErrorType<E: Error>(_ type: E.Type) throws // TODO: make not adhoc
424+
/// Record the error type of the distributed method.
425+
/// This method will not be invoked if the target is not throwing.
426+
mutating func recordErrorType<E: Error>(_ type: E.Type) throws
415427

416428
// /// Ad-hoc requirement
417429
// ///

stdlib/public/core/Misc.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,35 @@ public func _autorelease(_ x: AnyObject) {
4646
}
4747
#endif
4848

49+
50+
@available(SwiftStdlib 5.7, *)
51+
@_silgen_name("swift_getFunctionFullNameFromMangledName")
52+
public // SPI (Distributed)
53+
func _getFunctionFullNameFromMangledNameImpl(
54+
_ mangledName: UnsafePointer<UInt8>, _ mangledNameLength: UInt
55+
) -> (UnsafePointer<UInt8>, UInt)
56+
57+
/// Given a function's mangled name, return a human readable name.
58+
/// Used e.g. by Distributed.RemoteCallTarget to hide mangled names.
59+
@available(SwiftStdlib 5.7, *)
60+
public // SPI (Distributed)
61+
func _getFunctionFullNameFromMangledName(mangledName: String) -> String? {
62+
let mangledNameUTF8 = Array(mangledName.utf8)
63+
let (stringPtr, count) =
64+
mangledNameUTF8.withUnsafeBufferPointer { (mangledNameUTF8) in
65+
return _getFunctionFullNameFromMangledNameImpl(
66+
mangledNameUTF8.baseAddress!,
67+
UInt(mangledNameUTF8.endIndex))
68+
}
69+
70+
guard count > 0 else {
71+
return nil
72+
}
73+
74+
return String._fromUTF8Repairing(
75+
UnsafeBufferPointer(start: stringPtr, count: Int(count))).0
76+
}
77+
4978
// FIXME(ABI)#51 : this API should allow controlling different kinds of
5079
// qualification separately: qualification with module names and qualification
5180
// with type names that we are nested in.

0 commit comments

Comments
 (0)