Skip to content

[runtime] Remove TwoWordPair and use the Swift calling convention instead. #14373

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 13 additions & 64 deletions include/swift/Runtime/HeapObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,66 +90,10 @@ HeapObject *swift_initStaticObject(HeapMetadata const *metadata,
SWIFT_RUNTIME_EXPORT
void swift_verifyEndOfLifetime(HeapObject *object);

/// A structure that's two pointers in size.
///
/// C functions can use the TwoWordPair::Return type to return a value in
/// two registers, compatible with Swift's calling convention for tuples
/// and structs of two word-sized elements.
template<typename A, typename B>
struct TwoWordPair {
A first;
B second;

TwoWordPair() = default;
TwoWordPair(A first, B second);

// FIXME: rdar://36755525 clang miscompiles swiftcall functions
// Structs are returned indirectly on these platforms, but we want to return
// in registers, so cram the result into an unsigned long long.
// Use an enum class with implicit conversions so we don't dirty C callers
// too much.
#if __arm__ || __i386__ || defined(__CYGWIN__) || defined(_MSC_VER)
#if defined(__CYGWIN__)
enum class Return : unsigned __int128 {};
#else
enum class Return : unsigned long long {};
#endif

operator Return() const {
union {
TwoWordPair value;
Return mangled;
} reinterpret = {*this};

return reinterpret.mangled;
}

/*implicit*/ TwoWordPair(Return r) {
union {
Return mangled;
TwoWordPair value;
} reinterpret = {r};

*this = reinterpret.value;
}
#else
using Return = TwoWordPair;
#endif
struct BoxPair {
HeapObject *object;
OpaqueValue *buffer;
};

template<typename A, typename B>
inline TwoWordPair<A,B>::TwoWordPair(A first, B second)
: first(first), second(second)
{
static_assert(sizeof(A) == sizeof(void*),
"first type must be word-sized");
static_assert(sizeof(B) == sizeof(void*),
"second type must be word-sized");
static_assert(alignof(TwoWordPair) == alignof(void*),
"pair must be word-aligned");
}

using BoxPair = TwoWordPair<HeapObject *, OpaqueValue *>;

/// Allocates a heap object that can contain a value of the given type.
/// Returns a Box structure containing a HeapObject* pointer to the
Expand All @@ -158,16 +102,16 @@ using BoxPair = TwoWordPair<HeapObject *, OpaqueValue *>;
/// appropriate to store a value of the given type.
/// The heap object has an initial retain count of 1, and its metadata is set
/// such that destroying the heap object destroys the contained value.
SWIFT_RUNTIME_EXPORT
BoxPair::Return swift_allocBox(Metadata const *type);
SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
BoxPair swift_allocBox(Metadata const *type);

/// Performs a uniqueness check on the pointer to a box structure. If the check
/// fails allocates a new box and stores the pointer in the buffer.
///
/// if (!isUnique(buffer[0]))
/// buffer[0] = swift_allocBox(type)
SWIFT_RUNTIME_EXPORT
BoxPair::Return swift_makeBoxUnique(OpaqueValue *buffer, Metadata const *type,
SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
BoxPair swift_makeBoxUnique(OpaqueValue *buffer, Metadata const *type,
size_t alignMask);

/// Returns the address of a heap object representing all empty box types.
Expand Down Expand Up @@ -1147,11 +1091,16 @@ static inline bool swift_unknownUnownedIsEqual(UnownedReference *ref,

#endif /* SWIFT_OBJC_INTEROP */

struct TypeNamePair {
const char *data;
uintptr_t length;
};

/// Return the name of a Swift type represented by a metadata object.
/// func _getTypeName(_ type: Any.Type, qualified: Bool)
/// -> (UnsafePointer<UInt8>, Int)
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
TwoWordPair<const char *, uintptr_t>::Return
TypeNamePair
swift_getTypeName(const Metadata *type, bool qualified);

} // end namespace swift
Expand Down
2 changes: 0 additions & 2 deletions include/swift/Runtime/InstrumentsSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ HeapObject *(*_swift_allocObject)(HeapMetadata const *metadata,
size_t requiredSize,
size_t requiredAlignmentMask);
SWIFT_RUNTIME_EXPORT
BoxPair::Return (*_swift_allocBox)(Metadata const *type);
SWIFT_RUNTIME_EXPORT
HeapObject *(*_swift_retain)(HeapObject *object);
SWIFT_RUNTIME_EXPORT
HeapObject *(*_swift_retain_n)(HeapObject *object, uint32_t n);
Expand Down
6 changes: 3 additions & 3 deletions include/swift/Runtime/RuntimeFunctions.def
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@
#define FUNCTION(Id, Name, CC, ReturnTys, ArgTys, Attrs) FUNCTION_ID(Id)
#endif

FUNCTION(AllocBox, swift_allocBox, C_CC,
FUNCTION(AllocBox, swift_allocBox, SwiftCC,
RETURNS(RefCountedPtrTy, OpaquePtrTy),
ARGS(TypeMetadataPtrTy),
ATTRS(NoUnwind))

// BoxPair swift_makeBoxUnique(OpaqueValue *buffer, Metadata *type, size_t alignMask);
FUNCTION(MakeBoxUnique,
swift_makeBoxUnique,
C_CC,
SwiftCC,
RETURNS(RefCountedPtrTy, OpaquePtrTy),
ARGS(OpaquePtrTy, TypeMetadataPtrTy, SizeTy),
ATTRS(NoUnwind))
Expand Down Expand Up @@ -1311,7 +1311,7 @@ FUNCTION(DeletedMethodError, swift_deletedMethodError, C_CC,
ARGS(),
ATTRS(NoUnwind))

FUNCTION(AllocError, swift_allocError, C_CC,
FUNCTION(AllocError, swift_allocError, SwiftCC,
RETURNS(ErrorPtrTy, OpaquePtrTy),
ARGS(TypeMetadataPtrTy, WitnessTablePtrTy, OpaquePtrTy, Int1Ty),
ATTRS(NoUnwind))
Expand Down
6 changes: 3 additions & 3 deletions stdlib/public/SDK/Foundation/CheckClass.mm
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ static void logIfFirstOccurrence(Class objcClass, void (^log)(void)) {
template <size_t N>
StringRefLite(const char (&staticStr)[N]) : data(staticStr), length(N) {}

StringRefLite(swift::TwoWordPair<const char *, uintptr_t>::Return rawValue)
: data(swift::TwoWordPair<const char *, uintptr_t>(rawValue).first),
length(swift::TwoWordPair<const char *, uintptr_t>(rawValue).second){}
StringRefLite(swift::TypeNamePair rawValue)
: data(rawValue.data),
length(rawValue.length){}

NS_RETURNS_RETAINED
NSString *newNSStringNoCopy() const {
Expand Down
13 changes: 6 additions & 7 deletions stdlib/public/runtime/Casting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,8 @@ std::string swift::nameForMetadata(const Metadata *type,
return result;
}

TwoWordPair<const char *, uintptr_t>::Return
TypeNamePair
swift::swift_getTypeName(const Metadata *type, bool qualified) {
using Pair = TwoWordPair<const char *, uintptr_t>;
using Key = llvm::PointerIntPair<const Metadata *, 1, bool>;

static StaticReadWriteLock TypeNameCacheLock;
Expand All @@ -132,7 +131,7 @@ swift::swift_getTypeName(const Metadata *type, bool qualified) {
auto found = cache.find(key);
if (found != cache.end()) {
auto result = found->second;
return Pair{result.first, result.second};
return TypeNamePair{result.first, result.second};
}
}

Expand All @@ -145,7 +144,7 @@ swift::swift_getTypeName(const Metadata *type, bool qualified) {
auto found = cache.find(key);
if (found != cache.end()) {
auto result = found->second;
return Pair{result.first, result.second};
return TypeNamePair{result.first, result.second};
}

// Build the metadata name.
Expand All @@ -157,7 +156,7 @@ swift::swift_getTypeName(const Metadata *type, bool qualified) {
result[size] = 0;

cache.insert({key, {result, size}});
return Pair{result, size};
return TypeNamePair{result, size};
}
}

Expand Down Expand Up @@ -954,7 +953,7 @@ static bool _dynamicCastToExistential(OpaqueValue *dest,
(canConsumeDynamicValue && (flags & DynamicCastFlags::TakeOnSuccess));
BoxPair destBox = swift_allocError(srcDynamicType, errorWitness,
srcDynamicValue, isTake);
*destBoxAddr = reinterpret_cast<SwiftError*>(destBox.first);
*destBoxAddr = reinterpret_cast<SwiftError*>(destBox.object);
maybeDeallocateSource(true);
return true;
}
Expand Down Expand Up @@ -1976,7 +1975,7 @@ static id dynamicCastValueToNSError(OpaqueValue *src,

BoxPair errorBox = swift_allocError(srcType, srcErrorWitness, src,
/*isTake*/ flags & DynamicCastFlags::TakeOnSuccess);
return _swift_stdlib_bridgeErrorToNSError((SwiftError*)errorBox.first);
return _swift_stdlib_bridgeErrorToNSError((SwiftError*)errorBox.object);
}

#endif
Expand Down
8 changes: 4 additions & 4 deletions stdlib/public/runtime/ErrorObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,10 @@ struct SwiftError : SwiftErrorHeader {
/// copied (or taken if \c isTake is true) into the newly-allocated error box.
/// If value is null, the box's contents will be left uninitialized, and
/// \c isTake should be false.
SWIFT_RUNTIME_STDLIB_API
BoxPair::Return swift_allocError(const Metadata *type,
const WitnessTable *errorConformance,
OpaqueValue *value, bool isTake);
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
BoxPair swift_allocError(const Metadata *type,
const WitnessTable *errorConformance,
OpaqueValue *value, bool isTake);

/// Deallocate an error object whose contained object has already been
/// destroyed.
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/runtime/ErrorObject.mm
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ static Class getSwiftNativeNSErrorClass() {
}

/// Allocate a catchable error object.
BoxPair::Return
BoxPair
swift::swift_allocError(const Metadata *type,
const WitnessTable *errorConformance,
OpaqueValue *initialValue,
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/runtime/ErrorObjectNative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ static const FullMetadata<HeapMetadata> ErrorMetadata{
Metadata{MetadataKind::ErrorObject},
};

BoxPair::Return
BoxPair
swift::swift_allocError(const swift::Metadata *type,
const swift::WitnessTable *errorConformance,
OpaqueValue *initialValue,
Expand Down
14 changes: 4 additions & 10 deletions stdlib/public/runtime/HeapObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ class BoxCacheEntry {

static SimpleGlobalCache<BoxCacheEntry> Boxes;

BoxPair::Return swift::swift_makeBoxUnique(OpaqueValue *buffer, const Metadata *type,
BoxPair swift::swift_makeBoxUnique(OpaqueValue *buffer, const Metadata *type,
size_t alignMask) {
auto *inlineBuffer = reinterpret_cast<ValueBuffer*>(buffer);
HeapObject *box = reinterpret_cast<HeapObject *>(inlineBuffer->PrivateData[0]);
Expand All @@ -222,8 +222,8 @@ BoxPair::Return swift::swift_makeBoxUnique(OpaqueValue *buffer, const Metadata *
auto *oldObjectAddr = reinterpret_cast<OpaqueValue *>(
reinterpret_cast<char *>(box) + headerOffset);
// Copy the data.
type->vw_initializeWithCopy(refAndObjectAddr.second, oldObjectAddr);
inlineBuffer->PrivateData[0] = refAndObjectAddr.first;
type->vw_initializeWithCopy(refAndObjectAddr.buffer, oldObjectAddr);
inlineBuffer->PrivateData[0] = refAndObjectAddr.object;
// Release ownership of the old box.
swift_release(box);
return refAndObjectAddr;
Expand All @@ -235,11 +235,7 @@ BoxPair::Return swift::swift_makeBoxUnique(OpaqueValue *buffer, const Metadata *
}
}

BoxPair::Return swift::swift_allocBox(const Metadata *type) {
return _swift_allocBox(type);
}

static BoxPair::Return _swift_allocBox_(const Metadata *type) {
BoxPair swift::swift_allocBox(const Metadata *type) {
// Get the heap metadata for the box.
auto metadata = &Boxes.getOrInsert(type).first->Data;

Expand All @@ -251,8 +247,6 @@ static BoxPair::Return _swift_allocBox_(const Metadata *type) {
return BoxPair{allocation, projection};
}

auto swift::_swift_allocBox = _swift_allocBox_;

void swift::swift_deallocBox(HeapObject *o) {
auto metadata = static_cast<const GenericBoxHeapMetadata *>(o->metadata);
// Move the object to the deallocating state (+1 -> +0).
Expand Down
8 changes: 4 additions & 4 deletions stdlib/public/runtime/Metadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,8 +591,8 @@ static OpaqueValue *tuple_allocateBuffer(ValueBuffer *buffer,
if (IsInline)
return reinterpret_cast<OpaqueValue*>(buffer);
BoxPair refAndValueAddr(swift_allocBox(metatype));
*reinterpret_cast<HeapObject **>(buffer) = refAndValueAddr.first;
return refAndValueAddr.second;
*reinterpret_cast<HeapObject **>(buffer) = refAndValueAddr.object;
return refAndValueAddr.buffer;
}

/// Generic tuple value witness for 'destroy'.
Expand Down Expand Up @@ -2672,8 +2672,8 @@ template <> OpaqueValue *Metadata::allocateBoxForExistentialIn(ValueBuffer *buff

// Allocate the box.
BoxPair refAndValueAddr(swift_allocBox(this));
buffer->PrivateData[0] = refAndValueAddr.first;
return refAndValueAddr.second;
buffer->PrivateData[0] = refAndValueAddr.object;
return refAndValueAddr.buffer;
}

template <> OpaqueValue *Metadata::allocateBufferIn(ValueBuffer *buffer) const {
Expand Down
6 changes: 3 additions & 3 deletions stdlib/public/runtime/ProtocolConformance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,10 @@ ProtocolConformanceDescriptor::getWitnessTable(const Metadata *type) const {
// array of witness tables to pass along to the accessor.

// Pretty-print the type name.
auto typeNamePair = TwoWordPair<const char *, uintptr_t>(
auto typeNamePair = TypeNamePair(
swift_getTypeName(type, /*qualified=*/true));
std::string typeName(typeNamePair.first,
typeNamePair.first + typeNamePair.second);
std::string typeName(typeNamePair.data,
typeNamePair.data + typeNamePair.length);

// Demangle the protocol name.
DemangleOptions options;
Expand Down
16 changes: 8 additions & 8 deletions stdlib/public/runtime/Reflection.mm
Original file line number Diff line number Diff line change
Expand Up @@ -714,21 +714,21 @@ void swift_EnumMirror_subscript(String *outString,
BoxPair pair = swift_allocBox(boxType);

type->vw_destructiveProjectEnumData(const_cast<OpaqueValue *>(value));
boxType->vw_initializeWithCopy(pair.second, const_cast<OpaqueValue *>(value));
boxType->vw_initializeWithCopy(pair.buffer, const_cast<OpaqueValue *>(value));
type->vw_destructiveInjectEnumTag(const_cast<OpaqueValue *>(value),
(int) (tag - Description.getNumPayloadCases()));

SWIFT_CC_PLUSONE_GUARD(swift_release(owner));

owner = pair.first;
value = pair.second;
owner = pair.object;
value = pair.buffer;

// If the payload is indirect, we need to jump through the box to get it.
if (indirect) {
owner = *reinterpret_cast<HeapObject * const *>(value);
value = swift_projectBox(const_cast<HeapObject *>(owner));
swift_retain(owner);
swift_release(pair.first);
swift_release(pair.object);
}

new (outString) String(getFieldName(Description.CaseNames, tag));
Expand Down Expand Up @@ -1129,12 +1129,12 @@ static Mirror ObjC_getMirrorForSuperclass(Class sup,
BoxPair box = swift_allocBox(T);

if (take)
T->vw_initializeWithTake(box.second, value);
T->vw_initializeWithTake(box.buffer, value);
else
T->vw_initializeWithCopy(box.second, value);
std::tie(T, Self, MirrorWitness) = getImplementationForType(T, box.second);
T->vw_initializeWithCopy(box.buffer, value);
std::tie(T, Self, MirrorWitness) = getImplementationForType(T, box.buffer);

Data = {box.first, box.second, T};
Data = {box.object, box.buffer, T};
}

/// MagicMirror ownership-sharing subvalue constructor.
Expand Down
9 changes: 6 additions & 3 deletions stdlib/public/runtime/SwiftObject.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1398,10 +1398,13 @@ static bool usesNativeSwiftReferenceCounting_nonNull(
return object->refCounts.isUniquelyReferencedOrPinned();
}

using ClassExtents = TwoWordPair<size_t, size_t>;
struct ClassExtents {
size_t negative;
size_t positive;
};

SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
ClassExtents::Return
ClassExtents
_getSwiftClassInstanceExtents(const Metadata *c) {
assert(c && c->isClassObject());
auto metaData = c->getClassObject();
Expand All @@ -1414,7 +1417,7 @@ static bool usesNativeSwiftReferenceCounting_nonNull(
#if SWIFT_OBJC_INTEROP

SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
ClassExtents::Return
ClassExtents
_getObjCClassInstanceExtents(const ClassMetadata* c) {
// Pure ObjC classes never have negative extents.
if (c->isPureObjC())
Expand Down
Loading