ronantakizawa/codereview-bench huggingface dataset:
Repository: dotnet/runtime
File: src/coreclr/pal/src/thread/process.cpp (C++)

Code before:
{
    // This function takes the address of a variable to ensure
    // it's preserved and available in crash dumps
    (void)p;
}

#ifdef HOST_ANDROID
#include <minipal/log.h>
extern "C" void LogCallstackForAndroidNativeCrash() __attribute__((weak));

static Volatile<LONG> s_crashReportAlreadyLogged = FALSE;

/*++
Function:
  PAL_MarkCrashReportAlreadyLogged

Abstract:
  Signals that a crash report has already been logged for this crash.
  Android currently does not support CreateDump, so a crash report is manually logged.
  This prevents duplicate stack traces from being logged (e.g. unhandled exception)
--*/
VOID
PALAPI
PAL_MarkCrashReportAlreadyLogged()
{
    InterlockedExchange(&s_crashReportAlreadyLogged, TRUE);
}
#endif // HOST_ANDROID

VOID
PROCCreateCrashReportAndDumpIfEnabled(int signal, siginfo_t* siginfo, void* context, bool serialize)
{
    // Preserve context pointer to prevent optimization
    DoNotOptimize(&context);

#ifdef HOST_ANDROID
    // Android CoreCLR currently does not support CreateDump, so log a crash report until then.
    // Use atomic exchange to ensure only one thread logs the crash report to avoid interleaved output.
    if (InterlockedCompareExchange(&s_crashReportAlreadyLogged, TRUE, FALSE) == FALSE &&
        LogCallstackForAndroidNativeCrash != nullptr)
    {
        minipal_log_write_fatal(".NET runtime crash report\n");
        LogCallstackForAndroidNativeCrash();
    }
#endif //HOST_ANDROID

    PROCCreateCrashDumpIfEnabled(signal, siginfo, context, serialize);
}

/*++
Function:

Review comment (bug):
```suggestion
    s_crashReportAlreadyLogged = TRUE;
```
Nit: This does not need to be InterlockedExchange. Simple assignment is enough.

Code after:
    {
        result = PROCCreateCrashDump(argvCreateDump, errorMessageBuffer, cbErrorMessageBuffer, false);
    }
    free(program);
    free(pidarg);
    return result;
}

// Helper function to prevent compiler from optimizing away a variable
__attribute__((noinline,NOOPT_ATTRIBUTE))
static void DoNotOptimize(const void* p)
{
    // This function takes the address of a variable to ensure
    // it's preserved and available in crash dumps
    (void)p;
}

static LPCWSTR GetSignalName(int signal)
{
    switch (signal)
    {
        case SIGSEGV: return W("SIGSEGV");
        case SIGBUS:  return W("SIGBUS");
        case SIGFPE:  return W("SIGFPE");
        case SIGILL:  return W("SIGILL");
        case SIGABRT: return W("SIGABRT");
        case SIGTRAP: return W("SIGTRAP");
        case SIGTERM: return W("SIGTERM");
        default:      return W("Unknown signal");
    }
}

/*++
Function:
  PROCLogManagedCallstackForSignal

  Invokes the registered callback to log the managed callstack for a signal.
  Used by Android since CreateDump is not supported there.

Parameters:
  signal - POSIX signal number

(no return value)
--*/
VOID
PROCLogManagedCallstackForSignal(int signal)
{
    if (g_logManagedCallstackForSignalCallback != nullptr)
    {
        LPCWSTR signalName = GetSignalName(signal);
        g_logManagedCallstackForSignalCallback(signalName);
Repository: dotnet/runtime
File: src/coreclr/pal/src/exception/signal.cpp (C++)

Code before:
    // stack overflow too. Those are held in the sigsegv_handler with blocked signals until
    // the process exits.

#ifdef __APPLE__
    if (!g_canSendSignalToDispatchQueueThreads)
    {
        // On macOS older than 14.4, pthread_kill is not allowed to sent a signal to dispatch queue threads
        if (status == ENOTSUP)
        {
            return ERROR_NOT_SUPPORTED;
        }
    }
#endif

    // ESRCH may happen on some OSes when the thread is exiting.
    if (status == EAGAIN || status == ESRCH)
    {
        return ERROR_CANCELLED;
    }

    if (status != 0)
    {
        // Failure to send the signal is fatal. There are only two cases when sending
        // the signal can fail. First, if the signal ID is invalid and second,
        // if the thread doesn't exist anymore.
        PROCLogCallstackForFatalError(SIGABRT);
        PROCAbort();
    }

    return NO_ERROR;
#else
    return ERROR_CANCELLED;
#endif
}


#if !HAVE_MACH_EXCEPTIONS
/*++
Function :
    signal_ignore_handler

    Simple signal handler which does nothing

Parameters :
    POSIX signal handler parameter list ("man sigaction" for details)

(no return value)
--*/
static void signal_ignore_handler(int code, siginfo_t *siginfo, void *context)
{
}

Review comment (bug):
This is method is called in the middle of thread suspension. I am not sure whether logging a managed stacktrace has any chance to work here.

Can you try simulating the crash at this point by commenting our `if (status != 0)` and see whether we are able to log the managed stacktrace successfully at this spot (e.g, run libraries tests - they should hit this spot fairly regularly)?

Code after:
    // stack overflow too. Those are held in the sigsegv_handler with blocked signals until
    // the process exits.

#ifdef __APPLE__
    if (!g_canSendSignalToDispatchQueueThreads)
    {
        // On macOS older than 14.4, pthread_kill is not allowed to sent a signal to dispatch queue threads
        if (status == ENOTSUP)
        {
            return ERROR_NOT_SUPPORTED;
        }
    }
#endif

    // ESRCH may happen on some OSes when the thread is exiting.
    if (status == EAGAIN || status == ESRCH)
    {
        return ERROR_CANCELLED;
    }

    if (status != 0)
    {
        // Failure to send the signal is fatal. There are only two cases when sending
        // the signal can fail. First, if the signal ID is invalid and second,
        // if the thread doesn't exist anymore.
        PROCLogManagedCallstackForSignal(SIGABRT);
        PROCAbort();
    }

    return NO_ERROR;
#else
    return ERROR_CANCELLED;
#endif
}


