text:
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

/*
 * GCENV.EE.CPP
 *
 * GCToEEInterface implementation
 *

 *
 */

void GCToEEInterface::SuspendEE(SUSPEND_REASON reason)
{
    WRAPPER_NO_CONTRACT;

    static_assert_no_msg(SUSPEND_FOR_GC == (int)ThreadSuspend::SUSPEND_FOR_GC);
    static_assert_no_msg(SUSPEND_FOR_GC_PREP == (int)ThreadSuspend::SUSPEND_FOR_GC_PREP);

    _ASSERTE(reason == SUSPEND_FOR_GC || reason == SUSPEND_FOR_GC_PREP);

    g_pDebugInterface->SuspendForGarbageCollectionStarted();

    ThreadSuspend::SuspendEE((ThreadSuspend::SUSPEND_REASON)reason);

    g_pDebugInterface->SuspendForGarbageCollectionCompleted();
}

void GCToEEInterface::RestartEE(bool bFinishedGC)
{
    WRAPPER_NO_CONTRACT;

    g_pDebugInterface->ResumeForGarbageCollectionStarted();

    ThreadSuspend::RestartEE(bFinishedGC, TRUE);
}

VOID GCToEEInterface::SyncBlockCacheWeakPtrScan(HANDLESCANPROC scanProc, uintptr_t lp1, uintptr_t lp2)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
    }
    CONTRACTL_END;

    SyncBlockCache::GetSyncBlockCache()->GCWeakPtrScan(scanProc, lp1, lp2);
}

//EE can perform post stack scanning action, while the
// user threads are still suspended
VOID GCToEEInterface::AfterGcScanRoots (int condemned, int max_gen,
                                   ScanContext* sc)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
    }
    CONTRACTL_END;

#ifdef FEATURE_COMINTEROP
    // Go through all the only app domain and detach all the *unmarked* RCWs to prevent
    // the RCW cache from resurrecting them.
    ::GetAppDomain()->DetachRCWs();
#endif // FEATURE_COMINTEROP
}

/*
 * Scan all stack roots
 */

static void ScanStackRoots(Thread * pThread, promote_func* fn, ScanContext* sc)
{
    GCCONTEXT   gcctx;

    gcctx.f  = fn;
    gcctx.sc = sc;
    gcctx.cf = NULL;

    ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();

    // Either we are in a concurrent situation (in which case the thread is unknown to
    // us), or we are performing a synchronous GC and we are the GC thread, holding
    // the threadstore lock.

    _ASSERTE(dbgOnly_IsSpecialEEThread() ||
                GetThread() == NULL ||
                // this is for background GC threads which always call this when EE is suspended.
                IsGCSpecialThread() ||
                (GetThread() == ThreadSuspend::GetSuspensionThread() && ThreadStore::HoldingThreadStore()));

    Frame* pTopFrame = pThread->GetFrame();
    Object ** topStack = (Object **)pTopFrame;
    if ((pTopFrame != ((Frame*)-1))
        && (pTopFrame->GetVTablePtr() == InlinedCallFrame::GetMethodFrameVPtr())) {
        // It is an InlinedCallFrame. Get SP from it.
        InlinedCallFrame* pInlinedFrame = (InlinedCallFrame*)pTopFrame;
        topStack = (Object **)pInlinedFrame->GetCallSiteSP();
    }

    sc->stack_limit = (uintptr_t)topStack;

#ifdef FEATURE_CONSERVATIVE_GC
    if (g_pConfig->GetGCConservative())
    {
        // Conservative stack root reporting
        // We will treat everything on stack as a pinned interior GC pointer
        // Since we report every thing as pinned, we don't need to run following code for relocation phase.
        if (sc->promotion)
        {
            Object ** bottomStack = (Object **) pThread->GetCachedStackBase();
            Object ** walk;
            for (walk = topStack; walk < bottomStack; walk ++)
            {
                if (((void*)*walk > (void*)bottomStack || (void*)*walk < (void*)topStack) &&
                    ((void*)*walk >= (void*)g_lowest_address && (void*)*walk <= (void*)g_highest_address)
                    )
                {
                    //DbgPrintf("promote " FMT_ADDR " : " FMT_ADDR "\n", walk, *walk);
                    fn(walk, sc, GC_CALL_INTERIOR|GC_CALL_PINNED);
                }
            }
        }

        // Also ask the explicit Frames to report any references they might know about.
        // Generally these will be a subset of the objects reported below but there's
        // nothing that guarantees that and in the specific case of a GC protect frame the
        // references it protects may live at a lower address than the frame itself (and
        // thus escape the stack range we scanned above).
        Frame *pFrame = pThread->GetFrame();
        while (pFrame != FRAME_TOP)
        {
            pFrame->GcScanRoots(fn, sc);
            pFrame = pFrame->PtrNextFrame();
        }
    }
    else
#endif
    {
        unsigned flagsStackWalk = ALLOW_ASYNC_STACK_WALK | ALLOW_INVALID_OBJECTS;
#if defined(FEATURE_EH_FUNCLETS)
        flagsStackWalk |= GC_FUNCLET_REFERENCE_REPORTING;
#endif // defined(FEATURE_EH_FUNCLETS)
        pThread->StackWalkFrames( GcStackCrawlCallBack, &gcctx, flagsStackWalk);
    }

    GCFrame* pGCFrame = pThread->GetGCFrame();
    while (pGCFrame != NULL)
    {
        pGCFrame->GcScanRoots(fn, sc);
        pGCFrame = pGCFrame->PtrNextFrame();
    }
}

void GCToEEInterface::GcScanRoots(promote_func* fn, int condemned, int max_gen, ScanContext* sc)
{
    STRESS_LOG1(LF_GCROOTS, LL_INFO10, "GCScan: Promotion Phase = %d\n", sc->promotion);

    // In server GC, we should be competing for marking the statics
    if (GCHeapUtilities::MarkShouldCompeteForStatics())
    {
        if (condemned == max_gen && sc->promotion)
        {
            SystemDomain::EnumAllStaticGCRefs(fn, sc);
        }
    }

    Thread* pThread = NULL;
    while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL)
    {
        STRESS_LOG2(LF_GC | LF_GCROOTS, LL_INFO100, "{ Starting scan of Thread %p ID = %x\n", pThread, pThread->GetThreadId());

        if (GCHeapUtilities::GetGCHeap()->IsThreadUsingAllocationContextHeap(
            pThread->GetAllocContext(), sc->thread_number))
        {
            sc->thread_under_crawl = pThread;
#ifdef FEATURE_EVENT_TRACE
            sc->dwEtwRootKind = kEtwGCRootKindStack;
#endif // FEATURE_EVENT_TRACE
            ScanStackRoots(pThread, fn, sc);
#ifdef FEATURE_EVENT_TRACE
            sc->dwEtwRootKind = kEtwGCRootKindOther;
#endif // FEATURE_EVENT_TRACE
        }
        STRESS_LOG2(LF_GC | LF_GCROOTS, LL_INFO100, "Ending scan of Thread %p ID = 0x%x }\n", pThread, pThread->GetThreadId());
    }
}

void GCToEEInterface::GcStartWork (int condemned, int max_gen)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
    }
    CONTRACTL_END;

#ifdef VERIFY_HEAP
    // Validate byrefs pinned by IL stubs since the last GC.
    StubHelpers::ProcessByrefValidationList();
#endif // VERIFY_HEAP

    ExecutionManager::CleanupCodeHeaps();

#ifdef FEATURE_EVENT_TRACE
    ETW::TypeSystemLog::Cleanup();
#endif

#ifdef FEATURE_COMINTEROP
    //
    // Let GC detect managed/native cycles with input from jupiter
    // Jupiter will
    // 1. Report reference from RCW to CCW based on native reference in Jupiter
    // 2. Identify the subset of CCWs that needs to be rooted
    //
    // We'll build the references from RCW to CCW using
    // 1. Preallocated arrays
    // 2. Dependent handles
    //
    RCWWalker::OnGCStarted(condemned);
#endif // FEATURE_COMINTEROP

    if (condemned == max_gen)
    {
        ThreadStore::s_pThreadStore->OnMaxGenerationGCStarted();
    }
}

void GCToEEInterface::GcDone(int condemned)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
    }
    CONTRACTL_END;

#ifdef FEATURE_COMINTEROP
    //
    // Tell Jupiter GC has finished
    //
    RCWWalker::OnGCFinished(condemned);
#endif // FEATURE_COMINTEROP
}

bool GCToEEInterface::RefCountedHandleCallbacks(Object * pObject)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
    }
    CONTRACTL_END;

#ifdef FEATURE_COMINTEROP
    //<REVISIT_TODO>@todo optimize the access to the ref-count
    ComCallWrapper* pWrap = ComCallWrapper::GetWrapperForObject((OBJECTREF)pObject);

    return pWrap != NULL && pWrap->IsWrapperActive();
#else
    return false;
#endif
}

void GCToEEInterface::GcBeforeBGCSweepWork()
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
    }
    CONTRACTL_END;

#ifdef VERIFY_HEAP
    // Validate byrefs pinned by IL stubs since the last GC.
    StubHelpers::ProcessByrefValidationList();
#endif // VERIFY_HEAP
}

void GCToEEInterface::SyncBlockCacheDemote(int max_gen)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
    }
    CONTRACTL_END;

    SyncBlockCache::GetSyncBlockCache()->GCDone(TRUE, max_gen);
}

void GCToEEInterface::SyncBlockCachePromotionsGranted(int max_gen)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
    }
    CONTRACTL_END;

    SyncBlockCache::GetSyncBlockCache()->GCDone(FALSE, max_gen);
}

uint32_t GCToEEInterface::GetActiveSyncBlockCount()
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
    }
    CONTRACTL_END;

    return SyncBlockCache::GetSyncBlockCache()->GetActiveCount();
}

gc_alloc_context * GCToEEInterface::GetAllocContext()
{
    WRAPPER_NO_CONTRACT;

    Thread* pThread = ::GetThread();
    if (!pThread)
    {
        return nullptr;
    }

    return pThread->GetAllocContext();
}

void GCToEEInterface::GcEnumAllocContexts(enum_alloc_context_func* fn, void* param)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
    }
    CONTRACTL_END;

    if (GCHeapUtilities::UseThreadAllocationContexts())
    {
        Thread * pThread = NULL;
        while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL)
        {
            fn(pThread->GetAllocContext(), param);
        }
    }
    else
    {
        fn(&g_global_alloc_context, param);
    }
}

uint8_t* GCToEEInterface::GetLoaderAllocatorObjectForGC(Object* pObject)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
    }
    CONTRACTL_END;

    return pObject->GetGCSafeMethodTable()->GetLoaderAllocatorObjectForGC();
}

bool GCToEEInterface::IsPreemptiveGCDisabled()
{
    WRAPPER_NO_CONTRACT;

    Thread* pThread = ::GetThread();

    return (pThread && pThread->PreemptiveGCDisabled());
}

bool GCToEEInterface::EnablePreemptiveGC()
{
    WRAPPER_NO_CONTRACT;

    Thread* pThread = ::GetThread();

    if (pThread && pThread->PreemptiveGCDisabled())
    {
        pThread->EnablePreemptiveGC();
        return true;
    }

    return false;
}

void GCToEEInterface::DisablePreemptiveGC()
{
    WRAPPER_NO_CONTRACT;

    Thread* pThread = ::GetThread();
    if (pThread)
    {
        pThread->DisablePreemptiveGC();
    }
}

Thread* GCToEEInterface::GetThread()
{
    WRAPPER_NO_CONTRACT;

    return ::GetThread();
}

