Export (0) Print
Expand All

Using the JIT Recompilation Methods to Add Instrumentation

.NET Framework 4.5

Starting with the .NET Framework 4.5, profilers can instrument methods that have already been just-in-time (JIT) compiled by using the ICorProfilerInfo4 methods to recompile the program.

A profiler can request the JIT compiler to recompile a function at any time. When recompiling a function, the profiler specifies code generation flags and Common Intermediate Language (CIL) bodies as follows:

  1. The profiler states its intention to use the JIT recompilation methods on startup. It does this by specifying the COR_PRF_ENABLE_REJIT flag when it calls the ICorProfilerInfo::SetEventMask method. The profiler also specifies the COR_PRF_DISABLE_ALL_NGEN_IMAGES flag to prevent NGEN modules from loading.

  2. When modules have finished loading, the profiler performs all metadata edits and additions required to support any instrumentation it will do later against methods from that module. At any time after that point, the profiler calls the ICorProfilerInfo4::RequestReJIT method from a thread it created previously, and passes the method a list of functions to recompile.

  3. The common language runtime (CLR) identifies these functions for recompilation the next time they are called. If there are multiple instances of a function (each instance represented by a FunctionID), all instances are identified for recompilation. The next time any function instance is called, the CLR performs a JIT recompilation.

  4. If the instance of a function is the first instance to be recompiled, the CLR issues an ICorProfilerCallback4::GetReJITParameters method callback to get instructions from the profiler. The GetReJITParameters callback provides an ICorProfilerFunctionControl Interface. The profiler calls back on this interface to set the code generation parameters and new CIL body to use when recompiling the function. These parameters apply to all instances of the function.

  5. The CLR then issues an ICorProfilerCallback4::ReJITCompilationStarted callback.

  6. When the recompilation is complete, the CLR issues an ICorProfilerCallback4::ReJITCompilationFinished callback. The function call that caused the recompilation is then directed to the new (recompiled) code. Any further calls to this instance also go to the new code.

  7. At any time thereafter, the profiler, running on a thread it previously created, can call the ICorProfilerInfo4::RequestRevert method to reinstate the originally JIT-compiled version (without profiler modifications) of the specified functions.

Each function instance has only one current version, which corresponds to one of the following:

  • If a recompile has not occurred for the function, it is the original version.

  • If the last JIT operation for the function was a recompilation, it is the most recent recompiled version.

  • If the last JIT operation for the function reverted the recompilation, it is the original version.

New invocations of a function instance always activate the current version of the function.

A profiler that uses JIT recompilation methods cannot perform the following operations:

  • Modify metadata for a module (other than adding new LocalVarSigTokens) after the module’s ICorProfilerCallback::ModuleLoadFinished callback has returned.

  • Recompile method bodies that were created by the Native Image Generator (NGen.exe).

  • Recompile methods when using attach/detach profiling.

  • Recompile inlined functions.

  • Allow any Native Image Generator assemblies to load. (COR_PRF_DISABLE_ALL_NGEN_IMAGES must be included in the flags passed to the ICorProfilerInfo::SetEventMask method on startup.)

  • Recompile dynamic methods and dynamic assemblies.

Note Note

The CLR reclaims any memory used by JIT recompilation when the containing AppDomain is unloaded. The CLR does not reclaim this memory any earlier, even if the recompiled method has been reverted.

  1. Instrumentation profiler: A profiler that allows its user to profile and gather insight into an application by adding targeted instrumentation code into the application, gathering the data resulting out of the instrumentation, and analyzing or summarizing the data.

  2. Common Intermediate Language (CIL) : The lowest-level human-readable programming language defined by the Common Language Infrastructure specification and used by the .NET Framework.

  3. JIT recompilation : The recompilation of native code from CIL using the JIT compiler.

  4. ReJITID : An opaque identifier (defined as typedef UINT_PTR ReJITID;) for a specific recompiled version of a function. A (FunctionID, ReJITID) pair is necessary to uniquely identify a recompiled function instance. ReJITIDs for different FunctionIDs are not related to one another, even if the FunctionIDs are related. For example, if Function<T>() is recompiled, the resulting ReJITIDs for Function<Int>() and Function<String>() are not necessarily the same. ReJITID=0 references the original version of the function.

  5. Function: Used in the metadata sense of the word. For example, Function<T>() is uniquely identified by (Module, MethodDef).

  6. Function instance: An instantiation of a function for a given type at run time. Generic functions can have multiple instances; for example, Function<T>() can be Function<Int>() and Function<String>(). Even non-generic functions can have an instance in each of multiple application domains. A function instance is uniquely identified by a FunctionID.

  7. Function version: A particular recompiled version of a function (for example, the original version of Function<Int>() or the second recompiled version of Function<String>()), uniquely identified by (FunctionID, ReJITID).

© 2014 Microsoft