extern "C" void PyString_InternInPlace(PyObject** p) noexcept { BoxedString* s = (BoxedString*)*p; if (s == NULL || !PyString_Check(s)) Py_FatalError("PyString_InternInPlace: strings only please!"); /* If it's a string subclass, we don't really know what putting it in the interned dict might do. */ if (!PyString_CheckExact(s)) return; if (PyString_CHECK_INTERNED(s)) return; auto it = interned_strings.find(s); if (it != interned_strings.end()) { auto entry = *it; Py_INCREF(entry); Py_DECREF(*p); *p = entry; } else { // TODO: do CPython's refcounting here num_interned_strings.log(); interned_strings.insert(s); Py_INCREF(s); // CPython returns mortal but in our current implementation they are inmortal s->interned_state = SSTATE_INTERNED_IMMORTAL; } }
bool ConsumedResultToEpilogueRetainMatcher:: isTransitiveSuccessorsRetainFree(llvm::DenseSet<SILBasicBlock *> BBs) { // For every block with retain, we need to check the transitive // closure of its successors are retain-free. for (auto &I : EpilogueRetainInsts) { auto *CBB = I->getParent(); for (auto &Succ : CBB->getSuccessors()) { if (BBs.find(Succ) != BBs.end()) continue; return false; } } for (auto CBB : BBs) { for (auto &Succ : CBB->getSuccessors()) { if (BBs.find(Succ) != BBs.end()) continue; return false; } } return true; }
BoxedString* internStringImmortal(llvm::StringRef s) noexcept { auto it = interned_strings.find_as(s); if (it != interned_strings.end()) return incref(*it); num_interned_strings.log(); BoxedString* entry = boxString(s); // CPython returns mortal but in our current implementation they are inmortal entry->interned_state = SSTATE_INTERNED_IMMORTAL; interned_strings.insert((BoxedString*)entry); Py_INCREF(entry); return entry; }
/// TODO: We should consult the cached LoweredLocalCaptures the SIL /// TypeConverter calculates, but that would require plumbing SILModule& /// through every SILDeclRef constructor. Since this is only used to determine /// "natural uncurry level", and "uncurry level" is a concept we'd like to /// phase out, it's not worth it. static bool hasLoweredLocalCaptures(AnyFunctionRef AFR, llvm::DenseSet<AnyFunctionRef> &visited) { if (!AFR.getCaptureInfo().hasLocalCaptures()) return false; // Scan for local, non-function captures. bool functionCapturesToRecursivelyCheck = false; auto addFunctionCapture = [&](AnyFunctionRef capture) { if (visited.find(capture) == visited.end()) functionCapturesToRecursivelyCheck = true; }; for (auto &capture : AFR.getCaptureInfo().getCaptures()) { if (!capture.getDecl()->getDeclContext()->isLocalContext()) continue; // We transitively capture a local function's captures. if (auto func = dyn_cast<AbstractFunctionDecl>(capture.getDecl())) { addFunctionCapture(func); continue; } // We may either directly capture properties, or capture through their // accessors. if (auto var = dyn_cast<VarDecl>(capture.getDecl())) { switch (var->getStorageKind()) { case VarDecl::StoredWithTrivialAccessors: llvm_unreachable("stored local variable with trivial accessors?"); case VarDecl::InheritedWithObservers: llvm_unreachable("inherited local variable?"); case VarDecl::StoredWithObservers: case VarDecl::Addressed: case VarDecl::AddressedWithTrivialAccessors: case VarDecl::AddressedWithObservers: case VarDecl::ComputedWithMutableAddress: // Directly capture storage if we're supposed to. if (capture.isDirect()) return true; // Otherwise, transitively capture the accessors. SWIFT_FALLTHROUGH; case VarDecl::Computed: addFunctionCapture(var->getGetter()); if (auto setter = var->getSetter()) addFunctionCapture(setter); continue; case VarDecl::Stored: return true; } } // Anything else is directly captured. return true; } // Recursively consider function captures, since we didn't have any direct // captures. auto captureHasLocalCaptures = [&](AnyFunctionRef capture) -> bool { if (visited.insert(capture).second) return hasLoweredLocalCaptures(capture, visited); return false; }; if (functionCapturesToRecursivelyCheck) { for (auto &capture : AFR.getCaptureInfo().getCaptures()) { if (!capture.getDecl()->getDeclContext()->isLocalContext()) continue; if (auto func = dyn_cast<AbstractFunctionDecl>(capture.getDecl())) { if (captureHasLocalCaptures(func)) return true; continue; } if (auto var = dyn_cast<VarDecl>(capture.getDecl())) { switch (var->getStorageKind()) { case VarDecl::StoredWithTrivialAccessors: llvm_unreachable("stored local variable with trivial accessors?"); case VarDecl::InheritedWithObservers: llvm_unreachable("inherited local variable?"); case VarDecl::StoredWithObservers: case VarDecl::Addressed: case VarDecl::AddressedWithTrivialAccessors: case VarDecl::AddressedWithObservers: case VarDecl::ComputedWithMutableAddress: assert(!capture.isDirect() && "should have short circuited out"); // Otherwise, transitively capture the accessors. SWIFT_FALLTHROUGH; case VarDecl::Computed: if (captureHasLocalCaptures(var->getGetter())) return true; if (auto setter = var->getSetter()) if (captureHasLocalCaptures(setter)) return true; continue; case VarDecl::Stored: llvm_unreachable("should have short circuited out"); } } llvm_unreachable("should have short circuited out"); } } return false; }