Initial version of the inline tree
authorAndy Ayers <andya@microsoft.com>
Wed, 6 Jan 2016 17:49:23 +0000 (09:49 -0800)
committerAndy Ayers <andya@microsoft.com>
Thu, 7 Jan 2016 20:05:35 +0000 (12:05 -0800)
commitb6ed20b4c0ba3bf877a305c44864a32786e905ea
treeba8ce037c548b4d832a1b0874b39859fc3d4a45a
parente8d94bca0185e621c20b2923f2536729eedebef9
Initial version of the inline tree

Extend `inlExpLst` to to describe the full inlining tree in a method, with a
corresponding dump method.

Add a top-level tree node to serve as the root of the tree. Set this as the
inline context for all top-level expressions. Update the code that links in new
nodes when there is a successful inline to build the tree links. Since the
child list is extended by a prepend and candidates are currently visited in
lexical (increasing "local" IL offset) order, the child list ends up reversed.
The dumper prints the list entries from back to front to compensate so the tree
display reflects lexical order.

Capture IL offset to help in identifying call sites. Note this is incomplete and
offets are often missing copies of the parent's offset. Will work on improving
this subsequently.

Update the depth check to return the depth. This is currently only used in
diagnostic messages.

Remove some unused inlining-related data members from the compiler class. Cache
the `JitPrintInlinedMethods` config value and use it to dump the tree when
inlining is done, if there were any inlines.

The jit traditionally (and probably inadvertently) allowed one level of
recursive inlining. Added a test case showing how this can happen.

Because there is now a top-level inlining context, the recursion check can now
potentially detect and block these recursive inlines. Support legacy behavior
for now by setting `ixlCode` to `nullptr` in the top-level record.

This change should be no diff.

Sample output:
```
Inlines into Enumerable:Where(ref,ref):ref
  [IL=3] Error:ArgumentNull(ref):ref
  [IL=17] Error:ArgumentNull(ref):ref
  [IL=?] WhereArrayIterator`1:.ctor(ref,ref):this
    [IL=?] Iterator`1:.ctor():this
      [IL=?] Object:.ctor():this
      [IL=?] Environment:get_CurrentManagedThreadId():int
        [IL=?] Thread:get_CurrentThread():ref
  [IL=?] WhereListIterator`1:.ctor(ref,ref):this
    [IL=?] Iterator`1:.ctor():this
      [IL=?] Object:.ctor():this
      [IL=?] Environment:get_CurrentManagedThreadId():int
        [IL=?] Thread:get_CurrentThread():ref
  [IL=?] WhereEnumerableIterator`1:.ctor(ref,ref):this
    [IL=?] Iterator`1:.ctor():this
      [IL=?] Object:.ctor():this
      [IL=?] Environment:get_CurrentManagedThreadId():int
        [IL=?] Thread:get_CurrentThread():ref
```
Sample showing the recursive inline:
```
Inlines into Fact:factRx(int,int,int,int):int
  [IL=6] Fact:factRx(int,int,int,int):int
```
src/jit/block.cpp
src/jit/block.h
src/jit/compiler.h
src/jit/flowgraph.cpp
tests/src/JIT/opt/Inline/tests/fact.cs [new file with mode: 0644]
tests/src/JIT/opt/Inline/tests/fact.csproj [new file with mode: 0644]