//
// Diagnostics code
//

#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)

// Tracks all surviving objects (moved or otherwise).
inline bool ShouldTrackSurvivorsForProfilerOrEtw()
{
#ifdef GC_PROFILING
    if (CORProfilerTrackGC())
        return true;
#endif

#ifdef FEATURE_EVENT_TRACE
    if (ETW::GCLog::ShouldTrackMovementForEtw())
        return true;
#endif

    return false;
}

// Only tracks surviving objects in compacting GCs (moved or otherwise).
inline bool ShouldTrackSurvivorsInCompactingGCsForProfiler()
{
#ifdef GC_PROFILING
    if (CORProfilerTrackGCMovedObjects())
        return true;
#endif
    return false;
}
#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)

void ProfScanRootsHelper(Object** ppObject, ScanContext *pSC, uint32_t dwFlags)
{
#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
    Object *pObj = *ppObject;
    if (dwFlags & GC_CALL_INTERIOR)
    {
        pObj = GCHeapUtilities::GetGCHeap()->GetContainingObject(pObj, true);
        if (pObj == nullptr)
            return;
    }
    ScanRootsHelper(pObj, ppObject, pSC, dwFlags);
#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
}

// TODO - at some point we would like to completely decouple profiling
// from ETW tracing using a pattern similar to this, where the
// ProfilingScanContext has flags about whether or not certain things
// should be tracked, and each one of these ProfilerShouldXYZ functions
// will check these flags and determine what to do based upon that.
// GCProfileWalkHeapWorker can, in turn, call those methods without fear
// of things being ifdef'd out.

// Returns TRUE if GC profiling is enabled and the profiler
// should scan dependent handles, FALSE otherwise.
BOOL ProfilerShouldTrackConditionalWeakTableElements()
{
#if defined(GC_PROFILING)
    return CORProfilerTrackConditionalWeakTableElements();
#else
    return FALSE;
#endif // defined (GC_PROFILING)
}

// If GC profiling is enabled, informs the profiler that we are done
// tracing dependent handles.
void ProfilerEndConditionalWeakTableElementReferences(void* heapId)
{
#if defined (GC_PROFILING)
    g_profControlBlock.pProfInterface->EndConditionalWeakTableElementReferences(heapId);
#else
    UNREFERENCED_PARAMETER(heapId);
#endif // defined (GC_PROFILING)
}

// If GC profiling is enabled, informs the profiler that we are done
// tracing root references.
void ProfilerEndRootReferences2(void* heapId)
{
#if defined (GC_PROFILING)
    g_profControlBlock.pProfInterface->EndRootReferences2(heapId);
#else
    UNREFERENCED_PARAMETER(heapId);
#endif // defined (GC_PROFILING)
}

void GcScanRootsForProfilerAndETW(promote_func* fn, int condemned, int max_gen, ScanContext* sc)
{
    Thread* pThread = NULL;
    while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL)
    {
        sc->thread_under_crawl = pThread;
#ifdef FEATURE_EVENT_TRACE
        sc->dwEtwRootKind = kEtwGCRootKindStack;
#endif // FEATURE_EVENT_TRACE
        ScanStackRoots(pThread, fn, sc);
#ifdef FEATURE_EVENT_TRACE
        sc->dwEtwRootKind = kEtwGCRootKindOther;
#endif // FEATURE_EVENT_TRACE
    }
}

void ScanHandleForProfilerAndETW(Object** pRef, Object* pSec, uint32_t flags, ScanContext* context, bool isDependent)
{
    ProfilingScanContext* pSC = (ProfilingScanContext*)context;

#ifdef GC_PROFILING
    // Give the profiler the objectref.
    if (pSC->fProfilerPinned)
    {
        if (!isDependent)
        {
            BEGIN_PIN_PROFILER(CORProfilerTrackGC());
            g_profControlBlock.pProfInterface->RootReference2(
                (uint8_t *)*pRef,
                kEtwGCRootKindHandle,
                (EtwGCRootFlags)flags,
                pRef,
                &pSC->pHeapId);
            END_PIN_PROFILER();
        }
        else
        {
            BEGIN_PIN_PROFILER(CORProfilerTrackConditionalWeakTableElements());
            g_profControlBlock.pProfInterface->ConditionalWeakTableElementReference(
                (uint8_t*)*pRef,
                (uint8_t*)pSec,
                pRef,
                &pSC->pHeapId);
            END_PIN_PROFILER();
        }
    }
#endif // GC_PROFILING

#if defined(FEATURE_EVENT_TRACE)
    // Notify ETW of the handle
    if (ETW::GCLog::ShouldWalkHeapRootsForEtw())
    {
        ETW::GCLog::RootReference(
            pRef,
            *pRef,          // object being rooted
            pSec,           // pSecondaryNodeForDependentHandle
            isDependent,
            pSC,
            0,              // dwGCFlags,
            flags);     // ETW handle flags
    }
#endif // defined(FEATURE_EVENT_TRACE)
}

// This is called only if we've determined that either:
//     a) The Profiling API wants to do a walk of the heap, and it has pinned the
//     profiler in place (so it cannot be detached), and it's thus safe to call into the
//     profiler, OR
//     b) ETW infrastructure wants to do a walk of the heap either to log roots,
//     objects, or both.
// This can also be called to do a single walk for BOTH a) and b) simultaneously.  Since
// ETW can ask for roots, but not objects
#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
void GCProfileWalkHeapWorker(BOOL fProfilerPinned, BOOL fShouldWalkHeapRootsForEtw, BOOL fShouldWalkHeapObjectsForEtw)
{
    {
        ProfilingScanContext SC(fProfilerPinned);
        unsigned max_generation = GCHeapUtilities::GetGCHeap()->GetMaxGeneration();

        // **** Scan roots:  Only scan roots if profiling API wants them or ETW wants them.
        if (fProfilerPinned || fShouldWalkHeapRootsForEtw)
        {
            GcScanRootsForProfilerAndETW(&ProfScanRootsHelper, max_generation, max_generation, &SC);
            SC.dwEtwRootKind = kEtwGCRootKindFinalizer;
            GCHeapUtilities::GetGCHeap()->DiagScanFinalizeQueue(&ProfScanRootsHelper, &SC);

            // Handles are kept independent of wks/svr/concurrent builds
            SC.dwEtwRootKind = kEtwGCRootKindHandle;
            GCHeapUtilities::GetGCHeap()->DiagScanHandles(&ScanHandleForProfilerAndETW, max_generation, &SC);

            // indicate that regular handle scanning is over, so we can flush the buffered roots
            // to the profiler.  (This is for profapi only.  ETW will flush after the
            // entire heap was is complete, via ETW::GCLog::EndHeapDump.)
            if (fProfilerPinned)
            {
                ProfilerEndRootReferences2(&SC.pHeapId);
            }
        }

        // **** Scan dependent handles: only if the profiler supports it or ETW wants roots
        if ((fProfilerPinned && ProfilerShouldTrackConditionalWeakTableElements()) ||
            fShouldWalkHeapRootsForEtw)
        {
            // GcScanDependentHandlesForProfiler double-checks
            // CORProfilerTrackConditionalWeakTableElements() before calling into the profiler

            ProfilingScanContext* pSC = &SC;

            // we'll re-use pHeapId (which was either unused (0) or freed by EndRootReferences2
            // (-1)), so reset it to NULL
            _ASSERTE((*((size_t *)(&pSC->pHeapId)) == (size_t)(-1)) ||
                    (*((size_t *)(&pSC->pHeapId)) == (size_t)(0)));
            pSC->pHeapId = NULL;

            GCHeapUtilities::GetGCHeap()->DiagScanDependentHandles(&ScanHandleForProfilerAndETW, max_generation, &SC);

            // indicate that dependent handle scanning is over, so we can flush the buffered roots
            // to the profiler.  (This is for profapi only.  ETW will flush after the
            // entire heap was is complete, via ETW::GCLog::EndHeapDump.)
            if (fProfilerPinned && ProfilerShouldTrackConditionalWeakTableElements())
            {
                ProfilerEndConditionalWeakTableElementReferences(&SC.pHeapId);
            }
        }

        ProfilerWalkHeapContext profilerWalkHeapContext(fProfilerPinned, SC.pvEtwContext);

        // **** Walk objects on heap: only if profiling API wants them or ETW wants them.
        if (fProfilerPinned || fShouldWalkHeapObjectsForEtw)
        {
            GCHeapUtilities::GetGCHeap()->DiagWalkHeap(&HeapWalkHelper, &profilerWalkHeapContext, max_generation, true /* walk the large object heap */);
        }

#ifdef FEATURE_EVENT_TRACE
        // **** Done! Indicate to ETW helpers that the heap walk is done, so any buffers
        // should be flushed into the ETW stream
        if (fShouldWalkHeapObjectsForEtw || fShouldWalkHeapRootsForEtw)
        {
            ETW::GCLog::EndHeapDump(&profilerWalkHeapContext);
        }
#endif // FEATURE_EVENT_TRACE
    }
}
#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)

void GCProfileWalkHeap()
{
    BOOL fWalkedHeapForProfiler = FALSE;

#ifdef FEATURE_EVENT_TRACE
    if (ETW::GCLog::ShouldWalkStaticsAndCOMForEtw())
        ETW::GCLog::WalkStaticsAndCOMForETW();

    BOOL fShouldWalkHeapRootsForEtw = ETW::GCLog::ShouldWalkHeapRootsForEtw();
    BOOL fShouldWalkHeapObjectsForEtw = ETW::GCLog::ShouldWalkHeapObjectsForEtw();
#else // !FEATURE_EVENT_TRACE
    BOOL fShouldWalkHeapRootsForEtw = FALSE;
    BOOL fShouldWalkHeapObjectsForEtw = FALSE;
#endif // FEATURE_EVENT_TRACE

#if defined (GC_PROFILING)
    {
        BEGIN_PIN_PROFILER(CORProfilerTrackGC());
        GCProfileWalkHeapWorker(TRUE /* fProfilerPinned */, fShouldWalkHeapRootsForEtw, fShouldWalkHeapObjectsForEtw);
        fWalkedHeapForProfiler = TRUE;
        END_PIN_PROFILER();
    }
#endif // defined (GC_PROFILING)

#if defined (GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
    // we need to walk the heap if one of GC_PROFILING or FEATURE_EVENT_TRACE
    // is defined, since both of them make use of the walk heap worker.
    if (!fWalkedHeapForProfiler &&
        (fShouldWalkHeapRootsForEtw || fShouldWalkHeapObjectsForEtw))
    {
        GCProfileWalkHeapWorker(FALSE /* fProfilerPinned */, fShouldWalkHeapRootsForEtw, fShouldWalkHeapObjectsForEtw);
    }
#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
}

void WalkFReachableObjects(bool isCritical, void* objectID)
{
	g_profControlBlock.pProfInterface->FinalizeableObjectQueued(isCritical, (ObjectID)objectID);
}

static fq_walk_fn g_FQWalkFn = &WalkFReachableObjects;

void GCToEEInterface::DiagGCStart(int gen, bool isInduced)
{
#ifdef GC_PROFILING
    DiagUpdateGenerationBounds();
    GarbageCollectionStartedCallback(gen, isInduced);
    {
        BEGIN_PIN_PROFILER(CORProfilerTrackGC());
        size_t context = 0;

        // When we're walking objects allocated by class, then we don't want to walk the large
        // object heap because then it would count things that may have been around for a while.
        GCHeapUtilities::GetGCHeap()->DiagWalkHeap(&AllocByClassHelper, (void *)&context, 0, false);

        // Notify that we've reached the end of the Gen 0 scan
        g_profControlBlock.pProfInterface->EndAllocByClass(&context);
        END_PIN_PROFILER();
    }

#endif // GC_PROFILING
}

