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, ...