My thoughts are many, and inline below:<br><br><div class="gmail_quote">On Thu, Jul 7, 2011 at 10:55 AM, Anderson, Todd A <span dir="ltr"><<a href="mailto:todd.a.anderson@intel.com">todd.a.anderson@intel.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div bgcolor="white" lang="EN-US" link="blue" vlink="purple"><div><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">For the past few years, my group in Intel Labs has been working on a project similar to LLVM and C--, and perhaps our experience in handling roots and stack walking could be useful in deciding how LLVM should evolve in the GC area.  Our project is called Pillar (you can see our paper "Pillar: A Parallel Implementation Language" in Languages and Compilers for Parallel Computing 2008 for a general overview).  Pillar is a generic language and runtime designed to support managed languages and parallel languages although most of our work so far has been on the managed side.  We've implemented a JVM and a functional language on top of Pillar so it has evidenced some generality.<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">In the Pillar language, we have a generalized ref (similar to llvm.gcroot) data type that encompases different kinds of pointers and types into the managed heap.  This could be regular pointers, a couple varieties of interior pointers, or user-defined pointer types.  The underlying compiler then generates per-callsite stack maps.  Those stack maps can indicate when a live ref (local or parameter) is at a known offset from the start of the frame and can also indicate when a live ref is present in a register.<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u></span></p></div></div></blockquote><div><br></div><div>I assume that by interior pointer you mean a pointer to the inside of another object?</div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div bgcolor="white" lang="EN-US" link="blue" vlink="purple"><div><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">If we want to enumerate the refs of a call stack, we call a runtime function, prtYoungestActivation, and that gives us back a stack iterator for the sequence of activations.  The iterator contains the value for esp and pointers to the memory locations where ebp, eip, edi, esi, and ebx were last saved to the stack.  (For architectures other than 32-bit x86, the register-specific contents of the activation would of course be defined differently.)  In the eip case, this is saved for every activation as part of the call sequence and so provides you with the ability to determine which call site you are at.  The other registers may have been saved by the current frame or a subsequent frame.  The stack iterator also contains a virtual frame number that basically allows an unwinder to see logical activations instead of physical activations that may combine multiple logical activations via inlining.<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> </span></p></div></div></blockquote><div>That all makes sense.</div><div><br></div><div>I would say that your framework is at a somewhat higher level than I would expect LLVM to support - by that, I mean that ideally it should be possible to use the primitives that LLVM supplies to build exactly what you have described. My own use case has slightly different requirements, and as a result I could not adopt your framework as it is - but I see no reason why I should not be able to use the same LLVM primitives to build what I need.</div>

<div><br></div><div>The main difference has to do with the handling of disjoint types in my language. For example, if I declare a variable using the following syntax:</div><div><br></div><div><font class="Apple-style-span" face="'courier new', monospace">   var a:String or float or int;</font></div>

<div><br></div><div>What the compiler generates is a data structure that looks like this (as it would appear in C):</div><div><br></div><div><font class="Apple-style-span" face="'courier new', monospace">   struct {</font></div>

<div><font class="Apple-style-span" face="'courier new', monospace">     int disc:2; // 0 = String, 1 = int, 2 = float</font></div><div><font class="Apple-style-span" face="'courier new', monospace">     union {</font></div>

<div><font class="Apple-style-span" face="'courier new', monospace">       String * s;</font></div><div><font class="Apple-style-span" face="'courier new', monospace">       int i;</font></div><div><font class="Apple-style-span" face="'courier new', monospace">       float f;</font></div>

<div><font class="Apple-style-span" face="'courier new', monospace">     };</font></div><div><font class="Apple-style-span" face="'courier new', monospace">   };</font></div><div><br></div><div>The garbage collector needs to examine the 'disc' field in order to know whether to trace 's' or not. The way I handle this is by treating the entire structure as a root, rather than just the pointer field, so that what the garbage collector sees is a pointer to the beginning of the struct.</div>

<div><br></div><div>I suspect that register maps wouldn't be able to handle this case very well. SInce the data structure can't fit into a single register, it would have to be 'sliced' - half in one register and half in another - and the register map would need some way to communicate to the collector which half of the struct is in which register. (Or worse, what if only one half was in a register and the other half on the stack?) I'm guessing that the right answer is "don't do that" - meaning, don't allow this data structure to be sliced in that way, at least not during a safe point.</div>