void GCToEEInterface::DiagUpdateGenerationBounds()
{
#ifdef GC_PROFILING
    if (CORProfilerTrackGC() || CORProfilerTrackBasicGC())
        UpdateGenerationBounds();
#endif // GC_PROFILING
}

void GCToEEInterface::DiagGCEnd(size_t index, int gen, int reason, bool fConcurrent)
{
#ifdef GC_PROFILING
    // We were only doing generation bounds and GC finish callback for non concurrent GCs so
    // I am keeping that behavior to not break profilers. But if BasicGC monitoring is enabled
    // we will do these for all GCs.
    if (!fConcurrent)
    {
        GCProfileWalkHeap();
    }

    if (CORProfilerTrackBasicGC() || (!fConcurrent && CORProfilerTrackGC()))
    {
        DiagUpdateGenerationBounds();
        GarbageCollectionFinishedCallback();
    }
#endif // GC_PROFILING
}

void GCToEEInterface::DiagWalkFReachableObjects(void* gcContext)
{
#ifdef GC_PROFILING
    if (CORProfilerTrackGC())
    {
        BEGIN_PIN_PROFILER(CORProfilerPresent());
        GCHeapUtilities::GetGCHeap()->DiagWalkFinalizeQueue(gcContext, g_FQWalkFn);
        END_PIN_PROFILER();
    }
#endif //GC_PROFILING
}

// Note on last parameter: when calling this for bgc, only ETW
// should be sending these events so that existing profapi profilers
// don't get confused.
void WalkMovedReferences(uint8_t* begin, uint8_t* end,
                         ptrdiff_t reloc,
                         void* context,
                         bool fCompacting,
                         bool fBGC)
{
    ETW::GCLog::MovedReference(begin, end,
                               (fCompacting ? reloc : 0),
                               (size_t)context,
                               fCompacting,
                               !fBGC);
}

void GCToEEInterface::DiagWalkSurvivors(void* gcContext, bool fCompacting)
{
#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
    if (ShouldTrackSurvivorsForProfilerOrEtw() ||
        (fCompacting && ShouldTrackSurvivorsInCompactingGCsForProfiler()))
    {
        size_t context = 0;
        ETW::GCLog::BeginMovedReferences(&context);
        GCHeapUtilities::GetGCHeap()->DiagWalkSurvivorsWithType(gcContext, &WalkMovedReferences, (void*)context, walk_for_gc);
        ETW::GCLog::EndMovedReferences(context);
    }
#endif //GC_PROFILING || FEATURE_EVENT_TRACE
}

void GCToEEInterface::DiagWalkLOHSurvivors(void* gcContext)
{
#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
    if (ShouldTrackSurvivorsForProfilerOrEtw())
    {
        size_t context = 0;
        ETW::GCLog::BeginMovedReferences(&context);
        GCHeapUtilities::GetGCHeap()->DiagWalkSurvivorsWithType(gcContext, &WalkMovedReferences, (void*)context, walk_for_loh);
        ETW::GCLog::EndMovedReferences(context);
    }
#endif //GC_PROFILING || FEATURE_EVENT_TRACE
}

void GCToEEInterface::DiagWalkBGCSurvivors(void* gcContext)
{
#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
    if (ShouldTrackSurvivorsForProfilerOrEtw())
    {
        size_t context = 0;
        ETW::GCLog::BeginMovedReferences(&context);
        GCHeapUtilities::GetGCHeap()->DiagWalkSurvivorsWithType(gcContext, &WalkMovedReferences, (void*)context, walk_for_bgc);
        ETW::GCLog::EndMovedReferences(context);
    }
#endif //GC_PROFILING || FEATURE_EVENT_TRACE
}

void GCToEEInterface::StompWriteBarrier(WriteBarrierParameters* args)
{
    assert(args != nullptr);
    int stompWBCompleteActions = SWB_PASS;
    bool is_runtime_suspended = args->is_runtime_suspended;

    switch (args->operation)
    {
    case WriteBarrierOp::StompResize:
        // StompResize requires a new card table, a new lowest address, and
        // a new highest address
        assert(args->card_table != nullptr);
        assert(args->lowest_address != nullptr);
        assert(args->highest_address != nullptr);

        // We are sensitive to the order of writes here (more comments on this further in the method)
        // In particular g_card_table must be written before writing the heap bounds.
        // For platforms with weak memory ordering we will issue fences, for x64/x86 we are ok
        // as long as compiler does not reorder these writes.
        // That is unlikely since we have method calls in between.
        // Just to be robust agains possible refactoring/inlining we will do a compiler-fenced store here.
        VolatileStoreWithoutBarrier(&g_card_table, args->card_table);

#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
        assert(args->card_bundle_table != nullptr);
        g_card_bundle_table = args->card_bundle_table;
#endif

#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
        if (g_sw_ww_enabled_for_gc_heap && (args->write_watch_table != nullptr))
        {
            assert(args->is_runtime_suspended);
            g_sw_ww_table = args->write_watch_table;
        }
#endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP

        stompWBCompleteActions |= ::StompWriteBarrierResize(is_runtime_suspended, args->requires_upper_bounds_check);
        is_runtime_suspended = (stompWBCompleteActions & SWB_EE_RESTART) || is_runtime_suspended;

        if (stompWBCompleteActions & SWB_ICACHE_FLUSH)
        {
            // flushing/invalidating the write barrier's body for the current process
            // NOTE: the underlying API may flush more than needed or nothing at all if Icache is coherent.
            ::FlushWriteBarrierInstructionCache();
        }

        // IMPORTANT: managed heap segments may surround unmanaged/stack segments. In such cases adding another managed
        //     heap segment may put a stack/unmanaged write inside the new heap range. However the old card table would
        //     not cover it. Therefore we must ensure that the write barriers see the new table before seeing the new bounds.
        //
        //     On architectures with strong ordering, we only need to prevent compiler reordering.
        //     Otherwise we put a process-wide fence here (so that we could use an ordinary read in the barrier)

#if defined(_ARM64_) || defined(_ARM_)
        if (!is_runtime_suspended)
        {
            // If runtime is not suspended, force all threads to see the changed table before seeing updated heap boundaries.
            // See: http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/346765
            FlushProcessWriteBuffers();
        }
#endif

        g_lowest_address = args->lowest_address;
        g_highest_address = args->highest_address;

#if defined(_ARM64_) || defined(_ARM_)
        // Need to reupdate for changes to g_highest_address g_lowest_address
        stompWBCompleteActions |= ::StompWriteBarrierResize(is_runtime_suspended, args->requires_upper_bounds_check);

#ifdef _ARM_
        if (stompWBCompleteActions & SWB_ICACHE_FLUSH)
        {
            // flushing/invalidating the write barrier's body for the current process
            // NOTE: the underlying API may flush more than needed or nothing at all if Icache is coherent.
            ::FlushWriteBarrierInstructionCache();
        }
#endif
#endif

        // At this point either the old or the new set of globals (card_table, bounds etc) can be used. Card tables and card bundles allow such use.
        // When card tables are de-published (at EE suspension) all the info will be merged, so the information will not be lost.
        // Another point - we should not yet have any managed objects/addresses outside of the former bounds, so either old or new bounds are fine.
        // That is - because bounds can only become wider and we are not yet done with widening.
        //
        // However!!
        // Once we are done, a new object can (and likely will) be allocated outside of the former bounds.
        // So, before such object can be used in a write barier, we must ensure that the barrier also uses the new bounds.
        //
        // This is easy to arrange for architectures with strong memory ordering. We only need to ensure that
        // - object is allocated/published _after_ we publish bounds here
        // - write barrier reads bounds after reading the new object locations
        //
        // for architectures with strong memory ordering (x86/x64) both conditions above are naturally guaranteed.
        // Systems with weak ordering are more interesting. We could either:
        // a) issue a write fence here and pair it with a read fence in the write barrier, or
        // b) issue a process-wide full fence here and do ordinary reads in the barrier.
        //
        // We will do "b" because executing write barrier is by far more common than updating card table.
        //
        // I.E. - for weak architectures we have to do a process-wide fence.
        //
        // NOTE: suspending/resuming EE works the same as process-wide fence for our purposes here.
        //       (we care only about managed threads and suspend/resume will do full fences - good enough for us).
        //

#if defined(_ARM64_) || defined(_ARM_)
        is_runtime_suspended = (stompWBCompleteActions & SWB_EE_RESTART) || is_runtime_suspended;
        if (!is_runtime_suspended)
        {
            // If runtime is not suspended, force all threads to see the changed state before observing future allocations.
            FlushProcessWriteBuffers();
        }
#endif

        if (stompWBCompleteActions & SWB_EE_RESTART)
        {
            assert(!args->is_runtime_suspended &&
                "if runtime was suspended in patching routines then it was in running state at begining");
            ThreadSuspend::RestartEE(FALSE, TRUE);
        }
        return; // unlike other branches we have already done cleanup so bailing out here
    case WriteBarrierOp::StompEphemeral:
        assert(args->is_runtime_suspended && "the runtime must be suspended here!");
        // StompEphemeral requires a new ephemeral low and a new ephemeral high
        assert(args->ephemeral_low != nullptr);
        assert(args->ephemeral_high != nullptr);
        g_ephemeral_low = args->ephemeral_low;
        g_ephemeral_high = args->ephemeral_high;
        stompWBCompleteActions |= ::StompWriteBarrierEphemeral(args->is_runtime_suspended);
        break;
    case WriteBarrierOp::Initialize:
        assert(args->is_runtime_suspended && "the runtime must be suspended here!");
        // This operation should only be invoked once, upon initialization.
        assert(g_card_table == nullptr);
        assert(g_lowest_address == nullptr);
        assert(g_highest_address == nullptr);
        assert(args->card_table != nullptr);
        assert(args->lowest_address != nullptr);
        assert(args->highest_address != nullptr);
        assert(args->ephemeral_low != nullptr);
        assert(args->ephemeral_high != nullptr);
        assert(!args->requires_upper_bounds_check && "the ephemeral generation must be at the top of the heap!");

        g_card_table = args->card_table;

#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
        assert(g_card_bundle_table == nullptr);
        g_card_bundle_table = args->card_bundle_table;
#endif

        g_lowest_address = args->lowest_address;
        g_highest_address = args->highest_address;
        stompWBCompleteActions |= ::StompWriteBarrierResize(true, false);

        // StompWriteBarrierResize does not necessarily bash g_ephemeral_low
        // usages, so we must do so here. This is particularly true on x86,
        // where StompWriteBarrierResize will not bash g_ephemeral_low when
        // called with the parameters (true, false), as it is above.
        g_ephemeral_low = args->ephemeral_low;
        g_ephemeral_high = args->ephemeral_high;
        stompWBCompleteActions |= ::StompWriteBarrierEphemeral(true);
        break;
    case WriteBarrierOp::SwitchToWriteWatch:
#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
        assert(args->is_runtime_suspended && "the runtime must be suspended here!");
        assert(args->write_watch_table != nullptr);
        g_sw_ww_table = args->write_watch_table;
        g_sw_ww_enabled_for_gc_heap = true;
        stompWBCompleteActions |= ::SwitchToWriteWatchBarrier(true);
#else
        assert(!"should never be called without FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP");
#endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
        break;
    case WriteBarrierOp::SwitchToNonWriteWatch:
#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
        assert(args->is_runtime_suspended && "the runtime must be suspended here!");
        g_sw_ww_table = 0;
        g_sw_ww_enabled_for_gc_heap = false;
        stompWBCompleteActions |= ::SwitchToNonWriteWatchBarrier(true);
#else
        assert(!"should never be called without FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP");
#endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
        break;
    default:
        assert(!"unknown WriteBarrierOp enum");
    }
    if (stompWBCompleteActions & SWB_ICACHE_FLUSH)
    {
        ::FlushWriteBarrierInstructionCache();
    }
    if (stompWBCompleteActions & SWB_EE_RESTART)
    {
        assert(!args->is_runtime_suspended &&
            "if runtime was suspended in patching routines then it was in running state at begining");
        ThreadSuspend::RestartEE(FALSE, TRUE);
    }
}

