Skip to content

Commit 3bd7f02

Browse files
committed
Runtime: use SmallVector instead of std::vector to avoid memory allocations in most cases.
This dramatically reduces the number of needed malloc calls. Unfortunately I had to add the implementation of SmallVectorBase::grow_pod to the runtime, as we don't link LLVM. This is a bad hack, but better than re-inventing a new SmallVector implementation. SR-10028 rdar://problem/48575729
1 parent 9050be6 commit 3bd7f02

File tree

8 files changed

+77
-37
lines changed

8 files changed

+77
-37
lines changed

include/swift/Demangling/TypeDecoder.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ class TypeDecoder {
315315
if (Node->getNumChildren() < 2)
316316
return BuiltType();
317317

318-
std::vector<BuiltType> args;
318+
SmallVector<BuiltType, 8> args;
319319

320320
const auto &genericArgs = Node->getChild(1);
321321
assert(genericArgs->getKind() == NodeKind::TypeList);
@@ -427,7 +427,7 @@ class TypeDecoder {
427427
return BuiltType();
428428

429429
// Find the protocol list.
430-
std::vector<BuiltProtocolDecl> Protocols;
430+
SmallVector<BuiltProtocolDecl, 8> Protocols;
431431
auto TypeList = Node->getChild(0);
432432
if (TypeList->getKind() == NodeKind::ProtocolList &&
433433
TypeList->getNumChildren() >= 1) {
@@ -514,7 +514,7 @@ class TypeDecoder {
514514
return BuiltType();
515515

516516
bool hasParamFlags = false;
517-
std::vector<FunctionParam<BuiltType>> parameters;
517+
SmallVector<FunctionParam<BuiltType>, 8> parameters;
518518
if (!decodeMangledFunctionInputType(Node->getChild(isThrow ? 1 : 0),
519519
parameters, hasParamFlags))
520520
return BuiltType();
@@ -531,9 +531,9 @@ class TypeDecoder {
531531
}
532532
case NodeKind::ImplFunctionType: {
533533
auto calleeConvention = ImplParameterConvention::Direct_Unowned;
534-
std::vector<ImplFunctionParam<BuiltType>> parameters;
535-
std::vector<ImplFunctionResult<BuiltType>> results;
536-
std::vector<ImplFunctionResult<BuiltType>> errorResults;
534+
SmallVector<ImplFunctionParam<BuiltType>, 8> parameters;
535+
SmallVector<ImplFunctionResult<BuiltType>, 8> results;
536+
SmallVector<ImplFunctionResult<BuiltType>, 8> errorResults;
537537
ImplFunctionTypeFlags flags;
538538

539539
for (unsigned i = 0; i < Node->getNumChildren(); i++) {
@@ -611,7 +611,7 @@ class TypeDecoder {
611611
return decodeMangledType(Node->getChild(0));
612612

613613
case NodeKind::Tuple: {
614-
std::vector<BuiltType> elements;
614+
SmallVector<BuiltType, 8> elements;
615615
std::string labels;
616616
bool variadic = false;
617617
for (auto &element : *Node) {
@@ -785,7 +785,7 @@ class TypeDecoder {
785785
private:
786786
template <typename T>
787787
bool decodeImplFunctionPart(Demangle::NodePointer node,
788-
std::vector<T> &results) {
788+
SmallVectorImpl<T> &results) {
789789
if (node->getNumChildren() != 2)
790790
return true;
791791

@@ -871,7 +871,7 @@ class TypeDecoder {
871871

872872
bool decodeMangledFunctionInputType(
873873
Demangle::NodePointer node,
874-
std::vector<FunctionParam<BuiltType>> &params,
874+
SmallVectorImpl<FunctionParam<BuiltType>> &params,
875875
bool &hasParamFlags) {
876876
// Look through a couple of sugar nodes.
877877
if (node->getKind() == NodeKind::Type ||

include/swift/Reflection/TypeRefBuilder.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -274,21 +274,21 @@ class TypeRefBuilder {
274274

275275
const BoundGenericTypeRef *
276276
createBoundGenericType(const Optional<std::string> &mangledName,
277-
const std::vector<const TypeRef *> &args,
277+
ArrayRef<const TypeRef *> args,
278278
const TypeRef *parent) {
279279
return BoundGenericTypeRef::create(*this, *mangledName, args, parent);
280280
}
281281

282282
const TupleTypeRef *
283-
createTupleType(const std::vector<const TypeRef *> &elements,
283+
createTupleType(ArrayRef<const TypeRef *> elements,
284284
std::string &&labels, bool isVariadic) {
285285
// FIXME: Add uniqueness checks in TupleTypeRef::Profile and
286286
// unittests/Reflection/TypeRef.cpp if using labels for identity.
287287
return TupleTypeRef::create(*this, elements, isVariadic);
288288
}
289289

290290
const FunctionTypeRef *createFunctionType(
291-
const std::vector<remote::FunctionParam<const TypeRef *>> &params,
291+
ArrayRef<remote::FunctionParam<const TypeRef *>> params,
292292
const TypeRef *result, FunctionTypeFlags flags) {
293293
return FunctionTypeRef::create(*this, params, result, flags);
294294
}
@@ -406,7 +406,7 @@ class TypeRefBuilder {
406406

407407
const ObjCClassTypeRef *
408408
createBoundGenericObjCClassType(const std::string &name,
409-
std::vector<const TypeRef *> &args) {
409+
ArrayRef<const TypeRef *> args) {
410410
// Remote reflection just ignores generic arguments for Objective-C
411411
// lightweight generic types, since they don't affect layout.
412412
return createObjCClassType(name);

stdlib/public/Reflection/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ set(swiftReflection_SOURCES
33
TypeLowering.cpp
44
TypeRef.cpp
55
TypeRefBuilder.cpp
6+
"${SWIFT_SOURCE_DIR}/stdlib/public/runtime/LLVMSupport.cpp"
67
"${SWIFT_SOURCE_DIR}/lib/Demangling/Context.cpp"
78
"${SWIFT_SOURCE_DIR}/lib/Demangling/OldDemangler.cpp"
89
"${SWIFT_SOURCE_DIR}/lib/Demangling/Demangler.cpp"
@@ -21,7 +22,7 @@ endif(LLVM_ENABLE_ASSERTIONS)
2122
if(SWIFT_BUILD_STDLIB)
2223
add_swift_target_library(swiftReflection STATIC TARGET_LIBRARY
2324
${swiftReflection_SOURCES}
24-
C_COMPILE_FLAGS ${SWIFT_RUNTIME_CXX_FLAGS}
25+
C_COMPILE_FLAGS ${SWIFT_RUNTIME_CXX_FLAGS} -DswiftCore_EXPORTS
2526
LINK_FLAGS ${SWIFT_RUNTIME_LINK_FLAGS}
2627
INSTALL_IN_COMPONENT dev)
2728
endif()

stdlib/public/runtime/Demangle.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ swift::_buildDemanglingForContext(const ContextDescriptor *context,
3333
NodePointer node = nullptr;
3434

3535
// Walk up the context tree.
36-
std::vector<const ContextDescriptor *> descriptorPath;
36+
SmallVector<const ContextDescriptor *, 8> descriptorPath;
3737
{
3838
const ContextDescriptor *parent = context;
3939
while (parent) {
@@ -283,11 +283,11 @@ _buildDemanglingForNominalType(const Metadata *type, Demangle::Demangler &Dem) {
283283

284284
// Gather the complete set of generic arguments that must be written to
285285
// form this type.
286-
std::vector<const Metadata *> allGenericArgs;
286+
SmallVector<const Metadata *, 8> allGenericArgs;
287287
gatherWrittenGenericArgs(type, description, allGenericArgs, Dem);
288288

289289
// Demangle the generic arguments.
290-
std::vector<NodePointer> demangledGenerics;
290+
SmallVector<NodePointer, 8> demangledGenerics;
291291
for (auto genericArg : allGenericArgs) {
292292
// When there is no generic argument, put in a placeholder.
293293
if (!genericArg) {
@@ -468,7 +468,7 @@ swift::_swift_buildDemanglingForMetadata(const Metadata *type,
468468
break;
469469
}
470470

471-
std::vector<std::pair<NodePointer, bool>> inputs;
471+
SmallVector<std::pair<NodePointer, bool>, 8> inputs;
472472
for (unsigned i = 0, e = func->getNumParameters(); i < e; ++i) {
473473
auto param = func->getParameter(i);
474474
auto flags = func->getParameterFlags(i);

stdlib/public/runtime/LLVMSupport.cpp

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include "llvm/ADT/SmallVector.h"
14+
1315
// ADT uses report_bad_alloc_error to report an error when it can't allocate
1416
// elements for a data structure. The swift runtime uses ADT without linking
1517
// against libSupport, so here we provide a stub to make sure we don't fail
1618
// to link.
1719
#if defined(swiftCore_EXPORTS)
1820
namespace llvm {
21+
1922
#if defined(_WIN32)
2023
extern void report_bad_alloc_error(const char *Reason, bool GenCrashDiag);
2124
void _report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {}
@@ -28,6 +31,42 @@ void _report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {}
2831
void __attribute__((__weak__, __visibility__("hidden")))
2932
report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {}
3033
#endif
31-
} // end namespace llvm
34+
35+
// The same for SmallVector: provide the grow_pod implementation (the only
36+
// SmallVector function which is not inlined) as we don't link LLVM.
37+
// TODO: This is a hack. This implementaiton is copied from LLVM and has to stay
38+
// in sync with it.
39+
40+
/// grow_pod - This is an implementation of the grow() method which only works
41+
/// on POD-like datatypes and is out of line to reduce code duplication.
42+
void
43+
#if !defined(_WIN32)
44+
__attribute__((__weak__, __visibility__("hidden")))
3245
#endif
46+
llvm::SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity,
47+
size_t TSize) {
48+
// Ensure we can fit the new capacity in 32 bits.
49+
if (MinCapacity > UINT32_MAX)
50+
report_bad_alloc_error("SmallVector capacity overflow during allocation");
3351

52+
size_t NewCapacity = 2 * capacity() + 1; // Always grow.
53+
NewCapacity =
54+
std::min(std::max(NewCapacity, MinCapacity), size_t(UINT32_MAX));
55+
56+
void *NewElts;
57+
if (BeginX == FirstEl) {
58+
NewElts = safe_malloc(NewCapacity * TSize);
59+
60+
// Copy the elements over. No need to run dtors on PODs.
61+
memcpy(NewElts, this->BeginX, size() * TSize);
62+
} else {
63+
// If this wasn't grown from the inline copy, grow the allocated space.
64+
NewElts = safe_realloc(this->BeginX, NewCapacity * TSize);
65+
}
66+
67+
this->BeginX = NewElts;
68+
this->Capacity = NewCapacity;
69+
}
70+
71+
} // end namespace llvm
72+
#endif // defined(swiftCore_EXPORTS)

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,7 @@ Optional<unsigned> swift::_depthIndexToFlatIndex(
821821
/// \returns true if the innermost descriptor is generic.
822822
bool swift::_gatherGenericParameterCounts(
823823
const ContextDescriptor *descriptor,
824-
std::vector<unsigned> &genericParamCounts,
824+
SmallVectorImpl<unsigned> &genericParamCounts,
825825
Demangler &BorrowFrom) {
826826
// If we have an extension descriptor, extract the extended type and use
827827
// that.
@@ -1027,7 +1027,7 @@ class DecodedMetadataBuilder {
10271027

10281028
// Figure out the various levels of generic parameters we have in
10291029
// this type.
1030-
std::vector<unsigned> genericParamCounts;
1030+
SmallVector<unsigned, 8> genericParamCounts;
10311031
(void)_gatherGenericParameterCounts(typeDecl, genericParamCounts, demangler);
10321032
unsigned numTotalGenericParams =
10331033
genericParamCounts.empty() ? 0 : genericParamCounts.back();
@@ -1041,13 +1041,13 @@ class DecodedMetadataBuilder {
10411041
return BuiltType();
10421042
}
10431043

1044-
std::vector<const void *> allGenericArgsVec;
1044+
SmallVector<const void *, 8> allGenericArgsVec;
10451045

10461046
// If there are generic parameters at any level, check the generic
10471047
// requirements and fill in the generic arguments vector.
10481048
if (!genericParamCounts.empty()) {
10491049
// Compute the set of generic arguments "as written".
1050-
std::vector<const Metadata *> allGenericArgs;
1050+
SmallVector<const Metadata *, 8> allGenericArgs;
10511051

10521052
// If we have a parent, gather it's generic arguments "as written".
10531053
if (parent) {
@@ -1159,8 +1159,8 @@ class DecodedMetadataBuilder {
11591159
BuiltType createFunctionType(
11601160
ArrayRef<Demangle::FunctionParam<BuiltType>> params,
11611161
BuiltType result, FunctionTypeFlags flags) const {
1162-
std::vector<BuiltType> paramTypes;
1163-
std::vector<uint32_t> paramFlags;
1162+
SmallVector<BuiltType, 8> paramTypes;
1163+
SmallVector<uint32_t, 8> paramFlags;
11641164

11651165
// Fill in the parameters.
11661166
paramTypes.reserve(params.size());
@@ -1625,7 +1625,7 @@ demangleToGenericParamRef(StringRef typeName) {
16251625
void swift::gatherWrittenGenericArgs(
16261626
const Metadata *metadata,
16271627
const TypeContextDescriptor *description,
1628-
std::vector<const Metadata *> &allGenericArgs,
1628+
SmallVectorImpl<const Metadata *> &allGenericArgs,
16291629
Demangler &BorrowFrom) {
16301630
auto generics = description->getGenericContext();
16311631
if (!generics)
@@ -1679,7 +1679,7 @@ void swift::gatherWrittenGenericArgs(
16791679
// canonicalized away. Use same-type requirements to reconstitute them.
16801680

16811681
// Retrieve the mapping information needed for depth/index -> flat index.
1682-
std::vector<unsigned> genericParamCounts;
1682+
SmallVector<unsigned, 8> genericParamCounts;
16831683
(void)_gatherGenericParameterCounts(description, genericParamCounts,
16841684
BorrowFrom);
16851685

stdlib/public/runtime/Private.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ class TypeInfo {
278278

279279
/// Information about the generic context descriptors that make up \c
280280
/// descriptor, from the outermost to the innermost.
281-
mutable std::vector<PathElement> descriptorPath;
281+
mutable llvm::SmallVector<PathElement, 8> descriptorPath;
282282

283283
/// The number of key generic parameters.
284284
mutable unsigned numKeyGenericParameters = 0;
@@ -356,10 +356,10 @@ class TypeInfo {
356356
/// Use with \c _getTypeByMangledName to decode potentially-generic types.
357357
class SWIFT_RUNTIME_LIBRARY_VISIBILITY SubstGenericParametersFromWrittenArgs {
358358
/// The complete set of generic arguments.
359-
const std::vector<const Metadata *> &allGenericArgs;
359+
const SmallVectorImpl<const Metadata *> &allGenericArgs;
360360

361361
/// The counts of generic parameters at each level.
362-
const std::vector<unsigned> &genericParamCounts;
362+
const SmallVectorImpl<unsigned> &genericParamCounts;
363363

364364
public:
365365
/// Initialize a new function object to handle substitutions. Both
@@ -373,8 +373,8 @@ class TypeInfo {
373373
/// \param genericParamCounts The count of generic parameters at each
374374
/// generic level, typically gathered by _gatherGenericParameterCounts.
375375
explicit SubstGenericParametersFromWrittenArgs(
376-
const std::vector<const Metadata *> &allGenericArgs,
377-
const std::vector<unsigned> &genericParamCounts)
376+
const SmallVectorImpl<const Metadata *> &allGenericArgs,
377+
const SmallVectorImpl<unsigned> &genericParamCounts)
378378
: allGenericArgs(allGenericArgs), genericParamCounts(genericParamCounts) {
379379
}
380380

@@ -386,7 +386,7 @@ class TypeInfo {
386386
///
387387
/// \returns true if the innermost descriptor is generic.
388388
bool _gatherGenericParameterCounts(const ContextDescriptor *descriptor,
389-
std::vector<unsigned> &genericParamCounts,
389+
llvm::SmallVectorImpl<unsigned> &genericParamCounts,
390390
Demangler &BorrowFrom);
391391

392392
/// Map depth/index to a flat index.
@@ -407,7 +407,7 @@ class TypeInfo {
407407
/// \returns true if an error occurred, false otherwise.
408408
bool _checkGenericRequirements(
409409
llvm::ArrayRef<GenericRequirementDescriptor> requirements,
410-
std::vector<const void *> &extraArguments,
410+
llvm::SmallVectorImpl<const void *> &extraArguments,
411411
SubstGenericParameterFn substGenericParam,
412412
SubstDependentWitnessTableFn substWitnessTable);
413413

@@ -452,7 +452,7 @@ class TypeInfo {
452452
/// \endcode
453453
void gatherWrittenGenericArgs(const Metadata *metadata,
454454
const TypeContextDescriptor *description,
455-
std::vector<const Metadata *> &allGenericArgs,
455+
llvm::SmallVectorImpl<const Metadata *> &allGenericArgs,
456456
Demangler &BorrowFrom);
457457

458458
Demangle::NodePointer

stdlib/public/runtime/ProtocolConformance.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ template<>
162162
const WitnessTable *
163163
ProtocolConformanceDescriptor::getWitnessTable(const Metadata *type) const {
164164
// If needed, check the conditional requirements.
165-
std::vector<const void *> conditionalArgs;
165+
SmallVector<const void *, 8> conditionalArgs;
166166
if (hasConditionalRequirements()) {
167167
SubstGenericParametersFromMetadata substitutions(type);
168168
bool failed =
@@ -626,7 +626,7 @@ swift::_searchConformancesByMangledTypeName(Demangle::NodePointer node) {
626626

627627
bool swift::_checkGenericRequirements(
628628
llvm::ArrayRef<GenericRequirementDescriptor> requirements,
629-
std::vector<const void *> &extraArguments,
629+
SmallVectorImpl<const void *> &extraArguments,
630630
SubstGenericParameterFn substGenericParam,
631631
SubstDependentWitnessTableFn substWitnessTable) {
632632
for (const auto &req : requirements) {

0 commit comments

Comments
 (0)