<div> <div bgcolor="white" lang="EN-US" link="blue" vlink="purple"><div><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">You can then call another runtime function, prtEnumerateRootsOfActivation, to ask for the roots associated with the given stack iterator's current activation to be enumerated.  To this function, you pass a PrtRseInfo struct that contains a callback that gets invoked once per live ref found and a opaque environment variable passed (unexamined) onto the callback function.  To go to the next activation on the call stack, you then call the runtime's prtNextActivation.  There are routines to determine when you've got to the bottom of the call stack as well.  In addition, there are routines for performing other (non-GC) operations the stack iterator's activation, such as looking up data associated with the SPAN construct (taken from C--) or exception handlers.<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><br></span></p>In my own case, I don't have an iterator for roots within a single activation, rather I have a static data structure that describes how to find all of the roots within the call frame. One of my design goals is to minimize the number of function calls required to trace a pointer, so the different parts of my code accept whole stack maps as arguments instead of single pointers.</div>

<div><br></div><div>However, the LLVM approach to generating stack maps is flexible enough to handle either case - your GCStrategy plugin gets a list of all stack roots for each safe point, and you can transform that into whatever data structures you need.</div>

<div><br><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">We have a couple of associated constructs in this regard.  The first is the concept of code regions.  We can define regions of code and define different owners for each region.  A typical configuration is for most code to be in a region associated with our compiler, another region for code implemented in the Pillar runtime, and another region for code implemented in our GC.  You first register a code info manager with the Pillar runtime and then associate regions of code with that manager.  When you register, you provide a set of callback functions to enumerate roots, unwind to the next activation, etc.  So, the Pillar compiler's code info manager uses a callback that consults the previously generated stack maps in order to enumerate roots.  The GC could optimize its barriers and provide its own code info manager to handle enumerating roots in those barriers.<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">Thoughts?<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">Todd<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">Below are the relevant portions from our runtime’s include files.<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/* This is essentially a pointer-sized integer. */<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">typedef char *PrtRegister;<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal">

<span style="font-size:11.0pt;color:#1F497D">/* These are used to document function parameters to indicate whether they are IN, OUT, or INOUT. */<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">#define PRT_IN<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">#define PRT_OUT<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">#define PRT_INOUT<u></u><u></u></span></p><p class="MsoNormal">

<span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/*<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> ***********************************************************************************************<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> * Basic constants, definitions, and types.<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> ***********************************************************************************************<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> */<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/* These are tags that the GC uses to interpret roots that are enumerated.<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">   Some tags require additional parameters that need to be passed in as well.<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">   The interface includes a single argument that can be used directly for a<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">   single parameter, or treated as an array or struct pointer if multiple<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">   parameters are required.<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">   Several tags are predefined for the compiler's benefit, but the high-level<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">   language is free to use them as well.<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">     "Default": The root points to the canonical object address (usually the base).<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                No additional parameters are used, and the argument is ignored.<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">     "Offset": The root is at a known offset from the canonical object address.<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">               Subtract the int-type parameter from the root to get the canonical<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">               object address.  Example: the root points to a specific field of<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">               an object.<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">     "Base": The root is related to an object whose canonical address is found as<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">             the ref-type parameter.  Example: the root points to some array element<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">             contained within the object.<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">   Any tag value starting from UserDefined and beyond can be defined and used<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">   by the high-level language and its associated GC implementation. <u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">  */<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">typedef enum { PrtGcTagDefault = 0, PrtGcTagOffset = 1, PrtGcTagBase = 2, PrtGcTagUserDefined = 3 } PrtGcTag;<u></u><u></u></span></p><p class="MsoNormal">