void GCToEEInterface::EnableFinalization(bool foundFinalizers)
{
    if (foundFinalizers || FinalizerThread::HaveExtraWorkForFinalizer())
    {
        FinalizerThread::EnableFinalization();
    }
}

void GCToEEInterface::HandleFatalError(unsigned int exitCode)
{
    EEPOLICY_HANDLE_FATAL_ERROR(exitCode);
}

bool GCToEEInterface::EagerFinalized(Object* obj)
{
    MethodTable* pMT = obj->GetGCSafeMethodTable();
    if (pMT == pWeakReferenceMT ||
        pMT->GetCanonicalMethodTable() == pWeakReferenceOfTCanonMT)
    {
        FinalizeWeakReference(obj);
        return true;
    }

    return false;
}

MethodTable* GCToEEInterface::GetFreeObjectMethodTable()
{
    assert(g_pFreeObjectMethodTable != nullptr);
    return g_pFreeObjectMethodTable;
}

// This is arbitrary, we shouldn't ever be having config keys
// longer than these lengths.
const size_t MaxConfigKeyLength = 255;

bool GCToEEInterface::GetBooleanConfigValue(const char* key, bool* value)
{
    CONTRACTL {
        NOTHROW;
        GC_NOTRIGGER;
    } CONTRACTL_END;

    // these configuration values are given to us via startup flags.
    if (strcmp(key, "gcServer") == 0)
    {
        *value = g_heap_type == GC_HEAP_SVR;
        return true;
    }

    if (strcmp(key, "gcConcurrent") == 0)
    {
        *value = !!g_pConfig->GetGCconcurrent();
        return true;
    }

    if (strcmp(key, "GCRetainVM") == 0)
    {
        *value = !!g_pConfig->GetGCRetainVM();
        return true;
    }

    WCHAR configKey[MaxConfigKeyLength];
    if (MultiByteToWideChar(CP_ACP, 0, key, -1 /* key is null-terminated */, configKey, MaxConfigKeyLength) == 0)
    {
        // whatever this is... it's not something we care about. (It was too long, wasn't unicode, etc.)
        return false;
    }

    // otherwise, ask the config subsystem.
    if (CLRConfig::IsConfigOptionSpecified(configKey))
    {
        CLRConfig::ConfigDWORDInfo info { configKey , 0, CLRConfig::EEConfig_default };
        *value = CLRConfig::GetConfigValue(info) != 0;
        return true;
    }

    return false;
}

bool GCToEEInterface::GetIntConfigValue(const char* key, int64_t* value)
{
    CONTRACTL {
      NOTHROW;
      GC_NOTRIGGER;
    } CONTRACTL_END;

    if (strcmp(key, "GCSegmentSize") == 0)
    {
        *value = g_pConfig->GetSegmentSize();
        return true;
    }

    if (strcmp(key, "GCgen0size") == 0)
    {
        *value = g_pConfig->GetGCgen0size();
        return true;
    }

    if (strcmp(key, "GCHeapHardLimit") == 0)
    {
        *value = g_pConfig->GetGCHeapHardLimit();
        return true;
    }

    if (strcmp(key, "GCHeapHardLimitPercent") == 0)
    {
        *value = g_pConfig->GetGCHeapHardLimitPercent();
        return true;
    }

    if (strcmp(key, "GCLOHThreshold") == 0)
    {
        *value = g_pConfig->GetGCLOHThreshold();
        return true;
    }

    WCHAR configKey[MaxConfigKeyLength];
    if (MultiByteToWideChar(CP_ACP, 0, key, -1 /* key is null-terminated */, configKey, MaxConfigKeyLength) == 0)
    {
        // whatever this is... it's not something we care about. (It was too long, wasn't unicode, etc.)
        return false;
    }

    // There is no ConfigULONGLONGInfo, and the GC uses 64 bit values for things like GCHeapAffinitizeMask,
    // so have to fake it with getting the string and converting to uint64_t
    if (CLRConfig::IsConfigOptionSpecified(configKey))
    {
        CLRConfig::ConfigStringInfo info { configKey, CLRConfig::EEConfig_default };
        LPWSTR out = CLRConfig::GetConfigValue(info);
        if (!out)
        {
            // config not found
            CLRConfig::FreeConfigString(out);
            return false;
        }

        WCHAR *end;
        uint64_t result;
        errno = 0;
        result = _wcstoui64(out, &end, 16);
        // errno is ERANGE if the number is out of range, and end is set to pvalue if
        // no valid conversion exists.
        if (errno == ERANGE || end == out)
        {
            CLRConfig::FreeConfigString(out);
            return false;
        }

        *value = static_cast<int64_t>(result);
        CLRConfig::FreeConfigString(out);
        return true;
    }

    return false;
}

bool GCToEEInterface::GetStringConfigValue(const char* key, const char** value)
{
    CONTRACTL {
      NOTHROW;
      GC_NOTRIGGER;
    } CONTRACTL_END;

    WCHAR configKey[MaxConfigKeyLength];
    if (MultiByteToWideChar(CP_ACP, 0, key, -1 /* key is null-terminated */, configKey, MaxConfigKeyLength) == 0)
    {
        // whatever this is... it's not something we care about. (It was too long, wasn't unicode, etc.)
        return false;
    }

    CLRConfig::ConfigStringInfo info { configKey, CLRConfig::EEConfig_default };
    LPWSTR out = CLRConfig::GetConfigValue(info);
    if (!out)
    {
        // config not found
        return false;
    }

    int charCount = WideCharToMultiByte(CP_ACP, 0, out, -1 /* out is null-terminated */, NULL, 0, nullptr, nullptr);
    if (charCount == 0)
    {
        // this should only happen if the config subsystem gives us a string that's not valid
        // unicode.
        CLRConfig::FreeConfigString(out);
        return false;
    }

    // not allocated on the stack since it escapes this function
    AStringHolder configResult = new (nothrow) char[charCount];
    if (!configResult)
    {
        CLRConfig::FreeConfigString(out);
        return false;
    }

    if (WideCharToMultiByte(CP_ACP, 0, out, -1 /* out is null-terminated */,
          configResult.GetValue(), charCount, nullptr, nullptr) == 0)
    {
        // this should never happen, the previous call to WideCharToMultiByte that computed the charCount should
        // have caught all issues.
        assert(false);
        CLRConfig::FreeConfigString(out);
        return false;
    }

    *value = configResult.Extract();
    CLRConfig::FreeConfigString(out);
    return true;
}

void GCToEEInterface::FreeStringConfigValue(const char* value)
{
    delete [] value;
}

bool GCToEEInterface::IsGCThread()
{
    return !!::IsGCThread();
}

bool GCToEEInterface::WasCurrentThreadCreatedByGC()
{
    return !!::IsGCSpecialThread();
}

struct SuspendableThreadStubArguments
{
    void* Argument;
    void (*ThreadStart)(void*);
    Thread* Thread;
    bool HasStarted;
    CLREvent ThreadStartedEvent;
};

struct ThreadStubArguments
{
    void* Argument;
    void (*ThreadStart)(void*);
    HANDLE Thread;
    bool HasStarted;
    CLREvent ThreadStartedEvent;
};

namespace
{
    const size_t MaxThreadNameSize = 255;

    bool CreateSuspendableThread(
        void (*threadStart)(void*),
        void* argument,
        const WCHAR* name)
    {
        LIMITED_METHOD_CONTRACT;

        SuspendableThreadStubArguments args;
        args.Argument = argument;
        args.ThreadStart = threadStart;
        args.Thread = nullptr;
        args.HasStarted = false;
        if (!args.ThreadStartedEvent.CreateAutoEventNoThrow(FALSE))
        {
            return false;
        }

        EX_TRY
        {
            args.Thread = SetupUnstartedThread(FALSE);
        }
        EX_CATCH
        {
        }
        EX_END_CATCH(SwallowAllExceptions)

        if (!args.Thread)
        {
            args.ThreadStartedEvent.CloseEvent();
            return false;
        }

        auto threadStub = [](void* argument) -> DWORD
        {
            SuspendableThreadStubArguments* args = static_cast<SuspendableThreadStubArguments*>(argument);
            assert(args != nullptr);

            ClrFlsSetThreadType(ThreadType_GC);
            args->Thread->SetGCSpecial(true);
            STRESS_LOG_RESERVE_MEM(GC_STRESSLOG_MULTIPLY);
            args->HasStarted = !!args->Thread->HasStarted(false);

            Thread* thread = args->Thread;
            auto threadStart = args->ThreadStart;
            void* threadArgument = args->Argument;
            bool hasStarted = args->HasStarted;
            args->ThreadStartedEvent.Set();

            // The stubArgs cannot be used once the event is set, since that releases wait on the
            // event in the function that created this thread and the stubArgs go out of scope.
            if (hasStarted)
            {
                threadStart(threadArgument);
                DestroyThread(thread);
            }

            return 0;
        };
        if (!args.Thread->CreateNewThread(0, threadStub, &args, name))
        {
            args.Thread->DecExternalCount(FALSE);
            args.ThreadStartedEvent.CloseEvent();
            return false;
        }

        args.Thread->SetBackground(TRUE, FALSE);
        args.Thread->StartThread();

        // Wait for the thread to be in its main loop
        uint32_t res = args.ThreadStartedEvent.Wait(INFINITE, FALSE);
        args.ThreadStartedEvent.CloseEvent();
        _ASSERTE(res == WAIT_OBJECT_0);

        if (!args.HasStarted)
        {
            // The thread has failed to start and the Thread object was destroyed in the Thread::HasStarted
            // failure code path.
            return false;
        }

        return true;
    }

    bool CreateNonSuspendableThread(
        void (*threadStart)(void*),
        void* argument,
        const WCHAR* name)
    {
        LIMITED_METHOD_CONTRACT;

        ThreadStubArguments args;
        args.Argument = argument;
        args.ThreadStart = threadStart;
        args.Thread = INVALID_HANDLE_VALUE;
        if (!args.ThreadStartedEvent.CreateAutoEventNoThrow(FALSE))
        {
            return false;
        }

        auto threadStub = [](void* argument) -> DWORD
        {
            ThreadStubArguments* args = static_cast<ThreadStubArguments*>(argument);
            assert(args != nullptr);

            ClrFlsSetThreadType(ThreadType_GC);
            STRESS_LOG_RESERVE_MEM(GC_STRESSLOG_MULTIPLY);

            args->HasStarted = true;
            auto threadStart = args->ThreadStart;
            void* threadArgument = args->Argument;
            args->ThreadStartedEvent.Set();

            // The stub args cannot be used once the event is set, since that releases wait on the
            // event in the function that created this thread and the stubArgs go out of scope.
            threadStart(threadArgument);
            return 0;
        };

        args.Thread = Thread::CreateUtilityThread(Thread::StackSize_Medium, threadStub, &args, name);
        if (args.Thread == INVALID_HANDLE_VALUE)
        {
            args.ThreadStartedEvent.CloseEvent();
            return false;
        }

        // Wait for the thread to be in its main loop
        uint32_t res = args.ThreadStartedEvent.Wait(INFINITE, FALSE);
        args.ThreadStartedEvent.CloseEvent();
        _ASSERTE(res == WAIT_OBJECT_0);

        CloseHandle(args.Thread);
        return true;
    }
} // anonymous namespace

