26
26
#include " swift/Reflection/TypeRefBuilder.h"
27
27
28
28
#include < iostream>
29
+ #include < set>
29
30
#include < vector>
30
31
#include < unordered_map>
31
32
@@ -46,6 +47,8 @@ class ReflectionContext
46
47
using super::getBuilder;
47
48
using super::readIsaMask;
48
49
using super::readTypeFromMetadata;
50
+ using super::readParentFromMetadata;
51
+ using super::readGenericArgFromMetadata;
49
52
using super::readMetadataFromInstance;
50
53
using typename super::StoredPointer;
51
54
@@ -202,6 +205,225 @@ class ReflectionContext
202
205
const TypeInfo *getTypeInfo (const TypeRef *TR) {
203
206
return getBuilder ().getTypeConverter ().getTypeInfo (TR);
204
207
}
208
+
209
+ private:
210
+ const TypeInfo *getClosureContextInfo (StoredPointer Context,
211
+ const ClosureContextInfo &Info) {
212
+ RecordTypeInfoBuilder Builder (getBuilder ().getTypeConverter (),
213
+ RecordKind::ClosureContext);
214
+
215
+ auto Metadata = readMetadataFromInstance (Context);
216
+ if (!Metadata.first )
217
+ return nullptr ;
218
+
219
+ // Calculate the offset of the first capture.
220
+ // See GenHeap.cpp, buildPrivateMetadata().
221
+ auto OffsetToFirstCapture =
222
+ this ->readOffsetToFirstCaptureFromMetadata (Metadata.second );
223
+ if (!OffsetToFirstCapture.first )
224
+ return nullptr ;
225
+
226
+ // Initialize the builder.
227
+ Builder.addField (OffsetToFirstCapture.second , sizeof (StoredPointer));
228
+
229
+ // FIXME: should be unordered_set but I'm too lazy to write a hash
230
+ // functor
231
+ std::set<std::pair<const TypeRef *, const MetadataSource *>> Done;
232
+ GenericArgumentMap Subs;
233
+
234
+ ArrayRef<const TypeRef *> CaptureTypes = Info.CaptureTypes ;
235
+
236
+ // Closure context element layout depends on the layout of the
237
+ // captured types, but captured types might depend on element
238
+ // layout (of previous elements). Use an iterative approach to
239
+ // solve the problem.
240
+ while (!CaptureTypes.empty ()) {
241
+ const TypeRef *OrigCaptureTR = CaptureTypes[0 ];
242
+ const TypeRef *SubstCaptureTR = nullptr ;
243
+
244
+ // If we have enough substitutions to make this captured value's
245
+ // type concrete, or we know it's size anyway (because it is a
246
+ // class reference or metatype, for example), go ahead and add
247
+ // it to the layout.
248
+ if (OrigCaptureTR->isConcreteAfterSubstitutions (Subs))
249
+ SubstCaptureTR = OrigCaptureTR->subst (getBuilder (), Subs);
250
+ else if (getBuilder ().getTypeConverter ().hasFixedSize (OrigCaptureTR))
251
+ SubstCaptureTR = OrigCaptureTR;
252
+
253
+ if (SubstCaptureTR != nullptr ) {
254
+ Builder.addField (" " , SubstCaptureTR);
255
+ if (Builder.isInvalid ())
256
+ return nullptr ;
257
+
258
+ // Try the next capture type.
259
+ CaptureTypes = CaptureTypes.slice (1 );
260
+ continue ;
261
+ }
262
+
263
+ // Ok, we do not have enough substitutions yet. Perhaps we have
264
+ // enough elements figured out that we can pick off some
265
+ // metadata sources though, and use those to derive some new
266
+ // substitutions.
267
+ bool Progress = false ;
268
+ for (auto Source : Info.MetadataSources ) {
269
+ // Don't read a source more than once.
270
+ if (Done.count (Source))
271
+ continue ;
272
+
273
+ // If we don't have enough information to read this source
274
+ // (because it is fulfilled by metadata from a capture at
275
+ // at unknown offset), keep going.
276
+ if (!isMetadataSourceReady (Source.second , Builder))
277
+ continue ;
278
+
279
+ auto Metadata = readMetadataSource (Context, Source.second , Builder);
280
+ if (!Metadata.first )
281
+ return nullptr ;
282
+
283
+ auto *SubstTR = readTypeFromMetadata (Metadata.second );
284
+ if (SubstTR == nullptr )
285
+ return nullptr ;
286
+
287
+ if (!TypeRef::deriveSubstitutions (Subs, Source.first , SubstTR))
288
+ return nullptr ;
289
+
290
+ Done.insert (Source);
291
+ Progress = true ;
292
+ }
293
+
294
+ // If we failed to make any forward progress above, we're stuck
295
+ // and cannot close out this layout.
296
+ if (!Progress)
297
+ return nullptr ;
298
+ }
299
+
300
+ // Ok, we have a complete picture now.
301
+ return Builder.build ();
302
+ }
303
+
304
+ // / Checks if we have enough information to read the given metadata
305
+ // / source.
306
+ // /
307
+ // / \param Builder Used to obtain offsets of elements known so far.
308
+ bool isMetadataSourceReady (const MetadataSource *MS,
309
+ const RecordTypeInfoBuilder &Builder) {
310
+ switch (MS->getKind ()) {
311
+ case MetadataSourceKind::ClosureBinding:
312
+ return true ;
313
+ case MetadataSourceKind::ReferenceCapture: {
314
+ unsigned Index = cast<ReferenceCaptureMetadataSource>(MS)->getIndex ();
315
+ return Index < Builder.getNumFields ();
316
+ }
317
+ case MetadataSourceKind::MetadataCapture: {
318
+ unsigned Index = cast<MetadataCaptureMetadataSource>(MS)->getIndex ();
319
+ return Index < Builder.getNumFields ();
320
+ }
321
+ case MetadataSourceKind::GenericArgument: {
322
+ auto Base = cast<GenericArgumentMetadataSource>(MS)->getSource ();
323
+ return isMetadataSourceReady (Base, Builder);
324
+ }
325
+ case MetadataSourceKind::Parent: {
326
+ auto Base = cast<ParentMetadataSource>(MS)->getChild ();
327
+ return isMetadataSourceReady (Base, Builder);
328
+ }
329
+ case MetadataSourceKind::Self:
330
+ case MetadataSourceKind::SelfWitnessTable:
331
+ return true ;
332
+ }
333
+ }
334
+
335
+ // / Read metadata for a captured generic type from a closure context.
336
+ // /
337
+ // / \param Context The closure context in the remote process.
338
+ // /
339
+ // / \param MS The metadata source, which must be "ready" as per the
340
+ // / above.
341
+ // /
342
+ // / \param Builder Used to obtain offsets of elements known so far.
343
+ std::pair<bool , StoredPointer>
344
+ readMetadataSource (StoredPointer Context,
345
+ const MetadataSource *MS,
346
+ const RecordTypeInfoBuilder &Builder) {
347
+ switch (MS->getKind ()) {
348
+ case MetadataSourceKind::ClosureBinding: {
349
+ unsigned Index = cast<ClosureBindingMetadataSource>(MS)->getIndex ();
350
+
351
+ // Skip the context's isa pointer.
352
+ //
353
+ // Metadata bindings are stored consecutively at the beginning of the
354
+ // closure context.
355
+ unsigned Offset = ((sizeof (StoredPointer) == 4 ? 12 : 8 ) +
356
+ sizeof (StoredPointer) * Index);
357
+
358
+ StoredPointer MetadataAddress;
359
+ if (!getReader ().readInteger (RemoteAddress (Context + Offset),
360
+ &MetadataAddress))
361
+ break ;
362
+
363
+ return std::make_pair (true , MetadataAddress);
364
+ }
365
+ case MetadataSourceKind::ReferenceCapture: {
366
+ unsigned Index = cast<ReferenceCaptureMetadataSource>(MS)->getIndex ();
367
+
368
+ // We should already have enough type information to know the offset
369
+ // of this capture in the context.
370
+ unsigned CaptureOffset = Builder.getFieldOffset (Index);
371
+
372
+ StoredPointer CaptureAddress;
373
+ if (!getReader ().readInteger (RemoteAddress (Context + CaptureOffset),
374
+ &CaptureAddress))
375
+ break ;
376
+
377
+ // Read the requested capture's isa pointer.
378
+ return readMetadataFromInstance (CaptureAddress);
379
+ }
380
+ case MetadataSourceKind::MetadataCapture: {
381
+ unsigned Index = cast<MetadataCaptureMetadataSource>(MS)->getIndex ();
382
+
383
+ // We should already have enough type information to know the offset
384
+ // of this capture in the context.
385
+ unsigned CaptureOffset = Builder.getFieldOffset (Index);
386
+
387
+ StoredPointer CaptureAddress;
388
+ if (!getReader ().readInteger (RemoteAddress (Context + CaptureOffset),
389
+ &CaptureAddress))
390
+ break ;
391
+
392
+ return std::make_pair (true , CaptureAddress);
393
+ }
394
+ case MetadataSourceKind::GenericArgument: {
395
+ auto *GAMS = cast<GenericArgumentMetadataSource>(MS);
396
+ auto Base = readMetadataSource (Context, GAMS->getSource (), Builder);
397
+ if (!Base.first )
398
+ break ;
399
+
400
+ unsigned Index = GAMS->getIndex ();
401
+ auto Arg = readGenericArgFromMetadata (Base.second , Index);
402
+ if (!Arg.first )
403
+ break ;
404
+
405
+ return Arg;
406
+ }
407
+ case MetadataSourceKind::Parent: {
408
+ auto Base = readMetadataSource (Context,
409
+ cast<ParentMetadataSource>(MS)->getChild (),
410
+ Builder);
411
+ if (!Base.first )
412
+ break ;
413
+
414
+ auto Parent = readParentFromMetadata (Base.second );
415
+ if (!Parent.first )
416
+ break ;
417
+
418
+ return Parent;
419
+ }
420
+ case MetadataSourceKind::Self:
421
+ case MetadataSourceKind::SelfWitnessTable:
422
+ break ;
423
+ }
424
+
425
+ return std::make_pair (false , StoredPointer (0 ));
426
+ }
205
427
};
206
428
207
429
} // end namespace reflection
0 commit comments