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:
Joe Groff
2014-12-02 17:34:36 +00:00
parent b44f7a5d3a
commit 27f49cd19d
4 changed files with 40 additions and 13 deletions

View File

@@ -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,

View File

@@ -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.

View File

@@ -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,9 +1252,16 @@ void swift::swift_installCommonValueWitnesses(ValueWitnessTable *vwtable) {
vwtable->initializeArrayWithTakeBackToFront
= pod_indirect_initializeArrayWithTakeBackToFront;
}
return;
}
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.

View File

@@ -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 */