bool GCToEEInterface::CreateThread(void (*threadStart)(void*), void* arg, bool is_suspendable, const char* name)
{
    InlineSString<MaxThreadNameSize> wideName;
    const WCHAR* namePtr = nullptr;
    EX_TRY
    {
        if (name != nullptr)
        {
            wideName.SetUTF8(name);
            namePtr = wideName.GetUnicode();
        }
    }
        EX_CATCH
    {
        // we're not obligated to provide a name - if it's not valid,
        // just report nullptr as the name.
    }
    EX_END_CATCH(SwallowAllExceptions)

    LIMITED_METHOD_CONTRACT;
    if (is_suspendable)
    {
        return CreateSuspendableThread(threadStart, arg, namePtr);
    }
    else
    {
        return CreateNonSuspendableThread(threadStart, arg, namePtr);
    }
}

void GCToEEInterface::WalkAsyncPinnedForPromotion(Object* object, ScanContext* sc, promote_func* callback)
{
    LIMITED_METHOD_CONTRACT;

    assert(object != nullptr);
    assert(sc != nullptr);
    assert(callback != nullptr);
    if (object->GetGCSafeMethodTable() != g_pOverlappedDataClass)
    {
        // not an overlapped data object - nothing to do.
        return;
    }

    // reporting the pinned user objects
    OverlappedDataObject *pOverlapped = (OverlappedDataObject *)object;
    if (pOverlapped->m_userObject != NULL)
    {
        if (pOverlapped->m_userObject->GetGCSafeMethodTable() == g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT]->GetMethodTable())
        {
            // OverlappedDataObject is very special.  An async pin handle keeps it alive.
            // During GC, we also make sure
            // 1. m_userObject itself does not move if m_userObject is not array
            // 2. Every object pointed by m_userObject does not move if m_userObject is array
            // We do not want to pin m_userObject if it is array.
            ArrayBase* pUserObject = (ArrayBase*)OBJECTREFToObject(pOverlapped->m_userObject);
            Object **ppObj = (Object**)pUserObject->GetDataPtr(TRUE);
            size_t num = pUserObject->GetNumComponents();
            for (size_t i = 0; i < num; i++)
            {
                callback(ppObj + i, sc, GC_CALL_PINNED);
            }
        }
        else
        {
            callback(&OBJECTREF_TO_UNCHECKED_OBJECTREF(pOverlapped->m_userObject), (ScanContext *)sc, GC_CALL_PINNED);
        }
    }
}

void GCToEEInterface::WalkAsyncPinned(Object* object, void* context, void (*callback)(Object*, Object*, void*))
{
    LIMITED_METHOD_CONTRACT;

    assert(object != nullptr);
    assert(callback != nullptr);

    if (object->GetGCSafeMethodTable() != g_pOverlappedDataClass)
    {
        return;
    }

    OverlappedDataObject *pOverlapped = (OverlappedDataObject *)(object);
    if (pOverlapped->m_userObject != NULL)
    {
        Object * pUserObject = OBJECTREFToObject(pOverlapped->m_userObject);
        callback(object, pUserObject, context);
        if (pOverlapped->m_userObject->GetGCSafeMethodTable() == g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT]->GetMethodTable())
        {
            ArrayBase* pUserArrayObject = (ArrayBase*)pUserObject;
            Object **pObj = (Object**)pUserArrayObject->GetDataPtr(TRUE);
            size_t num = pUserArrayObject->GetNumComponents();
            for (size_t i = 0; i < num; i ++)
            {
                callback(pUserObject, pObj[i], context);
            }
        }
    }
}

IGCToCLREventSink* GCToEEInterface::EventSink()
{
    LIMITED_METHOD_CONTRACT;

    return &g_gcToClrEventSink;
}

uint32_t GCToEEInterface::GetTotalNumSizedRefHandles()
{
    LIMITED_METHOD_CONTRACT;

    return SystemDomain::System()->GetTotalNumSizedRefHandles();
}

bool GCToEEInterface::AnalyzeSurvivorsRequested(int condemnedGeneration)
{
    LIMITED_METHOD_CONTRACT;

    // Is the list active?
    GcNotifications gn(g_pGcNotificationTable);
    if (gn.IsActive())
    {
        GcEvtArgs gea = { GC_MARK_END, { (1<<condemnedGeneration) } };
        if (gn.GetNotification(gea) != 0)
        {
            return true;
        }
    }

    return false;
}

void GCToEEInterface::AnalyzeSurvivorsFinished(int condemnedGeneration)
{
    LIMITED_METHOD_CONTRACT;

    // Is the list active?
    GcNotifications gn(g_pGcNotificationTable);
    if (gn.IsActive())
    {
        GcEvtArgs gea = { GC_MARK_END, { (1<<condemnedGeneration) } };
        if (gn.GetNotification(gea) != 0)
        {
            DACNotify::DoGCNotification(gea);
        }
    }
}

void GCToEEInterface::VerifySyncTableEntry()
{
    LIMITED_METHOD_CONTRACT;

#ifdef VERIFY_HEAP
    SyncBlockCache::GetSyncBlockCache()->VerifySyncTableEntry();
#endif // VERIFY_HEAP
}

void GCToEEInterface::UpdateGCEventStatus(int currentPublicLevel, int currentPublicKeywords, int currentPrivateLevel, int currentPrivateKeywords)
{
#if defined(__linux__) && defined(FEATURE_EVENT_TRACE)
    LIMITED_METHOD_CONTRACT;
    // LTTng does not have a notion of enabling events via "keyword"/"level" but we have to
    // somehow implement a similar behavior to it.

    // To do this, we manaully check for events that are enabled via different provider/keywords/level.
    // Ex 1. GCJoin_V2 is what we use to check whether the GC keyword is enabled in verbose level in the public provider
    // Ex 2. SetGCHandle is what we use to check whether the GCHandle keyword is enabled in informational level in the public provider
    // Refer to the comments in src/vm/gcenv.ee.h next to the EXTERN C definitions to see which events are enabled.

    // WARNING: To change an event's GC level, perfcollect script needs to be updated simultaneously to reflect it.
    BOOL keyword_gc_verbose = EventXplatEnabledGCJoin_V2() || EventPipeEventEnabledGCJoin_V2();
    BOOL keyword_gc_informational = EventXplatEnabledGCStart() || EventPipeEventEnabledGCStart();

    BOOL keyword_gc_heapsurvival_and_movement_informational = EventXplatEnabledGCGenerationRange() || EventPipeEventEnabledGCGenerationRange();
    BOOL keyword_gchandle_informational = EventXplatEnabledSetGCHandle() || EventPipeEventEnabledSetGCHandle();
    BOOL keyword_gchandle_prv_informational = EventXplatEnabledPrvSetGCHandle() || EventPipeEventEnabledPrvSetGCHandle();

    BOOL prv_gcprv_informational = EventXplatEnabledBGCBegin() || EventPipeEventEnabledBGCBegin();
    BOOL prv_gcprv_verbose = EventXplatEnabledPinPlugAtGCTime() || EventPipeEventEnabledPinPlugAtGCTime();

    int publicProviderLevel = keyword_gc_verbose ? GCEventLevel_Verbose : (keyword_gc_informational ? GCEventLevel_Information : GCEventLevel_None);
    int publicProviderKeywords = (keyword_gc_informational ? GCEventKeyword_GC : GCEventKeyword_None) |
                                 (keyword_gchandle_informational ? GCEventKeyword_GCHandle : GCEventKeyword_None) |
                                 (keyword_gc_heapsurvival_and_movement_informational ? GCEventKeyword_GCHeapSurvivalAndMovement : GCEventKeyword_None);

    int privateProviderLevel = prv_gcprv_verbose ? GCEventLevel_Verbose : (prv_gcprv_informational ? GCEventLevel_Information : GCEventLevel_None);
    int privateProviderKeywords = (prv_gcprv_informational ? GCEventKeyword_GCPrivate : GCEventKeyword_None) |
        (keyword_gchandle_prv_informational ? GCEventKeyword_GCHandlePrivate : GCEventKeyword_None);

    if (publicProviderLevel != currentPublicLevel || publicProviderKeywords != currentPublicKeywords)
    {
        GCEventLevel publicLevel = static_cast<GCEventLevel>(publicProviderLevel);
        GCEventKeyword publicKeywords = static_cast<GCEventKeyword>(publicProviderKeywords);
        GCHeapUtilities::RecordEventStateChange(true, publicKeywords, publicLevel);
    }
    if (privateProviderLevel != currentPrivateLevel || privateProviderKeywords != currentPrivateKeywords)
    {
        GCEventLevel privateLevel = static_cast<GCEventLevel>(privateProviderLevel);
        GCEventKeyword privateKeywords = static_cast<GCEventKeyword>(privateProviderKeywords);
        GCHeapUtilities::RecordEventStateChange(false, privateKeywords, privateLevel);
    }
#endif // __linux__ && FEATURE_EVENT_TRACE
}


text:
<?php

/**
 * YsJQRing todo description.
 *
 * @method YsJQRing _bearing
 * @method YsJQRing _tilt
 * @method YsJQRing _minZ
 * @method YsJQRing _maxZ
 * @method YsJQRing _minOpacity
 * @method YsJQRing _maxOpacity
 * @method YsJQRing _minScale
 * @method YsJQRing _maxScale
 * @method YsJQRing _duration
 * @method YsJQRing _btnNext
 * @method YsJQRing _btnPrev
 * @method YsJQRing _easing
 * @method YsJQRing _clickToFocus
 * @method YsJQRing _focusBearing
 * @method YsJQRing _shape
 * @method YsJQRing _debug
 * @method YsJQRing _childSelector
 * @method YsJQRing _startingChild
 * @method YsJQRing _reflect
 *
 * @package    YepSua
 * @subpackage jQuery4PHP
 * @author     Omar Yepez <omar.yepez@yepsua.com>
 * @version    SVN: $Id$
 */
class YsJQRing extends YsJQueryPlugin {

  const VERSION = "v1.1";
  const LICENSE = "BSD license";

  public static $SHAPE_LAZY_SUSAN = 'lazySusan';
  public static $SHAPE_WATER_WHEEL = 'waterWheel';
  public static $SHAPE_FIGURE8 = 'figure8';
  public static $SHAPE_SQUARE = 'square';
  public static $SHAPE_CONVEYOR_BELT_LEFT = 'conveyorBeltLeft';
  public static $SHAPE_CONVEYOR_BELT_RIGHT = 'conveyorBeltRight';
  public static $SHAPE_DIAGONAL_RING_LEFT = 'diagonalRingLeft';
  public static $SHAPE_DIAGONAL_RING_RIGHT = 'diagonalRingRight';
  public static $SHAPE_ROLLER_COASTER = 'rollerCoaster';
  public static $SHAPE_TEAR_DROP = 'tearDrop';
  public static $SHAPE_THE_JUGGLER = 'theJuggler';
  public static $SHAPE_GOODBYE_CRUEL_WORLD = 'goodbyeCruelWorld';

  public static $event = 'roundabout';

