Skip to content

Commit

Permalink
Code
Browse files Browse the repository at this point in the history
  • Loading branch information
cshung committed Dec 11, 2024
1 parent bb0fa18 commit 199ee57
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 5 deletions.
7 changes: 7 additions & 0 deletions src/coreclr/minipal/Windows/doublemapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,15 @@ void* VMToOSInterface::ReserveDoubleMappedMemory(void *mapperHandle, size_t offs
return pResult;
}

extern void andrew_debug();

void *VMToOSInterface::CommitDoubleMappedMemory(void* pStart, size_t size, bool isExecutable)
{
if (isExecutable)
{
// Whenever this is called, we are generating code.
andrew_debug();
}
return VirtualAlloc(pStart, size, MEM_COMMIT, isExecutable ? PAGE_EXECUTE_READ : PAGE_READWRITE);
}

Expand Down
43 changes: 43 additions & 0 deletions src/coreclr/vm/callhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "invokeutil.h"
#include "argdestination.h"

void andrew_debug();

#if defined(FEATURE_MULTICOREJIT) && defined(_DEBUG)

// Allow system module for Appx
Expand All @@ -33,6 +35,10 @@ void AssertMulticoreJitAllowedModule(PCODE pTarget)

#endif

void* ToInterpreterMethodInfo(MethodDesc* pMd);

void CallInterpretMethod(void* interpreterMethodInfo, BYTE* ilArgs);

// For X86, INSTALL_COMPLUS_EXCEPTION_HANDLER grants us sufficient protection to call into
// managed code.
//
Expand Down Expand Up @@ -60,7 +66,44 @@ void CallDescrWorkerWithHandler(

BEGIN_CALL_TO_MANAGEDEX(fCriticalCall ? EEToManagedCriticalCall : EEToManagedDefault);

#ifdef FEATURE_INTERPRETER
uint64_t pCallTarget = (uint64_t)(pCallDescrData->pTarget);
if ((pCallTarget & 0x3) == 0x3)
{
//
// Experiment comment:
// Step 4: When we call a method, we simply redirect it to use CallInterpretMethod instead
// of calling a stub and then redirecting back to call InterpretMethod anyway.
//
// That involves first converting the MethodDesc to an InterpreterMethodInfo. We will store
// that on the MethodTable slot so we do not do repeated conversion.
//
MethodDesc* pMD = (MethodDesc*)(pCallTarget & (~0x3));

if (pMD->IsIL() && !pMD->IsUnboxingStub())
{
void* translated = ToInterpreterMethodInfo(pMD);
*(pMD->GetAddrOfSlot()) = pCallTarget = (PCODE)translated;
}
}
if ((pCallTarget & 0x3) == 0x1)
{
//
// Experiment comment:
// Step 5: Now we have an InterpreterMethodInfo, simply call CallInterpretMethod
//
// That involves first converting the MethodDesc to an InterpreterMethodInfo. We will store
// that on the MethodTable slot so we do not do repeated conversion.
//
CallInterpretMethod((void*)(pCallTarget & (~0x1)), (BYTE*)pCallDescrData->pSrc);
}
else
{
CallDescrWorker(pCallDescrData);
}
#else
CallDescrWorker(pCallDescrData);
#endif

END_CALL_TO_MANAGED();
}
Expand Down
9 changes: 9 additions & 0 deletions src/coreclr/vm/ecall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,16 @@ void ECall::PopulateManagedStringConstructors()
MethodDesc* pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__STRING__CTORF_FIRST + i));
_ASSERTE(pMD != NULL);

#ifdef FEATURE_INTERPRETER
//
// Experiment Comment:
// Step 3: GetMultiCallableAddrOfCode will eventually try to interpret the entry point
// as a Precode. For that, we simply ignore that work.
//
PCODE pDest = (PCODE)((uint64_t)pMD & 0x03);
#else
PCODE pDest = pMD->GetMultiCallableAddrOfCode();
#endif