<span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/* Points to executable code.  It is "unsigned char *" so that arithmetic is valid. */<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">typedef unsigned char *PrtCodeAddress;<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/* Points to a sequence of data bytes.  It is "unsigned char *" so that arithmetic is valid. */<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">typedef unsigned char *PrtDataPointer;<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/* Forward declarations of nonexistent structures, to avoid typedef'ing to void*. */<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">struct PrtCimSpecificDataStruct;<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">struct PrtCodeInfoManagerStruct;<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/*<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> * The context for stack frames that is used during stack walking. We use pointers in place of <u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> * direct values to support root set enumeration.<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> */<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">struct PrtStackIterator <u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">{<u></u><u></u></span></p><p class="MsoNormal">

<span style="font-size:11.0pt;color:#1F497D">    /* Stack pointer, eip, and frame pointer */<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">    PrtRegister  esp;<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">    PrtRegister *ebpPtr;<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">    PrtCodeAddress *eipPtr;<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">    /* Callee-save registers */<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">    PrtRegister *ediPtr;<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">    PrtRegister *esiPtr;<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">    PrtRegister *ebxPtr;<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">    /* The Pillar compiler may inline several "virtual" frames into a single "physical" frame.<u></u><u></u></span></p><p class="MsoNormal">

<span style="font-size:11.0pt;color:#1F497D">       However, the stack iterator should maintain the illusion that no inlining was done.<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">       This field keeps track of which virtual frame we are at within the physical frame.<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">       The value 0 means the newest, innermost frame, and the value is incremented when<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">       doing a virtual unwind within the same physical frame. */<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">    unsigned virtualFrameNumber;<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">}; /* struct PrtStackIterator */<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/*<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> * Type of procedures called once for each enumerated root. "rootAddr" is the address of a pointer-sized field<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> * containing either a reference to a heap object or a managed pointer. "env" is an (opaque to Pillar) value <u></u><u></u></span></p><p class="MsoNormal">

<span style="font-size:11.0pt;color:#1F497D"> * that the client passed in a PrtRseInfo structure in the call<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> */<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">typedef void (*PrtRseCallback)(void *env, void **rootAddr, PrtGcTag tag, void *parameter);<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">struct PrtRseInfo <u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">{<u></u><u></u></span></p><p class="MsoNormal">

<span style="font-size:11.0pt;color:#1F497D">    PrtRseCallback callback;  /* invoked for each enumerated root */<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">    void *env;                /* opaque value to be passed in each call to the callback function */<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">}; /* struct PrtRseInfo */<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal">

<span style="font-size:11.0pt;color:#1F497D">/*<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> **********************************************************************************************************<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> * Stack iteration functions<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> **********************************************************************************************************<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> */<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/* <u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> * Create a stack iterator for the current task. "si" points to client-allocated storage.<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> */<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">void prtYoungestActivation(PRT_OUT struct PrtStackIterator *si);<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/* Go to the activation previous to (older than) the current one. */<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">void prtNextActivation(PRT_INOUT struct PrtStackIterator *si);<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/* Return True iff no activations remain on the stack. */<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">#define prtIsActivationPastEnd(si) (((si)->eipPtr == NULL)? PrtTrue : PrtFalse)<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/* Return the ip for the current activation. */<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">#define prtGetActivationIP(si) ((PrtCodeAddress)((si)->eipPtr ? *(si)->eipPtr : 0))<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/* Convenience function for updating all writable fields of a stack iterator at once.<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">   The advantage of using this consistently is that if the PrtStackIterator<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">   ever changes, this function can be changed accordingly, and all calls to<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">   it can be easily found and modified.<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> */<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">void prtSetStackIteratorFields(PRT_OUT struct PrtStackIterator *context,<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                               PRT_IN PrtCodeAddress *eipPtr,<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                               PRT_IN PrtRegister esp,<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                               PRT_IN PrtRegister *ebxPtr,<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                               PRT_IN PrtRegister *ebpPtr,<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                               PRT_IN PrtRegister *esiPtr,<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                               PRT_IN PrtRegister *ediPtr,<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                               PRT_IN unsigned virtualFrameNumber);<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/* <u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> * Returns the value associated with the smallest span tagged with "key" and containing the program point <u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> * where "si" is suspended.  Returns (PrtDataPointer)NULL if there is no such span. <u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> */ <u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">PrtDataPointer prtGetSpanDescriptor(PRT_IN struct PrtStackIterator *si, PRT_IN unsigned key);<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/* Enumerate the roots of a frame given by the specified stack iterator. */<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">void prtEnumerateRootsOfActivation(PRT_IN struct PrtStackIterator *si, PRT_IN struct PrtRseInfo *rootSetInfo);<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/* <u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> ***********************************************************************************************<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> * Code Info Manager functions  <u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> ***********************************************************************************************<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> */<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">typedef struct PrtCodeInfoManagerStruct *PrtCodeInfoManager;<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/* Type of client-specified data that a client can associate with each code range with a prtCodeInfoManager. */<u></u><u></u></span></p><p class="MsoNormal">

