mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Runtime: Optional-like enums with single-refcounted payloads can share the refcounted value witnesses.
swift_retain and objc_retain both handle nil already, so we can bypass the generic Optional value witnesses when instantiating Optional on a class type, which happens kind of a lot. Swift SVN r23613
This commit is contained in:
@@ -2190,14 +2190,6 @@ swift_getTupleTypeMetadata3(const Metadata *elt0, const Metadata *elt1,
|
||||
const Metadata *elt2, const char *labels,
|
||||
const ValueWitnessTable *proposedWitnesses);
|
||||
|
||||
/// Replace entries of a freshly-instantiated value witness table with more
|
||||
/// efficient common implementations where applicable.
|
||||
///
|
||||
/// For instance, if the value witness table represents a POD type, this will
|
||||
/// insert POD value witnesses into the table. The vwtable's flags must have
|
||||
/// been initialized before calling this function.
|
||||
void swift_installCommonValueWitnesses(ValueWitnessTable *vwtable);
|
||||
|
||||
/// Initialize the value witness table and struct field offset vector for a
|
||||
/// struct, using the "Universal" layout strategy.
|
||||
extern "C" void swift_initStructMetadata_UniversalStrategy(size_t numFields,
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "swift/Basic/Fallthrough.h"
|
||||
#include "swift/Runtime/Metadata.h"
|
||||
#include "swift/Runtime/Enum.h"
|
||||
#include "Private.h"
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
@@ -73,7 +74,22 @@ swift::swift_initEnumValueWitnessTableSinglePayload(ValueWitnessTable *vwtable,
|
||||
vwtable->stride = llvm::RoundUpToAlignment(size, align);
|
||||
|
||||
// Substitute in better common value witnesses if we have them.
|
||||
swift_installCommonValueWitnesses(vwtable);
|
||||
// If the payload type is a single-refcounted pointer, and the enum has
|
||||
// a single empty case, then we can borrow the witnesses of the single
|
||||
// refcounted pointer type, since swift_retain and objc_retain are both
|
||||
// nil-aware. Most single-refcounted types will use the standard
|
||||
// value witness tables for NativeObject or UnknownObject. This isn't
|
||||
// foolproof but should catch the common case of optional class types.
|
||||
auto payloadVWT = payload->getValueWitnesses();
|
||||
if (emptyCases == 1
|
||||
&& (payloadVWT == &_TWVBo
|
||||
|| payloadVWT == &_TWVBO)) {
|
||||
#define COPY_PAYLOAD_WITNESS(NAME) vwtable->NAME = payloadVWT->NAME;
|
||||
FOR_ALL_FUNCTION_VALUE_WITNESSES(COPY_PAYLOAD_WITNESS)
|
||||
#undef COPY_PAYLOAD_WITNESS
|
||||
} else {
|
||||
installCommonValueWitnesses(vwtable);
|
||||
}
|
||||
|
||||
// If the payload has extra inhabitants left over after the ones we used,
|
||||
// forward them as our own.
|
||||
|
||||
@@ -1217,7 +1217,7 @@ static OpaqueValue *pod_direct_initializeArrayWithTakeFrontToBack(
|
||||
#define pod_indirect_initializeArrayWithTakeBackToFront \
|
||||
pod_direct_initializeArrayWithTakeFrontToBack
|
||||
|
||||
void swift::swift_installCommonValueWitnesses(ValueWitnessTable *vwtable) {
|
||||
void swift::installCommonValueWitnesses(ValueWitnessTable *vwtable) {
|
||||
auto flags = vwtable->flags;
|
||||
if (flags.isPOD()) {
|
||||
// Use POD value witnesses.
|
||||
@@ -1230,6 +1230,7 @@ void swift::swift_installCommonValueWitnesses(ValueWitnessTable *vwtable) {
|
||||
FOR_ALL_FUNCTION_VALUE_WITNESSES(INSTALL_POD_INDIRECT_WITNESS)
|
||||
#undef INSTALL_POD_INDIRECT_WITNESS
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (vwtable->flags.isBitwiseTakable()) {
|
||||
@@ -1251,10 +1252,17 @@ void swift::swift_installCommonValueWitnesses(ValueWitnessTable *vwtable) {
|
||||
vwtable->initializeArrayWithTakeBackToFront
|
||||
= pod_indirect_initializeArrayWithTakeBackToFront;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!vwtable->flags.isInlineStorage()) {
|
||||
// For values stored out-of-line, initializeBufferWithTakeOfBuffer is
|
||||
// always a memcpy.
|
||||
vwtable->initializeBufferWithTakeOfBuffer
|
||||
= pod_indirect_initializeBufferWithTakeOfBuffer;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*** Structs ***************************************************************/
|
||||
|
||||
@@ -1275,7 +1283,7 @@ void swift::swift_initStructMetadata_UniversalStrategy(size_t numFields,
|
||||
vwtable->stride = layout.stride;
|
||||
|
||||
// Substitute in better value witnesses if we have them.
|
||||
swift_installCommonValueWitnesses(vwtable);
|
||||
installCommonValueWitnesses(vwtable);
|
||||
|
||||
// We have extra inhabitants if the first element does.
|
||||
// FIXME: generalize this.
|
||||
|
||||
@@ -99,6 +99,17 @@ namespace swift {
|
||||
/// where there is no common root class. rdar://problem/18987058
|
||||
const ClassMetadata *getRootSuperclass();
|
||||
|
||||
/// Replace entries of a freshly-instantiated value witness table with more
|
||||
/// efficient common implementations where applicable.
|
||||
///
|
||||
/// For instance, if the value witness table represents a POD type, this will
|
||||
/// insert POD value witnesses into the table. The vwtable's flags must have
|
||||
/// been initialized before calling this function.
|
||||
///
|
||||
/// Returns true if common value witnesses were used, false otherwise.
|
||||
void installCommonValueWitnesses(ValueWitnessTable *vwtable);
|
||||
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif /* SWIFT_RUNTIME_PRIVATE_H */
|
||||
|
||||
Reference in New Issue
Block a user