ECall::DynamicallyAssignFCallImpl(pDest, ECallCtor_First + i);
}
Expand Down
92 changes: 88 additions & 4 deletions src/coreclr/vm/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1692,11 +1692,20 @@ CorJitResult Interpreter::GenerateInterpreterStub(CEEInfo* comp,
#else
#error unsupported platform
#endif
stub = sl.Link(SystemDomain::GetGlobalLoaderAllocator()->GetStubHeap());
if (false)
{
stub = sl.Link(SystemDomain::GetGlobalLoaderAllocator()->GetStubHeap());

*nativeSizeOfCode = static_cast<ULONG>(stub->GetNumCodeBytes());
// TODO: manage reference count of interpreter stubs. Look for examples...
*nativeEntry = dac_cast<BYTE*>(stub->GetEntryPoint());
*nativeSizeOfCode = static_cast<ULONG>(stub->GetNumCodeBytes());
// TODO: manage reference count of interpreter stubs. Look for examples...
*nativeEntry = dac_cast<BYTE*>(stub->GetEntryPoint());
}
else
{
// Intentionally avoid generating any code - but it is required
// for us to have an unique nativeEntry since it will be part of some hash table
*nativeEntry = (BYTE*)(((uint64_t)interpMethInfo) | 0x1);
}
}

// Initialize the arg offset information.
Expand Down Expand Up @@ -1773,6 +1782,81 @@ ARG_SLOT Interpreter::ExecuteMethodWrapper(struct InterpreterMethodInfo* interpM
return retVal;
}

COR_ILMETHOD_DECODER* CopiedGetAndVerifyMetadataILHeader(MethodDesc* pMD, PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pDecoderMemory)
{
// STANDARD_VM_CONTRACT;
_ASSERTE(pMD != NULL);
_ASSERTE(!pMD->IsNoMetadata());
_ASSERTE(pConfig != NULL);
_ASSERTE(pDecoderMemory != NULL);

COR_ILMETHOD_DECODER* pHeader = NULL;
COR_ILMETHOD* ilHeader = pConfig->GetILHeader();
if (ilHeader == NULL)
return NULL;

COR_ILMETHOD_DECODER::DecoderStatus status = COR_ILMETHOD_DECODER::FORMAT_ERROR;
{
// Decoder ctor can AV on a malformed method header
AVInRuntimeImplOkayHolder AVOkay;
pHeader = new (pDecoderMemory) COR_ILMETHOD_DECODER(ilHeader, pMD->GetMDImport(), &status);
}

if (status == COR_ILMETHOD_DECODER::FORMAT_ERROR)
COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL);

return pHeader;
}

COR_ILMETHOD_DECODER* CopiedGetAndVerifyILHeader(MethodDesc* pMD, PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pIlDecoderMemory)
{
// STANDARD_VM_CONTRACT;
_ASSERTE(pMD != NULL);
if (pMD->IsIL())
{
return CopiedGetAndVerifyMetadataILHeader(pMD, pConfig, pIlDecoderMemory);
}
else if (pMD->IsILStub())
{
ILStubResolver* pResolver = pMD->AsDynamicMethodDesc()->GetILStubResolver();
return pResolver->GetILHeader();
}

_ASSERTE(pMD->IsNoMetadata());
return NULL;
}

void ToMethodInfo(MethodDesc* ftn, COR_ILMETHOD_DECODER* ILHeader, CORINFO_METHOD_INFO* pMethodInfo);

void* ToInterpreterMethodInfo(MethodDesc* pMd)
{
// Given a methodDesc, convert it into an InterpreterMethodInfo
GCX_PREEMP();
NativeCodeVersion activeCodeVersion(pMd);
PrepareCodeConfigBuffer pccb(activeCodeVersion);
PrepareCodeConfig* pConfig = pccb.GetConfig();
COR_ILMETHOD_DECODER ilDecoderTemp;
COR_ILMETHOD_DECODER* pilHeader = CopiedGetAndVerifyILHeader(pMd, pConfig, &ilDecoderTemp);
CORINFO_METHOD_INFO methodInfo;
ToMethodInfo(pMd, pilHeader, &methodInfo);
CEEInfo* jitInfo = new CEEInfo(pMd, true);

InterpreterMethodInfo* interpreterMethodInfo;
BYTE* unusedEntry;
uint32_t unusedSize;

// The method is modified so that it won't generate code anymore
Interpreter::GenerateInterpreterStub(jitInfo, &methodInfo, &unusedEntry, &unusedSize, &interpreterMethodInfo, false);
return (void*)(((uint64_t)interpreterMethodInfo) | 0x1);
}

void CallInterpretMethod(void* interpreterMethodInfo, BYTE* ilArgs)
{
struct InterpreterMethodInfo* interpMethInfo = (struct InterpreterMethodInfo*)interpreterMethodInfo;
// TODO, return!
Interpreter::InterpretMethodBody(interpMethInfo, true, ilArgs, nullptr);
}

// TODO: Add GSCookie checks

