<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>David Broman's CLR Profiling API Blog</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/davbr/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/davbr/feed.xml</link>
    <description>Info about the Common Language Runtime&amp;#039;s Profiling API</description>
    <lastBuildDate>Tue, 16 Apr 2019 04:59:07 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Goodbye from Dave</title>
      <link>https://docs.microsoft.com/archive/blogs/davbr/goodbye-from-dave</link>
      <pubDate>Thu, 10 Oct 2013 17:13:00 GMT</pubDate>
      <dc:creator><![CDATA[David Broman]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davbr/2013/10/10/goodbye-from-dave/</guid>
      <description><![CDATA[Hello to my millions of readers across the world.&nbsp; Or, well, maybe 10 readers across the...]]></description>
      <content:encoded><![CDATA[<p>Hello to my millions of readers across the world.&nbsp; Or, well, maybe 10 readers across the world.&nbsp; Something like that.</p>
<p>Anyway, I wanted to let you all know that the CLR Profiling API is shifting ownership to some other fantastic folks on the CLR team.&nbsp; So after many years of working on this facet of the CLR, it's time for me to say goodbye.</p>
<p>Please continue to monitor the .NET Team blog (<a href="https://blogs.msdn.com/b/dotnet/">https://blogs.msdn.com/b/dotnet/</a>) for exciting new happenings in the CLR, including the profiling API.</p>
<p>So long, and thanks for the memories!</p>
<p>&nbsp;</p>
<p>Dave</p>]]></content:encoded>
    </item>
    <item>
      <title>Writing a Profiler of Windows Store apps</title>
      <link>https://docs.microsoft.com/archive/blogs/davbr/writing-a-profiler-of-windows-store-apps</link>
      <pubDate>Wed, 09 Jan 2013 12:48:28 GMT</pubDate>
      <dc:creator><![CDATA[David Broman]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davbr/2013/01/09/writing-a-profiler-of-windows-store-apps/</guid>
      <description><![CDATA[If you’ve written a profiler that consumes the CLR Profiling API, and are looking to update it to...]]></description>
      <content:encoded><![CDATA[<p>If you’ve written a profiler that consumes the CLR Profiling API, and are looking to update it to analyze Windows Store apps, then you’ll be interested in this new whitepaper: </p>  <p><a href="https://go.microsoft.com/fwlink/?LinkID=271485">https://go.microsoft.com/fwlink/?LinkID=271485</a></p>  <p>The whitepaper provides recommendations for all the changes you’ll need to make so your profiler can profile Windows Store apps.&#160; As you read through the whitepaper, keep in mind that the source code to <a href="https://blogs.msdn.com/b/davbr/archive/2012/11/19/clrprofiler-4-5-released-includes-windows-store-app-support.aspx">CLRProfiler 4.5</a> can also be used to illustrate many of these changes you’ll need to make.</p>  <p>Happy coding!</p>]]></content:encoded>
    </item>
    <item>
      <title>New sample code for rewriting IL: ILRewrite Profiler</title>
      <link>https://docs.microsoft.com/archive/blogs/davbr/new-sample-code-for-rewriting-il-ilrewrite-profiler</link>
      <pubDate>Mon, 19 Nov 2012 14:14:36 GMT</pubDate>
      <dc:creator><![CDATA[David Broman]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davbr/2012/11/19/new-sample-code-for-rewriting-il-ilrewrite-profiler/</guid>
      <description><![CDATA[In my previous post, I mentioned the new home for CLRProfiler, where you can find its latest...]]></description>
      <content:encoded><![CDATA[<p>In my <a href="https://blogs.msdn.com/b/davbr/archive/2012/11/19/clrprofiler-4-5-released-includes-windows-store-app-support.aspx">previous post</a>, I mentioned the new home for CLRProfiler, where you can find its latest version, 4.5: <a title="https://clrprofiler.codeplex.com/" href="https://clrprofiler.codeplex.com/">https://clrprofiler.codeplex.com/</a>.&#160; On the same CodePlex site you can also find a new sample, <strong>ILRewrite</strong>.&#160; ILRewrite contains sample code demonstrating the following:</p>  <ul>   <li>Parsing a stream of IL bytes into a linked list of editable structures </li>    <li>Writing that linked list back out into a new stream of IL bytes </li>    <li>Using the metadata API to add AssemblyRefs, TypeRefs, and MemberRefs to modules you instrument </li>    <li>Using the metadata API to add brand new methods into mscorlib.dll </li>    <li>Using the new RequestReJIT and RequestRevert APIs. </li> </ul>  <p>Click on the <strong>ILRewrite10Source </strong>download from the <strong>Downloads</strong> <strong>tab</strong>.&#160; You can find some basic documentation on the <strong>Documentation tab</strong>, and more detailed documentation in the <strong>readme.txt</strong> distributed as part of the source.</p>]]></content:encoded>
    </item>
    <item>
      <title>CLRProfiler 4.5 released: includes Windows Store app support</title>
      <link>https://docs.microsoft.com/archive/blogs/davbr/clrprofiler-4-5-released-includes-windows-store-app-support</link>
      <pubDate>Mon, 19 Nov 2012 14:12:34 GMT</pubDate>
      <dc:creator><![CDATA[David Broman]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davbr/2012/11/19/clrprofiler-4-5-released-includes-windows-store-app-support/</guid>
      <description><![CDATA[You can find CLRProfiler 4.5 at its new home on CodePlex: https://clrprofiler.codeplex.com/  If...]]></description>
      <content:encoded><![CDATA[<p>You can find CLRProfiler 4.5 at its new home on CodePlex: <a title="https://clrprofiler.codeplex.com/" href="https://clrprofiler.codeplex.com/">https://clrprofiler.codeplex.com/</a></p>  <p>If you’re interested in <em>using</em> CLRProfiler to diagnose memory issues with your managed app, including managed Windows Store apps, all you need is the <strong>CLRProfiler45Binaries</strong> download from the <strong>Downloads</strong> <strong>tab</strong>.&#160; <font color="#ff0000">Please be sure to read the installation instructions first</font>.&#160; You will find a link to the installation instructions from the Downloads tab.</p>  <p>If you’re interested in <em>writing </em>your own profiler to diagnose Windows Store apps, you may find CLRProfiler 4.5 useful as an example.&#160; You’ll want the <strong>CLRProfiler45Source</strong> download from the <strong>Downloads</strong> <strong>tab</strong>.&#160; (Note, in early December we expect also to release a white paper documenting what you’ll need to know about writing a profiler that analyzes Windows Store apps.)</p>  <p>In the coming weeks we expect to publish more complete information on CLRProfiler 4.5, but I wanted to get this small post out there now so you’re aware that CLRProfiler 4.5 is available.</p>]]></content:encoded>
    </item>
    <item>
      <title>GC Heap and Alignment Padding</title>
      <link>https://docs.microsoft.com/archive/blogs/davbr/gc-heap-and-alignment-padding</link>
      <pubDate>Thu, 29 Dec 2011 11:48:00 GMT</pubDate>
      <dc:creator><![CDATA[David Broman]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davbr/2011/12/29/gc-heap-and-alignment-padding/</guid>
      <description><![CDATA[The docs for GetObjectSize have recently been updated with this info, but I wanted to mention it...]]></description>
      <content:encoded><![CDATA[<p>The docs for <a href="https://msdn.microsoft.com/en-US/library/ms231885(v=VS.100).aspx">GetObjectSize</a> have recently been updated with this info, but I wanted to mention it here, too, to ensure you were aware of this information.</p>  <p>Some profilers manually advance through objects on the heap, inspecting their field values, by starting at an ObjectID and moving forward by its size to the next ObjectID, repeating this process, for all the reported generation ranges (via GetGenerationBounds or MovedReferences/SurvivingReferences).&#160; If your profiler doesn’t do this, then this blog entry will be of no interest to you, and you can skip it.&#160; But if your profiler does do this, you need to be aware of the alignment rules that the CLR employs as it allocates and moves objects around on the GC heap.</p>  <ul>   <li><strong><u>On x86</u></strong>: All objects are 4-byte aligned, except for objects on the large-object-heap, which are always 8-byte aligned.</li>    <li><strong><u>On x64</u></strong>: All objects are always 8-byte aligned, in all generations.</li> </ul>  <p>And the important point to note is that GetObjectSize does NOT include alignment padding in the size that it reports.&#160; Thus, as your profiler manually skips from object to object by using GetObjectSize() to determine how far to skip, your profiler must manually add in any alignment padding necessary to achieve the alignment rules listed above.</p>]]></content:encoded>
    </item>
    <item>
      <title>When is it safe to use ObjectIDs?</title>
      <link>https://docs.microsoft.com/archive/blogs/davbr/when-is-it-safe-to-use-objectids</link>
      <pubDate>Thu, 29 Dec 2011 11:33:00 GMT</pubDate>
      <dc:creator><![CDATA[David Broman]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davbr/2011/12/29/when-is-it-safe-to-use-objectids/</guid>
      <description><![CDATA[As mentioned in this post, ObjectIDs are really pointers to managed objects on the GC heap.&nbsp;...]]></description>
      <content:encoded><![CDATA[<p>As mentioned in <a href="https://blogs.msdn.com/b/davbr/archive/2007/12/18/debugging-your-profiler-ii-sos-and-ids.aspx">this post</a>, ObjectIDs are really pointers to managed objects on the GC heap.&nbsp; And as you know, objects get collected or move around on the heap during GCs.&nbsp; So how do you safely work with ObjectIDs?</p>
<p>The overall guidance is that if you plan to dereference an ObjectID or pass it to an ICorProfilerInfo(2,3,4) method, then you must do so either:</p>
<ol>
<li>From inside a GC, from a thread doing the GC (e.g., in response to one of the GC callbacks, in which case you're guaranteed that the GC is blocked by this call), OR</li>
<li>From a callback that gave you the ObjectID (in which case you're guaranteed that the GC is blocked by the callback that gave you the ObjectID)</li>
</ol>
<p>Of course, taking an ObjectID that you were given and caching it away somewhere is a big no-no, unless you take pains to update all the ObjectIDs in your cache on every GC, by using the SurvivingReferences/MovedReferences callbacks.&nbsp; And even with a well-updated cache such as this, the CLR will still require that you pass ObjectIDs to Info methods only in the above two circumstances, or else you will receive an error HRESULT.&nbsp; This extra checking was added in .NET 4.0.</p>
<p>The reason for this is that some code paths in the CLR assume that their thread is already blocking the GC (to ensure referenced objects stay put), but there was no enforcement in place to ensure this.&nbsp; So we added this enforcement in .NET 4.0.&nbsp; Without checks like this, it could be possible to cause nondeterministic GC heap corruptions or to reference the wrong memory.&nbsp; For example, calling GetObjectSize on a thread that you create (i.e., not a manage thread) does not intrinsically block the GC, and thus is considered unsafe.</p>]]></content:encoded>
    </item>
    <item>
      <title>Metadata Tokens, Run-Time IDs, and Type Loading</title>
      <link>https://docs.microsoft.com/archive/blogs/davbr/metadata-tokens-run-time-ids-and-type-loading</link>
      <pubDate>Mon, 17 Oct 2011 18:29:42 GMT</pubDate>
      <dc:creator><![CDATA[David Broman]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davbr/2011/10/17/metadata-tokens-run-time-ids-and-type-loading/</guid>
      <description><![CDATA[Overview  In this post, I write about the two primary kinds of IDs your profiler deals with, when...]]></description>
      <content:encoded><![CDATA[<h1>Overview</h1>  <p>In this post, I write about the two primary kinds of IDs your profiler deals with, when each kind is appropriate to use, how to convert between those two types of IDs, and some gotchas with those conversions—particularly in how they may invoke the type loader.</p>  <h1>The two kinds of IDs</h1>  <p>Profilers have to deal with two kinds of IDs.&#160; The first kind are IDs from metadata, a.k.a., <strong>metadata tokens</strong>.&#160; These are the mdToken values, like mdMethodDef or mdTypeDef, which are read straight out of the metadata of managed modules.&#160; These values do not change for a given module from process to process.&#160; They are placed in the module by the language compiler that generates the IL (e.g., csc.exe).&#160; Profilers typically use metadata tokens in order to look up symbolic information from the metadata (e.g., for pretty-printing names of methods or classes), and for performing IL rewriting.&#160; Metadata tokens are also fantastic for deferring symbolic lookup to a post-processing phase.&#160; For example, a sampling profiler could log metadata tokens for classes and functions encountered on a sample at run-time and defer looking up the names of those classes and functions to a post-processing phase that occurs after the profiled process has exited.&#160; This keeps the profiler’s data collection lightweight, and is only possible because metadata tokens don’t change so long as the managed modules defining those tokens don’t change.</p>  <p>The second kind of IDs are <strong>run-time IDs</strong>, such as FunctionID or ClassID which are defined in corprof.idl.&#160; These values do change from process to process, and they represent internal data structures that the CLR builds up at run-time as it loads modules, loads types, JIT compiles functions, etc.&#160; Profilers use these values as its main currency between ICorProfilerInfo* and ICorProfilerCallback* methods.&#160; The CLR uses these values when it notifies profilers of various events (ICorProfilerCallback* methods), and the profiler passes these values back into the CLR (ICorProfilerInfo* methods) in order to get further information about them.&#160; These IDs are handy because they are your profiler’s key to unlocking class layout, generated code, object addresses, and everything else that the CLR maintains about the actively executing managed code at run-time.&#160; See <a href="https://blogs.msdn.com/davbr/archive/2007/12/18/debugging-your-profiler-ii-sos-and-ids.aspx">this post</a> for more info about what these IDs really are.</p>  <h1>Converting between metadata tokens and run-time IDs</h1>  <p>Since metadata tokens are good for some things and run-time IDs are good for others, you will inevitably find yourself in situations where you have one kind of ID handy, but you really need the other kind of ID.&#160; Can you convert from one kind of ID to another?&#160; Yes, but there are some caveats!</p>  <p>It’s always safe to go this direction: run-time ID –&gt; metadata token.&#160; Just use methods such as GetFunctionInfo2 and GetClassIDInfo2, which take run-time IDs as input, and provide their module + metadata token as (part of) the output.</p>  <p>However, it is problematic going the opposite direction: metadata token –&gt; run-time ID.&#160; Why?&#160; Because a given type may not be loaded yet, and thus the run-time ID may not exist.&#160; There exist methods on the ICorProfilerInfo* interfaces that go this direction, namely GetFunctionFromToken(AndTypeArgs) and GetClassFromToken(AndTypeArgs).&#160; However, they are dangerous to use (see below), and should be avoided.&#160; Instead, it’s preferable that your profiler build up its own run-time ID –&gt; metadata token map as it encounters run-time IDs, and then performing reverse lookups in that map as necessary.&#160; For example, as your profiler encounters ClassIDs via callbacks like ClassLoadFinished, it goes the “safe” direction (run-time ID –&gt; metadata token), to build up its map.&#160; When it later encounters an mdTypeDef for a class, it checks to see if that mdTypeDef exists yet in its map—if so, your profiler uses that map to find the corresponding ClassID.&#160; Safe and easy.</p>  <p>“Dave, stop telling us to do impossible things.&#160; You know full well that profilers which attach to a process after it has started up don’t have the benefit of seeing all the ClassLoad* notifications.&#160; Also, if regular NGEN’d images are used, ClassLoad* notifications are not reliably sent.”</p>  <p>True.&#160; Though you will come across ClassIDs other ways.&#160; Memory profilers will encounter ObjectIDs on the heap, and can call GetClassFromObject to start filling up its map of ClassIDs and thus mdTypeDefs.&#160; Similarly, sampling profilers encounter FunctionIDs during stack walks, and can then get the ClassIDs containing those FunctionIDs and thus build up its map that way.</p>  <p>“You’re a dreamer, man.&#160; There will still be cases where I have a metadata token, but have not yet encountered the ClassID.&#160; Think about deep inspection of embedded structs!”</p>  <p>Yes, that is a good example.&#160; You are an astute reader.&#160; Memory profilers that wish to deeply inspect values of classes and structures on the heap need to know the ClassIDs in order to call GetClassLayout.&#160; This works great when you’re dealing with reference types whose fields point to other reference types: as you bounce from object to object, you can take the ObjectID (i.e., the location in memory where the object starts), pass it to GetClassFromObject, and there’s your ClassID.&#160; But what happens when a struct is embedded inside an object?&#160; Sure, you can get the layout of the object, and determine the offset into the object where the embedded struct lives.&#160; But then what?&#160; How to inspect and report on the values of fields <em>inside the embedded struct</em>?&#160; At this point, all you can get is the mdTypeDef for the struct (from the metadata of the containing class), but you may never have seen the ClassID for that struct.</p>  <p>“Told you so.”</p>  <h1>Going from metadata token to run-time ID</h1>  <h1></h1>  <h1></h1>  <p>As I mentioned above, the safest way to do this is to build up your own map and do reverse-lookups as necessary.&#160; If that scheme meets your needs, then by all means do that, and stop reading!&#160; But in the cases where this is insufficient, you may need to resort to using GetFunctionFromToken(AndTypeArgs) and GetClassFromToken(AndTypeArgs).&#160; There is no simple, foolproof way to use these APIs safely, but here is your guideline:</p>  <p><strong>Never call GetFunctionFromToken(AndTypeArgs) and GetClassFromToken(AndTypeArgs) unless you’re certain the relevant types have been loaded.</strong>&#160; (“Relevant types” include the ClassID containing the FunctionID whose mdMethodDef you pass to GetFunctionFromToken(AndTypeArgs), and the ClassID whose mdTypeDef you pass to GetClassFromToken(AndTypeArgs).)&#160; If these types have not been loaded, <em>you may cause them to be loaded now</em>!&#160; This is bad because:</p>  <ul>   <li>This is an easy way to crash the app.&#160; Trying to load a type at the wrong time could cause cycles, causing infinite loops (depending on what your profiler does in response to class load notifications) or outright crashes.&#160; For example, trying to load a type while its containing assembly is still in an early phase of loading is a great and fun way to crash the CLR. </li>    <li>You will impact the behavior of the app.&#160; If you’re lucky enough not to crash the app, you’ve still impacted its behavior, by causing types to get loaded in a different order than they normally would.&#160; Any impact to app behavior like this makes it difficult for your users to reproduce problems that they are trying to use your tool to diagnose, or may hide problems that they don’t discover until they run their application outside of your tool. </li> </ul>  <h2>Determining whether a class was loaded</h2>  <p>So how do you know a class has been fully loaded?</p>  <p>Unfortunately, receiving the <strong>ClassLoadFinished</strong> callback does not necessarily mean that ClassID has been fully loaded yet, as the MSDN <a href="https://msdn.microsoft.com/en-us/library/ms230794.aspx">documentation</a> warns us.</p>  <p>Basically, the CLR type loader is one of the laziest things on this planet.&#160; It doesn’t want to do anything unless it really, really has to.&#160; The best guideline I can give you is this:&#160; If the app is currently executing managed code that uses a type, then the type is loaded.&#160; For example, if you do a stackwalk, and determine that the app is executing inside of</p>  <p>MyRetType MyClass::MyFunction(MyArgumentType myArgumentType)</p>  <p>then you can be reasonably assured that the following are loaded:</p>  <ul>   <li>MyClass </li>    <li>MyArgumentType (if it’s a value-type) </li>    <li>MyRetType (if it’s a value-type) </li>    <li>For any class you know is loaded, so should be:      <ul>       <li>its base class </li>        <li>its value-type fields (not necessarily reference-type fields!) </li>        <li>implemented interfaces </li>        <li>value-type generic type arguments (and even reference-type generic type arguments in the case of MyClass) </li>     </ul>   </li> </ul>  <p>So much for stacks.&#160; What if you encounter an instance of a class on the heap?&#160; Surely the class is loaded then, right?&#160; Well, probably.&#160; If you encounter an object on heap just after GC (inside <strong>GarbageCollectionFinished</strong>, before you return), it should be safe to inspect the class’s layout, and then peek through ObjectIDs to see the values of their fields.</p>  <p>But what if you encounter an object earlier than that?&#160; For example, if you receive an <strong>ObjectAllocated</strong> callback, and call <strong>GetClassFromObject</strong> on the allocated ObjectID, can you be certain the ClassID has been fully loaded?&#160; Well, usually.&#160; But I have seen cases in the past, with types stored in NGENd images, where the CLR may issue an ObjectAllocated callback <em>just before</em> the type has been fully loaded from the NGENd image.&#160; I’ve recently tried to get this to happen again but couldn’t, which probably means this is rather unlikely, but not necessarily impossible.&#160; Ugh.</p>  <p>In general, a lot of the uncertainty above comes from types stored in NGENd modules.&#160; If we actually JIT-compile a function at run-time and load the types it uses from non-NGENd modules, then you can have much greater certainty about the above types being loaded.&#160; You can even make further assumptions about locals and types from signatures of direct callees being loaded. </p>  <h2>Interlude: Remember the Unloads!</h2>  <p>Now is a good time remind you that, not only is it dangerous to inspect run-time IDs too early (i.e., before they load); it’s also dangerous to inspect run-time IDs too late (i.e., after they <strong>unload</strong>).&#160; For example, if you store ClassIDs and FunctionIDs for later use, and use them “too late”, you can easily crash the CLR.&#160; The profiling API does pretty much no validation of anything (in many cases, it’s incapable of doing so without using up significant amounts of memory to maintain lookup tables for everything).&#160; So we generally take any run-time ID that you pass to ICorProfilerInfo* methods, cast it to an internal CLR structure ptr, and go boom if the ID is bad.</p>  <p>There is no way to just ask the CLR if a FunctionID or ClassID is valid.&#160; Indeed, classes could get unloaded, and new classes loaded, and your ClassID may now refer to a totally different (valid) class.&#160; </p>  <p>You need to keep track of the unloads yourself.&#160; You are notified when run-time IDs go out of scope (today, this happens at the level of an AppDomain unloading or a collectible assembly unloading—in both cases all IDs “contained” in the unloading thing are now invalid).&#160; Once a run-time ID is out of scope, you are not allowed to pass that run-time ID back to the CLR.&#160; In fact, you should consider whether thread synchronization will be necessary in your profiler to maintain this invariant.&#160; For example, if a run-time ID gets unloaded on thread A, you’re still not allowed to pass that run-time ID back to the CLR on thread B.&#160; So you may need to block on a critical section in thread A during the *UnloadStarted / AppDomainShutdown* callbacks, to prevent them from returning to the CLR until any uses of the contained IDs in thread B are finished.</p>  <p>Take a look at the <a href="https://msdn.microsoft.com/en-us/library/bb384619.aspx">docs</a> is for more info.</p>  <h1>TypeRefs</h1>  <p>So far I’ve been talking about how to go from a typeDef to its run-time ID, and by now that should seem hard enough that we don’t need to throw a monkey wrench into the works.&#160; But the sad fact is we’re rarely lucky enough even to have a typeDef.&#160; A class’s fields or even base type, might have their types defined in <em>other modules</em>, in which case the metadata tells us the fields or base type might actually be typeRefs, and not typeDefs.&#160; Ugh.&#160; Whaddya do with that?!</p>  <p>I’ll tell you what you <em>don’t</em> do.&#160; You don’t call the enticingly-named IMetaDataImport::ResolveTypeRef.&#160; On the surface, it seems like ResolveTypeRef would do exactly what you want: starting from a typeRef, please find the referenced module and return an IMetaDataImport on that module, along with the typeDef in that target module to which the typeRef refers.&#160; But the problem lies with how ResolveTypeRef determines the module to which a typeRef refers.</p>  <p>I think ResolveTypeRef was originally designed for use at build-time (by language compilers), though I don’t know if it’s even used in that scenario anymore.&#160; It is certainly not good for use at run-time, where the loader’s decision on how to locate a referenced assembly can be arbitrarily complex.&#160; Different AppDomains in the same process may have different rules on how to locate the referenced assembly due to varying permission sets, host settings, or assembly versions.&#160; In the limit, the CLR may even <em>call into the user’s managed code</em> to dynamically influence the decision of where the referenced assembly exists (see <a href="https://msdn.microsoft.com/en-us/library/system.appdomain.assemblyresolve.aspx">AppDomain.AssemblyResolve Event</a>).</p>  <p>ResolveTypeRef doesn’t know about any of this—it was never designed to be used in a running application with all these environmental factors.&#160; It has an extremely simple (and inaccurate) algorithm to iterate through a set of “known modules”, in an arbitrary order, looking for the first one that matches the reference.&#160; What does “known modules” mean?&#160; It’s a set of modules that have been opened into the metadata system, which is NOT the same as the list of modules already loaded by the assembly loader (and thus notified to your profiler).&#160; And it’s certainly not the same as the set of modules installed onto the disk.</p>  <p>If you absolutely need to resolve refs to defs, your best bet may be to use your own algorithm which will be as accurate as you can make it, under the circumstances, and which will never try to locate a module that hasn’t been loaded yet.&#160; That means that you shouldn’t try to resolve a ref to a def if that def hasn’t actually been loaded into a type by the CLR.&#160; Consider using an algorithm similar to the following:</p>  <ol>   <li>Get the AssemblyRef from the TypeRef to get to the name, public key token and version of the assembly where the type should reside. </li>    <li>Enumerate all loaded modules that the Profiling API has notified you of (or via <a href="https://msdn.microsoft.com/en-us/library/dd490890">EnumModules</a>) (you can filter out a specific AppDomain at this point if you want). </li>    <li>In each enumerated module, search for a TypeDef with the same name and namespace as the TypeRef (IMetaDataImport::FindTypeDefByName) </li>    <li>Pay attention to <strong>type forwarding</strong>!&#160; Once you find the TypeDef, it may actually be an “exported” type, in which case you will need to follow the trail to the next module.&#160; Read toward the bottom of <a title="https://blogs.msdn.com/b/davbr/archive/2009/09/30/type-forwarding.aspx" href="https://blogs.msdn.com/b/davbr/archive/2009/09/30/type-forwarding.aspx">https://blogs.msdn.com/b/davbr/archive/2009/09/30/type-forwarding.aspx</a> for more info. </li> </ol>  <p>The above can be a little bit smarter by paying attention to what order you choose to search through the modules:</p>  <ul>   <li>First search for the TypeDef in assemblies which exactly match the name, public key token and version for the AssemblyRef. </li>    <li>If that fails, then search through assemblies matching name and public key token (where the version is higher than the one supplied – this can happen for Framework assemblies). </li>    <li>If that fails, then search through all the other assemblies </li> </ul>  <p>I must warn you that the above scheme is <strong>not tested and not supported.&#160; Use at your own risk!</strong></p>  <h1>Future</h1>  <p>Although I cannot comment on what will or will not be in any particular future version of the CLR, I can tell you that it is clear to us on the CLR team that we have work to do, to make dealing with metadata tokens and their corresponding run-time type information easier from the profiling API.&#160; After all, it doesn’t take a rocket scientist to read the above and conclude that it does take a rocket scientist to actually follow all this advice.&#160; So for now, enjoy the fact that what you do is really hard, making you difficult to replace, and thus your job all the more secure.&#160; You’re welcome.</p>  <p>&#160;</p>  <p>Special thanks to David Wrighton and Karel Zikmund, who have helped considerably with all content in this entry around the type system and metadata.</p>]]></content:encoded>
    </item>
    <item>
      <title>ReJIT: A How-To Guide</title>
      <link>https://docs.microsoft.com/archive/blogs/davbr/rejit-a-how-to-guide</link>
      <pubDate>Wed, 12 Oct 2011 18:38:38 GMT</pubDate>
      <dc:creator><![CDATA[David Broman]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davbr/2011/10/12/rejit-a-how-to-guide/</guid>
      <description><![CDATA[By now, you’ve surely downloaded your copy of the .NET 4.5 Developer Preview, and you’ve opened up...]]></description>
      <content:encoded><![CDATA[<p>By now, you’ve surely downloaded your copy of the .NET 4.5 Developer Preview, and you’ve opened up the brand-spanking new corprof.idl, and searched that file for all the new APIs available in 4.5.&#160; There’s a bunch with “ReJIT” in the name, and all you need to know is how and when to call what.</p>  <p>If none of the above makes any sense to you, you’ve probably stumbled onto the wrong blog.&#160; Indeed, both “rejit” and “ejit” have other definitions (some rather unfriendly) that are completely unrelated to the CLR.&#160; I’m talking about that ReJIT thing you do when you want to instrument and then JIT-compile code that has already been JIT-compiled before.</p>  <p>This post is organized in chronological order, telling what your profiler should be doing at the following times in the process:</p>  <ul>   <li>Startup Time </li>    <li>ModuleLoadFinished Time </li>    <li>RequestReJIT Time </li>    <li>Actual ReJIT Time </li>    <li>RequestRevert Time </li> </ul>  <p>&#160;</p>  <h2>Startup Time</h2>  <p>The first thing your profiler will do is get itself loaded on startup of a managed application—the old environment variable way, not the new attach way.&#160; I’m sure you’ve already read up on the <a href="https://blogs.msdn.com/b/davbr/archive/2011/10/10/rejit-limitations-in-net-4-5.aspx">limitations</a>!</p>  <p>Inside your profiler’s Initialize() method, it will of course call SetEventMask().&#160; In that call, your profiler must include (<strong>COR_PRF_ENABLE_REJIT | COR_PRF_DISABLE_ALL_NGEN_IMAGES</strong>) in the bitmask.&#160; COR_PRF_ENABLE_REJIT is required to use any of the ReJIT APIs later on (they’ll fail immediately otherwise).&#160; COR_PRF_DISABLE_ALL_NGEN_IMAGES causes the CLR’s assembly loader to ignore all NGENd images (even NGEN /Profile images), and thus all code will be JITted from scratch, and all classes loaded from scratch.&#160; If you try to be tricky and specify only COR_PRF_ENABLE_REJIT (without COR_PRF_DISABLE_ALL_NGEN_IMAGES), then SetEventMask will fail.&#160; Conversely, though, you’re perfectly welcome to specify COR_PRF_DISABLE_ALL_NGEN_IMAGES without COR_PRF_ENABLE_REJIT if you want.</p>  <p>At this time you will likely want to set other flags that control optimizations, particularly <strong>inlining</strong> (COR_PRF_DISABLE_OPTIMIZATIONS, COR_PRF_DISABLE_INLINING), or at least subscribe to the inlining callbacks (COR_PRF_MONITOR_JIT_COMPILATION).</p>  <p>Typically, your profiler will also create a new thread at this point, call it your “<strong>ReJIT Thread</strong>”.&#160; The expected use-case of ReJIT is to perform instrumentation “on demand”, triggered by some user action (like fiddling with dials in your profiler’s out-of-process GUI).&#160; As such, you’ll need an unmanaged thread of your own creation to receive and act on these requests from out-of-process.&#160; Perhaps you already have such a thread to service other kinds of requests.&#160; It’s perfectly acceptable for such a thread to now also act as your ReJIT Thread.</p>  <h2>ModuleLoadFinished Time</h2>  <h3></h3>  <h3></h3>  <h3>&#160;</h3>  <h3>Metadata Changes</h3>  <p>As each module loads, you will likely need to add metadata so that your future ReJITs will have the tokens they need.&#160; What you do here heavily depends on the kind of instrumentation you want to do.&#160; I’m assuming you’re doing instrumentation that adds some calls from the user code into brand new profiler helper methods you will add somewhere.&#160; If you plan to instrument mscorlib, you will likely want to add those profiler helper methods into mscorlib (remember, mscorlib is not allowed to contain an AssemblyRef that points to any other assembly!).&#160; Otherwise, perhaps you plan to ship a managed helper assembly that will sit on your user’s disk, and all your profiler helper methods will reside in this on-disk managed helper assembly.</p>  <p>So…</p>  <p>IF the module loading is mscorlib AND you plan to <strong>add your profiler helper methods</strong> into mscorlib, THEN use the metadata APIs now to add those methods.</p>  <p>IF the module loading contains methods that you might possibly ever want to instrument, THEN use the metadata APIs to <strong>add any AssemblyRefs, TypeRefs, MemberRefs, etc.</strong>, which point to your profiler helper methods, that you might possibly need later when you potentially instrument methods from this loading module.&#160; The guiding principle here is that metadata changes may be done at ModuleLoadFinished time, and not later.&#160; So you need to assume you might possibly want to ReJIT methods in the loading module <em>eventually</em>, and proactively add to the loading module whatever metadata you will eventually need (should you actually perform the ReJIT later), and add that metadata <em>now</em>, just in case.</p>  <h3>Re-Request Prior ReJITs</h3>  <p>This won’t make much sense until you’ve read the next section, but I’m placing it here to keep it in chronological order.&#160; If you’ve made a prior call to RequestReJIT for an unshared (non-domain-neutral) ModuleID, AND if you want that request to apply to the mdMethodDef that appears in all other unshared copies of the module, AND if you’re inside ModuleLoadFinished for the load of a new ModuleID that is just such a new unshared copy of the module, THEN you’ll want to explicitly call RequestReJIT on this newly-loaded ModuleID with that mdMethodDef.&#160; Note that this is optional—if you want to treat AppDomains differently and want, say, only one unshared copy of the function to be ReJITted, then you’re perfectly welcome to cause that behavior and not to call RequestReJIT on any new ModuleIDs relating to the module.&#160; Come back and re-read those last two sentences after you’ve read the next section.</p>  <h2>RequestReJIT Time</h2>  <p>Now imagine your user has turned some dial on your out-of-process GUI, to request that some functions get instrumented (or re-instrumented (or re-re-instrumented (or …))).&#160; This results in a signal sent to your in-process profiler component.&#160; Your ReJIT Thread now knows it must call <strong>RequestReJIT</strong>.&#160; You can call this API once in bulk for a list of functions to ReJIT.&#160; Note that functions are expressed in terms of ModuleID + mdMethodDef metadata tokens.&#160; A few things to note about this:</p>  <ul>   <li>You request that all instantiations of a generic function (or function on a generic class) get ReJITted with a single ModuleID + mdMethodDef pair.&#160; You cannot request a specific instantiation be ReJITted, or provide instantiation-specific IL.&#160; This is nothing new, as classic first-JIT-instrumentation should never be customized per instantiation either.&#160; But the ReJIT API is designed with this restriction in mind, as you’ll see later on. </li>    <li>ModuleID is specific to one AppDomain for unshared modules, or the SharedDomain for shared modules.&#160; Thus:      <ul>       <li>If ModuleID is shared, then your request will simultaneously apply to all domains using the shared copy of this module (and thus function) </li>        <li>If ModuleID is unshared, then your request will apply only to the single AppDomain using this module (and function) </li>        <li>Therefore, if you want this ReJIT request to apply to <em>all unshared copies</em> of this function:           <ul>           <li>You’ll need to include all such ModuleIDs in this request. </li>            <li>And… any <em>future</em> unshared loads of this module will result in new ModuleIDs.&#160; So as those loads happen, you’ll need to make further calls to RequestReJIT with the new ModuleIDs to ensure those copies get ReJITted as well. </li>            <li>This is optional, and only need be done if you truly want this ReJIT request to apply to all unshared copies of the function.&#160; You’re perfectly welcome to ReJIT only those unshared copies you want (and / or the shared copy). </li>            <li>Now you can re-read the “Re-Request Prior ReJITs” section above.&#160; :-) </li>         </ul>       </li>     </ul>   </li> </ul>  <h2></h2>  <h3>&#160;</h3>  <h3>More on AppDomains</h3>  <p>This whole shared / multiple unshared business can get confusing.&#160; So to bring it home, consider your user.&#160; If your user expresses instrumentation intent at the level of a class/method name, then you pretty much want to ReJIT every copy of that function (all unshared copies plus the shared copy).&#160; But if your user expresses instrumentation intent at the level of a class/method name <em>plus AppDomain </em>(think one single AppPool inside ASP.NET), then you’d only want to ReJIT the copy of the function that resides in the single ModuleID associated with that AppDomain.</p>  <p>The SharedDomain can make that last alternative tricky, though.&#160; Because if the ModuleID ends up belonging to the SharedDomain, and you ReJIT a method in that ModuleID, then all AppDomains that share that module will see your instrumentation (whether you want them to or not).&#160; This is due to the very nature of SharedDomain / domain-neutrality.&#160; There’s only one shared copy of this function to instrument, so if two domains share the function, they both see it, either with or without instrumentation.&#160; It doesn’t make sense to instrument the function from the point of view of only one of those two domains.</p>  <h3>Pre-ReJIT</h3>  <p>Obviously, the main coolness of RequestReJIT is that you can call it with a function that has already been JITted.&#160; But one of the niceties of RequestReJIT is that you don’t actually have to wait until a function is first JITted to use it.&#160; You can request a ReJIT on a function that has never been JITted before (I call this “Pre-ReJIT”).&#160; Indeed, with generics, there’s no way to know if all the instantiations that will ever be used in an AppDomain have been JITted or not.&#160; There may always be some important instantiation that has not been JITted yet.&#160; RequestReJIT takes all this into account as follows:</p>  <p>If a function (or generic instantiation) has already been JITted, it is marked for ReJIT next time it is called.</p>  <p>If a function (or generic instantiation) has not yet been JITted, then it is marked internally for “Pre-ReJIT”.&#160; This means that once it is called, its original (non-instrumented) IL gets JIT-compiled as usual.&#160; Immediately after, it is then ReJITted.&#160; In this way, a Pre-ReJIT request works exactly like a ReJIT request.&#160; Original IL is compiled first, and then instrumented IL is compiled later.&#160; This ensures we can easily “revert” back to the original code at a later time using the same revert mechanism.&#160; (See below.)</p>  <h2>Actual ReJIT Time</h2>  <p>You may have noticed that you have read a whole lot of words so far, but we haven’t yet provided the instrumented IL to the CLR.&#160; This is because the function hasn’t ReJITted yet.&#160; You’ve only <em>requested </em>that it be ReJITted.&#160; But the actual ReJITting happens the next time the function is called.&#160;&#160; Until then, any threads already executing inside functions you requested to be ReJITted <em>stay</em> in those functions, and don’t see the instrumented code until they return and call the functions again.&#160; Once a function is finally called for the first time after its RequestReJIT, you get some callbacks.</p>  <p>IF this is the first generic instantiation to ReJIT, for a given RequestReJIT call (or this is not a generic at all), THEN:</p>  <ul>   <li>CLR calls <strong>GetReJITParameters</strong>       <ul>       <li>This callback passes an ICorProfilerFunctionControl to your profiler.&#160; Inside your implementation of GetReJITParameters (and no later!) you may call into ICorProfilerFunctionControl to provide the instrumented IL and codegen flags that the CLR should use during the ReJIT </li>        <li>Therefore it is here where you may:          <ul>           <li>Call GetILFunctionBody </li>            <li>Add any new LocalVarSigTokens to the function’s module’s metadata.&#160; (You may not do any other metadata modifications here, though!) </li>            <li>Rewrite the IL to your specifications, passing it to ICorProfilerFunctionControl::SetILFunctionBody. </li>         </ul>       </li>        <li>You may NOT call ICorProfilerInfo::SetILFunctionBody for a ReJIT!&#160; This API still exists if you want to do classic first-JIT IL rewriting only. </li>        <li>Note that GetReJITParameters expresses the function getting compiled in terms of the ModuleID + mdMethodDef pair you previously specified to RequestReJIT, and <em>not </em>in terms of a FunctionID.&#160; As mentioned before, you may not provide instantiation-specific IL! </li>     </ul>   </li> </ul>  <p>And then, for all ReJITs (regardless of whether they are for the first generic instantiation or not):</p>  <ul>   <li>CLR calls <strong>ReJITCompilationStarted</strong> </li>    <li>CLR calls <strong>ReJITCompilationFinished</strong> </li> </ul>  <p>These callbacks express the function getting compiled in terms of FunctionID + ReJITID.&#160; (ReJITID is simply a disambiguating value so that each ReJITted version of a function instantiation can be uniquely identified via FunctionID + ReJITID.)&#160; Your profiler doesn’t need to do anything in the above callbacks if it doesn’t want to.&#160; They just notify you that the ReJIT is occurring, and get called for each generic instantiation (or non-generic) that gets ReJITted.</p>  <p>And of course, for any calls to these functions after they have been ReJITted, there are no further ReJIT compilations or callbacks to your profiler.&#160; This ReJITted version is now the current and only version for all new calls to the function.</p>  <h3>Versions</h3>  <p>Your profiler is welcome to call RequestReJIT again on these functions, and the cycle starts again.&#160; The next time a call comes in, they’ll get ReJITted again, and you’ll provide instrumented IL at that time, as usual.&#160; At any given time, only the most recently ReJITted version of a function is active and in use for new calls.&#160; But any prior calls still inside previously ReJITted (or original) versions of the function stay in that version until they return.</p>  <h2>RequestRevert Time</h2>  <p>Eventually your user may turn the dial back down, and request that the original, un-instrumented, version of the function be reinstated.&#160; When this happens, your profiler receives this signal from out-of-proc using your nifty cross-proc communication channel, and your ReJIT Thread calls <strong>RequestRevert</strong>.</p>  <p>At this time, the CLR sets the original version of the function that it JITted the first time as being the <em>current</em> version for all future calls.&#160; Any prior calls still executing in various ReJITted versions of the function remain where they’re at until they return.&#160; All new calls go into the version originally JITted (from the original IL).</p>  <p>Note that RequestRevert allows you to revert back to the original JITted IL, and not back to some previous ReJITted version of the IL.&#160; If you want to revert back to a previous ReJITted version of the IL, you’ll need to do so manually, by using RequestReJIT instead, and providing that IL explicitly to the CLR.</p>  <h2>Errors</h2>  <p>If there are any errors with performing the ReJIT, you will be notified by the dedicated callback ICorProfilerCallback4::ReJITError().&#160; Errors can happen at a couple times:</p>  <ul>   <li><u>RequestReJIT Time</u>: These are fundamental errors with the request itself.&#160; This can include bad parameter values, requesting to ReJIT dynamic (Ref.Emit) code, out of memory, etc.&#160; If errors occur here, you’ll get a callback to your implementation of ReJITError(), sandwiched inside your call to RequestReJIT on your ReJIT Thread. </li>    <li><u>Actual ReJIT Time</u>: These are errors we don’t encounter until actually trying to ReJIT the function itself.&#160; When these later errors occur, your implementation of ReJITError() is called on whatever CLR thread encountered the error. </li> </ul>  <p>You’ll note that ReJITError can provide you not only the ModuleID + mdMethodDef pair that caused the error, but optionally a FunctionID as well.&#160; Depending on the nature of the error occurred, the FunctionID may be available, so that your profiler may know the exact generic instantiation involved with the error.&#160; If FunctionID is null, then the error was fundamental to the generic function itself (and thus occurred for all instantiations).</p>  <p>&#160;</p>  <p>Ok, that about covers it on how your profiler is expected to use ReJIT.&#160; As you can see, there are several different tasks your profiler needs to do at different times to get everything right.&#160; But I trust you, you’re smart.</p>]]></content:encoded>
    </item>
    <item>
      <title>ReJIT Limitations in .NET 4.5</title>
      <link>https://docs.microsoft.com/archive/blogs/davbr/rejit-limitations-in-net-4-5</link>
      <pubDate>Mon, 10 Oct 2011 16:59:02 GMT</pubDate>
      <dc:creator><![CDATA[David Broman]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davbr/2011/10/10/rejit-limitations-in-net-4-5/</guid>
      <description><![CDATA[Anyone who’s read a newspaper in the past few weeks knows that the Profiling API in .NET 4.5 will...]]></description>
      <content:encoded><![CDATA[<p>Anyone who’s read a newspaper in the past few weeks knows that the Profiling API in .NET 4.5 will supported a limited form of ReJIT.&#160; Well, the news might not be that hot, but that’s what I tell myself.&#160; I will be discussing the feature in depth in upcoming posts, but I thought my first post should be about what ReJIT will <em>not</em> be in 4.5.&#160; Many folks who have asked for this feature have a pre-set list of sub-features in mind that <em>of course </em>will be supported by ReJIT, they think.&#160; But many of those obvious sub-features will not be available in .NET 4.5.&#160; That’s what this post is about.</p>  <h2>Is ReJIT For You?</h2>  <p>If you’re writing a monitoring tool, typically run in production, and…</p>  <p>If your tool is always on, always monitoring, but needs a way to fine-tune the amount of instrumentation it does without forcing the monitored application to restart, and…</p>  <p>If your tool instruments potentially everything, including framework assemblies like mscorlib, and you therefore disable the use of NGENd images and are willing to put up with longer startup times as a result, then…</p>  <p>ReJIT may be for you.</p>  <p>The ReJIT we plan to release in .NET 4.5 was designed with this scenario in mind.&#160; As such, there are many potential sub-features of ReJIT that will not be available, because they are not essential for this scenario.</p>  <h2>List those Limitations!</h2>  <p><u>ReJIT + Attach? No!</u></p>  <p>In order to enable ReJIT, your profiler must load at startup, and set an immutable flag in your Initialize method that enables the ReJIT functionality.</p>  <p><u>ReJIT + </u><u>NGEN? No!</u></p>  <p>In order to set that ReJIT flag I just mentioned, you must also set a new flag which completely disables the use of NGENd images.&#160; Kind of similar to the existing COR_PRF_USE_PROFILE_IMAGES flag, except even NGEN /Profile images (should they exist) will be ignored, and everything will be JITted, when you set this new flag.&#160; This includes all framework assemblies like mscorlib.</p>  <p><u>Metadata changes in ModuleLoadFinished only</u></p>  <p>If you add any new methods, AssemblyRefs, MemberRefs, etc., your metadata changes must be done during the module’s ModuleLoadFinished callback.&#160; This is not a new limitation, but it could be a surprise to some that it’s still a limitation even with ReJIT.&#160; There is an exception to this.&#160; If you need to create a new LocalVarSigToken, you may do this “late”, at ReJIT time, rather than early at ModuleLoadFinished time.</p>  <p><u>Memory reclaimed at AppDomain unload, <em>not</em> revert</u></p>  <p>ReJIT will include the ability to “revert” back to the original IL from the assembly.&#160; Doing so, however, will not reclaim any memory that was allocated to support the ReJIT (e.g., the instrumented IL, the JITted code, internal bookkeeping, etc.)&#160; This memory will be reclaimed when the containing AppDomain is unloaded.&#160; And if the code is owned by the shared domain, then, well, that memory is never reclaimed.</p>  <p><u>ReJIT inlined functions?&#160; No!</u></p>  <p>If function A inlines function B, then you cannot ReJIT function B.&#160; Well, technically you can, you just won’t see the effect of that anytime A (or another inlining caller of B) is called.&#160; The reason is that, even if you create your new, instrumented B’, A still inlined the original B.&#160; So every time A is called, the code from the original B will be executed, and your B’ will be ignored.</p>  <p>Since your profiler must be loaded at startup, you can work around this by either turning off inlining altogether, or by monitoring it (via the JITInlining callback), so you know which callers to ReJIT.&#160; In the example above, you’d have to rejit A, and could then request that the rejitted A not inline anyone, so that your new B’ would get called.&#160; Note that you’d have to track the inliners recursively, as there can be arbitrarily many levels of inlining.</p>  <p><u>ReJIT + managed debugging? No!</u></p>  <p>While not technically disabled, it is not advised or supported to run a managed debugger against a process that also has a ReJITting profiler enabled.&#160; (Native-only debugging is just fine, though.)</p>  <p>Whatever debugging support there is, is only there for you, the profiler writer, and <em>not </em>for your profiler’s users.&#160; For example, there is no way for the ReJITting profiler to adjust the instrumented IL map for rejitted code (i.e., no equivalent of SetILInstrumentedCodeMap for ReJIT).&#160; And attempting to step into or set breakpoints in rejitted code will have unpredictable results.</p>  <p>However, as a profiler writer attempting to debug your own profiler, you should have a good experience debugging other parts of the process.&#160; For example, if rejitted user code calls into an on-disk profiler IL assembly, you could set breakpoints in your profiler’s IL assembly, and step through that code.</p>  <p><u>ReJIT dynamic code?&#160; No!</u></p>  <p>Not a new limitation, but just to be explicit, profilers are not allowed to instrument dynamic code generated via the Reflection.Emit namespace, and that includes ReJIT.</p>  <h2>Why so strict?</h2>  <p>ReJIT, as originally conceived by the CLR team, involved allowing profilers to attach to running processes and then instrument arbitrary code at any time.&#160; Just that one sentence would eliminate almost all the restrictions mentioned above.&#160; So what happened?</p>  <p>Reality, that’s what.</p>  <p>Stuff takes time.&#160; And in this case a <em>lot</em> of time.&#160; Lifting just about any of the above restrictions may well have increased development or testing time, or general risk, to the point where the entire ReJIT feature might have been jeopardized.&#160; So although it was a painful process, we had to think hard about every sub-feature we wanted to support that had non-trivial cost to implement.&#160; And at the same time, we had to think about actual, real-world, end-to-end scenarios that would be using ReJIT to ensure that we ended up with something that would be useful, if not perfect.</p>  <p>So we picked the real-world use-case of production monitoring tools that use instrumentation to gather data from various servers in a data center.&#160; “Attach” isn’t interesting to many of these tools (which run all the time), but they do want to dynamically change the level of instrumentation to help diagnose problems as they come up, without having to restart the process.&#160; This scenario fit very nicely with the time we had, and so that’s what we shot for.</p>  <p>I can’t comment on what we will or will not do in any releases of the CLR after 4.5, but I like to think that ReJIT in .NET 4.5 might simply be a first step toward a richer instrumentation feature set, such that some of these limitations may eventually get lifted.&#160; We won’t know if that’s true until the time comes, though.</p>]]></content:encoded>
    </item>
    <item>
      <title>ReJIT for Realz?!</title>
      <link>https://docs.microsoft.com/archive/blogs/davbr/rejit-for-realz</link>
      <pubDate>Mon, 26 Sep 2011 10:01:24 GMT</pubDate>
      <dc:creator><![CDATA[David Broman]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davbr/2011/09/26/rejit-for-realz/</guid>
      <description><![CDATA[Yes!&#160; Check out this new video on channel 9 for the scoop:...]]></description>
      <content:encoded><![CDATA[<p>Yes!&#160; Check out this new video on channel 9 for the scoop:</p>  <p><a title="https://channel9.msdn.com/Shows/Going+Deep/CLR-45-David-Broman-Inside-Re-JIT" href="https://channel9.msdn.com/Shows/Going+Deep/CLR-45-David-Broman-Inside-Re-JIT">https://channel9.msdn.com/Shows/Going+Deep/CLR-45-David-Broman-Inside-Re-JIT</a></p>  <p>In the upcoming .NET 4.5, we do indeed plan to include a limited form of ReJIT that will allow diagnostic tools to perform IL Rewriting after the code has been JITted—by instructing the CLR, via the Profiling API, to JIT the (now instrumented) method again (i.e., <strong>ReJIT it!</strong>).</p>  <p>If you want to play with this feature, it is available in the .NET 4.5 Developer Preview.&#160; You can search for it on the Microsoft Download Center, and you’ll find the .NET 4.5-only link and the full Visual Studio 11 link:</p>  <p><a title="https://www.microsoft.com/download/en/details.aspx?id=27537" href="https://www.microsoft.com/download/en/details.aspx?id=27537">https://www.microsoft.com/download/en/details.aspx?id=27537</a>    <br /><a title="https://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;id=27543" href="https://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;id=27543">https://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;id=27543</a></p>  <p>It will be tough to try it out now, though, as we don’t have docs or samples yet.&#160; And note that there are several limitations, some of which are touched on in the video.&#160; You’ll need to look through corprof.idl and turn on your mind-reading skills to figure it out.&#160; But I will have a lot more to say about the feature and how you can use it in upcoming posts right here.</p>]]></content:encoded>
    </item>
  </channel>
</rss>