Skip to content

Commit 09d0cfe

Browse files
committedApr 23, 2016
Hang closure capture descriptors from their heap metadata
Now we can discern the types of values in heap boxes at runtime! Closure reference captures are a common way of creating reference cycles, so this provides some basic infrastructure for detecting those someday. A closure capture descriptor has the following: - The number of captures. - The number of sources of metadata reachable from the closure. This is important for substituting generics at runtime since we can't know precisely what will get captured until we observe a closure. - The number of types in the NecessaryBindings structure. This is a holding tank in a closure for sources of metadata that can't be gotten from the captured values themselves. - The metadata source map, a list of pairs, for each source of metadata for every generic argument needed to perform substitution at runtime. Key: The typeref for the generic parameter visible from the closure in the Swift source. Value: The metadata source, which describes how to crawl the heap from the closure to get to the metadata for that generic argument. - A list of typerefs for the captured values themselves. Follow-up: IRGen tests for various capture scenarios, which will include MetadataSource encoding tests. rdar://problem/24989531
1 parent 8d736a1 commit 09d0cfe

22 files changed

+942
-691
lines changed
 

‎include/swift/Reflection/MetadataSource.h

+1-26
Original file line numberDiff line numberDiff line change
@@ -165,19 +165,6 @@ class MetadataSource {
165165
return A.template createParent(Child);
166166
}
167167