// static
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/vm/interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -746,8 +746,10 @@ class Interpreter
friend float F_CALL_CONV InterpretMethodFloat(InterpreterMethodInfo* methInfo, BYTE* ilArgs, void* stubContext);
friend double F_CALL_CONV InterpretMethodDouble(InterpreterMethodInfo* methInfo, BYTE* ilArgs, void* stubContext);

public:
// This will be inlined into the bodies of the methods above
static inline ARG_SLOT InterpretMethodBody(InterpreterMethodInfo* interpMethInfo, bool directCall, BYTE* ilArgs, void* stubContext);
private:

// The local frame size of the method being interpreted.
static size_t GetFrameSize(InterpreterMethodInfo* interpMethInfo);
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/vm/jitinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12885,6 +12885,11 @@ void ThrowExceptionForJit(HRESULT res)
BOOL g_fAllowRel32 = TRUE;
#endif

void ToMethodInfo(MethodDesc* ftn, COR_ILMETHOD_DECODER* ILHeader, CORINFO_METHOD_INFO* pMethodInfo)
{
MethodInfoHelperContext cxt{ ftn, ILHeader };
getMethodInfoHelper(cxt, pMethodInfo);
}

// ********************************************************************
// README!!
Expand Down
29 changes: 28 additions & 1 deletion src/coreclr/vm/method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2660,6 +2660,12 @@ MethodDesc* MethodDesc::GetMethodDescFromStubAddr(PCODE addr, BOOL fSpeculative

// Otherwise this must be some kind of precode
//
#ifdef FEATURE_INTERPRETER
if ((addr & 0x03) == 0x03)
{
return (MethodDesc*)((addr) & (~0x03));
}
#endif
PTR_Precode pPrecode = Precode::GetPrecodeFromEntryPoint(addr, fSpeculative);
PREFIX_ASSUME(fSpeculative || (pPrecode != NULL));
if (pPrecode != NULL)
Expand Down Expand Up @@ -2758,6 +2764,16 @@ void MethodDesc::EnsureTemporaryEntryPointCore(AllocMemTracker *pamTracker)
GetMethodDescChunk()->DetermineAndSetIsEligibleForTieredCompilation();
PTR_PCODE pSlot = GetAddrOfSlot();

#ifdef FEATURE_INTERPRETER
//
// Experiment comment:
// Step 1: Whenever we create a MethodDesc, we used to generate a precode for it
// This change avoids that and we put in a tagged MethodDesc there instead.
//
IfFailThrow(EnsureCodeDataExists(pamTracker));
// TODO: Interlocked?
PCODE tempEntryPoint = m_codeData->TemporaryEntryPoint = (PCODE)((uint64_t)this | 0x3);
#else
AllocMemTracker amt;
AllocMemTracker *pamTrackerPrecode = pamTracker != NULL ? pamTracker : &amt;
Precode* pPrecode = Precode::Allocate(GetPrecodeType(), this, GetLoaderAllocator(), pamTrackerPrecode);
Expand All @@ -2769,6 +2785,7 @@ void MethodDesc::EnsureTemporaryEntryPointCore(AllocMemTracker *pamTracker)

PCODE tempEntryPoint = m_codeData->TemporaryEntryPoint;
_ASSERTE(tempEntryPoint != (PCODE)NULL);
#endif

if (*pSlot == (PCODE)NULL)
{
Expand Down Expand Up @@ -2866,16 +2883,26 @@ Precode* MethodDesc::GetOrCreatePrecode()

void MethodDesc::MarkPrecodeAsStableEntrypoint()
{
#ifndef FEATURE_INTERPRETER
#if _DEBUG
PCODE tempEntry = GetTemporaryEntryPointIfExists();
_ASSERTE(tempEntry != (PCODE)NULL);
PrecodeType requiredType = GetPrecodeType();
//
// Experiment comment:
// Step 2: Later on, for various reasons, we might want to know more about the function
// Currently, it is done by Precode::GetPrecodeFromEntryPoint, which will obviously not
// work because the entry point is no longer a Precode.
//
// Depending on what we actually want, this needs to be fixed differently. For example
// this is just doing some assertion, we can simply ignore it.
//
PrecodeType availableType = Precode::GetPrecodeFromEntryPoint(tempEntry)->GetType();
_ASSERTE(requiredType == availableType);
#endif
_ASSERTE(!HasPrecode());
_ASSERTE(RequiresStableEntryPoint());

#endif
InterlockedUpdateFlags3(enum_flag3_HasStableEntryPoint | enum_flag3_HasPrecode, TRUE);
}

Expand Down

0 comments on commit 199ee57

Please sign in to comment.