#if !HAVE_MACH_EXCEPTIONS
/*++
Function :
    signal_ignore_handler

    Simple signal handler which does nothing

Parameters :
    POSIX signal handler parameter list ("man sigaction" for details)

(no return value)
--*/
static void signal_ignore_handler(int code, siginfo_t *siginfo, void *context)
{
}
Repository: dotnet/runtime
File: src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/QCallHandles.cs (C#)

Code before:
    internal unsafe ref struct StringHandleOnStack
    {
        private void* _ptr;

        internal StringHandleOnStack(ref string? s)
        {
            _ptr = Unsafe.AsPointer(ref s);
        }
    }

    // Wrapper for address of a object variable on stack
    internal unsafe ref struct ObjectHandleOnStack
    {
        private object* _ptr;

        private ObjectHandleOnStack(object* pObject)
        {
            _ptr = pObject;
        }

        internal static ObjectHandleOnStack Create<T>(ref T o) where T : class?
        {
            return new ObjectHandleOnStack((object*)Unsafe.AsPointer(ref o));
        }

        internal object Value { get => *_ptr; set => *_ptr = value; }
    }

    internal ref struct ByteRef
    {
        private ref byte _ref;

        internal ByteRef(ref byte byteReference)
        {
            _ref = ref byteReference;
        }

        internal ref byte Value { get => ref _ref; }
    }

    // Wrapper for address of a byref to byte variable on stack
    internal unsafe ref struct ByteRefOnStack
    {
        private readonly void* _pByteRef;
        private ByteRefOnStack(void* pByteRef)
        {
            _pByteRef = pByteRef;
        }

        internal static ByteRefOnStack Create(ref ByteRef byteRef)
        {

Review comment (suggestion):
The `Value` property getter and setter are typed as `object`, but they can legitimately handle null values since `*_ptr` can be null. The property should be typed as `object?` to accurately reflect that null values are valid.
```suggestion
        internal object? Value { get => *_ptr; set => *_ptr = value; }
```

Code after:
    internal unsafe ref struct StringHandleOnStack
    {
        private void* _ptr;

        internal StringHandleOnStack(ref string? s)
        {
            _ptr = Unsafe.AsPointer(ref s);
        }
    }

    // Wrapper for address of a object variable on stack
    internal unsafe ref struct ObjectHandleOnStack
    {
        private object* _ptr;

        private ObjectHandleOnStack(object* pObject)
        {
            _ptr = pObject;
        }

        internal static ObjectHandleOnStack Create<T>(ref T o) where T : class?
        {
            return new ObjectHandleOnStack((object*)Unsafe.AsPointer(ref o));
        }
    }

    internal ref struct ByteRef
    {
        private ref byte _ref;

        internal ByteRef(ref byte byteReference)
        {
            _ref = ref byteReference;
        }

        internal ref byte Value => ref _ref;
    }

    // Wrapper for address of a byref to byte variable on stack
    internal unsafe ref struct ByteRefOnStack
    {
        private readonly void* _pByteRef;
        private ByteRefOnStack(void* pByteRef)
        {
            _pByteRef = pByteRef;
        }

        internal static ByteRefOnStack Create(ref ByteRef byteRef)
        {
            // This is valid because the ByteRef is ByRefLike (stack allocated)
            // and the ByteRefOnStack is expected to have a shorter lifetime
Repository: dotnet/runtime
File: src/coreclr/vm/callhelpers.h (C/C++)

Code before:
        PERFORM_CALL

#define CALL_MANAGED_METHOD_RETREF(ret, reftype, args)  \
        PRECALL_PREP(args)                              \
        PERFORM_CALL                                    \
        ret = (reftype)ObjectToOBJECTREF((Object *)__retval);

#define ARGNUM_2 ARGNUM_N(2)
#define ARGNUM_3 ARGNUM_N(3)
#define ARGNUM_4 ARGNUM_N(4)
#define ARGNUM_5 ARGNUM_N(5)
#define ARGNUM_6 ARGNUM_N(6)
#define ARGNUM_7 ARGNUM_N(7)
#define ARGNUM_8 ARGNUM_N(8)


void CallDefaultConstructor(OBJECTREF ref);

//
// Helper types for calling managed methods marked with [UnmanagedCallersOnly]
// from native code.
//

// Base contract helper for CallerArgConverter
// All converters must derive from this to ensure proper contracts.
struct CallerArgConverterContract
{
    CallerArgConverterContract()
    {
        STANDARD_VM_CONTRACT;
    }
};

// Template for converting arguments when calling UnmanagedCallersOnly methods.
// The default implementation passes arguments through unchanged.
template<typename T>
struct CallerArgConverter final : public CallerArgConverterContract
{
    using IN_Type = T;
    using OUT_Type = T;

    OUT_Type _arg;
    explicit CallerArgConverter(IN_Type arg) : _arg{ arg } { }
    operator OUT_Type()
    {
        LIMITED_METHOD_CONTRACT;
        return _arg;
    }
};

// Specialization for OBJECTREF* - converts to QCall::ObjectHandleOnStack*

Review comment (suggestion):
These converters should not be needed if we start passing ObjectHandleOnStack by value.

Code after:
        PERFORM_CALL

#define CALL_MANAGED_METHOD_RETREF(ret, reftype, args)  \
        PRECALL_PREP(args)                              \
        PERFORM_CALL                                    \
        ret = (reftype)ObjectToOBJECTREF((Object *)__retval);

#define ARGNUM_2 ARGNUM_N(2)
#define ARGNUM_3 ARGNUM_N(3)
#define ARGNUM_4 ARGNUM_N(4)
#define ARGNUM_5 ARGNUM_N(5)
#define ARGNUM_6 ARGNUM_N(6)
#define ARGNUM_7 ARGNUM_N(7)
#define ARGNUM_8 ARGNUM_N(8)


void CallDefaultConstructor(OBJECTREF ref);

//
// Helper types for calling managed methods marked with [UnmanagedCallersOnly]
// from native code.
//

// Helper class for calling managed methods marked with [UnmanagedCallersOnly].
// This provides a more efficient alternative to MethodDescCallSite for methods
// using the reverse P/Invoke infrastructure.
// This class assumes the target method signature has a trailing argument for
// returning the exception (that is, Exception* in C#).
//
// Example usage:
//   UnmanagedCallersOnlyCaller caller(BinderMethodID::MyMethod);
//   ...
//   caller.InvokeThrowing(arg1, arg2);
//
// The corresponding C# method would be declared as:
//   [UnmanagedCallersOnly]
//   public static void MyMethod(int arg1, object* arg2, Exception* pException);
//
class UnmanagedCallersOnlyCaller final
{
    MethodDesc* _pMD;
public:
    explicit UnmanagedCallersOnlyCaller(BinderMethodID id)
        : _pMD{}
    {
        CONTRACTL
        {
            THROWS;
            GC_TRIGGERS;
            MODE_COOPERATIVE;
        }
Repository: dotnet/runtime
File: src/coreclr/vm/callhelpers.h (C/C++)

Code before:
// The corresponding C# method would be declared as:
//   [UnmanagedCallersOnly]
//   public static void MyMethod(int arg1, ObjectHandleOnStack arg2, ObjectHandleOnStack exception);
//
class UnmanagedCallersOnlyCaller final
{
    MethodDesc* _pMD;
    PCODE _fptr;
public:
    explicit UnmanagedCallersOnlyCaller(BinderMethodID id)
        : _pMD{}
        , _fptr{}
    {
        CONTRACTL
        {
            THROWS;
            GC_TRIGGERS;
            MODE_COOPERATIVE;
        }
        CONTRACTL_END;

        _pMD = CoreLibBinder::GetMethod(id);
        _ASSERTE(_pMD != NULL);
        _ASSERTE(_pMD->HasUnmanagedCallersOnlyAttribute());

        _fptr = _pMD->GetMultiCallableAddrOfCode(CORINFO_ACCESS_UNMANAGED_CALLER_MAYBE);
        _ASSERTE(_fptr != (PCODE)NULL);
    }

    template<typename... Args>
    void InvokeThrowing(Args... args)
    {
        CONTRACTL
        {
            THROWS;
            GC_TRIGGERS;
            MODE_COOPERATIVE;
            PRECONDITION(_fptr != (PCODE)NULL);
        }
        CONTRACTL_END;

        struct
        {
            OBJECTREF Exception;
        } gc;
        gc.Exception = NULL;
        GCPROTECT_BEGIN(gc);

        QCall::ObjectHandleOnStack exceptHandle{ &gc.Exception };
        {
            GCX_PREEMP();

Review comment (suggestion):
If we are not caching the function pointer and using it for multiple calls, we should be able to use `GetSingleCallableAddrOfCode`. It is a lot cheaper.

Code after:
//   [UnmanagedCallersOnly]
//   public static void MyMethod(int arg1, object* arg2, Exception* pException);
//
class UnmanagedCallersOnlyCaller final
{
    MethodDesc* _pMD;
public:
    explicit UnmanagedCallersOnlyCaller(BinderMethodID id)
        : _pMD{}
    {
        CONTRACTL
        {
            THROWS;
            GC_TRIGGERS;
            MODE_COOPERATIVE;
        }
        CONTRACTL_END;

        _pMD = CoreLibBinder::GetMethod(id);
        _ASSERTE(_pMD != NULL);
        _ASSERTE(_pMD->HasUnmanagedCallersOnlyAttribute());
    }

    template<typename... Args>
    void InvokeThrowing(Args... args)
    {
        CONTRACTL
        {
            THROWS;
            GC_TRIGGERS;
            MODE_COOPERATIVE;
        }
        CONTRACTL_END;

        struct
        {
            OBJECTREF Exception;
        } gc;
        gc.Exception = NULL;
        GCPROTECT_BEGIN(gc);

        {
            GCX_PREEMP();

            PCODE methodEntry = _pMD->GetSingleCallableAddrOfCodeForUnmanagedCallersOnly();
            _ASSERTE(methodEntry != (PCODE)NULL);

            // Cast the function pointer to the appropriate type.
            // Note that we append the exception handle argument.
            auto fptr = reinterpret_cast<void(*)(Args..., OBJECTREF*)>(methodEntry);
Repository: dotnet/runtime
File: src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/QCallHandles.cs (C#)

Code before:
    {
        private object* _ptr;

        private ObjectHandleOnStack(object* pObject)
        {
            _ptr = pObject;
        }

        internal static ObjectHandleOnStack Create<T>(ref T o) where T : class?
        {
            return new ObjectHandleOnStack((object*)Unsafe.AsPointer(ref o));
        }

        internal object? Value { get => *_ptr; }
    }

    internal ref struct ByteRef
    {
        private ref byte _ref;

        internal ByteRef(ref byte byteReference)
        {
            _ref = ref byteReference;
        }

        internal ref byte Value { get => ref _ref; }
    }

    // Wrapper for address of a byref to byte variable on stack
    internal unsafe ref struct ByteRefOnStack
    {
        private readonly void* _pByteRef;
        private ByteRefOnStack(void* pByteRef)
        {
            _pByteRef = pByteRef;
        }

        internal static ByteRefOnStack Create(ref ByteRef byteRef)
        {
            // This is valid because the ByteRef is ByRefLike (stack allocated)
            // and the ByteRefOnStack is expected to have a shorter lifetime
            // than the ByteRef instance.
            return new ByteRefOnStack(Unsafe.AsPointer(ref byteRef));
        }
    }

    // Wrapper for StackCrawlMark
    internal unsafe ref struct StackCrawlMarkHandle
    {
        private void* _ptr;


Review comment (suggestion):
```suggestion
        internal ref byte Value => ref _ref;
```

Code after:
    {
        private object* _ptr;

        private ObjectHandleOnStack(object* pObject)
        {
            _ptr = pObject;
        }

        internal static ObjectHandleOnStack Create<T>(ref T o) where T : class?
        {
            return new ObjectHandleOnStack((object*)Unsafe.AsPointer(ref o));
        }
    }

    internal ref struct ByteRef
    {
        private ref byte _ref;

        internal ByteRef(ref byte byteReference)
        {
            _ref = ref byteReference;
        }

        internal ref byte Value => ref _ref;
    }

    // Wrapper for address of a byref to byte variable on stack
    internal unsafe ref struct ByteRefOnStack
    {
        private readonly void* _pByteRef;
        private ByteRefOnStack(void* pByteRef)
        {
            _pByteRef = pByteRef;
        }

        internal static ByteRefOnStack Create(ref ByteRef byteRef)
        {
            // This is valid because the ByteRef is ByRefLike (stack allocated)
            // and the ByteRefOnStack is expected to have a shorter lifetime
            // than the ByteRef instance.
            return new ByteRefOnStack(Unsafe.AsPointer(ref byteRef));
        }
    }

    // Wrapper for StackCrawlMark
    internal unsafe ref struct StackCrawlMarkHandle
    {
        private void* _ptr;

        internal StackCrawlMarkHandle(ref StackCrawlMark stackMark)
        {
Repository: dotnet/runtime
File: src/coreclr/vm/reflectioninvocation.cpp (C++)

Code before:
{
    QCALL_CONTRACT;

    Assembly *pAssembly = pModule->GetAssembly();
    if (pAssembly != NULL && pAssembly->IsActive())
        return;

    BEGIN_QCALL;
    pAssembly->EnsureActive();
    END_QCALL;
}

static void PrepareMethodHelper(MethodDesc * pMD)
{
    STANDARD_VM_CONTRACT;

    pMD->EnsureActive();

    if (pMD->IsWrapperStub())
    {
        if (pMD->ShouldCallPrestub())
            pMD->DoPrestub(NULL);
        pMD = pMD->GetWrappedMethodDesc();
    }

    if (pMD->IsAsyncThunk())
    {
        if (pMD->ShouldCallPrestub())
            pMD->DoPrestub(NULL);
        pMD = pMD->GetAsyncVariant();
    }

    if (pMD->ShouldCallPrestub())
        pMD->DoPrestub(NULL);
}

// This method triggers a given method to be jitted. CoreCLR implementation of this method triggers jiting of the given method only.
// It does not walk a subset of callgraph to provide CER guarantees.
extern "C" void QCALLTYPE ReflectionInvocation_PrepareMethod(MethodDesc *pMD, TypeHandle *pInstantiation, UINT32 cInstantiation)
{
    CONTRACTL
    {
        QCALL_CHECK;
        PRECONDITION(pMD != NULL);
        PRECONDITION(CheckPointer(pInstantiation, NULL_OK));
    }
    CONTRACTL_END;

    BEGIN_QCALL;

    if (pMD->IsAbstract())

Review comment (suggestion):
```suggestion
    if (pMD->IsAsyncThunkMethod())
```

Code after:
{
    QCALL_CONTRACT;

    Assembly *pAssembly = pModule->GetAssembly();
    if (pAssembly != NULL && pAssembly->IsActive())
        return;

    BEGIN_QCALL;
    pAssembly->EnsureActive();
    END_QCALL;
}

static void PrepareMethodHelper(MethodDesc * pMD)
{
    STANDARD_VM_CONTRACT;

    pMD->EnsureActive();

    if (pMD->IsWrapperStub())
    {
        if (pMD->ShouldCallPrestub())
            pMD->DoPrestub(NULL);
        pMD = pMD->GetWrappedMethodDesc();
    }

    if (pMD->IsAsyncThunkMethod())
    {
        if (pMD->ShouldCallPrestub())
            pMD->DoPrestub(NULL);
        pMD = pMD->GetAsyncVariant();
    }

    if (pMD->ShouldCallPrestub())
        pMD->DoPrestub(NULL);
}

// This method triggers a given method to be jitted. CoreCLR implementation of this method triggers jiting of the given method only.
// It does not walk a subset of callgraph to provide CER guarantees.
extern "C" void QCALLTYPE ReflectionInvocation_PrepareMethod(MethodDesc *pMD, TypeHandle *pInstantiation, UINT32 cInstantiation)
{
    CONTRACTL
    {
        QCALL_CHECK;
        PRECONDITION(pMD != NULL);
        PRECONDITION(CheckPointer(pInstantiation, NULL_OK));
    }
    CONTRACTL_END;

    BEGIN_QCALL;

    if (pMD->IsAbstract())
Repository: dotnet/runtime
File: src/native/corehost/hostpolicy/deps_resolver.h (C/C++)

Code before:
#include "runtime_config.h"
#include "bundle/runner.h"

// Probe paths to be resolved for ordering
struct probe_paths_t
{
    pal::string_t tpa;
    pal::string_t native;
    pal::string_t resources;
    pal::string_t coreclr;
};

enum class probe_result_t
{
    not_found,
    bundled,
    serviced,
    found
};

struct deps_resolved_asset_t
{
    deps_resolved_asset_t(const deps_asset_t* asset, pal::string_t&& resolved_path)
        : resolved_path(std::move(resolved_path))
        , m_asset(asset) { }

    const version_t& assembly_version() const
    {
        return m_asset != nullptr ? m_asset->assembly_version : version_t::empty();
    }

    const version_t& file_version() const
    {
        return m_asset != nullptr ? m_asset->file_version : version_t::empty();
    }

    pal::string_t resolved_path;

private:
    const deps_asset_t* m_asset;
};

typedef std::unordered_map<pal::string_t, deps_resolved_asset_t> name_to_resolved_asset_map_t;

class deps_resolver_t
{
public:
    deps_resolver_t(
        const arguments_t& args,
        const fx_definition_vector_t& fx_definitions,
        const pal::char_t* additional_deps_serialized,

Review comment (refactor):
`deps_resolved_asset_t`'s inline constructor uses `std::move`, but this header doesn't include `<utility>`. Add an explicit `<utility>` include to avoid relying on transitive includes (which can break builds on some standard library implementations).

Code after:
#include "deps_entry.h"
#include "runtime_config.h"
#include "bundle/runner.h"

// Probe paths to be resolved for ordering
struct probe_paths_t
{
    pal::string_t tpa;
    pal::string_t native;
    pal::string_t resources;
    pal::string_t coreclr;
};

enum class probe_result_t
{
    not_found,
    bundled,
    serviced,
    found
};

struct deps_resolved_asset_t
{
    deps_resolved_asset_t(const deps_asset_t* asset, pal::string_t&& resolved_path)
        : resolved_path(std::move(resolved_path))
        , m_asset(asset) { }

    const version_t& assembly_version() const
    {
        return m_asset != nullptr ? m_asset->assembly_version : version_t::empty();
    }

    const version_t& file_version() const
    {
        return m_asset != nullptr ? m_asset->file_version : version_t::empty();
    }

    pal::string_t resolved_path;

private:
    // Asset from a deps.json that was resolved to this path. This should outlive any deps_resolved_asset_t.
    // If null, this entry is not from a deps.json (for example, there is no deps.json) and has no version information.
    const deps_asset_t* m_asset;
};

typedef std::unordered_map<pal::string_t, deps_resolved_asset_t> name_to_resolved_asset_map_t;

class deps_resolver_t
{
public:
    deps_resolver_t(