168-
template <typename Allocator>
169-
static const MetadataSource*
170-
decodeImpossible(Allocator &A,
171-
std::string::const_iterator &it,
172-
const std::string::const_iterator &end) {
173-
// Decode the impossible. Create the impossible.
174-
if (it == end || *it != 'I')
175-
return nullptr;
176-
177-
++it;
178-
return A.template createImpossible();
179-
}
180-
181168
template <typename Allocator>
182169
static const MetadataSource *decode(Allocator &A,
183170
std::string::const_iterator &it,
@@ -195,8 +182,6 @@ class MetadataSource {
195182
return decodeGenericArgument(A, it, end);
196183
case 'P':
197184
return decodeParent(A, it, end);
198-
case 'I':
199-
return decodeImpossible(A, it, end);
200185
default:
201186
return nullptr;
202187
}
@@ -211,7 +196,6 @@ class MetadataSource {
211196

212197
void dump() const;
213198
void dump(std::ostream &OS, unsigned Indent = 0) const;
214-
std::string encode() const;
215199
template <typename Allocator>
216200
static const MetadataSource *decode(Allocator &A, const std::string &str) {
217201
auto begin = str.begin();
@@ -347,18 +331,9 @@ class ParentMetadataSource final : public MetadataSource {
347331
const MetadataSource *getChild() const {
348332
return Child;
349333
}
350-
};
351-
352-
class ImpossibleMetadataSource final : public MetadataSource {
353-
static const ImpossibleMetadataSource *Singleton;
354-
public:
355-
ImpossibleMetadataSource()
356-
: MetadataSource(MetadataSourceKind::Impossible) {}
357-
358-
static const ImpossibleMetadataSource *get();
359334

360335
static bool classof(const MetadataSource *MS) {
361-
return MS->getKind() == MetadataSourceKind::Impossible;
336+
return MS->getKind() == MetadataSourceKind::Parent;
362337
}
363338
};
364339

‎include/swift/Reflection/MetadataSourceBuilder.h

-5
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,6 @@ class MetadataSourceBuilder {
6262
createParent(const MetadataSource *Child) {
6363
return ParentMetadataSource::create(*this, Child);
6464
}
65-
66-
const ImpossibleMetadataSource *
67-
createImpossible() {
68-
return ImpossibleMetadataSource::get();
69-
}
7065
};
7166

7267
} // end namespace reflection

‎include/swift/Reflection/MetadataSources.def

-1
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,3 @@ METADATA_SOURCE(ReferenceCapture, MetadataSource)
2121
METADATA_SOURCE(MetadataCapture, MetadataSource)
2222
METADATA_SOURCE(GenericArgument, MetadataSource)
2323
METADATA_SOURCE(Parent, MetadataSource)
24-
METADATA_SOURCE(Impossible, MetadataSource)

‎lib/IRGen/GenFunc.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,7 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM,
10771077
/// Emit a partial application thunk for a function pointer applied to a partial
10781078
/// set of argument values.
10791079
void irgen::emitFunctionPartialApplication(IRGenFunction &IGF,
1080+
SILFunction &SILFn,
10801081
llvm::Value *fnPtr,
10811082
llvm::Value *fnContext,
10821083
Explosion &args,
@@ -1287,14 +1288,17 @@ void irgen::emitFunctionPartialApplication(IRGenFunction &IGF,
12871288
HeapLayout layout(IGF.IGM, LayoutStrategy::Optimal, argValTypes, argTypeInfos,
12881289
/*typeToFill*/ nullptr,
12891290
std::move(bindings));
1291+
1292+
auto Descriptor = IGF.IGM.getAddrOfCaptureDescriptor(SILFn, layout);
1293+
12901294
llvm::Value *data;
12911295
if (layout.isKnownEmpty()) {
12921296
data = IGF.IGM.RefCountedNull;
12931297
} else {
12941298
// Allocate a new object.
12951299
HeapNonFixedOffsets offsets(IGF, layout);
12961300

1297-
data = IGF.emitUnmanagedAlloc(layout, "closure", &offsets);
1301+
data = IGF.emitUnmanagedAlloc(layout, "closure", Descriptor, &offsets);
12981302
Address dataAddr = layout.emitCastTo(IGF, data);
12991303

13001304

‎lib/IRGen/GenFunc.h

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ namespace irgen {
4848
/// Emit a partial application thunk for a function pointer applied to a
4949
/// partial set of argument values.
5050
void emitFunctionPartialApplication(IRGenFunction &IGF,
51+
SILFunction &SILFn,
5152
llvm::Value *fnPtr,
5253
llvm::Value *fnContext,
5354
Explosion &args,

‎lib/IRGen/GenHeap.cpp

+14-3
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ llvm::Constant *HeapLayout::createSizeFn(IRGenModule &IGM) const {
250250
static llvm::Constant *buildPrivateMetadata(IRGenModule &IGM,
251251
const HeapLayout &layout,
252252
llvm::Constant *dtorFn,
253+
llvm::Constant *captureDescriptor,
253254
MetadataKind kind) {
254255
// Build the fields of the private metadata.
255256
SmallVector<llvm::Constant*, 4> fields;
@@ -268,6 +269,8 @@ static llvm::Constant *buildPrivateMetadata(IRGenModule &IGM,
268269
offset = Size(0);
269270
fields.push_back(llvm::ConstantInt::get(IGM.Int32Ty, offset.getValue()));
270271

272+
fields.push_back(captureDescriptor);
273+
271274
llvm::Constant *init =
272275
llvm::ConstantStruct::get(IGM.FullBoxMetadataStructTy, fields);
273276

@@ -285,17 +288,21 @@ static llvm::Constant *buildPrivateMetadata(IRGenModule &IGM,
285288
/*Ty=*/nullptr, var, indices);
286289
}
287290

288-
llvm::Constant *HeapLayout::getPrivateMetadata(IRGenModule &IGM) const {
291+
llvm::Constant *
292+
HeapLayout::getPrivateMetadata(IRGenModule &IGM,
293+
llvm::Constant *captureDescriptor) const {
289294
if (!privateMetadata)
290295
privateMetadata = buildPrivateMetadata(IGM, *this, createDtorFn(IGM, *this),
296+
captureDescriptor,
291297
MetadataKind::HeapLocalVariable);
292298
return privateMetadata;
293299
}
294300

295301
llvm::Value *IRGenFunction::emitUnmanagedAlloc(const HeapLayout &layout,
296302
const llvm::Twine &name,
303+
llvm::Constant *captureDescriptor,
297304
const HeapNonFixedOffsets *offsets) {
298-
llvm::Value *metadata = layout.getPrivateMetadata(IGM);
305+
llvm::Value *metadata = layout.getPrivateMetadata(IGM, captureDescriptor);
299306
llvm::Value *size, *alignMask;
300307
if (offsets) {
301308
size = offsets->getSize();
@@ -1466,7 +1473,11 @@ class FixedBoxTypeInfoBase : public BoxTypeInfo {
14661473
allocate(IRGenFunction &IGF, SILType boxedType, const llvm::Twine &name)
14671474
const override {
14681475
// Allocate a new object using the layout.
1469-
llvm::Value *allocation = IGF.emitUnmanagedAlloc(layout, name);
1476+
1477+
auto nullCaptureDescriptor
1478+
= llvm::ConstantPointerNull::get(IGF.IGM.CaptureDescriptorPtrTy);
1479+
llvm::Value *allocation = IGF.emitUnmanagedAlloc(layout, name,
1480+
nullCaptureDescriptor);
14701481
Address rawAddr = project(IGF, allocation, boxedType);
14711482
return {rawAddr, allocation};
14721483
}

‎lib/IRGen/GenHeap.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ class HeapLayout : public StructLayout {
6767

6868
/// As a convenience, build a metadata object with internal linkage
6969
/// consisting solely of the standard heap metadata.
70-
llvm::Constant *getPrivateMetadata(IRGenModule &IGM) const;
70+
llvm::Constant *getPrivateMetadata(IRGenModule &IGM,
71+
llvm::Constant *captureDescriptor) const;
7172
};
7273

7374
class HeapNonFixedOffsets : public NonFixedOffsetsImpl {

‎lib/IRGen/GenObjC.cpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,13 @@ void irgen::emitObjCPartialApplication(IRGenFunction &IGF,
938938
auto *selfTypeInfo = &IGF.getTypeInfo(selfType);
939939
HeapLayout layout(IGF.IGM, LayoutStrategy::Optimal,
940940
selfType, selfTypeInfo);
941-
llvm::Value *data = IGF.emitUnmanagedAlloc(layout, "closure");
941+
942+
// FIXME: Either emit a descriptor for this or create a metadata kind
943+
// that indicates its trivial layout.
944+
auto Descriptor
945+
= llvm::ConstantPointerNull::get(IGF.IGM.CaptureDescriptorPtrTy);
946+
llvm::Value *data = IGF.emitUnmanagedAlloc(layout, "closure",
947+
Descriptor);
942948
// FIXME: non-fixed offsets
943949
NonFixedOffsets offsets = None;
944950
Address dataAddr = layout.emitCastTo(IGF, data);

‎lib/IRGen/GenObjC.h

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ namespace swift {
2727
class CanType;
2828
class FuncDecl;
2929
struct SILDeclRef;
30+
class SILFunction;
3031
class SILType;
3132
class Substitution;
3233

0 commit comments

Comments
 (0)
Please sign in to comment.