if (!nonpointer) { newisa.setClass(cls, this); } else { ASSERT(!DisableNonpointerIsa); ASSERT(!cls->instancesRequireRawIsa());
#if SUPPORT_INDEXED_ISA ASSERT(cls->classArrayIndex() > 0); newisa.bits = ISA_INDEX_MAGIC_VALUE; // isa.magic is part of ISA_MAGIC_VALUE // isa.nonpointer is part of ISA_MAGIC_VALUE newisa.has_cxx_dtor = hasCxxDtor; newisa.indexcls = (uintptr_t)cls->classArrayIndex(); #else newisa.bits = ISA_MAGIC_VALUE; // isa.magic is part of ISA_MAGIC_VALUE // isa.nonpointer is part of ISA_MAGIC_VALUE # if ISA_HAS_CXX_DTOR_BIT newisa.has_cxx_dtor = hasCxxDtor; # endif newisa.setClass(cls, this); #endif #if ISA_HAS_INLINE_RC newisa.extra_rc = 1; #endif }
// This write must be performed in a single store in some cases // (for example when realizing a class because other threads // may simultaneously try to use the class). // fixme use atomics here to guarantee single-store and to // guarantee memory order w.r.t. the class index table // ...but not too atomic because we don't want to hurt instantiation isa() = newisa; }
// Set the class field in an isa. Takes both the class to set and // a pointer to the object where the isa will ultimately be used. // This is necessary to get the pointer signing right. // // Note: this method does not support setting an indexed isa. When // indexed isas are in use, it can only be used to set the class of a // raw isa. inlinevoid isa_t::setClass(Class newCls, UNUSED_WITHOUT_PTRAUTH objc_object *obj) { // Match the conditional in isa.h. #if __has_feature(ptrauth_calls) || TARGET_OS_SIMULATOR # if ISA_SIGNING_SIGN_MODE == ISA_SIGNING_SIGN_NONE // No signing, just use the raw pointer. uintptr_t signedCls = (uintptr_t)newCls;
# elif ISA_SIGNING_SIGN_MODE == ISA_SIGNING_SIGN_ONLY_SWIFT // We're only signing Swift classes. Non-Swift classes just use // the raw pointer uintptr_t signedCls = (uintptr_t)newCls; if (newCls->isSwiftStable()) signedCls = (uintptr_t)ptrauth_sign_unauthenticated((void *)newCls, ISA_SIGNING_KEY, ptrauth_blend_discriminator(obj, ISA_SIGNING_DISCRIMINATOR));
#elif SUPPORT_INDEXED_ISA // Indexed isa only uses this method to set a raw pointer class. // Setting an indexed class is handled separately. cls = newCls;
#else// Nonpointer isa, no ptrauth shiftcls = (uintptr_t)newCls >> 3; #endif }
inline Class isa_t::getClass(MAYBE_UNUSED_AUTHENTICATED_PARAM bool authenticated)const{ #if SUPPORT_INDEXED_ISA return cls; #else
uintptr_t clsbits = bits;
# if __has_feature(ptrauth_calls) # if ISA_SIGNING_AUTH_MODE == ISA_SIGNING_AUTH // Most callers aren't security critical, so skip the // authentication unless they ask for it. Message sending and // cache filling are protected by the auth code in msgSend. if (authenticated) { // Mask off all bits besides the class pointer and signature. clsbits &= ISA_MASK; if (clsbits == 0) return Nil; clsbits = (uintptr_t)ptrauth_auth_data((void *)clsbits, ISA_SIGNING_KEY, ptrauth_blend_discriminator(this, ISA_SIGNING_DISCRIMINATOR)); } else { // If not authenticating, strip using the precomputed class mask. clsbits &= objc_debug_isa_class_mask; } # else // If not authenticating, strip using the precomputed class mask. clsbits &= objc_debug_isa_class_mask; # endif