<span style="font-size:11.0pt;color:#1F497D">typedef struct PrtCimSpecificDataStruct *PrtCimSpecificDataType;<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> /* <u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">  * A set of callback functions implemented by a producer of managed code (e.g., a JIT or static compiler) that the PRT<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">  * can call as part of its implementation of stack walking, root set enumeration, exception handling, etc. These are<u></u><u></u></span></p><p class="MsoNormal">

<span style="font-size:11.0pt;color:#1F497D">  * used to define a CodeInfoManager.<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">  */<u></u><u></u></span></p><p class="MsoNormal">

<span style="font-size:11.0pt;color:#1F497D">struct PrtCodeInfoManagerFunctions {<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">    /* Returns a string describing the current frame. */<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">    char *  ( *cimGetStringForFrame)(PRT_IN struct PrtStackIterator *si,<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                                          PRT_OUT char *buffer,<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                                          PRT_IN size_t bufferSize,<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                                          PRT_IN PrtCimSpecificDataType opaqueData);<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">    /* Modifies si to hold information about the frame previous to the current one. Returns True if this was successful,<u></u><u></u></span></p><p class="MsoNormal">

<span style="font-size:11.0pt;color:#1F497D">       and False if not. opaqueData is the same as the opaqueData that was passed to Pillar when the CIM registered <u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">       this code region. */<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">    void  ( *cimGetPreviousFrame)(PRT_INOUT struct PrtStackIterator *si, <u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                                        PRT_IN    PrtCimSpecificDataType opaqueData);<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">    /* Enumerates the live GC roots of the current stack frame.  The activation is guaranteed to be<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">       suspended at a call site. */<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">    void  ( *cimEnumerateRoots)(PRT_IN struct PrtStackIterator *si, <u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                                      PRT_IN struct PrtRseInfo *rootSetInfo, <u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                                      PRT_IN PrtCimSpecificDataType opaqueData);<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">    /* Returns the value associated with the smallest span tagged with "key" and containing the program point <u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">       where "si" is suspended.  "opaqueData" is the same data that the CIM passed to Pillar when it registered <u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">       the code region containing si's program point.  Returns (PrtDataPointer)NULL if there is no such span. */<u></u><u></u></span></p><p class="MsoNormal">

<span style="font-size:11.0pt;color:#1F497D">    PrtDataPointer  ( *cimGetSpanDescriptor)(PRT_IN struct PrtStackIterator *si, <u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                                             PRT_IN unsigned key, <u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                                             PRT_IN PrtCimSpecificDataType opaqueData);<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">}; /* struct PrtCodeInfoManagerFunctions */<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/* Creates a new PrtCodeInfoManager and registers a set of callback functions belonging to it. */<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">PrtCodeInfoManager prtRegisterCodeInfoManager(PRT_IN const char *theCimName, PRT_IN struct PrtCodeInfoManagerFunctions theCimFns);<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">/*<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> * Register the block of code in [start..end] with the given PrtCodeInfoManager. <u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> * Returns True on success and False on failure (e.g., if the code's region overlaps that of already-registered code).<u></u><u></u></span></p><p class="MsoNormal">

<span style="font-size:11.0pt;color:#1F497D"> * The opaqueData parameter is associated with this code region and passed back to the Cim during each of the calls <u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> * to the Cim for this code region.<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> */<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"> void prtAddCodeRegion(PRT_IN PrtCodeInfoManager theCim, <u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                       PRT_IN PrtCodeAddress start, <u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                       PRT_IN PrtCodeAddress end, <u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D">                       PRT_IN PrtCimSpecificDataType opaqueData);<u></u><u></u></span></p><p class="MsoNormal"><span style="font-size:11.0pt;color:#1F497D"><u></u> <u></u></span></p>

</div></div><br>_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:LLVMdev@cs.uiuc.edu">LLVMdev@cs.uiuc.edu</a>         <a href="http://llvm.cs.uiuc.edu" target="_blank">http://llvm.cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br><br></div></div>-- <br>-- Talin<br>