Skip to content

Commit

Permalink
chore: Reduce profiler iscoreclr checks and use correct tokenizer (#2012
Browse files Browse the repository at this point in the history
)
  • Loading branch information
nrcventura authored Oct 26, 2023
1 parent dcb0951 commit 1a1bc28
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 197 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,7 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter

_instructions->Append(_X("ldnull"));
BuildObjectArrayOfParameters();

if (_isCoreClr)
{
_instructions->Append(_X("call instance object [System.Private.CoreLib]System.Reflection.MethodBase::Invoke(object, object[])"));
}
else
{
_instructions->Append(_X("call instance object [mscorlib]System.Reflection.MethodBase::Invoke(object, object[])"));
}
_instructions->Append(_X("call instance object [") + _instructions->GetCoreLibAssemblyName() + _X("]System.Reflection.MethodBase::Invoke(object, object[])"));

if (_methodSignature->_returnType->_kind == SignatureParser::ReturnType::Kind::VOID_RETURN_TYPE)
{
Expand Down
102 changes: 20 additions & 82 deletions src/Agent/NewRelic/Profiler/MethodRewriter/FunctionManipulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,14 +229,7 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter
// create a Type array big enough to hold all of the method parameters
uint16_t parameterCount = uint16_t(_methodSignature->_parameters->size());
_instructions->Append(CEE_LDC_I4, uint32_t(parameterCount));
if (_isCoreClr)
{
_instructions->Append(CEE_NEWARR, _X("[System.Private.CoreLib]System.Type"));
}
else
{
_instructions->Append(CEE_NEWARR, _X("[mscorlib]System.Type"));
}
_instructions->Append(CEE_NEWARR, _X("[") + _instructions->GetCoreLibAssemblyName() + _X("]System.Type"));

// pack the type of each method parameter into our new Type[]
for (uint16_t i = 0; i < parameterCount; ++i)
Expand All @@ -258,14 +251,8 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter
// create an object array big enough to hold all of the method parameters
uint16_t parameterCount = uint16_t(_methodSignature->_parameters->size());
_instructions->Append(CEE_LDC_I4, uint32_t(parameterCount));
if (_isCoreClr)
{
_instructions->Append(CEE_NEWARR, _X("[System.Private.CoreLib]System.Object"));
}
else
{
_instructions->Append(CEE_NEWARR, _X("[mscorlib]System.Object"));
}
_instructions->Append(CEE_NEWARR, _X("[") + _instructions->GetCoreLibAssemblyName() + _X("]System.Object"));

// pack all method parameters into our new object[]
for (uint16_t i = 0; i < parameterCount; ++i)
{
Expand All @@ -279,41 +266,26 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter
_instructions->Append(CEE_STELEM_REF);
}
}

#ifdef DEBUG
void WriteLineToConsole(xstring_t message)
{
_instructions->AppendString(message);
if (_isCoreClr)
{
_instructions->Append(CEE_CALL, _X("void [System.Private.CoreLib]System.Console::WriteLine(string)"));
}
else
// System.Console is not available in System.Private.CoreLib it is defined in System.Console which is not already a reference
// in all assemblies. For now we can just allow this DEBUG build only writing in .net framework apps.
if (!_isCoreClr)
{
_instructions->Append(CEE_CALL, _X("void [mscorlib]System.Console::WriteLine(string)"));
}
}
#endif