  public function registerOptions(){
    return   array(
              //options
               '_bearing' =>  array('key' => 'bearing', 'is_quoted' => false),
               '_tilt' =>  array('key' => 'tilt', 'is_quoted' => false),
               '_minZ' =>  array('key' => 'minZ', 'is_quoted' => false),
               '_maxZ' =>  array('key' => 'maxZ', 'is_quoted' => false),
               '_minOpacity' =>  array('key' => 'minOpacity', 'is_quoted' => false),
               '_maxOpacity' =>  array('key' => 'maxOpacity', 'is_quoted' => false),
               '_minScale' =>  array('key' => 'minScale', 'is_quoted' => false),
               '_maxScale' =>  array('key' => 'maxScale', 'is_quoted' => false),
               '_duration' =>  array('key' => 'duration', 'is_quoted' => false),
               '_btnNext' =>  array('key' => 'btnNext', 'is_quoted' => false),
               '_btnPrev' =>  array('key' => 'btnPrev', 'is_quoted' => false),
               '_easing' =>  array('key' => 'easing', 'is_quoted' => false),
               '_clickToFocus' =>  array('key' => 'clickToFocus', 'is_quoted' => false),
               '_focusBearing' =>  array('key' => 'focusBearing', 'is_quoted' => false),
               '_shape' =>  array('key' => 'shape', 'is_quoted' => false),
               '_debug' =>  array('key' => 'debug', 'is_quoted' => false),
               '_childSelector' =>  array('key' => 'childSelector', 'is_quoted' => false),
               '_startingChild' =>  array('key' => 'startingChild', 'is_quoted' => false),
               '_reflect' =>  array('key' => 'reflect', 'is_quoted' => false),
              );
  }

  /**
   * Retrieves a instance of this class.
   * @return YsJQRing
   */
  public static function getInstance()
  {
    $object = __CLASS__;
    self::$instance = new $object();
    return self::$instance;
  }

  public static function build(){
    $jquery = self::getInstance();
    $jquery->setEvent(self::$event);
    return $jquery;
  }

  private static function initWithShape($jQuerySelector,$shapeName){
    return self::build()->in($jQuerySelector)->_shape($shapeName);
  }

  public static function shapeWaterWheel($jQuerySelector){
    return self::initWithShape($jQuerySelector,self::$SHAPE_WATER_WHEEL);
  }

  public static function shapeFigure8($jQuerySelector){
    return self::initWithShape($jQuerySelector,self::$SHAPE_FIGURE8);
  }

  public static function shapeSquare($jQuerySelector){
    return self::initWithShape($jQuerySelector,self::$SHAPE_SQUARE);
  }

  public static function shapeConveyorBeltLeft($jQuerySelector){
    return self::initWithShape($jQuerySelector,self::$SHAPE_CONVEYOR_BELT_LEFT);
  }

  public static function shapeConveyorBeltRight($jQuerySelector){
    return self::initWithShape($jQuerySelector,self::$SHAPE_CONVEYOR_BELT_RIGHT);
  }

  public static function shapeDiagonalRingLeft($jQuerySelector){
    return self::initWithShape($jQuerySelector,self::$SHAPE_DIAGONAL_RING_LEFT);
  }

  public static function shapeDiagonalRingRight($jQuerySelector){
    return self::initWithShape($jQuerySelector,self::$SHAPE_DIAGONAL_RING_RIGHT);
  }

  public static function shapeRollerCoaster($jQuerySelector){
    return self::initWithShape($jQuerySelector,self::$SHAPE_ROLLER_COASTER);
  }

  public static function shapeTearDrop($jQuerySelector){
    return self::initWithShape($jQuerySelector,self::$SHAPE_TEAR_DROP);
  }

  public static function shapeTheJuggler($jQuerySelector){
    return self::initWithShape($jQuerySelector,self::$SHAPE_THE_JUGGLER);
  }

  public static function shapeGoodbyeCruelWorld($jQuerySelector){
    return self::initWithShape($jQuerySelector,self::$SHAPE_GOODBYE_CRUEL_WORLD);
  }

  // BASIC TEMPLATES
  /**
   * Starts the standar HTML tags for build this widget
   * @param string $id The widget id
   * @param string $htmlProperties custom HTML properties like 'style="display:none"'
   * @return YsHTML HTML tags
   */
  public static function initWidget($id, $htmlProperties = null, $tag = YsHTML::UL){
    return parent::initWidget($id , $htmlProperties,$tag);
  }

  /**
   * Ends the standar HTML tags for build this widget
   * @return YsHTML HTML tags
   */
  public static function endWidget($tag = YsHTML::UL){
    return parent::endWidget();
  }
}

redpajama_set_name: RedPajamaGithub


text:
package us.gov.dod.standard.ssrf._3_1.contact;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
import us.gov.dod.standard.ssrf._3_1.Contact;
import us.gov.dod.standard.ssrf._3_1.Organisation;
import us.gov.dod.standard.ssrf._3_1.Role;
import us.gov.dod.standard.ssrf._3_1.metadata.domains.S20;
import us.gov.dod.standard.ssrf._3_1.metadata.domains.S50;
import us.gov.dod.standard.ssrf._3_1.metadata.domains.TString;
import us.gov.dod.standard.ssrf._3_1.metadata.lists.ListCBO;
import us.gov.dod.standard.ssrf._3_1.metadata.lists.ListCCL;

/**
 * TelephoneFax reflects the telephone and/or telefax number(s) of the Contact,
 * Organisation or Role.
 *

 * Element of {@link Contact}, {@link Organisation}, {@link Role}
 *

 * Example:
 *

 * <TelephoneFax>
 *   <Type cls="U">TEL-Civil</Type>
 *   <Number cls="U">(202)281-3824x1234</Number>
 * </TelephoneFax>
 *

 *

 * @author Key Bridge LLC <developer@keybridge.ch>
 * @version 3.1.0, 03/30/2015
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "TelephoneFax", propOrder = {
  "preferred",
  "type",
  "fax",
  "maxCls",
  "number"
})
public class TelephoneFax {

  /**
   * Preferred - Preferred Number (Optional)
   *

   * A code "Yes" for the preferred number(s) and a code "No" for the others.
   *

   * Format is L:CBO
   *

   * @since 3.1.0
   */
  @XmlElement(name = "Preferred", required = false)
  private TString preferred;
  /**
   * Type - System or Network (Optional)
   *

   * The name of the network on which this number can be dialed (e.g., DSN,
   * IVSN, CORMORANT). Use "PUBLIC" for normal public telephone or GSM.
   *

   * Format is S20
   *

   * @since 3.1.0
   */
  @XmlElement(name = "Type", required = false)
  private S20 type;
  /**
   * Fax - Telefax Indicator (Optional)
   *

   * "Yes" if the number is for a telefax. If this item is empty, it SHOULD be
   * considered as "No".
   *

   * Format is L:CBO
   *

   * @since 3.1.0
   */
  @XmlElement(name = "Fax", required = false)
  private TString fax;
  /**
   * MaxCls - System Maximum Classification (Optional)
   *

   * The highest classification that can be used on the network. Note for the
   * USA: The letter "R" MUST NOT be used in USA created datasets.
   *

   * Format is L:CCL
   *

   * @since 3.1.0
   */
  @XmlElement(name = "MaxCls", required = false)
  private TString maxCls;
  /**
   * Number - Tel or Fax Number (Required)
   *

   * The area code, telephone/telefax number (including the extension if
   * necessary) of individual or contact organisation.
   *

   * Format is S50
   *

   * @since 3.1.0
   */
  @XmlElement(name = "Number", required = true)
  private S50 number;

  /**
   * Get a code "Yes" for the preferred number(s) and a code "No" for the
   * others..
   *

   * @return the Preferred value in a {@link TString} data type
   * @since 3.1.0
   */
  public TString getPreferred() {
    return preferred;
  }

  /**
   * Set a code "Yes" for the preferred number(s) and a code "No" for the
   * others..
   *

   * @param value the Preferred value in a {@link TString} data type
   * @since 3.1.0
   */
  public void setPreferred(TString value) {
    this.preferred = value;
  }

  /**
   * Determine if the Preferred is configured.
   *

   * If configured this method also inspects the {@link TString} wrapped value.
   *

   * @return TRUE if the field is set, FALSE if the field is null
   */
  public boolean isSetPreferred() {
    return (this.preferred != null ? this.preferred.isSetValue() : false);
  }

  /**
   * Get the name of the network on which this number can be dialed (e.g., DSN,
   * IVSN, CORMORANT). Use "PUBLIC" for normal public telephone or GSM..
   *

   * @return a {@link S20} instance
   * @since 3.1.0
   */
  public S20 getType() {
    return type;
  }

  /**
   * Set the name of the network on which this number can be dialed (e.g., DSN,
   * IVSN, CORMORANT). Use "PUBLIC" for normal public telephone or GSM..
   *

   * @param value a {@link S20} instance
   * @since 3.1.0
   */
  public void setType(S20 value) {
    this.type = value;
  }

  /**
   * Determine if the Type is configured.
   *

   * @return TRUE if the field is set, FALSE if the field is null
   */
  public boolean isSetType() {
    return (this.type != null ? this.type.isSetValue() : false);
  }

  /**
   * Get "Yes" if the number is for a telefax. If this item is empty, it SHOULD
   * be considered as "No"..
   *

   * @return the Fax value in a {@link TString} data type
   * @since 3.1.0
   */
  public TString getFax() {
    return fax;
  }

  /**
   * Set "Yes" if the number is for a telefax. If this item is empty, it SHOULD
   * be considered as "No"..
   *

   * @param value the Fax value in a {@link TString} data type
   * @since 3.1.0
   */
  public void setFax(TString value) {
    this.fax = value;
  }

  /**
   * Determine if the Fax is configured.
   *

   * If configured this method also inspects the {@link TString} wrapped value.
   *

   * @return TRUE if the field is set, FALSE if the field is null
   */
  public boolean isSetFax() {
    return (this.fax != null ? this.fax.isSetValue() : false);
  }

  /**
   * Get the highest classification that can be used on the network. Note for
   * the USA: The letter "R" MUST NOT be used in USA created datasets..
   *

   * @return the MaxCls value in a {@link TString} data type
   * @since 3.1.0
   */
  public TString getMaxCls() {
    return maxCls;
  }

  /**
   * Set the highest classification that can be used on the network. Note for
   * the USA: The letter "R" MUST NOT be used in USA created datasets..
   *

   * @param value the MaxCls value in a {@link TString} data type
   * @since 3.1.0
   */
  public void setMaxCls(TString value) {
    this.maxCls = value;
  }

  /**
   * Determine if the MaxCls is configured.
   *

   * If configured this method also inspects the {@link TString} wrapped value.
   *

   * @return TRUE if the field is set, FALSE if the field is null
   */
  public boolean isSetMaxCls() {
    return (this.maxCls != null ? this.maxCls.isSetValue() : false);
  }

  /**
   * Get the area code, telephone/telefax number (including the extension if
   * necessary) of individual or contact organisation..
   *

   * @return a {@link S50} instance
   * @since 3.1.0
   */
  public S50 getNumber() {
    return number;
  }

  /**
   * Set the area code, telephone/telefax number (including the extension if
   * necessary) of individual or contact organisation..
   *

   * @param value a {@link S50} instance
   * @since 3.1.0
   */
  public void setNumber(S50 value) {
    this.number = value;
  }

  /**
   * Determine if the Number is configured.
   *

   * @return TRUE if the field is set, FALSE if the field is null
   */
  public boolean isSetNumber() {
    return (this.number != null ? this.number.isSetValue() : false);
  }

  /**
   * Set a code "Yes" for the preferred number(s) and a code "No" for the
   * others.
   *

   * @param value An instances of type {@link ListCBO}.
   * @return The current TelephoneFax object instance.
   * @since 3.1.0
   */
  public TelephoneFax withPreferred(ListCBO value) {
    setPreferred(new TString(value.value()));
    return this;
  }

  /**
   * Set the name of the network on which this number can be dialed (e.g., DSN,
   * IVSN, CORMORANT). Use "PUBLIC" for normal public telephone or GSM.
   *

   * @param value An instances of type {@link String}.
   * @return The current TelephoneFax object instance.
   * @since 3.1.0
   */
  public TelephoneFax withType(String value) {
    setType(new S20(value));
    return this;
  }

  /**
   * Set "Yes" if the number is for a telefax. If this item is empty, it SHOULD
   * be considered as "No".
   *

   * @param value An instances of type {@link ListCBO}.
   * @return The current TelephoneFax object instance.
   * @since 3.1.0
   */
  public TelephoneFax withFax(ListCBO value) {
    setFax(new TString(value.value()));
    return this;
  }

  /**
   * Set the highest classification that can be used on the network. Note for
   * the USA: The letter "R" MUST NOT be used in USA created datasets.
   *

   * @param value An instances of type {@link ListCCL}.
   * @return The current TelephoneFax object instance.
   * @since 3.1.0
   */
  public TelephoneFax withMaxCls(ListCCL value) {
    setMaxCls(new TString(value.value()));
    return this;
  }

  /**
   * Set the area code, telephone/telefax number (including the extension if
   * necessary) of individual or contact organisation.
   *

   * @param value An instances of type {@link String}.
   * @return The current TelephoneFax object instance.
   * @since 3.1.0
   */
  public TelephoneFax withNumber(String value) {
    setNumber(new S50(value));
    return this;
  }

  /**
   * Get a string representation of this TelephoneFax instance configuration.
   *

   * @return The current object instance configuration as a non-null String
   */
  @Override
  public String toString() {
    return "\n  TelephoneFax {"
           + (fax != null ? " fax [" + fax + "]" : "")
           + (maxCls != null ? " maxCls [" + maxCls + "]" : "")
           + (number != null ? " number [" + number + "]" : "")
           + (preferred != null ? " preferred [" + preferred + "]" : "")
           + (type != null ? " type [" + type + "]" : "")
           + "}";
  }

  /**
   * Determine if the required fields in this SSRF data type instance are set.
   *

   * {@link TelephoneFax} requires {@link S50 Number}.
   *

   * Note that this method only checks for the presence of required information;
   * this method does not validate the information format.
   *

   * @return TRUE if required fields are set, otherwise FALSE
   */
  public boolean isSet() {
    return isSetNumber();
  }

}


