/// \brief Partition. /// seec::Maybe<std::size_t> partition(std::size_t const Left, std::size_t const Right, std::size_t const Pivot) { // Move the pivot to the end. swap(Pivot, Right); // Shift all elements "less than" the pivot to the left side. std::size_t StoreIndex = Left; for (std::size_t i = Left; i < Right; ++i) { // Release memory so that the compare function can access it. releaseMemory(); // Compare the current element to the pivot. auto const Comparison = Compare(getElement(i), getElement(Right)); // Lock memory and ensure that the compare function hasn't deallocated it. if (!acquireMemory()) return seec::Maybe<std::size_t>(); if (Comparison < 0) { swap(i, StoreIndex); ++StoreIndex; } } // Move pivot to its final place. swap(StoreIndex, Right); // Return final index of pivot. return StoreIndex; }
/// \brief Perform the binary search. char const *bsearch() { if (!ElementCount) return nullptr; std::size_t Min = 0; std::size_t Max = ElementCount - 1; while (Min <= Max) { std::size_t const Mid = Min + ((Max - Min) / 2); // Compare the midpoint with the key. releaseMemory(); // Array element is always the left side of comparison, key object is // always the right side of comparison. Our pointer object information // in the shim is set according to this, so do not change. auto const Comparison = Compare(getElement(Mid), Key); if (!acquireMemory()) return nullptr; if (Comparison < 0) // Mid-point is less than Key Min = Mid + 1; else if (Comparison > 0) { // Mid-point is greater than Key if (Mid == 0) return nullptr; Max = Mid - 1; } else // Mid-point is equal to Key return getElement(Mid); } return nullptr; }
void Allocator::reinitialize(void) { if (!memAllocated_) { maxAllocated_ = 0; acquireMemory(); } }
/// \brief Perform the quicksort. /// void *operator()() { // TODO: This should be raised as a run-time error. assert(CompareFn && "Comparison function is unknown!"); auto const Caller = ThreadListener.getActiveFunction(); assert(Caller && !Caller->isShim()); auto const Call = llvm::ImmutableCallSite(Caller->getActiveInstruction()); auto const KeyPtrObj = Caller->getPointerObject(Call.getArgument(0)); auto const ArrayPtrObj = Caller->getPointerObject(Call.getArgument(1)); ThreadListener.pushShimFunction(); auto const Shim = ThreadListener.getActiveFunction(); // Array element is always the left side of comparison, key object is // always the right side of comparison. auto CompareFnArg = CompareFn->arg_begin(); Shim->setPointerObject( &*CompareFnArg, ArrayPtrObj); Shim->setPointerObject(&*++CompareFnArg, KeyPtrObj ); acquireMemory(); auto const Result = bsearch(); releaseMemory(); ThreadListener.popShimFunction(); // The C standard specifies the result is not const. auto const Unqualified = const_cast<char *>(Result); // Notify of the returned pointer (and its pointer object). auto const CallInst = Call.getInstruction(); auto const Idx = seec::trace::getThreadEnvironment().getInstructionIndex(); ThreadListener.notifyValue(Idx, CallInst, reinterpret_cast<void *>(Unqualified)); // Note that Caller is invalidated when the shim function is pushed, so we // need to retrieve a new pointer to the active function. ThreadListener.getActiveFunction() ->setPointerObject(CallInst, Result ? ArrayPtrObj : seec::trace::PointerTarget{}); // const_cast due to the C standard. return Unqualified; }
Allocator::Allocator(ByteCount bufferSize, UInt32 memoryQuotaMB, BufferCount nBuffers, BufferCount reserve, NAMemory* heap, ExExeStmtGlobals* exeGlobals, bool yieldQuota) : maxAllocated_(0), memAllocated_(0), quota_(0), exeGlobals_(exeGlobals), heap_(heap), bufferSize_(bufferSize), nInitial_(nBuffers), nReserve_(reserve), reuseList_(heap), yieldQuota_(yieldQuota) { quotaInitial_ = memoryQuotaMB * ONE_MEGABYTE; if (quotaInitial_) { ex_assert(((bufferSize_ * nInitial_) <= quotaInitial_), "inconsistent constructor arguments"); } ex_assert((nInitial_ >= nReserve_), "reserve > initial buffer count"); acquireMemory(); }
/// \brief Perform the quicksort. /// void operator()() { // TODO: This should be raised as a run-time error. assert(CompareFn && "Comparison function is unknown!"); auto const Caller = ThreadListener.getActiveFunction(); assert(Caller && !Caller->isShim()); auto const Call = llvm::ImmutableCallSite(Caller->getActiveInstruction()); auto const ArrayPtrObj = Caller->getPointerObject(Call.getArgument(0)); ThreadListener.pushShimFunction(); auto const Shim = ThreadListener.getActiveFunction(); auto CompareFnArg = CompareFn->arg_begin(); Shim->setPointerObject( &*CompareFnArg, ArrayPtrObj); Shim->setPointerObject(&*++CompareFnArg, ArrayPtrObj); acquireMemory(); quicksort(0, ElementCount - 1); releaseMemory(); ThreadListener.popShimFunction(); }