// Load the assembly using its full path and then load the given type from the assembly.
void LoadType(xstring_t assemblyPath, xstring_t typeName)
{
_instructions->AppendString(assemblyPath);
if (_isCoreClr)
{
_instructions->Append(CEE_CALL, _X("class [System.Private.CoreLib]System.Reflection.Assembly [System.Private.CoreLib]System.Reflection.Assembly::LoadFrom(string)"));
}
else
{
_instructions->Append(CEE_CALL, _X("class [mscorlib]System.Reflection.Assembly [mscorlib]System.Reflection.Assembly::LoadFrom(string)"));
}
_instructions->Append(CEE_CALL, _X("class [") + _instructions->GetCoreLibAssemblyName() + _X("]System.Reflection.Assembly [") + _instructions->GetCoreLibAssemblyName() + _X("]System.Reflection.Assembly::LoadFrom(string)"));
_instructions->AppendString(typeName);
if (_isCoreClr)
{
_instructions->Append(CEE_CALLVIRT, _X("instance class [System.Private.CoreLib]System.Type [System.Private.CoreLib]System.Reflection.Assembly::GetType(string)"));
}
else
{
_instructions->Append(CEE_CALLVIRT, _X("instance class [mscorlib]System.Type [mscorlib]System.Reflection.Assembly::GetType(string)"));
}
_instructions->Append(CEE_CALLVIRT, _X("instance class [") + _instructions->GetCoreLibAssemblyName() + _X("]System.Type [") + _instructions->GetCoreLibAssemblyName() + _X("]System.Reflection.Assembly::GetType(string)"));
#ifdef DEBUG
_instructions->Append(CEE_DUP);
auto afterMissing = _instructions->AppendJump(CEE_BRTRUE);
Expand All @@ -328,26 +300,12 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter
_instructions->AppendString(methodName);
if (argumentTypesLambda == NULL)
{
if (_isCoreClr)
{
_instructions->Append(CEE_CALLVIRT, _X("instance class [System.Private.CoreLib]System.Reflection.MethodInfo [System.Private.CoreLib]System.Type::GetMethod(string)"));
}
else
{
_instructions->Append(CEE_CALLVIRT, _X("instance class [mscorlib]System.Reflection.MethodInfo [mscorlib]System.Type::GetMethod(string)"));
}
_instructions->Append(CEE_CALLVIRT, _X("instance class [") + _instructions->GetCoreLibAssemblyName() + _X("]System.Reflection.MethodInfo [") + _instructions->GetCoreLibAssemblyName() + _X("]System.Type::GetMethod(string)"));
}
else
{
argumentTypesLambda();
if (_isCoreClr)
{
_instructions->Append(CEE_CALLVIRT, _X("instance class [System.Private.CoreLib]System.Reflection.MethodInfo [System.Private.CoreLib]System.Type::GetMethod(string, class [System.Private.CoreLib]System.Type[])"));
}
else
{
_instructions->Append(CEE_CALLVIRT, _X("instance class [mscorlib]System.Reflection.MethodInfo [mscorlib]System.Type::GetMethod(string, class [mscorlib]System.Type[])"));
}
_instructions->Append(CEE_CALLVIRT, _X("instance class [") + _instructions->GetCoreLibAssemblyName() + _X("]System.Reflection.MethodInfo [") + _instructions->GetCoreLibAssemblyName() + _X("]System.Type::GetMethod(string, class [") + _instructions->GetCoreLibAssemblyName() + _X("]System.Type[])"));
}
#ifdef DEBUG
_instructions->Append(CEE_DUP);
Expand All @@ -360,14 +318,7 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter
// Call MethodBase.Invoke(object, object[])
void InvokeMethodInfo()
{
if (_isCoreClr)
{
_instructions->Append(CEE_CALLVIRT, _X("instance object [System.Private.CoreLib]System.Reflection.MethodBase::Invoke(object, object[])"));
}
else
{
_instructions->Append(CEE_CALLVIRT, _X("instance object [mscorlib]System.Reflection.MethodBase::Invoke(object, object[])"));
}
_instructions->Append(CEE_CALLVIRT, _X("instance object [") + _instructions->GetCoreLibAssemblyName() + _X("]System.Reflection.MethodBase::Invoke(object, object[])"));
}

// Load the MethodInfo instance for the given class and method onto the stack.
Expand Down Expand Up @@ -409,14 +360,7 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter
argumentTypesLambda();
}

