|
43 | 43 | #else
|
44 | 44 | #include <sys/mman.h>
|
45 | 45 | #include <unistd.h>
|
| 46 | +#include <dlfcn.h> |
46 | 47 | #endif
|
47 | 48 | #include "llvm/ADT/DenseMap.h"
|
48 | 49 | #include "llvm/ADT/Hashing.h"
|
@@ -2610,58 +2611,96 @@ swift::swift_initClassMetadata(ClassMetadata *self,
|
2610 | 2611 | }
|
2611 | 2612 |
|
2612 | 2613 | #if SWIFT_OBJC_INTEROP
|
| 2614 | + |
| 2615 | +// Suppress diagnostic about the availability of _objc_realizeClassFromSwift. |
| 2616 | +// We test availability with a nullptr check, but the compiler doesn't see that. |
| 2617 | +#pragma clang diagnostic push |
| 2618 | +#pragma clang diagnostic ignored "-Wunguarded-availability-new" |
| 2619 | + |
2613 | 2620 | void
|
2614 | 2621 | swift::swift_updateClassMetadata(ClassMetadata *self,
|
2615 | 2622 | ClassLayoutFlags layoutFlags,
|
2616 | 2623 | size_t numFields,
|
2617 | 2624 | const TypeLayout * const *fieldTypes,
|
2618 | 2625 | size_t *fieldOffsets) {
|
2619 |
| -#ifndef NDEBUG |
2620 |
| - // If there is a mangled superclass name, demangle it to the superclass |
2621 |
| - // type. |
| 2626 | +#ifndef OBJC_REALIZECLASSFROMSWIFT_DEFINED |
| 2627 | + // Temporary workaround until _objc_realizeClassFromSwift is in the SDK. |
| 2628 | + static auto _objc_realizeClassFromSwift = |
| 2629 | + (Class (*)(Class _Nullable, void* _Nullable)) |
| 2630 | + dlsym(RTLD_NEXT, "_objc_realizeClassFromSwift"); |
| 2631 | +#endif |
| 2632 | + |
| 2633 | + bool requiresUpdate = (_objc_realizeClassFromSwift != nullptr); |
| 2634 | + |
| 2635 | + // If we're on a newer runtime, we're going to be initializing the |
| 2636 | + // field offset vector. Realize the superclass metadata first, even |
| 2637 | + // though our superclass field references it statically. |
2622 | 2638 | const ClassMetadata *super = nullptr;
|
2623 |
| - if (auto superclassNameBase = self->getDescription()->SuperclassType.get()) { |
2624 |
| - StringRef superclassName = |
2625 |
| - Demangle::makeSymbolicMangledNameStringRef(superclassNameBase); |
2626 |
| - SubstGenericParametersFromMetadata substitutions(self); |
2627 |
| - const Metadata *superclass = |
2628 |
| - _getTypeByMangledName(superclassName, substitutions); |
2629 |
| - if (!superclass) { |
2630 |
| - fatalError(0, |
2631 |
| - "failed to demangle superclass of %s from mangled name '%s'\n", |
2632 |
| - self->getDescription()->Name.get(), |
2633 |
| - superclassName.str().c_str()); |
2634 |
| - } |
2635 | 2639 |
|
2636 |
| -#if SWIFT_OBJC_INTEROP |
2637 |
| - if (auto objcWrapper = dyn_cast<ObjCClassWrapperMetadata>(superclass)) |
2638 |
| - superclass = objcWrapper->Class; |
| 2640 | + // In assert builds, realize the superclass metadata even if we're |
| 2641 | + // on an older runtime. |
| 2642 | +#ifndef NDEBUG |
| 2643 | + bool realizeSuperclass = true; |
| 2644 | +#else |
| 2645 | + bool realizeSuperclass = requiresUpdate; |
2639 | 2646 | #endif
|
2640 | 2647 |
|
2641 |
| - super = cast<ClassMetadata>(superclass); |
2642 |
| - } |
| 2648 | + if (realizeSuperclass) { |
| 2649 | + if (auto superclassNameBase = self->getDescription()->SuperclassType.get()) { |
| 2650 | + StringRef superclassName = |
| 2651 | + Demangle::makeSymbolicMangledNameStringRef(superclassNameBase); |
| 2652 | + SubstGenericParametersFromMetadata substitutions(self); |
| 2653 | + const Metadata *superclass = |
| 2654 | + _getTypeByMangledName(superclassName, substitutions); |
| 2655 | + if (!superclass) { |
| 2656 | + fatalError(0, |
| 2657 | + "failed to demangle superclass of %s from mangled name '%s'\n", |
| 2658 | + self->getDescription()->Name.get(), |
| 2659 | + superclassName.str().c_str()); |
| 2660 | + } |
2643 | 2661 |
|
2644 |
| - if (!super) |
2645 |
| - assert(self->Superclass == getRootSuperclass()); |
2646 |
| - else |
2647 |
| - assert(self->Superclass == super); |
2648 |
| -#endif |
| 2662 | + if (auto objcWrapper = dyn_cast<ObjCClassWrapperMetadata>(superclass)) |
| 2663 | + superclass = objcWrapper->Class; |
2649 | 2664 |
|
2650 |
| - // FIXME: Plumb this through |
2651 |
| -#if 1 |
2652 |
| - swift_getInitializedObjCClass((Class)self); |
2653 |
| -#else |
2654 |
| - initClassFieldOffsetVector(self, numFields, fieldTypes, fieldOffsets); |
2655 |
| - initObjCClass(self, numFields, fieldTypes, fieldOffsets); |
| 2665 | + super = cast<ClassMetadata>(superclass); |
| 2666 | + } |
2656 | 2667 |
|
2657 |
| - // Register this class with the runtime. This will also cause the |
2658 |
| - // runtime to slide the field offsets stored in the field offset |
2659 |
| - // globals. Note that the field offset vector is *not* updated; |
2660 |
| - // however we should not be using it for anything in a non-generic |
2661 |
| - // class. |
2662 |
| - swift_getInitializedObjCClassWithoutCallback(self); |
2663 |
| -#endif |
| 2668 | + // Check that it matches what's already in there. |
| 2669 | + if (!super) |
| 2670 | + assert(self->Superclass == getRootSuperclass()); |
| 2671 | + else |
| 2672 | + assert(self->Superclass == super); |
| 2673 | + } |
| 2674 | + |
| 2675 | + (void) super; |
| 2676 | + |
| 2677 | + // If we're running on a older Objective-C runtime, just realize |
| 2678 | + // the class. |
| 2679 | + if (!requiresUpdate) { |
| 2680 | + // Realize the class. This causes the runtime to slide the field offsets |
| 2681 | + // stored in the field offset globals. |
| 2682 | + // |
| 2683 | + // Note that the field offset vector is *not* updated; however in |
| 2684 | + // Objective-C interop mode, we don't actually use the field offset vector |
| 2685 | + // of non-generic classes. |
| 2686 | + // |
| 2687 | + // In particular, class mirrors always use the Objective-C ivar descriptors, |
| 2688 | + // which point at field offset globals and not the field offset vector. |
| 2689 | + swift_getInitializedObjCClass((Class)self); |
| 2690 | + } else { |
| 2691 | + // Update the field offset vector using runtime type information; the layout |
| 2692 | + // of resilient types might be different than the statically-emitted layout. |
| 2693 | + initClassFieldOffsetVector(self, numFields, fieldTypes, fieldOffsets); |
| 2694 | + |
| 2695 | + // Copy field offset vector entries to the field offset globals. |
| 2696 | + initObjCClass(self, numFields, fieldTypes, fieldOffsets); |
| 2697 | + |
| 2698 | + // See remark above about how this slides field offset globals. |
| 2699 | + _objc_realizeClassFromSwift((Class)self, (Class)self); |
| 2700 | + } |
2664 | 2701 | }
|
| 2702 | + |
| 2703 | +#pragma clang diagnostic pop |
2665 | 2704 | #endif
|
2666 | 2705 |
|
2667 | 2706 | #ifndef NDEBUG
|
|
0 commit comments