text:
using AutoMapper.Mappers;
using AutoMapper.Configuration.Conventions;
using Should;
using Xunit;

namespace AutoMapper.UnitTests
{
    public class MapToAttributeTest : AutoMapperSpecBase
    {
        public class CategoryDto
        {
            public string Id { get; set; }

            public string MyValueProperty { get; set; }
        }

        public class Category
        {
            public string Id { get; set; }

            [MapTo("MyValueProperty")]
            public string Key { get; set; }
        }

        protected override MapperConfiguration Configuration { get; } = new MapperConfiguration(cfg =>
        {
            cfg.CreateProfile("New Profile", profile =>
            {
                profile.AddConditionalObjectMapper().Where((s, d) => s.Name.Contains(d.Name) || d.Name.Contains(s.Name));
            });
        });

        [Fact]
        public void Sould_Map_MapToAttribute_To_Property_With_Matching_Name()
        {
            var category = new Category
            {
                Id = "3",
                Key = "MyKey"
            };
            CategoryDto result = Mapper.Map<CategoryDto>(category);
            result.Id.ShouldEqual("3");
            result.MyValueProperty.ShouldEqual("MyKey");
        }
    }
}


text:
package service

import (
	"context"
	"go-common/app/service/video/stream-mng/common"
	"go-common/app/service/video/stream-mng/model"
	"go-common/library/log"
	"go-common/library/net/metadata"
)

// ChangeSrc 切换cdn
func (s *Service) ChangeSrc(c context.Context, rid int64, toOrigin int64, source string, operateName string, reason string) error {
	_, origin, err := s.dao.OriginUpStreamInfo(c, rid)

	if err != nil {
		return err
	}

	// 更新正式流数据库
	toSrc := common.BitwiseMapSrc[toOrigin]
	err = s.dao.UpdateOfficialStreamStatus(c, rid, toSrc)
	if err != nil {
		return err
	}

	s.dao.UpdateStreamStatusCache(c, &model.StreamStatus{
		RoomID:          rid,
		DefaultChange:   true,
		DefaultUpStream: toOrigin,
	})

	go func(ctx context.Context, rid int64, origin int64, toOrigin int64, reason, operateName, source string) {
		// 更新main-stream
		if err := s.dao.ChangeDefaultVendor(ctx, rid, toOrigin); err != nil {
			log.Infov(ctx, log.KV("change_main_stream_default_err", err.Error()))
		}

		// 更新redis被切记录
		s.dao.UpdateChangeSrcCache(ctx, rid, origin)

		// 记录日志
		s.RecordChangeLog(ctx, &model.StreamChangeLog{
			RoomID:      rid,
			FromOrigin:  origin,
			ToOrigin:    toOrigin,
			Reason:      reason,
			OperateName: operateName,
			Source:      source,
		})
	}(metadata.WithContext(c), rid, origin, toOrigin, reason, operateName, source)

	return nil
}


text:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wjsams</groupId>
    <artifactId>javasandbox</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>javasandbox</name>
    <url>http://maven.apache.org</url>

    <properties>
        <java.version>1.7</java.version>
        <spring.version>3.2.3.RELEASE</spring.version>
        <cglib.version>2.2.2</cglib.version>
        <spring.security.version>3.1.4.RELEASE</spring.security.version>
        <spring.ldap.version>1.3.2.RELEASE</spring.ldap.version>
        <org.slf4j-version>1.7.5</org.slf4j-version>
        <netbeans.hint.deploy.server>Tomcat</netbeans.hint.deploy.server>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>

        <!-- Spring core & mvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
            <version>${spring.version}</version>
            <exclusions>
                <exclusion>
                    <artifactId>commons-logging</artifactId>
                    <groupId>commons-logging</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>${spring.security.version}</version>
        </dependency>
        <!--
        <dependency>
            <groupId>spring.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>${spring.security.version}</version>
        </dependency>
        -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-cas-client</artifactId>
            <version>3.0.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.batch</groupId>
            <artifactId>spring-batch-core</artifactId>
            <version>2.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.batch</groupId>
            <artifactId>spring-batch-infrastructure</artifactId>
            <version>2.2.2.RELEASE</version>
        </dependency>

        <!-- CGLib for @Configuration -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib-nodep</artifactId>
            <version>${cglib.version}</version>
            <scope>runtime</scope>
        </dependency>

        <!-- Servlet Spec -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.4</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>

        <!-- slf4j logging -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${org.slf4j-version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.3</version>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <id>springsource-milestones</id>
            <name>SpringSource Milestones Proxy</name>
            <url>https://oss.sonatype.org/content/repositories/springsource-milestones</url>
        </repository>
    </repositories>

    <build>
        <finalName>javasandbox</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.0.2</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>


text:
Boost Graph Library
===================

A generic interface for traversing graphs, using C++ templates.

The full documentation is available on [boost.org](http://www.boost.org/doc/libs/release/libs/graph/doc/index.html).

## Support, bugs and feature requests ##

Bugs and feature requests can be reported through the [Trac issue tracker](https://svn.boost.org/trac/boost/query?component=graph&desc=1&order=id)
(see [open issues](https://svn.boost.org/trac/boost/query?status=!closed&component=graph&desc=1&order=id) and
[closed issues](https://svn.boost.org/trac/boost/query?status=closed&component=graph&col=id&col=summary&col=status&col=owner&col=type&col=milestone&col=version&desc=1&order=id)). [Here](http://lists.boost.org/Archives/boost/2015/04/221780.php) is why Trac is still in use.

You can submit your changes through a [pull request](https://github.com/boostorg/graph/pulls). One of the maintainers will take a look (remember that it can take some time).

There is no mailing-list specific to Boost Graph, although you can use the general-purpose Boost [mailing-list](http://lists.boost.org/mailman/listinfo.cgi/boost-users) using the tag [graph].

## Development ##

Clone the whole boost project, which includes the individual Boost projects as submodules ([see boost+git doc](https://github.com/boostorg/boost/wiki/Getting-Started)):

    git clone https://github.com/boostorg/boost
    cd boost
    git submodule update --init

The Boost Graph Library is located in `libs/graph/`.

Boost Graph Library is mostly made of headers but also contains some compiled components. Here are the build commands:

    ./bootstrap.sh            <- compile b2
    ./b2 headers              <- just installs headers
    ./b2                      <- build compiled components

**Note:** The Boost Graph Library cannot currently be built outside of Boost itself.

### Running tests ###
First, make sure you are in `libs/graph/test`.
You can either run all the 300+ tests listed in `Jamfile.v2` or run a single test:

    ../../../b2                        <- run all tests
    ../../../b2 cycle_canceling_test   <- single test

You can also check the [regression tests reports](http://beta.boost.org/development/tests/develop/developer/graph.html).


text:
package uk.theretiredprogrammer.photogallery.nodes;

import java.awt.datatransfer.DataFlavor;
import java.io.IOException;
import java.util.List;
import javax.swing.Action;
import uk.theretiredprogrammer.photogallery.dataobjects.*;
import uk.theretiredprogrammer.nbpcglibrary.annotations.UseCommonNodeAction;
import uk.theretiredprogrammer.nbpcglibrary.annotations.UseCommonNodeActions;
import uk.theretiredprogrammer.nbpcglibrary.data.entity.*;
import uk.theretiredprogrammer.nbpcglibrary.node.nodes.*;
import uk.theretiredprogrammer.nbpcglibrary.node.properties.*;
import uk.theretiredprogrammer.nbpcglibrary.api.LogicException;
import org.openide.nodes.PropertySupport;
import uk.theretiredprogrammer.photogallery.dataobjects.User.UserField;

/**
 * Node for UserNode.
 *
 * (Class generated by NetBeans Platform Code Generator tools using script.xml.
 * Do not edit this file. Apply any changes to the definition file and
 * regenerate all files.)
 *
 * @author Richard Linsdale (richard at theretiredprogrammer.uk)
 */
public class UserNode extends TreeNode<Integer, User, Albumpermission, UserField> {

    /**
     * Data Flavor for Nodes of type UserNode
     */
    public static final DataFlavor USERNODE_FLAVOR = new DataFlavor(UserNode.class, "UserNode");

    /**
     * Constructor
     *
     * @param e the entity associated with this node
     */
    public UserNode(User e) {
        super("UserNode", e, User.EM.class, CAN_COPY | CAN_DELETE | CAN_CUT);
    }

    @UseCommonNodeActions({
        @UseCommonNodeAction(id = "uk.theretiredprogrammer.nbpcglibrary.node.actions.NodeCutAction",
                node = "UserNode",
                position = 850, separator = 800),
        @UseCommonNodeAction(id = "uk.theretiredprogrammer.nbpcglibrary.node.actions.NodeCopyAction",
                node = "UserNode", position = 870),
        @UseCommonNodeAction(id = "uk.theretiredprogrammer.nbpcglibrary.node.actions.NodeDeleteAction",
                node = "UserNode", position = 890),})
    private static void useCommonNodeActions() {
    } // a dummy method

    @Override
    protected DataFlavor nodeGetDataFlavor() {
        return USERNODE_FLAVOR;
    }

    /**
     * Get the node display name
     *
     * @return the display name
     */
    @Override
    public String getDisplayName() {
        return getEntity() != null ? getEntity().getDisplayName() : "#undefined#";
    }

    /**
     * Get the node display title
     *
     * @return the display title
     */
    @Override
    public String getDisplayTitle() {
        return getEntity() != null ? getEntity().getDisplayTitle() : "#undefined#";
    }

    StringReadonlyProperty usernameproperty;
    StringReadonlyProperty encodedpasswordproperty;
    StringReadonlyProperty usercodeproperty;
    StringReadonlyProperty enabledproperty;
    StringReadonlyProperty albumpermissionproperty;
    StringReadonlyProperty idproperty;
    StringReadonlyProperty createdbyproperty;
    StringReadonlyProperty createdonproperty;
    StringReadonlyProperty updatedbyproperty;
    StringReadonlyProperty updatedonproperty;

    @Override
    protected List<PropertySupport.ReadOnly<?>> createPropertyItems(List<PropertySupport.ReadOnly<?>> props) {
        User e = getEntity();
        if (e != null) {
            props.add(new StringReadonlyProperty("Node Type", "UserNode"));
            props.add(usernameproperty = new StringReadonlyProperty("Username", e.formatUsername()));
            props.add(encodedpasswordproperty = new StringReadonlyProperty("Encodedpassword", e.formatEncodedpassword()));
            props.add(usercodeproperty = new StringReadonlyProperty("Usercode", e.formatUsercode()));
            props.add(enabledproperty = new StringReadonlyProperty("Enabled", e.formatEnabled()));
            props.add(albumpermissionproperty = new StringReadonlyProperty("Albumpermission", e.formatAlbumpermission()));
            props.add(idproperty = new StringReadonlyProperty("Id", e.formatId()));
            props.add(createdbyproperty = new StringReadonlyProperty("Created by", e.formatCreatedby()));
            props.add(createdonproperty = new StringReadonlyProperty("Created on", e.formatCreatedon()));
            props.add(updatedbyproperty = new StringReadonlyProperty("Updated by", e.formatUpdatedby()));
            props.add(updatedonproperty = new StringReadonlyProperty("Updated on", e.formatUpdatedon()));
        }
        return props;
    }

    @Override
    protected void nodeProcessFieldChange(UserField field) {
        User e = getEntity();
        if (field == null) {
            if (e != null && idproperty != null) {
                usernameproperty.update(e.formatUsername());
                encodedpasswordproperty.update(e.formatEncodedpassword());
                usercodeproperty.update(e.formatUsercode());
                enabledproperty.update(e.formatEnabled());
                albumpermissionproperty.update(e.formatAlbumpermission());
                idproperty.update(e.formatId());
                createdbyproperty.update(e.formatCreatedby());
                createdonproperty.update(e.formatCreatedon());
                updatedbyproperty.update(e.formatUpdatedby());
                updatedonproperty.update(e.formatUpdatedon());
                propertyChange();
            }
        } else {
            switch (field) {
                case USERNAME:
                    if (e != null && usernameproperty != null) {
                        usernameproperty.update(e.formatUsername());
                        propertyChange("Username");
                    }
                    break;
                case ENCODEDPASSWORD:
                    if (e != null && encodedpasswordproperty != null) {
                        encodedpasswordproperty.update(e.formatEncodedpassword());
                        propertyChange("Encodedpassword");
                    }
                    break;
                case USERCODE:
                    if (e != null && usercodeproperty != null) {
                        usercodeproperty.update(e.formatUsercode());
                        propertyChange("Usercode");
                    }
                    break;
                case ENABLED:
                    if (e != null && enabledproperty != null) {
                        enabledproperty.update(e.formatEnabled());
                        propertyChange("Enabled");
                    }
                    break;
                case ALBUMPERMISSION:
                    if (e != null && albumpermissionproperty != null) {
                        albumpermissionproperty.update(e.formatAlbumpermission());
                        propertyChange("Albumpermission");
                    }
                    break;
            }
        }
    }

    @Override
    protected void nodeCutPaste(BasicNode child) throws IOException {
        CoreEntity e = child.getEntity();
        addNewChild(e);
    }

    @Override
    protected void nodeCopyPaste(BasicNode child) throws IOException {
        CoreEntity e = child.getEntity();
        addNewChild(e);
    }

    private void addNewChild(CoreEntity e) {
        throw new LogicException("User Entity does not have a child of the requested class (" + e.getClass().getSimpleName() + ")");
    }

    @Override
    protected void nodeDelete() throws IOException {
        getEntity().remove();
    }

    @Override
    protected void nodeReorderChildByFlavor(DataFlavor df, int[] perm) {
    }

    @Override
    public Action getPreferredAction() {
        return findDefaultAction("UserNode");
    }

    @Override
    public Action[] getActions(boolean context) {
        return findActions("UserNode");
    }
}


text:
public static partial class ReduxMiddleware
{
	public static Redux.Middleware createCrashReport = api => next => action => {
		try {
			return next(action);
		} catch (System.Exception e) {
			System.Diagnostics.Debug.WriteLine ("ReduxCrashReport: Caught an exception: " + e.Message);
			UnityEngine.Debug.LogError ("ReduxCrashReport: Caught an exception: " + e.Message);
			throw e;
		}
	};
}


text:
'''

This is my Python version of a Latin-Hypercube Search algorithm
not presented in

    "Clever Algorithms: Nature-Inspired Programming Recipes".

but based on the Random Search algorithm.

Find the book and the Ruby source codes on GitHub:

   https://github.com/jbrownlee/CleverAlgorithm:s
'''
import random

def objective_function(vector):
   return sum([x ** 2.0 for x in vector])

def latin_hypercube(minmax,max_iter):
    k = len(minmax)
    pranges=[]
    for i in range(k):
        tmp=[]
        low=float(minmax[i][0])
        high=float(minmax[i][1])
        delta=(high-low)/float(max_iter)
        for j in range(max_iter):
            tmp.append(random.uniform(low+j*delta,low+(j+1)*delta))
        pranges.append(tmp)

    s=[]
    for i in range(k):
        s.append(range(max_iter))

    result=[]
    for i in range(max_iter):
        tmp=[]
        for j in range(k):
            a = random.sample(s[j],1)[0]
            tmp.append(a)
            s[j].remove(a)
        result.append(tmp)

    sample = []
    for l in range(len(result)):
        tmp=[]
        for j in range(len(result[l])):
            tmp.append(pranges[j][result[l][j]])
        sample.append(tmp)
    return sample

def search(search_space, max_iter):
    best = None
    lhs = latin_hypercube(search_space,max_iter)
    for i in range(max_iter):
        candidate = {}
        candidate["pos"] = lhs[i]
        candidate["cost"] = objective_function(candidate["pos"])
        if best is None or candidate["cost"] < best["cost"]: best = candidate
        print " > iteration %i, best=%.4g" % (i, best["cost"])
    return best

if __name__ == "__main__":

    search_space = [[-5,5],[-5,5]]
    problem_size = 2
    max_iter = 100
    best = search(search_space, max_iter)
    print  "Done! Best solution: f = %.4g, v =" % best["cost"], best["pos"]


text:
package me.cyning.gifle.app.base;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

/**
 * Created by cyning on 12/2/14.
 */
public class BaseService extends Service {
    DroidApplication mBaseApplication = null;
    @Override
    public void onCreate() {
        super.onCreate();

    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}


text:
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Categories on Huan Zhang's blog</title>
    <link>https://fisher046.github.io/categories/</link>
    <description>Recent content in Categories on Huan Zhang's blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>

	<atom:link href="https://fisher046.github.io/categories/index.xml" rel="self" type="application/rss+xml" />

    <item>
      <title>Golang</title>
      <link>https://fisher046.github.io/categories/golang/</link>
      <pubDate>Fri, 10 Aug 2018 17:00:00 +0800</pubDate>

      <guid>https://fisher046.github.io/categories/golang/</guid>
      <description></description>
    </item>

    <item>
      <title>Kubernetes</title>
      <link>https://fisher046.github.io/categories/kubernetes/</link>
      <pubDate>Fri, 08 Mar 2019 09:05:12 +0800</pubDate>

      <guid>https://fisher046.github.io/categories/kubernetes/</guid>
      <description></description>
    </item>

  </channel>
</rss>


text:
module Azure::Monitor::Mgmt::V2018_01_01
  module Models
    #
    # Represents a metric value.
    #
    class MetricValue

      include MsRestAzure

      # @return [DateTime] the timestamp for the metric value in ISO 8601
      # format.
      attr_accessor :time_stamp

      # @return [Float] the average value in the time range.
      attr_accessor :average

      # @return [Float] the least value in the time range.
      attr_accessor :minimum

      # @return [Float] the greatest value in the time range.
      attr_accessor :maximum

      # @return [Float] the sum of all of the values in the time range.
      attr_accessor :total

      # @return [Float] the number of samples in the time range. Can be used to
      # determine the number of values that contributed to the average value.
      attr_accessor :count

      #
      # Mapper for MetricValue class as Ruby Hash.
      # This will be used for serialization/deserialization.
      #
      def self.mapper()
        {
          client_side_validation: true,
          required: false,
          serialized_name: 'MetricValue',
          type: {
            name: 'Composite',
            class_name: 'MetricValue',
            model_properties: {
              time_stamp: {
                client_side_validation: true,
                required: true,
                serialized_name: 'timeStamp',
                type: {
                  name: 'DateTime'
                }
              },
              average: {
                client_side_validation: true,
                required: false,
                serialized_name: 'average',
                type: {
                  name: 'Double'
                }
              },
              minimum: {
                client_side_validation: true,
                required: false,
                serialized_name: 'minimum',
                type: {
                  name: 'Double'
                }
              },
              maximum: {
                client_side_validation: true,
                required: false,
                serialized_name: 'maximum',
                type: {
                  name: 'Double'
                }
              },
              total: {
                client_side_validation: true,
                required: false,
                serialized_name: 'total',
                type: {
                  name: 'Double'
                }
              },
              count: {
                client_side_validation: true,
                required: false,
                serialized_name: 'count',
                type: {
                  name: 'Double'
                }
              }
            }
          }
        }
      end
    end
  end
end


text:
module Rack
  class CustomHeader
    def initialize(app, headers)
      @app = app
      @custom_headers = headers
    end

    def call(env)
      status, headers, body = @app.call(env)
      headers = headers.merge(@custom_headers)
      [status, headers, body]
    end
  end
end


text:
<?php

declare(strict_types=1);

namespace Roave\BetterReflectionTest\SourceLocator\Located;

use PHPUnit\Framework\TestCase;
use Roave\BetterReflection\SourceLocator\Located\InternalLocatedSource;

/** @covers \Roave\BetterReflection\SourceLocator\Located\InternalLocatedSource */
class InternalLocatedSourceTest extends TestCase
{
    public function testInternalsLocatedSource(): void
    {
        $locatedSource = new InternalLocatedSource('foo', 'name', 'fooExt');

        self::assertSame('foo', $locatedSource->getSource());
        self::assertSame('name', $locatedSource->getName());
        self::assertNull($locatedSource->getFileName());
        self::assertTrue($locatedSource->isInternal());
        self::assertFalse($locatedSource->isEvaled());
        self::assertSame('fooExt', $locatedSource->getExtensionName());
    }
}