if (_isCoreClr)
{
_instructions->Append(CEE_CALL, _X("class [System.Private.CoreLib]System.Reflection.MethodInfo [System.Private.CoreLib]System.CannotUnloadAppDomainException::GetMethodInfoFromAgentCache(string,string,string,string,class [System.Private.CoreLib]System.Type[])"));
}
else
{
_instructions->Append(CEE_CALL, _X("class [mscorlib]System.Reflection.MethodInfo [mscorlib]System.CannotUnloadAppDomainException::GetMethodInfoFromAgentCache(string,string,string,string,class [mscorlib]System.Type[])"));
}
_instructions->Append(CEE_CALL, _X("class [") + _instructions->GetCoreLibAssemblyName() + _X("]System.Reflection.MethodInfo [") + _instructions->GetCoreLibAssemblyName() + _X("]System.CannotUnloadAppDomainException::GetMethodInfoFromAgentCache(string,string,string,string,class [") + _instructions->GetCoreLibAssemblyName() + _X("]System.Type[])"));
}
else
{
Expand All @@ -430,14 +374,8 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter
void LoadArray(std::list<std::function<void()>> elementLoadLambdas)
{
_instructions->Append(CEE_LDC_I4, uint32_t(elementLoadLambdas.size()));
if (_isCoreClr)
{
_instructions->Append(CEE_NEWARR, _X("[System.Private.CoreLib]System.Object"));
}
else
{
_instructions->Append(CEE_NEWARR, _X("[mscorlib]System.Object"));
}
_instructions->Append(CEE_NEWARR, _X("[") + _instructions->GetCoreLibAssemblyName() + _X("]System.Object"));

uint32_t index = 0;

for (auto func : elementLoadLambdas)
Expand Down Expand Up @@ -490,20 +428,20 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter
instructions->Append(_X("ret"));
}

static void ThrowException(const InstructionSetPtr& instructions, const xstring_t& message, const bool& inCoreLib, const bool& isCoreClr)
static void ThrowException(const InstructionSetPtr& instructions, const xstring_t& message, const bool& inCoreLib)
{
auto exception = inCoreLib ? _X("instance void System.Exception::.ctor(string)") : (isCoreClr ? _X("instance void [[System.Private.CoreLib]]System.Exception::.ctor(string)") : _X("instance void [[mscorlib]]System.Exception::.ctor(string)"));
auto exception = inCoreLib ? _X("instance void System.Exception::.ctor(string)") : (_X("instance void [[") + instructions->GetCoreLibAssemblyName() + _X("]]System.Exception::.ctor(string)"));

instructions->AppendString(message);
instructions->Append(CEE_NEWOBJ, exception);
instructions->Append(CEE_THROW);
}

static void ThrowExceptionIfStackItemIsNull(const InstructionSetPtr& instructions, const xstring_t& message, const bool& inCoreLib, const bool& isCoreClr)
static void ThrowExceptionIfStackItemIsNull(const InstructionSetPtr& instructions, const xstring_t& message, const bool& inCoreLib)
{
instructions->Append(CEE_DUP);
auto afterThrow = instructions->AppendJump(CEE_BRTRUE);
ThrowException(instructions, message, inCoreLib, isCoreClr);
ThrowException(instructions, message, inCoreLib);
instructions->AppendLabel(afterThrow);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter
{
_instructions->Append(CEE_LDARG_0);
_instructions->Append(CEE_CALL, _X("class System.Reflection.Assembly System.Reflection.Assembly::LoadFrom(string)"));
ThrowExceptionIfStackItemIsNull(_instructions, _X("Failed to load assembly."), true, _isCoreClr);
ThrowExceptionIfStackItemIsNull(_instructions, _X("Failed to load assembly."), true);
_instructions->Append(CEE_RET);
}

Expand All @@ -83,7 +83,7 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter
_instructions->Append(CEE_CALL, _X("class System.Reflection.Assembly System.CannotUnloadAppDomainException::LoadAssemblyOrThrow(string)"));
_instructions->Append(CEE_LDARG_1);
_instructions->Append(CEE_CALLVIRT, _X("instance class System.Type System.Reflection.Assembly::GetType(string)"));
ThrowExceptionIfStackItemIsNull(_instructions, _X("Failed to load type from assembly via reflection."), true, _isCoreClr);
ThrowExceptionIfStackItemIsNull(_instructions, _X("Failed to load type from assembly via reflection."), true);
_instructions->Append(CEE_RET);
}

Expand Down Expand Up @@ -111,7 +111,7 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter
}
_instructions->AppendLabel(_X("after_GetMethod"));

ThrowExceptionIfStackItemIsNull(_instructions, _X("Failed to load method from type via reflection."), true, _isCoreClr);
ThrowExceptionIfStackItemIsNull(_instructions, _X("Failed to load method from type via reflection."), true);
_instructions->Append(CEE_RET);
}

Expand All @@ -123,7 +123,7 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter
void BuildStoreMethodInAppDomainStorageOrThrow()
{
_instructions->Append(CEE_CALL, _X("class System.AppDomain System.AppDomain::get_CurrentDomain()"));
ThrowExceptionIfStackItemIsNull(_instructions, _X("System.AppDomain.CurrentDomain == null."), true, _isCoreClr);
ThrowExceptionIfStackItemIsNull(_instructions, _X("System.AppDomain.CurrentDomain == null."), true);
_instructions->Append(CEE_LDARG_1);
_instructions->Append(CEE_LDARG_0);
_instructions->Append(CEE_CALLVIRT, _X("instance void System.AppDomain::SetData(string, object)"));
Expand All @@ -134,7 +134,7 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter
void BuildGetMethodFromAppDomainStorage()
{
_instructions->Append(CEE_CALL, _X("class System.AppDomain System.AppDomain::get_CurrentDomain()"));
ThrowExceptionIfStackItemIsNull(_instructions, _X("System.AppDomain.CurrentDomain == null."), true, _isCoreClr);
ThrowExceptionIfStackItemIsNull(_instructions, _X("System.AppDomain.CurrentDomain == null."), true);
_instructions->Append(CEE_LDARG_0);
_instructions->Append(CEE_CALLVIRT, _X("instance object System.AppDomain::GetData(string)"));
_instructions->Append(CEE_CASTCLASS, _X("class System.Reflection.MethodInfo"));
Expand Down
Loading

0 comments on commit 1a1bc28

Please sign in to comment.