Traversing the Execution Engine Stack

Once a Thread instance has been associated with an underlying PAL thread, managed code can be executed on it. One sequence that will kick off the execution of managed code can be found in MethodDesc::Call, which we discussed in Chapter 5 (and which can be found in sscli/clr/src/vm/method.cpp). The implementation of Call relies on the fact that two important tracking structures will be on the stack before JIT-compiled code is executed: an exception handler that will wrap the managed code (which we will see in great detail later in the "Handling Exceptions" section of this chapter), and a chain of execution engine frames (“frames,” for short—see the sidebar "Frames, Frames, Frames“) that will be used to annotate portions of the stack with runtime information produced by the execution engine.

Execution engine frames do not exist in the regions of the stack that are generated by the JIT compiler, since the execution engine already has intimate knowledge about how this code will use the stack and can read the resulting stack data directly, without using frames as markers. But the multiple calling conventions, exception paths, and other nasty details that must be understood when interpreting stack layouts for code not produced by the JIT compiler, or for JIT helper code, are what make frames a necessary part of the SSCLI execution strategy. The intricacies of tracing the stack, as well as the tight requirements placed on stack layout by security, ...

Get Shared Source CLI Essentials now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.