7f35dd0ad87ed6970110f81345f5c1a92b628f33
[platform/upstream/coreclr.git] / src / vm / frames.h
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 // FRAMES.H
5
6
7 //
8 // These C++ classes expose activation frames to the rest of the EE.
9 // Activation frames are actually created by JIT-generated or stub-generated
10 // code on the machine stack. Thus, the layout of the Frame classes and
11 // the JIT/Stub code generators are tightly interwined.
12 //
13 // IMPORTANT: Since frames are not actually constructed by C++,
14 // don't try to define constructor/destructor functions. They won't get
15 // called.
16 //
17 // IMPORTANT: Not all methods have full-fledged activation frames (in
18 // particular, the JIT may create frameless methods.) This is one reason
19 // why Frame doesn't expose a public "Next()" method: such a method would
20 // skip frameless method calls. You must instead use one of the
21 // StackWalk methods.
22 //
23 //
24 // The following is the hierarchy of frames:
25 //
26 //    Frame                     - the root class. There are no actual instances
27 //    |                           of Frames.
28 //    |
29 //    +-GCFrame                 - this frame doesn't represent a method call.
30 //    |                           it's sole purpose is to let the EE gc-protect
31 //    |                           object references that it is manipulating.
32 //    |
33 //    +- FaultingExceptionFrame - this frame was placed on a method which faulted
34 //    |                           to save additional state information
35 //    |
36 #ifdef FEATURE_HIJACK
37 //    |
38 //    +-HijackFrame             - if a method's return address is hijacked, we
39 //    |                           construct one of these to allow crawling back
40 //    |                           to where the return should have gone.
41 //    |
42 //    +-ResumableFrame          - this abstract frame provides the context necessary to
43 //    | |                         allow garbage collection during handling of
44 //    | |                         a resumable exception (e.g. during edit-and-continue,
45 //    | |                         or under GCStress4).
46 //    | |
47 //    | +-RedirectedThreadFrame - this frame is used for redirecting threads during suspension
48 //    |
49 #endif // FEATURE_HIJACK
50 //    |
51 //    |
52 //    |
53 //    +-InlinedCallFrame        - if a call to unmanaged code is hoisted into
54 //    |                           a JIT'ted caller, the calling method keeps
55 //    |                           this frame linked throughout its activation.
56 //    |
57 //    +-HelperMethodFrame       - frame used allow stack crawling inside jit helpers and fcalls
58 //    | |
59 //    + +-HelperMethodFrame_1OBJ- reports additional object references
60 //    | |
61 //    + +-HelperMethodFrame_2OBJ- reports additional object references
62 //    | |
63 //    + +-HelperMethodFrame_3OBJ- reports additional object references
64 //    | |
65 //    + +-HelperMethodFrame_PROTECTOBJ - reports additional object references
66 //    |
67 //    +-TransitionFrame         - this abstract frame represents a transition from
68 //    | |                         one or more nested frameless method calls
69 //    | |                         to either a EE runtime helper function or
70 //    | |                         a framed method.
71 //    | |
72 //    | +-StubHelperFrame       - for instantiating stubs that need to grow stack arguments
73 //    | |
74 //    | +-SecureDelegateFrame   - represents a call Delegate.Invoke for secure delegate
75 //    |   |
76 //    |   +-MulticastFrame      - this frame protects arguments to a MulticastDelegate
77 //    |                           Invoke() call while calling each subscriber.
78 //    |
79 //    | +-FramedMethodFrame     - this abstract frame represents a call to a method
80 //    |   |                       that generates a full-fledged frame.
81 //    |   |
82 #ifdef FEATURE_COMINTEROP
83 //    |   |
84 //    |   +-ComPlusMethodFrame  - represents a CLR to COM call using the generic worker
85 //    |   |
86 #endif //FEATURE_COMINTEROP
87 //    |   |
88 //    |   +-PInvokeCalliFrame   - protects arguments when a call to GetILStubForCalli is made
89 //    |   |                       to get or create IL stub for an unmanaged CALLI
90 //    |   |
91 //    |   +-PrestubMethodFrame  - represents a call to a prestub
92 //    |   |
93 //    |   +-StubDispatchFrame   - represents a call into the virtual call stub manager
94 //    |   |
95 //    |   |
96 //    |   +-ExternalMethodFrame  - represents a call from an ExternalMethdThunk
97 //    |   |
98 //    |   +-TPMethodFrame       - for calls on transparent proxy
99 //    |
100 //    +-UnmanagedToManagedFrame - this frame represents a transition from
101 //    | |                         unmanaged code back to managed code. It's
102 //    | |                         main functions are to stop COM+ exception
103 //    | |                         propagation and to expose unmanaged parameters.
104 //    | |
105 #ifdef FEATURE_COMINTEROP
106 //    | |
107 //    | +-ComMethodFrame        - this frame represents a transition from
108 //    |   |                       com to com+
109 //    |   |
110 //    |   +-ComPrestubMethodFrame - prestub frame for calls from COM to CLR
111 //    |
112 #endif //FEATURE_COMINTEROP
113 #ifdef _TARGET_X86_
114 //    | +-UMThkCallFrame        - this frame represents an unmanaged->managed
115 //    |                           transition through N/Direct
116 #endif
117 //    |
118 //    +-ContextTransitionFrame  - this frame is used to mark an appdomain transition
119 //    |
120 //    |
121 //    +-TailCallFrame           - padding for tailcalls
122 //    |
123 //    +-ProtectByRefsFrame
124 //    |
125 //    +-ProtectValueClassFrame
126 //    |
127 //    +-DebuggerClassInitMarkFrame - marker frame to indicate that "class init" code is running
128 //    |
129 //    +-DebuggerSecurityCodeMarkFrame - marker frame to indicate that security code is running
130 //    |
131 //    +-DebuggerExitFrame - marker frame to indicate that a "break" IL instruction is being executed
132 //    |
133 //    +-DebuggerU2MCatchHandlerFrame - marker frame to indicate that native code is going to catch and 
134 //    |                                swallow a managed exception
135 //    |
136 #ifdef DEBUGGING_SUPPORTED
137 //    +-FuncEvalFrame         - frame for debugger function evaluation
138 #endif // DEBUGGING_SUPPORTED
139 //    |
140 //    |
141 //    +-ExceptionFilterFrame - this frame wraps call to exception filter
142 //
143 //------------------------------------------------------------------------
144 #if 0
145 //------------------------------------------------------------------------
146
147 This is the list of Interop stubs & transition helpers with information
148 regarding what (if any) Frame they used and where they were set up:
149
150 P/Invoke:
151  JIT inlined: The code to call the method is inlined into the caller by the JIT.
152     InlinedCallFrame is erected by the JITted code.
153  Requires marshaling: The stub does not erect any frames explicitly but contains
154     an unmanaged CALLI which turns it into the JIT inlined case.
155
156 Delegate over a native function pointer:
157  The same as P/Invoke but the raw JIT inlined case is not present (the call always
158  goes through an IL stub).
159
160 Calli:
161  The same as P/Invoke.
162  PInvokeCalliFrame is erected in stub generated by GenerateGetStubForPInvokeCalli
163  before calling to GetILStubForCalli which generates the IL stub. This happens only
164  the first time a call via the corresponding VASigCookie is made.
165
166 ClrToCom:
167  Late-bound or eventing: The stub is generated by GenerateGenericComplusWorker
168     (x86) or exists statically as GenericComPlusCallStub[RetBuffArg] (64-bit),
169     and it erects a ComPlusMethodFrame frame.
170  Early-bound: The stub does not erect any frames explicitly but contains an
171     unmanaged CALLI which turns it into the JIT inlined case.
172
173 ComToClr:
174   Normal stub:
175  Interpreted: The stub is generated by ComCall::CreateGenericComCallStub
176     (in ComToClrCall.cpp) and it erects a ComMethodFrame frame.
177 Prestub:
178  The prestub is ComCallPreStub (in ComCallableWrapper.cpp) and it erects
179     a ComPrestubMethodFrame frame.
180
181 Reverse P/Invoke (used for C++ exports & fixups as well as delegates
182 obtained from function pointers):
183   Normal stub:
184  x86: The stub is generated by UMEntryThunk::CompileUMThunkWorker
185     (in DllImportCallback.cpp) and it is frameless. It calls directly
186     the managed target or to IL stub if marshaling is required.
187  non-x86: The stub exists statically as UMThunkStub and calls to IL stub.
188 Prestub:
189  The prestub is generated by GenerateUMThunkPrestub (x86) or exists statically
190     as TheUMEntryPrestub (64-bit), and it erects an UMThkCallFrame frame.
191
192 Reverse P/Invoke AppDomain selector stub:
193  The asm helper is IJWNOADThunkJumpTarget (in asmhelpers.asm) and it is frameless.
194
195 //------------------------------------------------------------------------
196 #endif // 0
197 //------------------------------------------------------------------------
198
199 #ifndef FRAME_ABSTRACT_TYPE_NAME
200 #define FRAME_ABSTRACT_TYPE_NAME(frameType)
201 #endif
202 #ifndef FRAME_TYPE_NAME
203 #define FRAME_TYPE_NAME(frameType)
204 #endif
205
206 FRAME_ABSTRACT_TYPE_NAME(FrameBase)
207 FRAME_ABSTRACT_TYPE_NAME(Frame)
208 FRAME_ABSTRACT_TYPE_NAME(TransitionFrame)
209 #ifdef FEATURE_HIJACK
210 FRAME_TYPE_NAME(ResumableFrame)
211 FRAME_TYPE_NAME(RedirectedThreadFrame)
212 #endif // FEATURE_HIJACK
213 FRAME_TYPE_NAME(FaultingExceptionFrame)
214 #ifdef DEBUGGING_SUPPORTED
215 FRAME_TYPE_NAME(FuncEvalFrame)
216 #endif // DEBUGGING_SUPPORTED
217 FRAME_TYPE_NAME(HelperMethodFrame)
218 FRAME_TYPE_NAME(HelperMethodFrame_1OBJ)
219 FRAME_TYPE_NAME(HelperMethodFrame_2OBJ)
220 FRAME_TYPE_NAME(HelperMethodFrame_3OBJ)
221 FRAME_TYPE_NAME(HelperMethodFrame_PROTECTOBJ)
222 FRAME_ABSTRACT_TYPE_NAME(FramedMethodFrame)
223 FRAME_TYPE_NAME(SecureDelegateFrame)
224 FRAME_TYPE_NAME(MulticastFrame)
225 FRAME_ABSTRACT_TYPE_NAME(UnmanagedToManagedFrame)
226 #ifdef FEATURE_COMINTEROP
227 FRAME_TYPE_NAME(ComMethodFrame)
228 FRAME_TYPE_NAME(ComPlusMethodFrame)
229 FRAME_TYPE_NAME(ComPrestubMethodFrame)
230 #endif // FEATURE_COMINTEROP
231 FRAME_TYPE_NAME(PInvokeCalliFrame)
232 #ifdef FEATURE_HIJACK
233 FRAME_TYPE_NAME(HijackFrame)
234 #endif // FEATURE_HIJACK
235 FRAME_TYPE_NAME(PrestubMethodFrame)
236 FRAME_TYPE_NAME(StubDispatchFrame)
237 FRAME_TYPE_NAME(ExternalMethodFrame)
238 #ifdef FEATURE_READYTORUN
239 FRAME_TYPE_NAME(DynamicHelperFrame)
240 #endif
241 #if !defined(_TARGET_X86_)
242 FRAME_TYPE_NAME(StubHelperFrame)
243 #endif
244 FRAME_TYPE_NAME(GCFrame)
245 #ifdef FEATURE_INTERPRETER
246 FRAME_TYPE_NAME(InterpreterFrame)
247 #endif // FEATURE_INTERPRETER
248 FRAME_TYPE_NAME(ProtectByRefsFrame)
249 FRAME_TYPE_NAME(ProtectValueClassFrame)
250 FRAME_TYPE_NAME(DebuggerClassInitMarkFrame)
251 FRAME_TYPE_NAME(DebuggerSecurityCodeMarkFrame)
252 FRAME_TYPE_NAME(DebuggerExitFrame)
253 FRAME_TYPE_NAME(DebuggerU2MCatchHandlerFrame)
254 #ifdef _TARGET_X86_
255 FRAME_TYPE_NAME(UMThkCallFrame)
256 #endif
257 FRAME_TYPE_NAME(InlinedCallFrame)
258 FRAME_TYPE_NAME(ContextTransitionFrame)
259 FRAME_TYPE_NAME(TailCallFrame)
260 FRAME_TYPE_NAME(ExceptionFilterFrame)
261 #if defined(_DEBUG)
262 FRAME_TYPE_NAME(AssumeByrefFromJITStack)
263 #endif // _DEBUG
264
265 #undef FRAME_ABSTRACT_TYPE_NAME
266 #undef FRAME_TYPE_NAME
267
268 //------------------------------------------------------------------------
269
270 #ifndef __frames_h__
271 #define __frames_h__
272 #if defined(_MSC_VER) && defined(_TARGET_X86_) && !defined(FPO_ON)
273 #pragma optimize("y", on)   // Small critical routines, don't put in EBP frame 
274 #define FPO_ON 1
275 #define FRAMES_TURNED_FPO_ON 1
276 #endif
277
278 #include "util.hpp"
279 #include "vars.hpp"
280 #include "regdisp.h"
281 #include "object.h"
282 #include <stddef.h>
283 #include "siginfo.hpp"
284 #include "method.hpp"
285 #include "stackwalk.h"
286 #include "stubmgr.h"
287 #include "gms.h"
288 #include "threads.h"
289 #include "callingconvention.h"
290
291 // Forward references
292 class Frame;
293 class FieldMarshaler;
294 class FramedMethodFrame;
295 typedef VPTR(class FramedMethodFrame) PTR_FramedMethodFrame;
296 struct HijackArgs;
297 class UMEntryThunk;
298 class UMThunkMarshInfo;
299 class Marshaler;
300 struct ResolveCacheElem;
301 #if defined(DACCESS_COMPILE)
302 class DacDbiInterfaceImpl;
303 #endif // DACCESS_COMPILE
304 #ifdef FEATURE_COMINTEROP
305 class ComMethodFrame;
306 class ComCallMethodDesc;
307 #endif // FEATURE_COMINTEROP
308
309 // Note: the value (-1) is used to generate the largest possible pointer value: this keeps frame addresses
310 // increasing upward. Because we want to ensure that we don't accidentally change this, we have a C_ASSERT
311 // in stackwalk.cpp. Since it requires constant values as args, we need to define FRAME_TOP in two steps.
312 // First we define FRAME_TOP_VALUE which we'll use when we do the compile-time check, then we'll define 
313 // FRAME_TOP in terms of FRAME_TOP_VALUE. Defining FRAME_TOP as a PTR_Frame means we don't have to type cast
314 // whenever we compare it to a PTR_Frame value (the usual use of the value). 
315 #define FRAME_TOP_VALUE  ~0     // we want to say -1 here, but gcc has trouble with the signed value
316 #define FRAME_TOP (PTR_Frame(FRAME_TOP_VALUE))
317
318 #ifndef DACCESS_COMPILE
319
320 #if defined(FEATURE_PAL) && !defined(CROSSGEN_COMPILE)
321
322 #define DEFINE_DTOR(klass)                      \
323     public:                                     \
324         virtual ~klass() { PopIfChained(); }
325
326 #else
327
328 #define DEFINE_DTOR(klass)
329
330 #endif // FEATURE_PAL && !CROSSGEN_COMPILE
331
332 #define DEFINE_VTABLE_GETTER(klass)             \
333     public:                                     \
334         static TADDR GetMethodFrameVPtr() {     \
335             LIMITED_METHOD_CONTRACT;            \
336             klass boilerplate(false);           \
337             return *((TADDR*)&boilerplate);     \
338         }                                       \
339         klass(bool dummy) { LIMITED_METHOD_CONTRACT; }
340
341 #define DEFINE_VTABLE_GETTER_AND_DTOR(klass)    \
342         DEFINE_VTABLE_GETTER(klass)             \
343         DEFINE_DTOR(klass)
344
345 #define DEFINE_VTABLE_GETTER_AND_CTOR(klass)    \
346         DEFINE_VTABLE_GETTER(klass)             \
347     protected:                                  \
348         klass() { LIMITED_METHOD_CONTRACT; }
349
350 #define DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(klass)    \
351         DEFINE_VTABLE_GETTER_AND_DTOR(klass)             \
352     protected:                                           \
353         klass() { LIMITED_METHOD_CONTRACT; }
354
355 #else
356
357 #define DEFINE_VTABLE_GETTER(klass)             \
358     public:                                     \
359         static TADDR GetMethodFrameVPtr() {     \
360             LIMITED_METHOD_CONTRACT;            \
361             return klass::VPtrTargetVTable();   \
362         }                                       \
363
364 #define DEFINE_VTABLE_GETTER_AND_DTOR(klass)    \
365         DEFINE_VTABLE_GETTER(klass)             \
366
367 #define DEFINE_VTABLE_GETTER_AND_CTOR(klass)    \
368         DEFINE_VTABLE_GETTER(klass)             \
369
370 #define DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(klass)    \
371         DEFINE_VTABLE_GETTER_AND_CTOR(klass)             \
372
373 #endif // #ifndef DACCESS_COMPILE
374
375 //-----------------------------------------------------------------------------
376 // For reporting on types of frames at runtime.
377 class FrameTypeName 
378
379 public:
380     TADDR vtbl; 
381     PTR_CSTR name; 
382 };
383 typedef DPTR(FrameTypeName) PTR_FrameTypeName;
384
385 //-----------------------------------------------------------------------------
386 // Frame depends on the location of its vtable within the object. This
387 // superclass ensures that the vtable for Frame objects is in the same
388 // location under both MSVC and GCC.
389 //-----------------------------------------------------------------------------
390
391 class FrameBase
392 {
393     VPTR_BASE_VTABLE_CLASS(FrameBase)
394
395 public:
396     FrameBase() {LIMITED_METHOD_CONTRACT; }
397
398     virtual void GcScanRoots(promote_func *fn, ScanContext* sc) {
399         LIMITED_METHOD_CONTRACT;
400         // Nothing to protect
401     }
402     
403 #ifdef DACCESS_COMPILE
404     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) = 0;
405 #endif
406 };
407
408 //------------------------------------------------------------------------
409 // Frame defines methods common to all frame types. There are no actual
410 // instances of root frames.
411 //------------------------------------------------------------------------
412
413 class Frame : public FrameBase
414 {
415     friend class CheckAsmOffsets;
416 #ifdef DACCESS_COMPILE
417     friend void Thread::EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
418 #endif
419
420     VPTR_ABSTRACT_VTABLE_CLASS(Frame, FrameBase)
421
422 public:
423
424     //------------------------------------------------------------------------
425     // Special characteristics of a frame
426     //------------------------------------------------------------------------
427     enum FrameAttribs {
428         FRAME_ATTR_NONE = 0,
429         FRAME_ATTR_EXCEPTION = 1,           // This frame caused an exception
430         FRAME_ATTR_OUT_OF_LINE = 2,         // The exception out of line (IP of the frame is not correct)
431         FRAME_ATTR_FAULTED = 4,             // Exception caused by Win32 fault
432         FRAME_ATTR_RESUMABLE = 8,           // We may resume from this frame
433         FRAME_ATTR_CAPTURE_DEPTH_2 = 0x10,  // This is a helperMethodFrame and the capture occurred at depth 2
434         FRAME_ATTR_EXACT_DEPTH = 0x20,      // This is a helperMethodFrame and a jit helper, but only crawl to the given depth
435         FRAME_ATTR_NO_THREAD_ABORT = 0x40,  // This is a helperMethodFrame that should not trigger thread aborts on entry
436     };
437     virtual unsigned GetFrameAttribs()
438     {
439         LIMITED_METHOD_DAC_CONTRACT;
440         return FRAME_ATTR_NONE;
441     }
442
443     //------------------------------------------------------------------------
444     // Performs cleanup on an exception unwind
445     //------------------------------------------------------------------------
446 #ifndef DACCESS_COMPILE
447     virtual void ExceptionUnwind()
448     {
449         // Nothing to do here.
450         LIMITED_METHOD_CONTRACT;
451     }
452 #endif
453
454     // Should be overridden to return TRUE if the frame contains register
455     // state of the caller.
456     virtual BOOL NeedsUpdateRegDisplay()
457     {
458         return FALSE;
459     }
460
461     //------------------------------------------------------------------------
462     // Is this a frame used on transition to native code from jitted code?
463     //------------------------------------------------------------------------
464     virtual BOOL IsTransitionToNativeFrame()
465     {
466         LIMITED_METHOD_CONTRACT;
467         return FALSE;
468     }
469
470     virtual MethodDesc *GetFunction()
471     {
472         LIMITED_METHOD_DAC_CONTRACT;
473         return NULL;
474     }
475
476     virtual Assembly *GetAssembly()
477     {
478         WRAPPER_NO_CONTRACT;
479         MethodDesc *pMethod = GetFunction();
480         if (pMethod != NULL)
481             return pMethod->GetModule()->GetAssembly();
482         else
483             return NULL;
484     }
485
486     // indicate the current X86 IP address within the current method
487     // return 0 if the information is not available
488     virtual PTR_BYTE GetIP()
489     {
490         LIMITED_METHOD_CONTRACT;
491         return NULL;
492     }
493
494     // DACCESS: GetReturnAddressPtr should return the
495     // target address of the return address in the frame.
496     virtual TADDR GetReturnAddressPtr()
497     {
498         LIMITED_METHOD_DAC_CONTRACT;
499         return NULL;
500     }
501
502     virtual PCODE GetReturnAddress()
503     {
504         WRAPPER_NO_CONTRACT;
505         TADDR ptr = GetReturnAddressPtr();
506         return (ptr != NULL) ? *PTR_PCODE(ptr) : NULL;
507     }
508
509     AppDomain *GetReturnDomain()
510     {
511         LIMITED_METHOD_CONTRACT;
512         return NULL;
513     }
514
515 #ifndef DACCESS_COMPILE
516     virtual Object **GetReturnExecutionContextAddr()
517     {
518         LIMITED_METHOD_CONTRACT;
519         return NULL;
520     }
521
522     void SetReturnAddress(TADDR val)
523     {
524         WRAPPER_NO_CONTRACT;
525         TADDR ptr = GetReturnAddressPtr();
526         _ASSERTE(ptr != NULL);
527         *(TADDR*)ptr = val;
528     }
529 #endif // #ifndef DACCESS_COMPILE
530
531     PTR_GSCookie GetGSCookiePtr()
532     {
533         WRAPPER_NO_CONTRACT;
534         return dac_cast<PTR_GSCookie>(dac_cast<TADDR>(this) + GetOffsetOfGSCookie());
535     }
536
537     static int GetOffsetOfGSCookie()
538     {
539         LIMITED_METHOD_DAC_CONTRACT;
540         return -(int)sizeof(GSCookie);
541     }
542
543     static bool HasValidVTablePtr(Frame * pFrame);
544     static PTR_GSCookie SafeGetGSCookiePtr(Frame * pFrame);
545     static void Init();
546
547     // Callers, note that the REGDISPLAY parameter is actually in/out. While
548     // UpdateRegDisplay is generally used to fill out the REGDISPLAY parameter, some
549     // overrides (e.g., code:ResumableFrame::UpdateRegDisplay) will actually READ what
550     // you pass in. So be sure to pass in a valid or zeroed out REGDISPLAY.
551     virtual void UpdateRegDisplay(const PREGDISPLAY)
552     {
553         LIMITED_METHOD_DAC_CONTRACT;
554         return;
555     }
556
557     //------------------------------------------------------------------------
558     // Debugger support
559     //------------------------------------------------------------------------
560
561
562 public:
563     enum ETransitionType
564     {
565         TT_NONE,
566         TT_M2U, // we can safely cast to a FramedMethodFrame
567         TT_U2M, // we can safely cast to a UnmanagedToManagedFrame
568         TT_AppDomain, // transitioniting between AppDomains.
569         TT_InternalCall, // calling into the CLR (ecall/fcall).
570     };
571
572     // Get the type of transition.
573     // M-->U, U-->M
574     virtual ETransitionType GetTransitionType()
575     {
576         LIMITED_METHOD_DAC_CONTRACT;
577         return TT_NONE;
578     }
579
580     enum
581     {
582         TYPE_INTERNAL,
583         TYPE_ENTRY,
584         TYPE_EXIT,
585         TYPE_CONTEXT_CROSS,
586         TYPE_INTERCEPTION,
587         TYPE_SECURITY,
588         TYPE_CALL,
589         TYPE_FUNC_EVAL,
590         TYPE_MULTICAST,
591         
592         // HMFs and derived classes should use this so the profiling API knows it needs
593         // to ensure HMF-specific lazy initialization gets done w/out re-entering to the host.
594         TYPE_HELPER_METHOD_FRAME,
595
596         TYPE_COUNT
597     };
598
599     virtual int GetFrameType()
600     {
601         LIMITED_METHOD_DAC_CONTRACT;
602         return TYPE_INTERNAL;
603     };
604
605     // When stepping into a method, various other methods may be called.
606     // These are refererred to as interceptors. They are all invoked
607     // with frames of various types. GetInterception() indicates whether
608     // the frame was set up for execution of such interceptors
609
610     enum Interception
611     {
612         INTERCEPTION_NONE,
613         INTERCEPTION_CLASS_INIT,
614         INTERCEPTION_EXCEPTION,
615         INTERCEPTION_CONTEXT,
616         INTERCEPTION_SECURITY,
617         INTERCEPTION_PRESTUB,
618         INTERCEPTION_OTHER,
619
620         INTERCEPTION_COUNT
621     };
622
623     virtual Interception GetInterception()
624     {
625         LIMITED_METHOD_DAC_CONTRACT;
626         return INTERCEPTION_NONE;
627     }
628
629     // Return information about an unmanaged call the frame
630     // will make.
631     // ip - the unmanaged routine which will be called
632     // returnIP - the address in the stub which the unmanaged routine
633     //            will return to.
634     // returnSP - the location returnIP is pushed onto the stack
635     //            during the call.
636     //
637     virtual void GetUnmanagedCallSite(TADDR* ip,
638                                       TADDR* returnIP,
639                                       TADDR* returnSP)
640     {
641         LIMITED_METHOD_CONTRACT;
642         if (ip)
643             *ip = NULL;
644
645         if (returnIP)
646             *returnIP = NULL;
647
648         if (returnSP)
649             *returnSP = NULL;
650     }
651
652     // Return where the frame will execute next - the result is filled
653     // into the given "trace" structure.  The frame is responsible for
654     // detecting where it is in its execution lifetime.
655     virtual BOOL TraceFrame(Thread *thread, BOOL fromPatch,
656                             TraceDestination *trace, REGDISPLAY *regs)
657     {
658         LIMITED_METHOD_CONTRACT;
659         LOG((LF_CORDB, LL_INFO10000,
660              "Default TraceFrame always returns false.\n"));
661         return FALSE;
662     }
663
664 #ifdef DACCESS_COMPILE
665     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
666     {
667         WRAPPER_NO_CONTRACT;
668         DAC_ENUM_VTHIS();
669
670         // Many frames store a MethodDesc pointer in m_Datum
671         // so pick that up automatically.
672         MethodDesc* func = GetFunction();
673         if (func)
674         {
675             func->EnumMemoryRegions(flags);
676         }
677
678         // Include the NegSpace
679         GSCookie * pGSCookie = GetGSCookiePtr();
680         _ASSERTE(FitsIn<ULONG32>(PBYTE(pGSCookie) - PBYTE(this)));
681         ULONG32 negSpaceSize = static_cast<ULONG32>(PBYTE(pGSCookie) - PBYTE(this));
682         DacEnumMemoryRegion(dac_cast<TADDR>(this) - negSpaceSize, negSpaceSize);
683     }
684 #endif
685
686     //---------------------------------------------------------------
687     // Expose key offsets and values for stub generation.
688     //---------------------------------------------------------------
689     static BYTE GetOffsetOfNextLink()
690     {
691         WRAPPER_NO_CONTRACT;
692         size_t ofs = offsetof(class Frame, m_Next);
693         _ASSERTE(FitsInI1(ofs));
694         return (BYTE)ofs;
695     }
696
697     // get your VTablePointer (can be used to check what type the frame is)
698     TADDR GetVTablePtr()
699     {
700         LIMITED_METHOD_DAC_CONTRACT;
701         return VPTR_HOST_VTABLE_TO_TADDR(*(LPVOID*)this);
702     }
703
704 #if defined(_DEBUG) && !defined(DACCESS_COMPILE)
705     virtual BOOL Protects(OBJECTREF *ppObjectRef)
706     {
707         LIMITED_METHOD_CONTRACT;
708         return FALSE;
709     }
710 #endif
711
712 #ifndef DACCESS_COMPILE
713     // Link and Unlink this frame
714     VOID Push();
715     VOID Pop();
716     VOID Push(Thread *pThread);
717     VOID Pop(Thread *pThread);
718 #endif // DACCESS_COMPILE
719
720 #ifdef _DEBUG_IMPL
721     void Log();
722     static BOOL ShouldLogTransitions() { WRAPPER_NO_CONTRACT; return LoggingOn(LF_STUBS, LL_INFO1000000); }
723     static void __stdcall LogTransition(Frame* frame);
724     void LogFrame(int LF, int LL);       // General purpose logging.
725     void LogFrameChain(int LF, int LL);  // Log the whole chain.
726     virtual const char* GetFrameTypeName() {return NULL;}
727     static PTR_CSTR GetFrameTypeName(TADDR vtbl);
728 #endif
729
730     //------------------------------------------------------------------------
731     // Returns the address of a security object or
732     // null if there is no space for an object on this frame.
733     //------------------------------------------------------------------------
734     virtual OBJECTREF *GetAddrOfSecurityDesc()
735     {
736         LIMITED_METHOD_CONTRACT;
737         return NULL;
738     }
739
740 private:
741     // Pointer to the next frame up the stack.
742
743 protected:
744     PTR_Frame m_Next;        // offset +4
745
746 public:
747     PTR_Frame PtrNextFrame() { return m_Next; }
748
749 private:
750     // Because JIT-method activations cannot be expressed as Frames,
751     // everyone must use the StackCrawler to walk the frame chain
752     // reliably. We'll expose the Next method only to the StackCrawler
753     // to prevent mistakes.
754     /*<TODO>@NICE: Restrict "friendship" again to the StackWalker method;
755       not done because of circular dependency with threads.h</TODO>
756     */
757     //        friend Frame* Thread::StackWalkFrames(PSTACKWALKFRAMESCALLBACK pCallback, VOID *pData);
758     friend class Thread;
759     friend void CrawlFrame::GotoNextFrame();
760     friend class StackFrameIterator;
761     friend class TailCallFrame;
762     friend class AppDomain;
763     friend VOID RealCOMPlusThrow(OBJECTREF
764 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
765         , CorruptionSeverity severity
766 #endif // FEATURE_CORRUPTING_EXCEPTIONS
767         );
768     friend FCDECL0(VOID, JIT_StressGC);
769 #ifdef _DEBUG
770     friend LONG WINAPI CLRVectoredExceptionHandlerShim(PEXCEPTION_POINTERS pExceptionInfo);
771 #endif
772 #ifdef _WIN64
773     friend Thread * __stdcall JIT_InitPInvokeFrame(InlinedCallFrame *pFrame, PTR_VOID StubSecretArg);
774 #endif
775 #ifdef WIN64EXCEPTIONS
776     friend class ExceptionTracker;
777 #endif
778 #if defined(DACCESS_COMPILE)
779     friend class DacDbiInterfaceImpl;
780 #endif // DACCESS_COMPILE
781
782     PTR_Frame  Next()
783     {
784         LIMITED_METHOD_DAC_CONTRACT;
785         return m_Next;
786     }
787
788 protected:
789     // Frame is considered an abstract class: this protected constructor
790     // causes any attempt to instantiate one to fail at compile-time.
791     Frame()
792     : m_Next(dac_cast<PTR_Frame>(nullptr))
793     { 
794         LIMITED_METHOD_CONTRACT;
795     }
796
797 #if defined(FEATURE_PAL) && !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
798     virtual ~Frame() { LIMITED_METHOD_CONTRACT; }
799
800     void PopIfChained();
801 #endif // FEATURE_PAL && !DACCESS_COMPILE && !CROSSGEN_COMPILE
802 };
803
804
805 //-----------------------------------------------------------------------------
806 // This frame provides context for a frame that
807 // took an exception that is going to be resumed.
808 //
809 // It is necessary to create this frame if garbage
810 // collection may happen during handling of the
811 // exception.  The FRAME_ATTR_RESUMABLE flag tells
812 // the GC that the preceding frame needs to be treated
813 // like the top of stack (with the important implication that
814 // caller-save-regsiters will be potential roots).
815 //-----------------------------------------------------------------------------
816 #ifdef FEATURE_HIJACK
817 //-----------------------------------------------------------------------------
818
819 class ResumableFrame : public Frame
820 {
821     VPTR_VTABLE_CLASS(ResumableFrame, Frame)
822
823 public:
824 #ifndef DACCESS_COMPILE
825     ResumableFrame(T_CONTEXT* regs) {
826         LIMITED_METHOD_CONTRACT;
827         m_Regs = regs;
828     }
829 #endif
830
831     virtual TADDR GetReturnAddressPtr();
832
833     virtual BOOL NeedsUpdateRegDisplay()
834     {
835         return TRUE;
836     }
837
838     virtual void UpdateRegDisplay(const PREGDISPLAY pRD);
839
840     virtual unsigned GetFrameAttribs() {
841         LIMITED_METHOD_DAC_CONTRACT;
842         return FRAME_ATTR_RESUMABLE;    // Treat the next frame as the top frame.
843     }
844
845     T_CONTEXT *GetContext() {
846         LIMITED_METHOD_DAC_CONTRACT;
847         return (m_Regs);
848     }
849
850 #ifdef DACCESS_COMPILE
851     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
852     {
853         WRAPPER_NO_CONTRACT;
854         Frame::EnumMemoryRegions(flags);
855         m_Regs.EnumMem();
856     }
857 #endif
858
859 protected:
860     PTR_CONTEXT m_Regs;
861
862     // Keep as last entry in class
863     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(ResumableFrame)
864 };
865
866
867 //-----------------------------------------------------------------------------
868 // RedirectedThreadFrame
869 //-----------------------------------------------------------------------------
870
871 class RedirectedThreadFrame : public ResumableFrame
872 {
873     VPTR_VTABLE_CLASS(RedirectedThreadFrame, ResumableFrame)
874     VPTR_UNIQUE(VPTR_UNIQUE_RedirectedThreadFrame)
875
876 public:
877 #ifndef DACCESS_COMPILE
878     RedirectedThreadFrame(T_CONTEXT *regs) : ResumableFrame(regs) {
879         LIMITED_METHOD_CONTRACT;
880     }
881
882     virtual void ExceptionUnwind();
883 #endif
884
885     // Keep as last entry in class
886     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(RedirectedThreadFrame)
887 };
888
889 typedef DPTR(RedirectedThreadFrame) PTR_RedirectedThreadFrame;
890
891 inline BOOL ISREDIRECTEDTHREAD(Thread * thread)
892 {
893     WRAPPER_NO_CONTRACT;
894     return (thread->GetFrame() != FRAME_TOP &&
895             thread->GetFrame()->GetVTablePtr() ==
896             RedirectedThreadFrame::GetMethodFrameVPtr());
897 }
898
899 inline T_CONTEXT * GETREDIRECTEDCONTEXT(Thread * thread)
900 {
901     WRAPPER_NO_CONTRACT;
902     _ASSERTE(ISREDIRECTEDTHREAD(thread));
903     return dac_cast<PTR_RedirectedThreadFrame>(thread->GetFrame())->GetContext();
904 }
905
906 //------------------------------------------------------------------------
907 #else // FEATURE_HIJACK
908 //------------------------------------------------------------------------
909
910 inline BOOL ISREDIRECTEDTHREAD(Thread * thread) { LIMITED_METHOD_CONTRACT; return FALSE; }
911 inline CONTEXT * GETREDIRECTEDCONTEXT(Thread * thread) { LIMITED_METHOD_CONTRACT; return (CONTEXT*) NULL; }
912
913 //------------------------------------------------------------------------
914 #endif // FEATURE_HIJACK
915 //------------------------------------------------------------------------
916 // This frame represents a transition from one or more nested frameless
917 // method calls to either a EE runtime helper function or a framed method.
918 // Because most stackwalks from the EE start with a full-fledged frame,
919 // anything but the most trivial call into the EE has to push this
920 // frame in order to prevent the frameless methods inbetween from
921 // getting lost.
922 //------------------------------------------------------------------------
923
924 class TransitionFrame : public Frame
925 {
926     VPTR_ABSTRACT_VTABLE_CLASS(TransitionFrame, Frame)
927
928 public:
929     virtual TADDR GetTransitionBlock() = 0;
930
931     // DACCESS: GetReturnAddressPtr should return the
932     // target address of the return address in the frame.
933     virtual TADDR GetReturnAddressPtr()
934     {
935         LIMITED_METHOD_DAC_CONTRACT;
936         return GetTransitionBlock() + TransitionBlock::GetOffsetOfReturnAddress();
937     }
938
939     //---------------------------------------------------------------
940     // Get the "this" object.
941     //---------------------------------------------------------------
942     OBJECTREF GetThis()
943     {
944         WRAPPER_NO_CONTRACT;
945         Object* obj = PTR_Object(*PTR_TADDR(GetAddrOfThis()));
946         return ObjectToOBJECTREF(obj);
947     }
948
949     PTR_OBJECTREF GetThisPtr()
950     {
951         WRAPPER_NO_CONTRACT;
952         return PTR_OBJECTREF(GetAddrOfThis());
953     }
954
955     //---------------------------------------------------------------
956     // Get the extra info for shared generic code.
957     //---------------------------------------------------------------
958     PTR_VOID GetParamTypeArg();
959
960     //---------------------------------------------------------------
961     // Gets value indicating whether the generic parameter type
962     // argument should be supressed.
963     //---------------------------------------------------------------
964     virtual BOOL SuppressParamTypeArg()
965     {
966         return FALSE;
967     }
968
969 protected:  // we don't want people using this directly
970     //---------------------------------------------------------------
971     // Get the address of the "this" object. WARNING!!! Whether or not "this"
972     // is gc-protected is depends on the frame type!!!
973     //---------------------------------------------------------------
974     TADDR GetAddrOfThis();
975
976 public:
977     //---------------------------------------------------------------
978     // For vararg calls, return cookie.
979     //---------------------------------------------------------------
980     VASigCookie *GetVASigCookie();
981
982     CalleeSavedRegisters *GetCalleeSavedRegisters()
983     {
984         LIMITED_METHOD_DAC_CONTRACT;
985         return dac_cast<PTR_CalleeSavedRegisters>(
986             GetTransitionBlock() + TransitionBlock::GetOffsetOfCalleeSavedRegisters());
987     }
988
989     ArgumentRegisters *GetArgumentRegisters()
990     {
991         LIMITED_METHOD_DAC_CONTRACT;
992         return dac_cast<PTR_ArgumentRegisters>(
993             GetTransitionBlock() + TransitionBlock::GetOffsetOfArgumentRegisters());
994     }
995
996     TADDR GetSP()
997     {
998         LIMITED_METHOD_DAC_CONTRACT;
999         return GetTransitionBlock() + sizeof(TransitionBlock);
1000     }
1001
1002     virtual BOOL NeedsUpdateRegDisplay()
1003     {
1004         return TRUE;
1005     }
1006
1007     virtual void UpdateRegDisplay(const PREGDISPLAY);
1008 #ifdef _TARGET_X86_
1009     void UpdateRegDisplayHelper(const PREGDISPLAY, UINT cbStackPop);
1010 #endif
1011
1012 #if defined (_DEBUG) && !defined (DACCESS_COMPILE)
1013     virtual BOOL Protects(OBJECTREF *ppORef);
1014 #endif //defined (_DEBUG) && defined (DACCESS_COMPILE)
1015
1016     // For use by classes deriving from FramedMethodFrame.
1017     void PromoteCallerStack(promote_func* fn, ScanContext* sc);
1018
1019     void PromoteCallerStackHelper(promote_func* fn, ScanContext* sc,
1020         MethodDesc * pMD, MetaSig *pmsig);
1021
1022     void PromoteCallerStackUsingGCRefMap(promote_func* fn, ScanContext* sc, PTR_BYTE pGCRefMap);
1023
1024 #ifdef _TARGET_X86_
1025     UINT CbStackPopUsingGCRefMap(PTR_BYTE pGCRefMap);
1026 #endif
1027
1028 protected:
1029     TransitionFrame()
1030     {
1031         LIMITED_METHOD_CONTRACT;
1032     }
1033 };
1034
1035 //-----------------------------------------------------------------------
1036 // TransitionFrames for exceptions
1037 //-----------------------------------------------------------------------
1038
1039 // The define USE_FEF controls how this class is used.  Look for occurances
1040 //  of USE_FEF.
1041
1042 class FaultingExceptionFrame : public Frame
1043 {
1044     friend class CheckAsmOffsets;
1045
1046 #ifndef WIN64EXCEPTIONS
1047 #ifdef _TARGET_X86_
1048     DWORD                   m_Esp;
1049     CalleeSavedRegisters    m_regs;
1050     TADDR                   m_ReturnAddress;
1051 #else  // _TARGET_X86_
1052     #error "Unsupported architecture"
1053 #endif // _TARGET_X86_
1054 #else // WIN64EXCEPTIONS
1055     BOOL                    m_fFilterExecuted;  // Flag for FirstCallToHandler
1056     TADDR                   m_ReturnAddress;
1057     T_CONTEXT               m_ctx;
1058 #endif // !WIN64EXCEPTIONS
1059
1060     VPTR_VTABLE_CLASS(FaultingExceptionFrame, Frame)
1061
1062 public:
1063 #ifndef DACCESS_COMPILE
1064     FaultingExceptionFrame() {
1065         LIMITED_METHOD_CONTRACT;
1066     }
1067 #endif
1068
1069     virtual TADDR GetReturnAddressPtr()
1070     {
1071         LIMITED_METHOD_DAC_CONTRACT;
1072         return PTR_HOST_MEMBER_TADDR(FaultingExceptionFrame, this, m_ReturnAddress);
1073     }
1074
1075     void Init(T_CONTEXT *pContext);
1076     void InitAndLink(T_CONTEXT *pContext);
1077
1078     Interception GetInterception()
1079     {
1080         LIMITED_METHOD_DAC_CONTRACT;
1081         return INTERCEPTION_EXCEPTION;
1082     }
1083
1084     unsigned GetFrameAttribs()
1085     {
1086         LIMITED_METHOD_DAC_CONTRACT;
1087         return FRAME_ATTR_EXCEPTION | FRAME_ATTR_FAULTED;
1088     }
1089
1090 #ifndef WIN64EXCEPTIONS
1091     CalleeSavedRegisters *GetCalleeSavedRegisters()
1092     {
1093 #ifdef _TARGET_X86_
1094         LIMITED_METHOD_DAC_CONTRACT;
1095         return &m_regs;
1096 #else
1097         PORTABILITY_ASSERT("GetCalleeSavedRegisters");
1098 #endif // _TARGET_X86_
1099     }
1100 #endif // WIN64EXCEPTIONS
1101
1102 #ifdef WIN64EXCEPTIONS
1103     T_CONTEXT *GetExceptionContext ()
1104     {
1105         LIMITED_METHOD_CONTRACT;
1106         return &m_ctx;
1107     }
1108
1109     BOOL * GetFilterExecutedFlag()
1110     {
1111         LIMITED_METHOD_CONTRACT;
1112         return &m_fFilterExecuted;
1113     }
1114 #endif // WIN64EXCEPTIONS
1115
1116     virtual BOOL NeedsUpdateRegDisplay()
1117     {
1118         return TRUE;
1119     }
1120
1121     virtual void UpdateRegDisplay(const PREGDISPLAY);
1122
1123     // Keep as last entry in class
1124     DEFINE_VTABLE_GETTER_AND_DTOR(FaultingExceptionFrame)
1125 };
1126
1127 //-----------------------------------------------------------------------
1128 // Frame for debugger function evaluation
1129 //
1130 // This frame holds a ptr to a DebuggerEval object which contains a copy
1131 // of the thread's context at the time it was hijacked for the func
1132 // eval.
1133 //
1134 // UpdateRegDisplay updates all registers inthe REGDISPLAY, not just
1135 // the callee saved registers, because we can hijack for a func eval
1136 // at any point in a thread's execution.
1137 //
1138 //-----------------------------------------------------------------------
1139
1140 #ifdef DEBUGGING_SUPPORTED
1141 class DebuggerEval;
1142 typedef DPTR(class DebuggerEval) PTR_DebuggerEval;
1143
1144 class FuncEvalFrame : public Frame
1145 {
1146     VPTR_VTABLE_CLASS(FuncEvalFrame, Frame)
1147
1148     TADDR           m_ReturnAddress;
1149     PTR_DebuggerEval m_pDebuggerEval;
1150
1151     BOOL            m_showFrame;
1152
1153 public:
1154 #ifndef DACCESS_COMPILE
1155     FuncEvalFrame(DebuggerEval *pDebuggerEval, TADDR returnAddress, BOOL showFrame)
1156     {
1157         LIMITED_METHOD_CONTRACT;
1158         m_pDebuggerEval = pDebuggerEval;
1159         m_ReturnAddress = returnAddress;
1160         m_showFrame = showFrame;
1161     }
1162 #endif
1163
1164     virtual BOOL IsTransitionToNativeFrame()
1165     {
1166         LIMITED_METHOD_CONTRACT;
1167         return FALSE;
1168     }
1169
1170     virtual int GetFrameType()
1171     {
1172         LIMITED_METHOD_DAC_CONTRACT;
1173         return TYPE_FUNC_EVAL;
1174     }
1175
1176     virtual unsigned GetFrameAttribs();
1177
1178     virtual BOOL NeedsUpdateRegDisplay()
1179     {
1180         return TRUE;
1181     }
1182
1183     virtual void UpdateRegDisplay(const PREGDISPLAY);
1184
1185     virtual DebuggerEval * GetDebuggerEval();
1186
1187     virtual TADDR GetReturnAddressPtr();
1188
1189     /*
1190      * ShowFrame
1191      *
1192      * Returns if this frame should be returned as part of a stack trace to a debugger or not.
1193      *
1194      */
1195     BOOL ShowFrame()
1196     {
1197         LIMITED_METHOD_CONTRACT;
1198
1199         return m_showFrame;
1200     }
1201
1202     // Keep as last entry in class
1203     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(FuncEvalFrame)
1204 };
1205
1206 typedef VPTR(FuncEvalFrame) PTR_FuncEvalFrame;
1207 #endif // DEBUGGING_SUPPORTED
1208
1209 //----------------------------------------------------------------------------------------------
1210 // A HelperMethodFrame is created by jit helper (Modified slightly it could be used
1211 // for native routines).   This frame just does the callee saved register fixup. 
1212 // It does NOT protect arguments; you must use GCPROTECT or one of the HelperMethodFrame
1213 // subclases. (see JitInterface for sample use, YOU CAN'T RETURN WHILE IN THE PROTECTED STATE!)
1214 //----------------------------------------------------------------------------------------------
1215
1216 class HelperMethodFrame : public Frame
1217 {
1218     VPTR_VTABLE_CLASS(HelperMethodFrame, Frame);
1219
1220 public:
1221 #ifndef DACCESS_COMPILE
1222     // Lazy initialization of HelperMethodFrame.  Need to
1223     // call InsureInit to complete initialization
1224     // If this is an FCall, the first param is the entry point for the FCALL.
1225     // The MethodDesc will be looked up form this (lazily), and this method
1226     // will be used in stack reporting, if this is not an FCall pass a 0
1227     FORCEINLINE HelperMethodFrame(void* fCallFtnEntry, unsigned attribs = 0)
1228     {
1229         WRAPPER_NO_CONTRACT;
1230         // Most of the initialization is actually done in HelperMethodFrame::Push()
1231         INDEBUG(memset(&m_Attribs, 0xCC, sizeof(HelperMethodFrame) - offsetof(HelperMethodFrame, m_Attribs));)
1232         m_Attribs = attribs;
1233         m_FCallEntry = (TADDR)fCallFtnEntry;
1234     }
1235 #endif // DACCESS_COMPILE
1236
1237     virtual int GetFrameType()
1238     {
1239         LIMITED_METHOD_DAC_CONTRACT;
1240         return TYPE_HELPER_METHOD_FRAME;
1241     };
1242
1243     virtual PCODE GetReturnAddress()
1244     {
1245         LIMITED_METHOD_DAC_CONTRACT;
1246
1247         if (!m_MachState.isValid())
1248         {
1249 #if defined(DACCESS_COMPILE)
1250             MachState unwoundState;
1251             InsureInit(false, &unwoundState);
1252             return unwoundState.GetRetAddr();
1253 #else  // !DACCESS_COMPILE
1254             _ASSERTE(!"HMF's should always be initialized in the non-DAC world.");
1255             return NULL;
1256
1257 #endif // !DACCESS_COMPILE
1258         }
1259
1260         return m_MachState.GetRetAddr();
1261     }
1262
1263     virtual MethodDesc* GetFunction();
1264
1265     virtual BOOL NeedsUpdateRegDisplay()
1266     {
1267         return TRUE;
1268     }
1269
1270     virtual void UpdateRegDisplay(const PREGDISPLAY);
1271
1272     virtual Interception GetInterception()
1273     {
1274         WRAPPER_NO_CONTRACT;
1275         LIMITED_METHOD_DAC_CONTRACT;
1276         if (GetFrameAttribs() & FRAME_ATTR_EXCEPTION)
1277             return(INTERCEPTION_EXCEPTION);
1278         return(INTERCEPTION_NONE);
1279     }
1280
1281     virtual ETransitionType GetTransitionType()
1282     {
1283         LIMITED_METHOD_DAC_CONTRACT;
1284         return TT_InternalCall;
1285     }
1286
1287 #ifdef _DEBUG
1288     void SetAddrOfHaveCheckedRestoreState(BOOL* pDoneCheck)
1289     {
1290         m_pDoneCheck = pDoneCheck;
1291     }
1292
1293     BOOL HaveDoneConfirmStateCheck()
1294     {
1295         LIMITED_METHOD_CONTRACT;
1296         _ASSERTE(m_pDoneCheck != NULL);
1297         return *m_pDoneCheck;
1298     }
1299
1300     void SetHaveDoneConfirmStateCheck()
1301     {
1302         LIMITED_METHOD_CONTRACT;
1303         _ASSERTE(m_pDoneCheck != NULL);
1304         *m_pDoneCheck = TRUE;
1305     }
1306 #endif
1307
1308     virtual unsigned GetFrameAttribs()
1309     {
1310         LIMITED_METHOD_DAC_CONTRACT;
1311         return(m_Attribs);
1312     }
1313
1314 #ifdef DACCESS_COMPILE
1315     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
1316     {
1317         WRAPPER_NO_CONTRACT;
1318         Frame::EnumMemoryRegions(flags);
1319     }
1320 #endif
1321
1322 #ifndef DACCESS_COMPILE
1323     void Push();
1324     void Pop();
1325
1326     FORCEINLINE void Poll()
1327     {
1328         WRAPPER_NO_CONTRACT;
1329         if (m_pThread->CatchAtSafePointOpportunistic())
1330             CommonTripThread();
1331     }
1332 #endif // DACCESS_COMPILE
1333
1334     BOOL InsureInit(bool initialInit, struct MachState* unwindState, HostCallPreference hostCallPreference = AllowHostCalls);
1335
1336     LazyMachState * MachineState() {
1337         LIMITED_METHOD_CONTRACT;
1338         return &m_MachState;
1339     }
1340
1341     Thread * GetThread() {
1342         LIMITED_METHOD_CONTRACT;
1343         return m_pThread;
1344     }
1345
1346 private:
1347     // Slow paths of Push/Pop are factored into a separate functions for better perf.
1348     NOINLINE void PushSlowHelper();
1349     NOINLINE void PopSlowHelper();
1350
1351 protected:
1352     PTR_MethodDesc m_pMD;
1353     unsigned m_Attribs;
1354     INDEBUG(BOOL* m_pDoneCheck;)
1355     PTR_Thread m_pThread;
1356     TADDR m_FCallEntry;              // used to determine our identity for stack traces
1357
1358     LazyMachState m_MachState;       // pRetAddr points to the return address and the stack arguments
1359
1360     // Keep as last entry in class
1361     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(HelperMethodFrame)
1362 };
1363
1364 // Restores registers saved in m_MachState
1365 EXTERN_C int __fastcall HelperMethodFrameRestoreState(
1366         INDEBUG_COMMA(HelperMethodFrame *pFrame)
1367         MachState *pState
1368     );
1369
1370
1371 // workhorse for our promotion efforts
1372 inline void DoPromote(promote_func *fn, ScanContext* sc, OBJECTREF *address, BOOL interior)
1373 {
1374     WRAPPER_NO_CONTRACT;
1375
1376     // We use OBJECTREF_TO_UNCHECKED_OBJECTREF since address may be an interior pointer
1377     LOG((LF_GC, INFO3,
1378          "    Promoting pointer argument at" FMT_ADDR "from" FMT_ADDR "to ",
1379          DBG_ADDR(address), DBG_ADDR(OBJECTREF_TO_UNCHECKED_OBJECTREF(*address)) ));
1380
1381     if (interior)
1382         PromoteCarefully(fn, PTR_PTR_Object(address), sc);
1383     else
1384         (*fn) (PTR_PTR_Object(address), sc, 0);
1385
1386     LOG((LF_GC, INFO3, "    " FMT_ADDR "\n", DBG_ADDR(OBJECTREF_TO_UNCHECKED_OBJECTREF(*address)) ));
1387 }
1388
1389
1390 //-----------------------------------------------------------------------------
1391 // a HelplerMethodFrames that also report additional object references
1392 //-----------------------------------------------------------------------------
1393
1394 class HelperMethodFrame_1OBJ : public HelperMethodFrame
1395 {
1396     VPTR_VTABLE_CLASS(HelperMethodFrame_1OBJ, HelperMethodFrame)
1397
1398 public:
1399 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
1400     HelperMethodFrame_1OBJ(void* fCallFtnEntry, unsigned attribs, OBJECTREF* aGCPtr1)
1401         : HelperMethodFrame(fCallFtnEntry, attribs)
1402     {
1403             LIMITED_METHOD_CONTRACT;            
1404             gcPtrs[0] = aGCPtr1;
1405             INDEBUG(Thread::ObjectRefProtected(aGCPtr1);)
1406             INDEBUG((*aGCPtr1).Validate ();)
1407     }
1408 #endif
1409
1410     void SetProtectedObject(PTR_OBJECTREF objPtr)
1411     {
1412         LIMITED_METHOD_CONTRACT;
1413         gcPtrs[0] = objPtr;
1414         INDEBUG(Thread::ObjectRefProtected(objPtr);)
1415         }
1416
1417     virtual void GcScanRoots(promote_func *fn, ScanContext* sc)
1418     {
1419         WRAPPER_NO_CONTRACT;
1420         DoPromote(fn, sc, gcPtrs[0], FALSE);
1421         HelperMethodFrame::GcScanRoots(fn, sc);
1422     }
1423
1424 #ifdef _DEBUG
1425 #ifndef DACCESS_COMPILE
1426     void Pop()
1427     {
1428         WRAPPER_NO_CONTRACT;
1429         HelperMethodFrame::Pop();
1430         Thread::ObjectRefNew(gcPtrs[0]);
1431     }
1432 #endif // DACCESS_COMPILE
1433
1434     BOOL Protects(OBJECTREF *ppORef)
1435     {
1436         LIMITED_METHOD_CONTRACT;
1437         return (ppORef == gcPtrs[0]) ? TRUE : FALSE;
1438     }
1439
1440 #endif
1441
1442 private:
1443     PTR_OBJECTREF gcPtrs[1];
1444
1445     // Keep as last entry in class
1446     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(HelperMethodFrame_1OBJ)
1447 };
1448
1449
1450 //-----------------------------------------------------------------------------
1451 // HelperMethodFrame_2OBJ
1452 //-----------------------------------------------------------------------------
1453
1454 class HelperMethodFrame_2OBJ : public HelperMethodFrame
1455 {
1456     VPTR_VTABLE_CLASS(HelperMethodFrame_2OBJ, HelperMethodFrame)
1457
1458 public:
1459 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
1460     HelperMethodFrame_2OBJ(
1461             void* fCallFtnEntry, 
1462             unsigned attribs, 
1463             OBJECTREF* aGCPtr1, 
1464             OBJECTREF* aGCPtr2)
1465         : HelperMethodFrame(fCallFtnEntry, attribs)
1466     {
1467             LIMITED_METHOD_CONTRACT;
1468         gcPtrs[0] = aGCPtr1;
1469         gcPtrs[1] = aGCPtr2;
1470         INDEBUG(Thread::ObjectRefProtected(aGCPtr1);)
1471         INDEBUG(Thread::ObjectRefProtected(aGCPtr2);)
1472         INDEBUG((*aGCPtr1).Validate ();)
1473         INDEBUG((*aGCPtr2).Validate ();)
1474     }
1475 #endif
1476
1477     virtual void GcScanRoots(promote_func *fn, ScanContext* sc)
1478     {
1479         WRAPPER_NO_CONTRACT;
1480         DoPromote(fn, sc, gcPtrs[0], FALSE);
1481         DoPromote(fn, sc, gcPtrs[1], FALSE);
1482         HelperMethodFrame::GcScanRoots(fn, sc);
1483     }
1484
1485 #ifdef _DEBUG
1486 #ifndef DACCESS_COMPILE
1487     void Pop()
1488     {
1489         WRAPPER_NO_CONTRACT;
1490         HelperMethodFrame::Pop();
1491         Thread::ObjectRefNew(gcPtrs[0]);
1492         Thread::ObjectRefNew(gcPtrs[1]);
1493     }
1494 #endif // DACCESS_COMPILE
1495
1496     BOOL Protects(OBJECTREF *ppORef)
1497     {
1498         LIMITED_METHOD_CONTRACT;
1499         return (ppORef == gcPtrs[0] || ppORef == gcPtrs[1]) ? TRUE : FALSE;
1500     }
1501 #endif
1502
1503 private:
1504     PTR_OBJECTREF gcPtrs[2];
1505
1506     // Keep as last entry in class
1507     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(HelperMethodFrame_2OBJ)
1508 };
1509
1510 //-----------------------------------------------------------------------------
1511 // HelperMethodFrame_3OBJ
1512 //-----------------------------------------------------------------------------
1513
1514 class HelperMethodFrame_3OBJ : public HelperMethodFrame
1515 {
1516     VPTR_VTABLE_CLASS(HelperMethodFrame_3OBJ, HelperMethodFrame)
1517
1518 public:
1519 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
1520     HelperMethodFrame_3OBJ(
1521             void* fCallFtnEntry, 
1522             unsigned attribs, 
1523             OBJECTREF* aGCPtr1, 
1524             OBJECTREF* aGCPtr2,
1525             OBJECTREF* aGCPtr3)
1526         : HelperMethodFrame(fCallFtnEntry, attribs)
1527     {
1528         LIMITED_METHOD_CONTRACT;
1529         gcPtrs[0] = aGCPtr1;
1530         gcPtrs[1] = aGCPtr2;
1531         gcPtrs[2] = aGCPtr3;
1532         INDEBUG(Thread::ObjectRefProtected(aGCPtr1);)
1533         INDEBUG(Thread::ObjectRefProtected(aGCPtr2);)
1534         INDEBUG(Thread::ObjectRefProtected(aGCPtr3);)
1535         INDEBUG((*aGCPtr1).Validate();)
1536         INDEBUG((*aGCPtr2).Validate();)
1537         INDEBUG((*aGCPtr3).Validate();)
1538     }
1539 #endif
1540
1541     virtual void GcScanRoots(promote_func *fn, ScanContext* sc)
1542     {
1543         WRAPPER_NO_CONTRACT;
1544         DoPromote(fn, sc, gcPtrs[0], FALSE);
1545         DoPromote(fn, sc, gcPtrs[1], FALSE);
1546         DoPromote(fn, sc, gcPtrs[2], FALSE);
1547         HelperMethodFrame::GcScanRoots(fn, sc);
1548     }
1549
1550 #ifdef _DEBUG
1551 #ifndef DACCESS_COMPILE
1552     void Pop()
1553     {
1554         WRAPPER_NO_CONTRACT;
1555         HelperMethodFrame::Pop();
1556         Thread::ObjectRefNew(gcPtrs[0]);
1557         Thread::ObjectRefNew(gcPtrs[1]);
1558         Thread::ObjectRefNew(gcPtrs[2]);
1559     }
1560 #endif // DACCESS_COMPILE
1561
1562     BOOL Protects(OBJECTREF *ppORef)
1563     {
1564         LIMITED_METHOD_CONTRACT;
1565         return (ppORef == gcPtrs[0] || ppORef == gcPtrs[1] || ppORef == gcPtrs[2]) ? TRUE : FALSE;
1566     }
1567 #endif
1568
1569 private:
1570     PTR_OBJECTREF gcPtrs[3];
1571
1572     // Keep as last entry in class
1573     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(HelperMethodFrame_3OBJ)
1574 };
1575
1576
1577 //-----------------------------------------------------------------------------
1578 // HelperMethodFrame_PROTECTOBJ
1579 //-----------------------------------------------------------------------------
1580
1581 class HelperMethodFrame_PROTECTOBJ : public HelperMethodFrame
1582 {
1583     VPTR_VTABLE_CLASS(HelperMethodFrame_PROTECTOBJ, HelperMethodFrame)
1584
1585 public:
1586 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
1587     HelperMethodFrame_PROTECTOBJ(void* fCallFtnEntry, unsigned attribs, OBJECTREF* pObjRefs, int numObjRefs)
1588         : HelperMethodFrame(fCallFtnEntry, attribs)
1589     {
1590         LIMITED_METHOD_CONTRACT;
1591         m_pObjRefs = pObjRefs;
1592         m_numObjRefs = numObjRefs;
1593 #ifdef _DEBUG
1594         for (UINT i = 0; i < m_numObjRefs; i++) {
1595             Thread::ObjectRefProtected(&m_pObjRefs[i]);
1596             m_pObjRefs[i].Validate();
1597         }
1598 #endif
1599     }
1600 #endif
1601
1602     virtual void GcScanRoots(promote_func *fn, ScanContext* sc)
1603     {
1604         WRAPPER_NO_CONTRACT;
1605         for (UINT i = 0; i < m_numObjRefs; i++) {
1606             DoPromote(fn, sc, &m_pObjRefs[i], FALSE);
1607         }
1608         HelperMethodFrame::GcScanRoots(fn, sc);
1609     }
1610
1611 #ifdef _DEBUG
1612 #ifndef DACCESS_COMPILE
1613     void Pop()
1614     {
1615         WRAPPER_NO_CONTRACT;
1616         HelperMethodFrame::Pop();
1617         for (UINT i = 0; i < m_numObjRefs; i++) {
1618             Thread::ObjectRefNew(&m_pObjRefs[i]);
1619         }
1620     }
1621 #endif // DACCESS_COMPILE
1622
1623     BOOL Protects(OBJECTREF *ppORef)
1624     {
1625         LIMITED_METHOD_CONTRACT;
1626         for (UINT i = 0; i < m_numObjRefs; i++) {
1627             if (ppORef == &m_pObjRefs[i])
1628                 return TRUE;
1629         }
1630         return FALSE;
1631     }
1632 #endif
1633
1634 private:
1635     PTR_OBJECTREF m_pObjRefs;
1636     UINT       m_numObjRefs;
1637
1638     // Keep as last entry in class
1639     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(HelperMethodFrame_PROTECTOBJ)
1640 };
1641
1642 class FramedMethodFrame : public TransitionFrame
1643 {
1644     VPTR_ABSTRACT_VTABLE_CLASS(FramedMethodFrame, TransitionFrame)
1645
1646     TADDR m_pTransitionBlock;
1647
1648 protected:
1649     PTR_MethodDesc m_pMD;
1650
1651 public:
1652 #ifndef DACCESS_COMPILE
1653     FramedMethodFrame(TransitionBlock * pTransitionBlock, MethodDesc * pMD)
1654         : m_pTransitionBlock(dac_cast<TADDR>(pTransitionBlock)), m_pMD(pMD)
1655     {
1656         LIMITED_METHOD_CONTRACT;
1657     }
1658 #endif // DACCESS_COMPILE
1659
1660     virtual TADDR GetTransitionBlock()
1661     {
1662         LIMITED_METHOD_DAC_CONTRACT;
1663         return m_pTransitionBlock;
1664     }
1665
1666     virtual MethodDesc *GetFunction()
1667     {
1668         LIMITED_METHOD_DAC_CONTRACT;
1669         return m_pMD;
1670     }
1671
1672 #ifndef DACCESS_COMPILE
1673     void SetFunction(MethodDesc *pMD)
1674     {
1675         CONTRACTL
1676         {
1677             NOTHROW;
1678             GC_NOTRIGGER;
1679             MODE_COOPERATIVE; // Frame MethodDesc should be always updated in cooperative mode to avoid racing with GC stackwalk
1680         }
1681         CONTRACTL_END;
1682
1683         m_pMD = pMD;
1684     }
1685 #endif
1686
1687     virtual ETransitionType GetTransitionType()
1688     {
1689         LIMITED_METHOD_DAC_CONTRACT;
1690         return TT_M2U; // we can safely cast to a FramedMethodFrame
1691     }
1692
1693     int GetFrameType()
1694     {
1695         LIMITED_METHOD_DAC_CONTRACT;
1696         return TYPE_CALL;
1697     }
1698
1699 #ifdef COM_STUBS_SEPARATE_FP_LOCATIONS
1700     static int GetFPArgOffset(int iArg)
1701     {
1702 #ifdef _TARGET_AMD64_
1703         // Floating point spill area is between return value and transition block for frames that need it
1704         // (code:TPMethodFrame and code:ComPlusMethodFrame)
1705         return -(4 * 0x10 /* floating point args */ + 0x8 /* alignment pad */ + TransitionBlock::GetNegSpaceSize()) + (iArg * 0x10);
1706 #endif
1707     }
1708 #endif
1709
1710     //
1711     // GetReturnObjectPtr and GetReturnValuePtr are only valid on frames 
1712     // that allocate 
1713     //
1714     PTR_PTR_Object GetReturnObjectPtr()
1715     {
1716         LIMITED_METHOD_DAC_CONTRACT;
1717         return PTR_PTR_Object(GetReturnValuePtr());
1718     }
1719
1720     // Get return value address
1721     PTR_VOID GetReturnValuePtr()
1722     {
1723         LIMITED_METHOD_DAC_CONTRACT;
1724 #ifdef COM_STUBS_SEPARATE_FP_LOCATIONS
1725         TADDR p = GetTransitionBlock() + GetFPArgOffset(0);
1726 #else
1727         TADDR p = GetTransitionBlock() - TransitionBlock::GetNegSpaceSize();
1728 #endif
1729         // Return value is right before the transition block (or floating point spill area on AMD64) for frames that need it
1730         // (code:TPMethodFrame and code:ComPlusMethodFrame)
1731 #ifdef ENREGISTERED_RETURNTYPE_MAXSIZE
1732         p -= ENREGISTERED_RETURNTYPE_MAXSIZE;
1733 #else
1734         p -= sizeof(ARG_SLOT);
1735 #endif
1736         return dac_cast<PTR_VOID>(p);
1737     }
1738
1739 protected:
1740     FramedMethodFrame()
1741     {
1742         LIMITED_METHOD_CONTRACT;
1743     }
1744 };
1745
1746 //+----------------------------------------------------------------------------
1747 //
1748 //  Class:      TPMethodFrame            private
1749 //
1750 //  Synopsis:   This frame is pushed onto the stack for calls on transparent
1751 //              proxy
1752 // 
1753 //
1754 //+----------------------------------------------------------------------------
1755
1756 //------------------------------------------------------------------------
1757 // This represents a call Delegate.Invoke for secure delegate
1758 // It's only used to gc-protect the arguments during the call.
1759 // Actually the only reason to have this frame is so a proper
1760 // Assembly can be reported
1761 //------------------------------------------------------------------------
1762
1763 class SecureDelegateFrame : public TransitionFrame
1764 {
1765     VPTR_VTABLE_CLASS(SecureDelegateFrame, TransitionFrame)
1766
1767     PTR_MethodDesc m_pMD;
1768     TransitionBlock m_TransitionBlock;
1769
1770 public:
1771     virtual MethodDesc* GetFunction()
1772     {
1773         LIMITED_METHOD_CONTRACT;
1774         return m_pMD;
1775     }
1776
1777     virtual TADDR GetTransitionBlock()
1778     {
1779         LIMITED_METHOD_DAC_CONTRACT;
1780         return PTR_HOST_MEMBER_TADDR(SecureDelegateFrame, this,
1781                                      m_TransitionBlock);
1782     }
1783
1784     static BYTE GetOffsetOfDatum()
1785     {
1786         LIMITED_METHOD_DAC_CONTRACT;
1787         return offsetof(SecureDelegateFrame, m_pMD);
1788     }
1789
1790     static int GetOffsetOfTransitionBlock()
1791     {
1792         LIMITED_METHOD_DAC_CONTRACT;
1793         return offsetof(SecureDelegateFrame, m_TransitionBlock);
1794     }
1795
1796     virtual void GcScanRoots(promote_func *fn, ScanContext* sc)
1797     {
1798         WRAPPER_NO_CONTRACT;
1799         TransitionFrame::GcScanRoots(fn, sc);
1800         PromoteCallerStack(fn, sc);
1801     }
1802
1803     virtual Assembly *GetAssembly();
1804
1805     int GetFrameType()
1806     {
1807         LIMITED_METHOD_DAC_CONTRACT;
1808         return TYPE_MULTICAST;
1809     }
1810
1811     // For the debugger:
1812     // Our base class, FramedMethodFrame, is a M2U transition;
1813     // but Delegate.Invoke isn't. So override and fix it here.
1814     // If we didn't do this, we'd see a Managed/Unmanaged transition in debugger's stack trace.
1815     virtual ETransitionType GetTransitionType()
1816     {
1817         LIMITED_METHOD_DAC_CONTRACT;
1818         return TT_NONE;
1819     }
1820
1821     virtual BOOL TraceFrame(Thread *thread, BOOL fromPatch,
1822                             TraceDestination *trace, REGDISPLAY *regs);
1823
1824     // Keep as last entry in class
1825     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(SecureDelegateFrame)
1826 };
1827
1828
1829 //------------------------------------------------------------------------
1830 // This represents a call Multicast.Invoke. It's only used to gc-protect
1831 // the arguments during the iteration.
1832 //------------------------------------------------------------------------
1833
1834 class MulticastFrame : public SecureDelegateFrame
1835 {
1836     VPTR_VTABLE_CLASS(MulticastFrame, SecureDelegateFrame)
1837
1838     public:
1839
1840     virtual Assembly *GetAssembly()
1841     {
1842         WRAPPER_NO_CONTRACT;
1843         return Frame::GetAssembly();
1844     }
1845
1846     int GetFrameType()
1847     {
1848         LIMITED_METHOD_DAC_CONTRACT;
1849         return TYPE_MULTICAST;
1850     }
1851
1852     virtual BOOL TraceFrame(Thread *thread, BOOL fromPatch,
1853                             TraceDestination *trace, REGDISPLAY *regs);
1854
1855     // Keep as last entry in class
1856     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(MulticastFrame)
1857 };
1858
1859
1860 //-----------------------------------------------------------------------
1861 // Transition frame from unmanaged to managed
1862 //-----------------------------------------------------------------------
1863
1864 class UnmanagedToManagedFrame : public Frame
1865 {
1866     friend class CheckAsmOffsets;
1867
1868     VPTR_ABSTRACT_VTABLE_CLASS_AND_CTOR(UnmanagedToManagedFrame, Frame)
1869
1870 public:
1871
1872     // DACCESS: GetReturnAddressPtr should return the
1873     // target address of the return address in the frame.
1874     virtual TADDR GetReturnAddressPtr()
1875     {
1876         LIMITED_METHOD_DAC_CONTRACT;
1877         return PTR_HOST_MEMBER_TADDR(UnmanagedToManagedFrame, this,
1878                                      m_ReturnAddress);
1879     }
1880
1881     virtual PCODE GetReturnAddress();
1882
1883     // Retrieves pointer to the lowest-addressed argument on
1884     // the stack. Depending on the calling convention, this
1885     // may or may not be the first argument.
1886     TADDR GetPointerToArguments()
1887     {
1888         LIMITED_METHOD_DAC_CONTRACT;
1889         return dac_cast<TADDR>(this) + GetOffsetOfArgs();
1890     }
1891
1892     // Exposes an offset for stub generation.
1893     static BYTE GetOffsetOfArgs()
1894     {
1895         LIMITED_METHOD_DAC_CONTRACT;
1896 #if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_)
1897         size_t ofs = offsetof(UnmanagedToManagedFrame, m_argumentRegisters);
1898 #else
1899         size_t ofs = sizeof(UnmanagedToManagedFrame);
1900 #endif
1901         _ASSERTE(FitsInI1(ofs));
1902         return (BYTE)ofs;
1903     }
1904
1905     // depends on the sub frames to return approp. type here
1906     TADDR GetDatum()
1907     {
1908         LIMITED_METHOD_DAC_CONTRACT;
1909         return m_pvDatum;
1910     }
1911
1912     static int GetOffsetOfDatum()
1913     {
1914         LIMITED_METHOD_CONTRACT;
1915         return offsetof(UnmanagedToManagedFrame, m_pvDatum);
1916     }
1917
1918 #ifdef _TARGET_X86_
1919     static int GetOffsetOfCalleeSavedRegisters()
1920     {
1921         LIMITED_METHOD_CONTRACT;
1922         return offsetof(UnmanagedToManagedFrame, m_calleeSavedRegisters);
1923     }
1924 #endif
1925
1926     int GetFrameType()
1927     {
1928         LIMITED_METHOD_DAC_CONTRACT;
1929         return TYPE_ENTRY;
1930     }
1931
1932     //------------------------------------------------------------------------
1933     // For the debugger.
1934     //------------------------------------------------------------------------
1935     virtual ETransitionType GetTransitionType()
1936     {
1937         LIMITED_METHOD_DAC_CONTRACT;
1938         return TT_U2M;
1939     }
1940
1941     //------------------------------------------------------------------------
1942     // Performs cleanup on an exception unwind
1943     //------------------------------------------------------------------------
1944 #ifndef DACCESS_COMPILE
1945     virtual void ExceptionUnwind();
1946 #endif
1947
1948 protected:
1949     TADDR           m_pvDatum;        // type depends on the sub class
1950
1951 #if defined(_TARGET_X86_)
1952     CalleeSavedRegisters  m_calleeSavedRegisters;
1953     TADDR           m_ReturnAddress;
1954 #elif defined(_TARGET_ARM_)
1955     TADDR           m_R11; // R11 chain
1956     TADDR           m_ReturnAddress;
1957     ArgumentRegisters m_argumentRegisters;
1958 #elif defined (_TARGET_ARM64_)
1959     TADDR           m_fp;
1960     TADDR           m_ReturnAddress;
1961     TADDR           m_x8; // ret buff arg
1962     ArgumentRegisters m_argumentRegisters;
1963 #else
1964     TADDR           m_ReturnAddress;  // return address into unmanaged code
1965 #endif
1966 };
1967
1968 #ifdef FEATURE_COMINTEROP
1969
1970 //------------------------------------------------------------------------
1971 // This frame represents a transition from COM to COM+
1972 //------------------------------------------------------------------------
1973
1974 class ComMethodFrame : public UnmanagedToManagedFrame
1975 {
1976     VPTR_VTABLE_CLASS(ComMethodFrame, UnmanagedToManagedFrame)
1977     VPTR_UNIQUE(VPTR_UNIQUE_ComMethodFrame)
1978
1979 public:
1980
1981 #ifdef _TARGET_X86_
1982     // Return the # of stack bytes pushed by the unmanaged caller.
1983     UINT GetNumCallerStackBytes();
1984 #endif
1985
1986     PTR_ComCallMethodDesc GetComCallMethodDesc()
1987     {
1988         LIMITED_METHOD_CONTRACT;
1989         return dac_cast<PTR_ComCallMethodDesc>(m_pvDatum);
1990     }
1991
1992 #ifndef DACCESS_COMPILE
1993     static void DoSecondPassHandlerCleanup(Frame * pCurFrame);
1994 #endif // !DACCESS_COMPILE
1995
1996 protected:
1997     // Keep as last entry in class
1998     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(ComMethodFrame)
1999 };
2000
2001 typedef DPTR(class ComMethodFrame) PTR_ComMethodFrame;
2002
2003 //------------------------------------------------------------------------
2004 // This represents a generic call from CLR to COM
2005 //------------------------------------------------------------------------
2006
2007 class ComPlusMethodFrame : public FramedMethodFrame
2008 {
2009     VPTR_VTABLE_CLASS(ComPlusMethodFrame, FramedMethodFrame)
2010
2011 public:
2012     ComPlusMethodFrame(TransitionBlock * pTransitionBlock, MethodDesc * pMethodDesc); 
2013
2014     virtual void GcScanRoots(promote_func *fn, ScanContext* sc);
2015
2016     virtual BOOL IsTransitionToNativeFrame()
2017     {
2018         LIMITED_METHOD_CONTRACT;
2019         return TRUE;
2020     }
2021
2022     int GetFrameType()
2023     {
2024         LIMITED_METHOD_DAC_CONTRACT;
2025         return TYPE_EXIT;
2026     }
2027
2028     void GetUnmanagedCallSite(TADDR* ip,
2029                               TADDR* returnIP,
2030                               TADDR* returnSP);
2031
2032     BOOL TraceFrame(Thread *thread, BOOL fromPatch,
2033                     TraceDestination *trace, REGDISPLAY *regs);
2034
2035     // Keep as last entry in class
2036     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(ComPlusMethodFrame)
2037 };
2038
2039 #endif // FEATURE_COMINTEROP
2040
2041 //------------------------------------------------------------------------
2042 // This represents a call from a helper to GetILStubForCalli
2043 //------------------------------------------------------------------------
2044
2045 class PInvokeCalliFrame : public FramedMethodFrame
2046 {
2047     VPTR_VTABLE_CLASS(PInvokeCalliFrame, FramedMethodFrame)
2048
2049     PTR_VASigCookie m_pVASigCookie;
2050     PCODE m_pUnmanagedTarget;
2051
2052 public:
2053     PInvokeCalliFrame(TransitionBlock * pTransitionBlock, VASigCookie * pVASigCookie, PCODE pUnmanagedTarget);
2054
2055     virtual void GcScanRoots(promote_func *fn, ScanContext* sc)
2056     {
2057         WRAPPER_NO_CONTRACT;
2058         FramedMethodFrame::GcScanRoots(fn, sc);
2059         PromoteCallerStack(fn, sc);
2060     }
2061
2062     void PromoteCallerStack(promote_func* fn, ScanContext* sc);
2063
2064     // not a method
2065     virtual MethodDesc *GetFunction()
2066     {
2067         LIMITED_METHOD_DAC_CONTRACT;
2068         return NULL;
2069     }
2070
2071     int GetFrameType()
2072     {
2073         LIMITED_METHOD_DAC_CONTRACT;
2074         return TYPE_INTERCEPTION;
2075     }
2076
2077     PCODE GetPInvokeCalliTarget()
2078     {
2079         LIMITED_METHOD_CONTRACT;
2080         return m_pUnmanagedTarget;
2081     }
2082
2083     PTR_VASigCookie GetVASigCookie()
2084     {
2085         LIMITED_METHOD_CONTRACT;
2086         return m_pVASigCookie;
2087     }
2088
2089 #ifdef _TARGET_X86_
2090     virtual void UpdateRegDisplay(const PREGDISPLAY);
2091 #endif // _TARGET_X86_
2092
2093     BOOL TraceFrame(Thread *thread, BOOL fromPatch,
2094                     TraceDestination *trace, REGDISPLAY *regs)
2095     {
2096         WRAPPER_NO_CONTRACT;
2097
2098         trace->InitForUnmanaged(GetPInvokeCalliTarget());
2099         return TRUE;
2100     }
2101
2102     // Keep as last entry in class
2103     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(PInvokeCalliFrame)
2104 };
2105
2106 // Some context-related forwards.
2107 #ifdef FEATURE_HIJACK
2108 //------------------------------------------------------------------------
2109 // This frame represents a hijacked return.  If we crawl back through it,
2110 // it gets us back to where the return should have gone (and eventually will
2111 // go).
2112 //------------------------------------------------------------------------
2113 class HijackFrame : public Frame
2114 {
2115     VPTR_VTABLE_CLASS(HijackFrame, Frame)
2116     VPTR_UNIQUE(VPTR_UNIQUE_HijackFrame);
2117
2118 public:
2119     // DACCESS: GetReturnAddressPtr should return the
2120     // target address of the return address in the frame.
2121     virtual TADDR GetReturnAddressPtr()
2122     {
2123         LIMITED_METHOD_DAC_CONTRACT;
2124         return PTR_HOST_MEMBER_TADDR(HijackFrame, this,
2125                                      m_ReturnAddress);
2126     }
2127
2128     virtual BOOL NeedsUpdateRegDisplay()
2129     {
2130         LIMITED_METHOD_CONTRACT;
2131         return TRUE;
2132     }
2133
2134     virtual void UpdateRegDisplay(const PREGDISPLAY);
2135     virtual void GcScanRoots(promote_func *fn, ScanContext* sc);
2136
2137     // HijackFrames are created by trip functions. See OnHijackTripThread()
2138     // They are real C++ objects on the stack. 
2139     // So, it's a public function -- but that doesn't mean you should make some.
2140     HijackFrame(LPVOID returnAddress, Thread *thread, HijackArgs *args);
2141
2142 protected:
2143
2144     TADDR               m_ReturnAddress;
2145     PTR_Thread          m_Thread;
2146     DPTR(HijackArgs)    m_Args;
2147
2148     // Keep as last entry in class
2149     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(HijackFrame)
2150 };
2151
2152 #endif // FEATURE_HIJACK
2153
2154 //------------------------------------------------------------------------
2155 // This represents a call to a method prestub. Because the prestub
2156 // can do gc and throw exceptions while building the replacement
2157 // stub, we need this frame to keep things straight.
2158 //------------------------------------------------------------------------
2159
2160 class PrestubMethodFrame : public FramedMethodFrame
2161 {
2162     VPTR_VTABLE_CLASS(PrestubMethodFrame, FramedMethodFrame)
2163
2164 public:
2165     PrestubMethodFrame(TransitionBlock * pTransitionBlock, MethodDesc * pMD);
2166
2167     virtual void GcScanRoots(promote_func *fn, ScanContext* sc)
2168     {
2169         WRAPPER_NO_CONTRACT;
2170         FramedMethodFrame::GcScanRoots(fn, sc);
2171         PromoteCallerStack(fn, sc);
2172     }
2173
2174     BOOL TraceFrame(Thread *thread, BOOL fromPatch,
2175                     TraceDestination *trace, REGDISPLAY *regs);
2176
2177     int GetFrameType()
2178     {
2179         LIMITED_METHOD_DAC_CONTRACT;
2180         return TYPE_INTERCEPTION;
2181     }
2182
2183     // Our base class is a a M2U TransitionType; but we're not. So override and set us back to None.
2184     ETransitionType GetTransitionType()
2185     {
2186         LIMITED_METHOD_DAC_CONTRACT;
2187         return TT_NONE;
2188     }
2189
2190     Interception GetInterception();
2191
2192     // Keep as last entry in class
2193     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(PrestubMethodFrame)
2194 };
2195
2196 //------------------------------------------------------------------------
2197 // This represents a call into the virtual call stub manager
2198 // Because the stub manager can do gc and throw exceptions while
2199 // building the resolve and dispatch stubs and needs to communicate
2200 // if we need to setup for a methodDesc call or do a direct call
2201 // we need this frame to keep things straight.
2202 //------------------------------------------------------------------------
2203
2204 class StubDispatchFrame : public FramedMethodFrame
2205 {
2206     VPTR_VTABLE_CLASS(StubDispatchFrame, FramedMethodFrame)
2207
2208     // Representative MethodTable * and slot. They are used to
2209     // compute the MethodDesc* lazily
2210     PTR_MethodTable m_pRepresentativeMT;
2211     UINT32          m_representativeSlot;
2212
2213     // Indirection cell and containing module. Used to compute pGCRefMap lazily.
2214     PTR_Module      m_pZapModule;
2215     TADDR           m_pIndirection;
2216
2217     // Cached pointer to native ref data.
2218     PTR_BYTE        m_pGCRefMap;
2219
2220 public:
2221     StubDispatchFrame(TransitionBlock * pTransitionBlock);
2222
2223     MethodDesc* GetFunction();
2224
2225     // Returns this frame GC ref map if it has one
2226     PTR_BYTE GetGCRefMap();
2227
2228 #ifdef _TARGET_X86_
2229     virtual void UpdateRegDisplay(const PREGDISPLAY pRD);
2230     virtual PCODE GetReturnAddress();
2231 #endif // _TARGET_X86_
2232
2233     PCODE GetUnadjustedReturnAddress()
2234     {
2235         LIMITED_METHOD_DAC_CONTRACT;
2236         return FramedMethodFrame::GetReturnAddress();
2237     }
2238
2239     virtual void GcScanRoots(promote_func *fn, ScanContext* sc);
2240
2241 #ifndef DACCESS_COMPILE
2242     void SetRepresentativeSlot(MethodTable * pMT, UINT32 representativeSlot)
2243     {
2244         LIMITED_METHOD_CONTRACT;
2245
2246         m_pRepresentativeMT = pMT;
2247         m_representativeSlot = representativeSlot;
2248     }
2249
2250     void SetCallSite(Module * pZapModule, TADDR pIndirection)
2251     {
2252         LIMITED_METHOD_CONTRACT;
2253
2254         m_pZapModule = pZapModule;
2255         m_pIndirection = pIndirection;
2256     }
2257
2258     void SetForNullReferenceException()
2259     {
2260         LIMITED_METHOD_CONTRACT;
2261
2262         // Nothing to do. Everything is initialized in Init.
2263     }
2264 #endif
2265
2266     BOOL TraceFrame(Thread *thread, BOOL fromPatch,
2267                     TraceDestination *trace, REGDISPLAY *regs);
2268
2269     int GetFrameType()
2270     {
2271         LIMITED_METHOD_CONTRACT;
2272         return TYPE_CALL;
2273     }
2274
2275     Interception GetInterception();
2276
2277     virtual BOOL SuppressParamTypeArg()
2278     {
2279         //
2280         // Shared default interface methods (i.e. virtual interface methods with an implementation) require
2281         // an instantiation argument. But if we're in the stub dispatch frame, we haven't actually resolved
2282         // the method yet (we could end up in class's override of this method, for example).
2283         //
2284         // So we need to pretent that unresolved default interface methods are like any other interface
2285         // methods and don't have an instantiation argument.
2286         //
2287         // See code:CEEInfo::getMethodSigInternal
2288         //
2289         assert(GetFunction()->GetMethodTable()->IsInterface());
2290         return TRUE;
2291     }
2292
2293 private:
2294     friend class VirtualCallStubManager;
2295
2296     // Keep as last entry in class
2297     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(StubDispatchFrame)
2298 };
2299
2300 typedef VPTR(class StubDispatchFrame) PTR_StubDispatchFrame;
2301
2302
2303 //------------------------------------------------------------------------
2304 // This represents a call from an ExternalMethodThunk or a VirtualImportThunk
2305 // Because the resolving of the target address can do gc and/or
2306 //  throw exceptions we need this frame to report the gc references.
2307 //------------------------------------------------------------------------
2308
2309 class ExternalMethodFrame : public FramedMethodFrame
2310 {
2311     VPTR_VTABLE_CLASS(ExternalMethodFrame, FramedMethodFrame)
2312
2313     // Indirection and containing module. Used to compute pGCRefMap lazily.
2314     PTR_Module      m_pZapModule;
2315     TADDR           m_pIndirection;
2316
2317     // Cached pointer to native ref data.
2318     PTR_BYTE        m_pGCRefMap;
2319
2320 public:
2321     ExternalMethodFrame(TransitionBlock * pTransitionBlock);
2322
2323     virtual void GcScanRoots(promote_func *fn, ScanContext* sc);
2324
2325     // Returns this frame GC ref map if it has one
2326     PTR_BYTE GetGCRefMap();
2327
2328 #ifndef DACCESS_COMPILE
2329     void SetCallSite(Module * pZapModule, TADDR pIndirection)
2330     {
2331         LIMITED_METHOD_CONTRACT;
2332
2333         m_pZapModule = pZapModule;
2334         m_pIndirection = pIndirection;
2335     }
2336 #endif
2337
2338     int GetFrameType()
2339     {
2340         LIMITED_METHOD_CONTRACT;
2341         return TYPE_CALL;
2342     }
2343
2344     Interception GetInterception();
2345
2346 #ifdef _TARGET_X86_
2347     virtual void UpdateRegDisplay(const PREGDISPLAY pRD);
2348 #endif
2349     
2350     // Keep as last entry in class
2351     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(ExternalMethodFrame)
2352 };
2353
2354 typedef VPTR(class ExternalMethodFrame) PTR_ExternalMethodFrame;
2355
2356 #ifdef FEATURE_READYTORUN
2357 class DynamicHelperFrame : public FramedMethodFrame
2358 {
2359     VPTR_VTABLE_CLASS(DynamicHelperFrame, FramedMethodFrame)
2360
2361     int m_dynamicHelperFrameFlags;
2362
2363 public:
2364     DynamicHelperFrame(TransitionBlock * pTransitionBlock, int dynamicHelperFrameFlags);
2365
2366     virtual void GcScanRoots(promote_func *fn, ScanContext* sc);
2367
2368 #ifdef _TARGET_X86_
2369     virtual void UpdateRegDisplay(const PREGDISPLAY pRD);
2370 #endif
2371
2372     virtual ETransitionType GetTransitionType()
2373     {
2374         LIMITED_METHOD_DAC_CONTRACT;
2375         return TT_InternalCall;
2376     }
2377     
2378     // Keep as last entry in class
2379     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(DynamicHelperFrame)
2380 };
2381
2382 typedef VPTR(class DynamicHelperFrame) PTR_DynamicHelperFrame;
2383 #endif // FEATURE_READYTORUN
2384
2385 //------------------------------------------------------------------------
2386 // This frame is used for instantiating stubs when the argument transform
2387 // is too complex to generate a tail-calling stub.
2388 //------------------------------------------------------------------------
2389 #if !defined(_TARGET_X86_)
2390 class StubHelperFrame : public TransitionFrame
2391 {
2392     friend class CheckAsmOffsets;
2393     friend class StubLinkerCPU;
2394
2395     VPTR_VTABLE_CLASS(StubHelperFrame, TransitionFrame)
2396     VPTR_UNIQUE(VPTR_UNIQUE_StubHelperFrame)
2397
2398     TransitionBlock m_TransitionBlock;
2399
2400     virtual TADDR GetTransitionBlock()
2401     {
2402         LIMITED_METHOD_DAC_CONTRACT;
2403         return PTR_HOST_MEMBER_TADDR(StubHelperFrame, this,
2404             m_TransitionBlock);
2405     }
2406
2407     static int GetOffsetOfTransitionBlock()
2408     {
2409         LIMITED_METHOD_DAC_CONTRACT;
2410         return offsetof(StubHelperFrame, m_TransitionBlock);
2411     }
2412
2413 private:
2414     // Keep as last entry in class
2415     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(StubHelperFrame)
2416 };
2417 #endif // _TARGET_X86_
2418
2419 #ifdef FEATURE_COMINTEROP
2420
2421 //------------------------------------------------------------------------
2422 // This represents a com to com+ call method prestub.
2423 // we need to catch exceptions etc. so this frame is not the same
2424 // as the prestub method frame
2425 // Note that in rare IJW cases, the immediate caller could be a managed method
2426 // which pinvoke-inlined a call to a COM interface, which happenned to be
2427 // implemented by a managed function via COM-interop.
2428 //------------------------------------------------------------------------
2429 class ComPrestubMethodFrame : public ComMethodFrame
2430 {
2431     friend class CheckAsmOffsets;
2432
2433     VPTR_VTABLE_CLASS(ComPrestubMethodFrame, ComMethodFrame)
2434
2435 public:
2436     // Set the vptr and GSCookie
2437     VOID Init();
2438
2439     int GetFrameType()
2440     {
2441         LIMITED_METHOD_DAC_CONTRACT;
2442         return TYPE_INTERCEPTION;
2443     }
2444
2445     // ComPrestubMethodFrame should return the same interception type as 
2446     // code:PrestubMethodFrame.GetInterception.
2447     virtual Interception GetInterception()
2448     {
2449         LIMITED_METHOD_DAC_CONTRACT;
2450         return INTERCEPTION_PRESTUB;
2451     }
2452
2453     // Our base class is a a M2U TransitionType; but we're not. So override and set us back to None.
2454     virtual ETransitionType GetTransitionType()
2455     {
2456         LIMITED_METHOD_DAC_CONTRACT;
2457         return TT_NONE;
2458     }
2459
2460     virtual void ExceptionUnwind()
2461     {
2462     }
2463
2464 private:
2465     // Keep as last entry in class
2466     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(ComPrestubMethodFrame)
2467 };
2468
2469 #endif // FEATURE_COMINTEROP
2470
2471
2472 //------------------------------------------------------------------------
2473 // This frame protects object references for the EE's convenience.
2474 // This frame type actually is created from C++.
2475 //------------------------------------------------------------------------
2476 class GCFrame : public Frame
2477 {
2478     VPTR_VTABLE_CLASS(GCFrame, Frame)
2479
2480 public:
2481
2482
2483     //--------------------------------------------------------------------
2484     // This constructor pushes a new GCFrame on the frame chain.
2485     //--------------------------------------------------------------------
2486 #ifndef DACCESS_COMPILE
2487     GCFrame() {
2488         LIMITED_METHOD_CONTRACT;
2489     };
2490
2491     GCFrame(OBJECTREF *pObjRefs, UINT numObjRefs, BOOL maybeInterior);
2492     GCFrame(Thread *pThread, OBJECTREF *pObjRefs, UINT numObjRefs, BOOL maybeInterior);
2493 #endif
2494     void Init(Thread *pThread, OBJECTREF *pObjRefs, UINT numObjRefs, BOOL maybeInterior);
2495
2496
2497     //--------------------------------------------------------------------
2498     // Pops the GCFrame and cancels the GC protection. Also
2499     // trashes the contents of pObjRef's in _DEBUG.
2500     //--------------------------------------------------------------------
2501     VOID Pop();
2502
2503     virtual void GcScanRoots(promote_func *fn, ScanContext* sc);
2504
2505 #ifdef _DEBUG
2506     virtual BOOL Protects(OBJECTREF *ppORef)
2507     {
2508         LIMITED_METHOD_CONTRACT;
2509         for (UINT i = 0; i < m_numObjRefs; i++) {
2510             if (ppORef == m_pObjRefs + i) {
2511                 return TRUE;
2512             }
2513         }
2514         return FALSE;
2515     }
2516 #endif
2517
2518 #ifndef DACCESS_COMPILE
2519     void *operator new (size_t sz, void* p)
2520     {
2521         LIMITED_METHOD_CONTRACT;
2522         return p ;
2523     }
2524 #endif
2525
2526 #if defined(_DEBUG_IMPL)
2527     const char* GetFrameTypeName() { LIMITED_METHOD_CONTRACT; return "GCFrame"; }
2528 #endif
2529
2530 private:
2531     PTR_OBJECTREF m_pObjRefs;
2532     UINT          m_numObjRefs;
2533     PTR_Thread    m_pCurThread;
2534     BOOL          m_MaybeInterior;
2535
2536     // Keep as last entry in class
2537     DEFINE_VTABLE_GETTER_AND_DTOR(GCFrame)
2538 };
2539
2540 #ifdef FEATURE_INTERPRETER
2541 class InterpreterFrame: public Frame
2542 {
2543     VPTR_VTABLE_CLASS(InterpreterFrame, Frame)
2544
2545     class Interpreter* m_interp;
2546
2547 public:
2548
2549 #ifndef DACCESS_COMPILE
2550     InterpreterFrame(class Interpreter* interp);
2551
2552     class Interpreter* GetInterpreter() { return m_interp; }
2553
2554     // Override.
2555     virtual void GcScanRoots(promote_func *fn, ScanContext* sc);
2556
2557     MethodDesc* GetFunction();
2558 #endif
2559
2560     DEFINE_VTABLE_GETTER_AND_DTOR(InterpreterFrame)
2561
2562 };
2563
2564 typedef VPTR(class InterpreterFrame) PTR_InterpreterFrame;
2565 #endif // FEATURE_INTERPRETER
2566
2567
2568 //-----------------------------------------------------------------------------
2569
2570 struct ByRefInfo;
2571 typedef DPTR(ByRefInfo) PTR_ByRefInfo;
2572
2573 struct ByRefInfo
2574 {
2575     PTR_ByRefInfo pNext;
2576     INT32      argIndex;
2577     CorElementType typ;
2578     TypeHandle typeHandle;
2579     char       data[1];
2580 };
2581
2582 //-----------------------------------------------------------------------------
2583 // ProtectByRefsFrame
2584 //-----------------------------------------------------------------------------
2585
2586 class ProtectByRefsFrame : public Frame
2587 {
2588     VPTR_VTABLE_CLASS(ProtectByRefsFrame, Frame)
2589
2590 public:
2591 #ifndef DACCESS_COMPILE
2592     ProtectByRefsFrame(Thread *pThread, ByRefInfo *brInfo)
2593         : m_brInfo(brInfo)
2594     {
2595         WRAPPER_NO_CONTRACT;
2596         Frame::Push(pThread);
2597     }
2598 #endif
2599
2600     virtual void GcScanRoots(promote_func *fn, ScanContext *sc);
2601
2602 private:
2603     PTR_ByRefInfo m_brInfo;
2604
2605     // Keep as last entry in class
2606     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(ProtectByRefsFrame)
2607 };
2608
2609
2610 //-----------------------------------------------------------------------------
2611
2612 struct ValueClassInfo;
2613 typedef DPTR(struct ValueClassInfo) PTR_ValueClassInfo;
2614
2615 struct ValueClassInfo
2616 {
2617     PTR_ValueClassInfo  pNext;
2618     PTR_MethodTable     pMT;
2619     PTR_VOID            pData;
2620
2621     ValueClassInfo(PTR_VOID aData, PTR_MethodTable aMT, PTR_ValueClassInfo aNext)
2622         : pNext(aNext), pMT(aMT), pData(aData)
2623     {
2624     }
2625 };
2626
2627 //-----------------------------------------------------------------------------
2628 // ProtectValueClassFrame
2629 //-----------------------------------------------------------------------------
2630
2631
2632 class ProtectValueClassFrame : public Frame
2633 {
2634     VPTR_VTABLE_CLASS(ProtectValueClassFrame, Frame)
2635
2636 public:
2637 #ifndef DACCESS_COMPILE
2638     ProtectValueClassFrame()
2639         : m_pVCInfo(NULL)
2640     {
2641         WRAPPER_NO_CONTRACT;
2642         Frame::Push();
2643     }
2644
2645     ProtectValueClassFrame(Thread *pThread, ValueClassInfo *vcInfo)
2646         : m_pVCInfo(vcInfo)
2647     {
2648         WRAPPER_NO_CONTRACT;
2649         Frame::Push(pThread);
2650     }
2651 #endif
2652
2653     virtual void GcScanRoots(promote_func *fn, ScanContext *sc);
2654
2655     ValueClassInfo ** GetValueClassInfoList()
2656     {
2657         LIMITED_METHOD_CONTRACT;
2658         return &m_pVCInfo;
2659     }
2660
2661 private:
2662
2663     ValueClassInfo *m_pVCInfo;
2664
2665     // Keep as last entry in class
2666     DEFINE_VTABLE_GETTER_AND_DTOR(ProtectValueClassFrame)
2667 };
2668
2669
2670 #ifdef _DEBUG
2671 BOOL IsProtectedByGCFrame(OBJECTREF *ppObjectRef);
2672 #endif
2673
2674
2675 //------------------------------------------------------------------------
2676 // DebuggerClassInitMarkFrame is a small frame whose only purpose in
2677 // life is to mark for the debugger that "class initialization code" is
2678 // being run. It does nothing useful except return good values from
2679 // GetFrameType and GetInterception.
2680 //------------------------------------------------------------------------
2681
2682 class DebuggerClassInitMarkFrame : public Frame
2683 {
2684     VPTR_VTABLE_CLASS(DebuggerClassInitMarkFrame, Frame)
2685
2686 public:
2687
2688 #ifndef DACCESS_COMPILE
2689     DebuggerClassInitMarkFrame()
2690     {
2691         WRAPPER_NO_CONTRACT;
2692         Push();
2693     };
2694 #endif
2695
2696     virtual int GetFrameType()
2697     {
2698         LIMITED_METHOD_DAC_CONTRACT;
2699         return TYPE_INTERCEPTION;
2700     }
2701
2702     virtual Interception GetInterception()
2703     {
2704         LIMITED_METHOD_DAC_CONTRACT;
2705         return INTERCEPTION_CLASS_INIT;
2706     }
2707
2708     // Keep as last entry in class
2709     DEFINE_VTABLE_GETTER_AND_DTOR(DebuggerClassInitMarkFrame)
2710 };
2711
2712
2713 //------------------------------------------------------------------------
2714 // DebuggerSecurityCodeMarkFrame is a small frame whose only purpose in
2715 // life is to mark for the debugger that "security code" is
2716 // being run. It does nothing useful except return good values from
2717 // GetFrameType and GetInterception.
2718 //------------------------------------------------------------------------
2719
2720 class DebuggerSecurityCodeMarkFrame : public Frame
2721 {
2722     VPTR_VTABLE_CLASS(DebuggerSecurityCodeMarkFrame, Frame)
2723
2724 public:
2725 #ifndef DACCESS_COMPILE
2726     DebuggerSecurityCodeMarkFrame()
2727     {
2728         WRAPPER_NO_CONTRACT;
2729         Push();
2730     }
2731 #endif
2732
2733     virtual int GetFrameType()
2734     {
2735         LIMITED_METHOD_DAC_CONTRACT;
2736         return TYPE_INTERCEPTION;
2737     }
2738
2739     virtual Interception GetInterception()
2740     {
2741         LIMITED_METHOD_DAC_CONTRACT;
2742         return INTERCEPTION_SECURITY;
2743     }
2744
2745     // Keep as last entry in class
2746     DEFINE_VTABLE_GETTER_AND_DTOR(DebuggerSecurityCodeMarkFrame)
2747 };
2748
2749 //------------------------------------------------------------------------
2750 // DebuggerExitFrame is a small frame whose only purpose in
2751 // life is to mark for the debugger that there is an exit transiton on
2752 // the stack.  This is special cased for the "break" IL instruction since
2753 // it is an fcall using a helper frame which returns TYPE_CALL instead of
2754 // an ecall (as in System.Diagnostics.Debugger.Break()) which returns
2755 // TYPE_EXIT.  This just makes the two consistent for debugging services.
2756 //------------------------------------------------------------------------
2757
2758 class DebuggerExitFrame : public Frame
2759 {
2760     VPTR_VTABLE_CLASS(DebuggerExitFrame, Frame)
2761
2762 public:
2763 #ifndef DACCESS_COMPILE
2764     DebuggerExitFrame()
2765     {
2766         WRAPPER_NO_CONTRACT;
2767         Push();
2768     }
2769 #endif
2770
2771     virtual int GetFrameType()
2772     {
2773         LIMITED_METHOD_DAC_CONTRACT;
2774         return TYPE_EXIT;
2775     }
2776
2777     // Return information about an unmanaged call the frame
2778     // will make.
2779     // ip - the unmanaged routine which will be called
2780     // returnIP - the address in the stub which the unmanaged routine
2781     //            will return to.
2782     // returnSP - the location returnIP is pushed onto the stack
2783     //            during the call.
2784     //
2785     virtual void GetUnmanagedCallSite(TADDR* ip,
2786                                       TADDR* returnIP,
2787                                       TADDR* returnSP)
2788     {
2789         LIMITED_METHOD_CONTRACT;
2790         if (ip)
2791             *ip = NULL;
2792
2793         if (returnIP)
2794             *returnIP = NULL;
2795
2796         if (returnSP)
2797             *returnSP = NULL;
2798     }
2799
2800     // Keep as last entry in class
2801     DEFINE_VTABLE_GETTER_AND_DTOR(DebuggerExitFrame)
2802 };
2803
2804 //---------------------------------------------------------------------------------------
2805 //
2806 // DebuggerU2MCatchHandlerFrame is a small frame whose only purpose in life is to mark for the debugger 
2807 // that there is catch handler inside the runtime which may catch and swallow managed exceptions.  The 
2808 // debugger needs this frame to send a CatchHandlerFound (CHF) notification.  Without this frame, the
2809 // debugger doesn't know where a managed exception is caught.
2810 //
2811 // Notes:
2812 //    Currently this frame is only used in code:DispatchInfo.InvokeMember, which is an U2M transition.
2813 //
2814
2815 class DebuggerU2MCatchHandlerFrame : public Frame
2816 {
2817     VPTR_VTABLE_CLASS(DebuggerU2MCatchHandlerFrame, Frame)
2818
2819 public:
2820 #ifndef DACCESS_COMPILE
2821     DebuggerU2MCatchHandlerFrame()
2822     {
2823         WRAPPER_NO_CONTRACT;
2824         Frame::Push();
2825     }
2826
2827     DebuggerU2MCatchHandlerFrame(Thread * pThread)
2828     {
2829         WRAPPER_NO_CONTRACT;
2830         Frame::Push(pThread);
2831     }
2832 #endif
2833
2834     ETransitionType GetTransitionType()
2835     {
2836         LIMITED_METHOD_DAC_CONTRACT;
2837         return TT_U2M;
2838     }
2839
2840     // Keep as last entry in class
2841     DEFINE_VTABLE_GETTER_AND_DTOR(DebuggerU2MCatchHandlerFrame)
2842 };
2843
2844
2845 class UMThunkMarshInfo;
2846 typedef DPTR(class UMThunkMarshInfo) PTR_UMThunkMarshInfo;
2847
2848 class UMEntryThunk;
2849 typedef DPTR(class UMEntryThunk) PTR_UMEntryThunk;
2850
2851 #if defined(_TARGET_X86_)
2852 //------------------------------------------------------------------------
2853 // This frame guards an unmanaged->managed transition thru a UMThk
2854 //------------------------------------------------------------------------
2855
2856 class UMThkCallFrame : public UnmanagedToManagedFrame
2857 {
2858     VPTR_VTABLE_CLASS(UMThkCallFrame, UnmanagedToManagedFrame)
2859
2860 public:
2861
2862 #ifdef DACCESS_COMPILE
2863     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
2864 #endif
2865
2866     PTR_UMEntryThunk GetUMEntryThunk();
2867
2868     static int GetOffsetOfUMEntryThunk()
2869     {
2870         WRAPPER_NO_CONTRACT;
2871         return GetOffsetOfDatum();
2872     }
2873
2874 protected:
2875
2876     // Keep as last entry in class
2877     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(UMThkCallFrame)
2878 };
2879 #endif // _TARGET_X86_ && !FEATURE_PAL
2880
2881 #if defined(_TARGET_X86_) && defined(FEATURE_COMINTEROP)
2882 //-------------------------------------------------------------------------
2883 // Exception handler for COM to managed frame
2884 //  and the layout of the exception registration record structure in the stack
2885 //  the layout is similar to the NT's EXCEPTIONREGISTRATION record
2886 //  followed by the UnmanagedToManagedFrame specific info
2887
2888 struct ComToManagedExRecord
2889 {
2890     EXCEPTION_REGISTRATION_RECORD   m_ExReg;
2891     ArgumentRegisters               m_argRegs;
2892     GSCookie                        m_gsCookie;
2893     UMThkCallFrame                  m_frame;
2894
2895     UnmanagedToManagedFrame * GetCurrFrame()
2896     {
2897         LIMITED_METHOD_CONTRACT;
2898         return &m_frame;
2899     }
2900 };
2901 #endif // _TARGET_X86_ && FEATURE_COMINTEROP
2902
2903
2904 //------------------------------------------------------------------------
2905 // This frame is pushed by any JIT'ted method that contains one or more
2906 // inlined N/Direct calls. Note that the JIT'ted method keeps it pushed
2907 // the whole time to amortize the pushing cost across the entire method.
2908 //------------------------------------------------------------------------
2909
2910 typedef DPTR(class InlinedCallFrame) PTR_InlinedCallFrame;
2911
2912 class InlinedCallFrame : public Frame
2913 {
2914     VPTR_VTABLE_CLASS(InlinedCallFrame, Frame)
2915
2916 public:
2917     virtual MethodDesc *GetFunction()
2918     {
2919         WRAPPER_NO_CONTRACT;
2920         if (FrameHasActiveCall(this) && HasFunction())
2921             return PTR_MethodDesc(m_Datum);
2922         else
2923             return NULL;
2924     }
2925
2926     BOOL HasFunction()
2927     {
2928         WRAPPER_NO_CONTRACT;
2929
2930 #ifdef _WIN64
2931         // See code:GenericPInvokeCalliHelper
2932         return ((m_Datum != NULL) && !(dac_cast<TADDR>(m_Datum) & 0x1));
2933 #else // _WIN64
2934         return ((dac_cast<TADDR>(m_Datum) & ~0xffff) != 0);
2935 #endif // _WIN64
2936     }
2937
2938     // Retrieves the return address into the code that called out
2939     // to managed code
2940     virtual TADDR GetReturnAddressPtr()
2941     {
2942         WRAPPER_NO_CONTRACT;
2943
2944         if (FrameHasActiveCall(this))
2945             return PTR_HOST_MEMBER_TADDR(InlinedCallFrame, this,
2946                                             m_pCallerReturnAddress);
2947         else
2948             return NULL;
2949     }
2950
2951     virtual BOOL NeedsUpdateRegDisplay()
2952     {
2953         WRAPPER_NO_CONTRACT;
2954         return FrameHasActiveCall(this);
2955     }
2956
2957     // Given a methodDesc representing an ILStub for a pinvoke call,
2958     // this method will return the MethodDesc for the actual interop
2959     // method if the current InlinedCallFrame is inactive.
2960     PTR_MethodDesc GetActualInteropMethodDesc()
2961     {
2962 #if defined(_TARGET_X86_) || defined(_TARGET_ARM_)
2963         // Important: This code relies on the way JIT lays out frames. Keep it in sync
2964         // with code:Compiler.lvaAssignFrameOffsets.
2965         //
2966         // |        ...         |
2967         // +--------------------+                                       
2968         // | lvaStubArgumentVar | <= filled with EAX in prolog          |
2969         // +--------------------+                                       |
2970         // |                    |                                       |
2971         // |  InlinedCallFrame  |                                       |
2972         // |                    | <= m_pCrawl.pFrame                    | to lower addresses
2973         // +--------------------+                                       V
2974         // |        ...         |
2975         //
2976         // Extract the actual MethodDesc to report from the InlinedCallFrame.
2977         TADDR addr = dac_cast<TADDR>(this) + sizeof(InlinedCallFrame);
2978         return PTR_MethodDesc(*PTR_TADDR(addr));
2979 #elif defined(_WIN64)
2980         // On 64bit, the actual interop MethodDesc is saved off in a field off the InlinedCrawlFrame
2981         // which is populated by the JIT. Refer to JIT_InitPInvokeFrame for details.
2982         return PTR_MethodDesc(m_StubSecretArg);
2983 #else
2984         _ASSERTE(!"NYI - Interop method reporting for this architecture!");
2985         return NULL;
2986 #endif // defined(_TARGET_X86_) || defined(_TARGET_ARM_)
2987     }
2988
2989     virtual void UpdateRegDisplay(const PREGDISPLAY);
2990
2991     // m_Datum contains MethodDesc ptr or
2992     // - on AMD64: CALLI target address (if lowest bit is set)
2993     // - on X86: argument stack size (if value is <64k)
2994     // See code:HasFunction.
2995     PTR_NDirectMethodDesc   m_Datum;
2996
2997 #ifdef _WIN64
2998     // IL stubs fill this field with the incoming secret argument when they erect
2999     // InlinedCallFrame so we know which interop method was invoked even if the frame
3000     // is not active at the moment.
3001     PTR_VOID                m_StubSecretArg;
3002 #endif // _WIN64
3003
3004     // X86: ESP after pushing the outgoing arguments, and just before calling
3005     // out to unmanaged code.
3006     // Other platforms: the field stays set throughout the declaring method.
3007     PTR_VOID             m_pCallSiteSP;
3008
3009     // EIP where the unmanaged call will return to. This will be a pointer into
3010     // the code of the managed frame which has the InlinedCallFrame
3011     // This is set to NULL in the method prolog. It gets set just before the
3012     // call to the target and reset back to NULL after the stop-for-GC check
3013     // following the call.
3014     TADDR                m_pCallerReturnAddress;
3015
3016     // This is used only for EBP. Hence, a stackwalk will miss the other
3017     // callee-saved registers for the method with the InlinedCallFrame.
3018     // To prevent GC-holes, we do not keep any GC references in callee-saved
3019     // registers across an NDirect call.
3020     TADDR                m_pCalleeSavedFP;
3021
3022     // This field is used to cache the current thread object where this frame is
3023     // executing. This is especially helpful on Unix platforms for the PInvoke assembly
3024     // stubs, since there is no easy way to inline an implementation of GetThread.
3025     PTR_VOID             m_pThread;
3026
3027 #ifdef _TARGET_ARM_
3028     // Store the value of SP after prolog to ensure we can unwind functions that use
3029     // stackalloc. In these functions, the m_pCallSiteSP can already be augmented by
3030     // the stackalloc size, which is variable.
3031     TADDR               m_pSPAfterProlog;
3032 #endif // _TARGET_ARM_
3033
3034 public:
3035     //---------------------------------------------------------------
3036     // Expose key offsets and values for stub generation.
3037     //---------------------------------------------------------------
3038
3039     static void GetEEInfo(CORINFO_EE_INFO::InlinedCallFrameInfo * pEEInfo);
3040
3041     // Is the specified frame an InlinedCallFrame which has an active call
3042     // inside it right now?
3043     static BOOL FrameHasActiveCall(Frame *pFrame)
3044     {
3045         WRAPPER_NO_CONTRACT;
3046         SUPPORTS_DAC;
3047         return pFrame &&
3048             pFrame != FRAME_TOP &&
3049             InlinedCallFrame::GetMethodFrameVPtr() == pFrame->GetVTablePtr() &&
3050             dac_cast<TADDR>(dac_cast<PTR_InlinedCallFrame>(pFrame)->m_pCallerReturnAddress) != NULL;
3051     }
3052
3053     // Marks the frame as inactive.
3054     void Reset()
3055     {
3056         m_pCallerReturnAddress = NULL;
3057     }
3058     
3059     int GetFrameType()
3060     {
3061         LIMITED_METHOD_DAC_CONTRACT;
3062         return TYPE_EXIT;
3063     }
3064
3065     virtual BOOL IsTransitionToNativeFrame()
3066     {
3067         LIMITED_METHOD_CONTRACT;
3068         return TRUE;
3069     }
3070
3071     PTR_VOID GetCallSiteSP()
3072     {
3073         LIMITED_METHOD_CONTRACT;
3074         return m_pCallSiteSP;
3075     }
3076
3077     TADDR GetCalleeSavedFP()
3078     {
3079         LIMITED_METHOD_DAC_CONTRACT;
3080         return m_pCalleeSavedFP;
3081     }
3082
3083     // Set the vptr and GSCookie
3084     VOID Init();
3085
3086     // Keep as last entry in class
3087     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(InlinedCallFrame)
3088 };
3089
3090 //------------------------------------------------------------------------
3091 // This frame is used to mark a Context/AppDomain Transition
3092 //------------------------------------------------------------------------
3093
3094 class ContextTransitionFrame : public Frame
3095 {
3096 private:
3097     PTR_Object  m_LastThrownObjectInParentContext;                                        
3098     ULONG_PTR   m_LockCount;            // Number of locks the thread takes
3099                                         // before the transition.
3100     VPTR_VTABLE_CLASS(ContextTransitionFrame, Frame)
3101
3102 public:
3103     virtual void GcScanRoots(promote_func *fn, ScanContext* sc);
3104
3105     OBJECTREF GetLastThrownObjectInParentContext()
3106     {
3107         return ObjectToOBJECTREF(m_LastThrownObjectInParentContext);
3108     }
3109
3110     void SetLastThrownObjectInParentContext(OBJECTREF lastThrownObject)
3111     {
3112         m_LastThrownObjectInParentContext = OBJECTREFToObject(lastThrownObject);
3113     }
3114
3115     void SetLockCount(DWORD lockCount)
3116     {
3117         LIMITED_METHOD_CONTRACT;
3118         m_LockCount = lockCount;
3119     }
3120     DWORD GetLockCount()
3121     {
3122         LIMITED_METHOD_CONTRACT;
3123         return (DWORD) m_LockCount;
3124     }
3125
3126
3127     // Let debugger know that we're transitioning between AppDomains.
3128     ETransitionType GetTransitionType()
3129     {
3130         LIMITED_METHOD_DAC_CONTRACT;
3131         return TT_AppDomain;
3132     }
3133
3134 #ifndef DACCESS_COMPILE
3135     ContextTransitionFrame()
3136     : m_LastThrownObjectInParentContext(NULL)
3137     , m_LockCount(0)
3138     {
3139         LIMITED_METHOD_CONTRACT;
3140     }
3141 #endif
3142
3143     // Keep as last entry in class
3144     DEFINE_VTABLE_GETTER_AND_DTOR(ContextTransitionFrame)
3145 };
3146
3147 // TODO [DAVBR]: For the full fix for VsWhidbey 450273, this
3148 // may be uncommented once isLegalManagedCodeCaller works properly
3149 // with non-return address inputs, and with non-DEBUG builds
3150 //bool isLegalManagedCodeCaller(TADDR retAddr);
3151 bool isRetAddr(TADDR retAddr, TADDR* whereCalled);
3152
3153 //------------------------------------------------------------------------
3154 #ifdef _TARGET_X86_
3155 // This frame is used as padding for virtual stub dispatch tailcalls.
3156 // When A calls B via virtual stub dispatch, the stub dispatch stub resolves
3157 // the target code for B and jumps to it. If A wants to do a tail call,
3158 // it does not get a chance to unwind its frame since the virtual stub dispatch
3159 // stub is not set up to return the address of the target code (rather
3160 // than just jumping to it).
3161 // To do a tail call, A calls JIT_TailCall, which unwinds A's frame
3162 // and sets up a TailCallFrame. It then calls the stub dispatch stub
3163 // which disassembles the caller (JIT_TailCall, in this case) to get some information, 
3164 // resolves the target code for B, and then jumps to B.
3165 // If B also does a virtual stub dispatch tail call, then we reuse the
3166 // existing TailCallFrame instead of setting up a second one.
3167 // 
3168 // We could eliminate TailCallFrame if we factor the VSD stub to return
3169 // the target code address. This is currently not a very important scenario
3170 // as tail calls on interface calls are uncommon.
3171 #else
3172 // This frame is used as padding for tailcalls which require more space
3173 // than the caller has in it's incoming argument space.
3174 // To do a tail call from A to B, A calls JIT_TailCall, which unwinds A's frame
3175 // and sets up a TailCallFrame and the arguments. It then jumps to B.
3176 // If B also does a tail call, then we reuse the
3177 // existing TailCallFrame instead of setting up a second one.
3178 // 
3179 // This is also used whenever value types that aren't enregisterable are
3180 // passed by value instead of ref. This is currently not a very important
3181 // scenario as tail calls are uncommon.
3182 #endif
3183 //------------------------------------------------------------------------
3184
3185 class TailCallFrame : public Frame
3186 {
3187     VPTR_VTABLE_CLASS(TailCallFrame, Frame)
3188
3189 #if defined(_TARGET_X86_)
3190     TADDR           m_CallerAddress;    // the address the tailcall was initiated from
3191     CalleeSavedRegisters    m_regs;     // callee saved registers - the stack walk assumes that all non-JIT frames have them
3192     TADDR           m_ReturnAddress;    // the return address of the tailcall
3193 #elif defined(_TARGET_AMD64_)
3194     TADDR                 m_pGCLayout;
3195     TADDR                 m_padding;    // code:StubLinkerCPU::CreateTailCallCopyArgsThunk expects the size of TailCallFrame to be 16-byte aligned
3196     CalleeSavedRegisters  m_calleeSavedRegisters;
3197     TADDR                 m_ReturnAddress;
3198 #elif defined(_TARGET_ARM_)
3199     union {
3200         CalleeSavedRegisters m_calleeSavedRegisters;
3201         // alias saved link register as m_ReturnAddress
3202         struct {
3203             INT32 r4, r5, r6, r7, r8, r9, r10;
3204             INT32 r11;
3205             TADDR m_ReturnAddress;
3206         };
3207     };
3208 #else
3209     TADDR                 m_ReturnAddress;
3210 #endif
3211
3212 public:
3213 #ifndef CROSSGEN_COMPILE
3214 #if !defined(_TARGET_X86_)
3215
3216 #ifndef DACCESS_COMPILE
3217     TailCallFrame(T_CONTEXT * pContext, Thread * pThread) 
3218     {
3219         InitFromContext(pContext);
3220         m_Next = pThread->GetFrame();
3221     }
3222
3223     void InitFromContext(T_CONTEXT * pContext);
3224
3225     // Architecture-specific method to initialize a CONTEXT record as if the first
3226     // part of the TailCallHelperStub had executed
3227     static TailCallFrame * AdjustContextForTailCallHelperStub(_CONTEXT * pContext, size_t cbNewArgArea, Thread * pThread);
3228 #endif
3229
3230     static TailCallFrame * GetFrameFromContext(CONTEXT * pContext);
3231 #endif // !_TARGET_X86_
3232
3233 #if defined(_TARGET_X86_)
3234     static TailCallFrame* FindTailCallFrame(Frame* pFrame)
3235     {
3236         LIMITED_METHOD_CONTRACT;
3237         // loop through the frame chain
3238         while (pFrame->GetVTablePtr() != TailCallFrame::GetMethodFrameVPtr())
3239             pFrame = pFrame->m_Next;
3240         return (TailCallFrame*)pFrame;
3241     }
3242
3243     TADDR GetCallerAddress()
3244     {
3245         LIMITED_METHOD_CONTRACT;
3246         return m_CallerAddress;
3247     }
3248 #endif // _TARGET_X86_
3249
3250     virtual TADDR GetReturnAddressPtr()
3251     {
3252         LIMITED_METHOD_DAC_CONTRACT;
3253         return PTR_HOST_MEMBER_TADDR(TailCallFrame, this,
3254                                         m_ReturnAddress);
3255     }
3256
3257     virtual BOOL NeedsUpdateRegDisplay()
3258     {
3259         return TRUE;
3260     }
3261
3262     virtual void UpdateRegDisplay(const PREGDISPLAY pRD);
3263 #endif // !CROSSGEN_COMPILE
3264 #ifdef _TARGET_AMD64_
3265     void SetGCLayout(TADDR pGCLayout)
3266     {
3267         LIMITED_METHOD_CONTRACT;
3268         m_pGCLayout = pGCLayout;
3269     }
3270
3271     virtual void GcScanRoots(promote_func *fn, ScanContext* sc);
3272 #else
3273     void SetGCLayout(TADDR pGCLayout)
3274     {
3275         LIMITED_METHOD_CONTRACT;
3276         _ASSERTE(pGCLayout == NULL);
3277     }
3278 #endif
3279
3280 private:
3281     // Keep as last entry in class
3282     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(TailCallFrame)
3283 };
3284
3285 //------------------------------------------------------------------------
3286 // ExceptionFilterFrame is a small frame whose only purpose in
3287 // life is to set SHADOW_SP_FILTER_DONE during unwind from exception filter.
3288 //------------------------------------------------------------------------
3289
3290 class ExceptionFilterFrame : public Frame
3291 {
3292     VPTR_VTABLE_CLASS(ExceptionFilterFrame, Frame)
3293     size_t* m_pShadowSP;
3294
3295 public:
3296 #ifndef DACCESS_COMPILE
3297     ExceptionFilterFrame(size_t* pShadowSP)
3298     {
3299         WRAPPER_NO_CONTRACT;
3300         m_pShadowSP = pShadowSP;
3301         Push();
3302     }
3303
3304     void Pop()
3305     {
3306         // Nothing to do here.
3307         WRAPPER_NO_CONTRACT;
3308         SetFilterDone();
3309         Frame::Pop();
3310     }
3311
3312     void SetFilterDone()
3313     {
3314         LIMITED_METHOD_CONTRACT;
3315
3316         // Mark the filter as having completed
3317         if (m_pShadowSP)
3318         {
3319             // Make sure that CallJitEHFilterHelper marked us as being in the filter.
3320             _ASSERTE(*m_pShadowSP & ICodeManager::SHADOW_SP_IN_FILTER);
3321             *m_pShadowSP |= ICodeManager::SHADOW_SP_FILTER_DONE;
3322         }
3323     }
3324 #endif
3325
3326 private:
3327     // Keep as last entry in class
3328     DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(ExceptionFilterFrame)
3329 };
3330
3331 #ifdef _DEBUG
3332 // We use IsProtectedByGCFrame to check if some OBJECTREF pointers are protected 
3333 // against GC. That function doesn't know if a byref is from managed stack thus
3334 // protected by JIT. AssumeByrefFromJITStack is used to bypass that check if an 
3335 // OBJECTRef pointer is passed from managed code to an FCall and it's in stack.
3336 class AssumeByrefFromJITStack : public Frame
3337 {
3338     VPTR_VTABLE_CLASS(AssumeByrefFromJITStack, Frame)
3339 public:
3340 #ifndef DACCESS_COMPILE
3341     AssumeByrefFromJITStack(OBJECTREF *pObjRef)
3342     {
3343         m_pObjRef      = pObjRef;
3344     }
3345 #endif
3346
3347     BOOL Protects(OBJECTREF *ppORef)
3348     {
3349         LIMITED_METHOD_CONTRACT;
3350         return ppORef == m_pObjRef;
3351     }
3352
3353 private:
3354     OBJECTREF *m_pObjRef;
3355
3356     // Keep as last entry in class
3357     DEFINE_VTABLE_GETTER_AND_DTOR(AssumeByrefFromJITStack)
3358 }; //AssumeByrefFromJITStack
3359
3360 #endif //_DEBUG
3361
3362 //-----------------------------------------------------------------------------
3363 // FrameWithCookie is used to declare a Frame in source code with a cookie
3364 // immediately preceeding it.
3365 // This is just a specialized version of GSCookieFor<T>
3366 //
3367 // For Frames that are set up by stubs, the stub is responsible for setting up
3368 // the GSCookie.
3369 //
3370 // Note that we have to play all these games for the GSCookie as the GSCookie
3371 // needs to precede the vtable pointer, so that the GSCookie is guaranteed to 
3372 // catch any stack-buffer-overrun corruptions that overwrite the Frame data.
3373 //
3374 //-----------------------------------------------------------------------------
3375
3376 class DebuggerEval;
3377
3378 class GCSafeCollection;
3379
3380 template <typename FrameType>
3381 class FrameWithCookie
3382 {
3383 protected:
3384
3385     GSCookie        m_gsCookie;
3386     FrameType       m_frame;
3387
3388 public:
3389
3390     //
3391     // Overload all the required constructors
3392     //
3393
3394     FrameWithCookie() :
3395         m_gsCookie(GetProcessGSCookie()), m_frame() { WRAPPER_NO_CONTRACT; }
3396
3397     FrameWithCookie(Thread * pThread) :
3398         m_gsCookie(GetProcessGSCookie()), m_frame(pThread) { WRAPPER_NO_CONTRACT; }
3399         
3400     FrameWithCookie(T_CONTEXT * pContext) :
3401         m_gsCookie(GetProcessGSCookie()), m_frame(pContext) { WRAPPER_NO_CONTRACT; }
3402
3403     FrameWithCookie(TransitionBlock * pTransitionBlock) :
3404         m_gsCookie(GetProcessGSCookie()), m_frame(pTransitionBlock) { WRAPPER_NO_CONTRACT; }
3405
3406     FrameWithCookie(TransitionBlock * pTransitionBlock, MethodDesc * pMD) :
3407         m_gsCookie(GetProcessGSCookie()), m_frame(pTransitionBlock, pMD) { WRAPPER_NO_CONTRACT; }
3408
3409     FrameWithCookie(TransitionBlock * pTransitionBlock, VASigCookie * pVASigCookie, PCODE pUnmanagedTarget) :
3410         m_gsCookie(GetProcessGSCookie()), m_frame(pTransitionBlock, pVASigCookie, pUnmanagedTarget) { WRAPPER_NO_CONTRACT; }
3411
3412     FrameWithCookie(TransitionBlock * pTransitionBlock, int frameFlags) :
3413         m_gsCookie(GetProcessGSCookie()), m_frame(pTransitionBlock, frameFlags) { WRAPPER_NO_CONTRACT; }
3414
3415
3416     // GCFrame
3417     FrameWithCookie(Thread * pThread, OBJECTREF *pObjRefs, UINT numObjRefs, BOOL maybeInterior) :
3418         m_gsCookie(GetProcessGSCookie()), m_frame(pThread, pObjRefs, numObjRefs, maybeInterior) { WRAPPER_NO_CONTRACT; }
3419
3420     FrameWithCookie(OBJECTREF *pObjRefs, UINT numObjRefs, BOOL maybeInterior) :
3421         m_gsCookie(GetProcessGSCookie()), m_frame(pObjRefs, numObjRefs, maybeInterior) { WRAPPER_NO_CONTRACT; }
3422
3423     // GCSafeCollectionFrame
3424     FrameWithCookie(GCSafeCollection *gcSafeCollection) :
3425         m_gsCookie(GetProcessGSCookie()), m_frame(gcSafeCollection) { WRAPPER_NO_CONTRACT; }
3426
3427 #ifdef FEATURE_INTERPRETER
3428     // InterpreterFrame
3429     FrameWithCookie(Interpreter* interp) :
3430         m_gsCookie(GetProcessGSCookie()), m_frame(interp) { WRAPPER_NO_CONTRACT; }
3431 #endif
3432
3433     // HijackFrame
3434     FrameWithCookie(LPVOID returnAddress, Thread *thread, HijackArgs *args) :
3435         m_gsCookie(GetProcessGSCookie()), m_frame(returnAddress, thread, args) { WRAPPER_NO_CONTRACT; }
3436
3437 #ifdef DEBUGGING_SUPPORTED
3438     // FuncEvalFrame
3439     FrameWithCookie(DebuggerEval *pDebuggerEval, TADDR returnAddress, BOOL showFrame) :
3440         m_gsCookie(GetProcessGSCookie()), m_frame(pDebuggerEval, returnAddress, showFrame) { WRAPPER_NO_CONTRACT; }
3441 #endif // DEBUGGING_SUPPORTED
3442
3443     // TailCallFrame
3444     FrameWithCookie(T_CONTEXT * pContext, Thread *thread) :
3445         m_gsCookie(GetProcessGSCookie()), m_frame(pContext, thread) { WRAPPER_NO_CONTRACT; }
3446
3447 #ifndef DACCESS_COMPILE
3448     // GSCookie for HelperMethodFrames is initialized in a common HelperMethodFrame init method
3449
3450     // HelperMethodFrame
3451     FORCEINLINE FrameWithCookie(void* fCallFtnEntry, unsigned attribs = 0) :
3452         m_frame(fCallFtnEntry, attribs) { WRAPPER_NO_CONTRACT; }
3453
3454     // HelperMethodFrame_1OBJ
3455     FORCEINLINE FrameWithCookie(void* fCallFtnEntry, unsigned attribs, OBJECTREF * aGCPtr1) :
3456         m_frame(fCallFtnEntry, attribs, aGCPtr1) { WRAPPER_NO_CONTRACT; }
3457
3458     // HelperMethodFrame_2OBJ
3459     FORCEINLINE FrameWithCookie(void* fCallFtnEntry, unsigned attribs, OBJECTREF * aGCPtr1, OBJECTREF * aGCPtr2) :
3460         m_frame(fCallFtnEntry, attribs, aGCPtr1, aGCPtr2) { WRAPPER_NO_CONTRACT; }
3461
3462     // HelperMethodFrame_3OBJ
3463     FORCEINLINE FrameWithCookie(void* fCallFtnEntry, unsigned attribs, OBJECTREF * aGCPtr1, OBJECTREF * aGCPtr2, OBJECTREF * aGCPtr3) :
3464         m_frame(fCallFtnEntry, attribs, aGCPtr1, aGCPtr2, aGCPtr3) { WRAPPER_NO_CONTRACT; }
3465
3466     // HelperMethodFrame_PROTECTOBJ
3467     FORCEINLINE FrameWithCookie(void* fCallFtnEntry, unsigned attribs, OBJECTREF* pObjRefs, int numObjRefs) :
3468         m_frame(fCallFtnEntry, attribs, pObjRefs, numObjRefs) { WRAPPER_NO_CONTRACT; }
3469
3470 #endif // DACCESS_COMPILE
3471
3472     // ProtectByRefsFrame
3473     FrameWithCookie(Thread * pThread, ByRefInfo * pByRefs) :
3474         m_gsCookie(GetProcessGSCookie()), m_frame(pThread, pByRefs) { WRAPPER_NO_CONTRACT; }
3475
3476     // ProtectValueClassFrame
3477     FrameWithCookie(Thread * pThread, ValueClassInfo * pValueClasses) :
3478         m_gsCookie(GetProcessGSCookie()), m_frame(pThread, pValueClasses) { WRAPPER_NO_CONTRACT; }
3479
3480     // ExceptionFilterFrame
3481     FrameWithCookie(size_t* pShadowSP) :
3482         m_gsCookie(GetProcessGSCookie()), m_frame(pShadowSP) { WRAPPER_NO_CONTRACT; }
3483         
3484 #ifdef _DEBUG
3485     // AssumeByrefFromJITStack
3486     FrameWithCookie(OBJECTREF *pObjRef) :
3487         m_gsCookie(GetProcessGSCookie()), m_frame(pObjRef) { WRAPPER_NO_CONTRACT; }
3488
3489     void SetAddrOfHaveCheckedRestoreState(BOOL* pDoneCheck)
3490     {
3491         WRAPPER_NO_CONTRACT;
3492         m_frame.SetAddrOfHaveCheckedRestoreState(pDoneCheck);
3493     }
3494
3495 #endif //_DEBUG
3496
3497     //
3498     // Overload some common Frame methods for easy redirection
3499     //
3500
3501     void Push() { WRAPPER_NO_CONTRACT; m_frame.Push(); }
3502     void Pop() { WRAPPER_NO_CONTRACT; m_frame.Pop(); }
3503     void Push(Thread * pThread) { WRAPPER_NO_CONTRACT; m_frame.Push(pThread); }
3504     void Pop(Thread * pThread) { WRAPPER_NO_CONTRACT; m_frame.Pop(pThread); }
3505     PCODE GetReturnAddress() { WRAPPER_NO_CONTRACT; return m_frame.GetReturnAddress(); }
3506     T_CONTEXT * GetContext() { WRAPPER_NO_CONTRACT; return m_frame.GetContext(); }
3507     FrameType* operator&() { LIMITED_METHOD_CONTRACT; return &m_frame; }
3508     LazyMachState * MachineState() { WRAPPER_NO_CONTRACT; return m_frame.MachineState(); }
3509     Thread * GetThread() { WRAPPER_NO_CONTRACT; return m_frame.GetThread(); }
3510     BOOL InsureInit(bool initialInit, struct MachState* unwindState)
3511         { WRAPPER_NO_CONTRACT; return m_frame.InsureInit(initialInit, unwindState); }
3512     void Poll() { WRAPPER_NO_CONTRACT; m_frame.Poll(); }
3513     void SetStackPointerPtr(TADDR sp) { WRAPPER_NO_CONTRACT; m_frame.SetStackPointerPtr(sp); }
3514     void InitAndLink(T_CONTEXT *pContext) { WRAPPER_NO_CONTRACT; m_frame.InitAndLink(pContext); }
3515     void Init(Thread *pThread, OBJECTREF *pObjRefs, UINT numObjRefs, BOOL maybeInterior)
3516         { WRAPPER_NO_CONTRACT; m_frame.Init(pThread, pObjRefs, numObjRefs, maybeInterior); }
3517     ValueClassInfo ** GetValueClassInfoList() { WRAPPER_NO_CONTRACT; return m_frame.GetValueClassInfoList(); }
3518
3519 #if 0
3520     //
3521     // Access to the underlying Frame
3522     // You should only need to use this if none of the above overloads work for you
3523     // Consider adding the required overload to the list above
3524     //
3525
3526     FrameType& operator->() { LIMITED_METHOD_CONTRACT; return m_frame; }
3527 #endif
3528
3529     // Since the "&" operator is overloaded, use this function to get to the
3530     // address of FrameWithCookie, rather than that of FrameWithCookie::m_frame.
3531     GSCookie * GetGSCookiePtr() { LIMITED_METHOD_CONTRACT; return &m_gsCookie; }
3532 };
3533
3534 //------------------------------------------------------------------------
3535 // These macros GC-protect OBJECTREF pointers on the EE's behalf.
3536 // In between these macros, the GC can move but not discard the protected
3537 // objects. If the GC moves an object, it will update the guarded OBJECTREF's.
3538 // Typical usage:
3539 //
3540 //   OBJECTREF or = <some valid objectref>;
3541 //   GCPROTECT_BEGIN(or);
3542 //
3543 //   ...<do work that can trigger GC>...
3544 //
3545 //   GCPROTECT_END();
3546 //
3547 //
3548 // These macros can also protect multiple OBJECTREF's if they're packaged
3549 // into a structure:
3550 //
3551 //   struct xx {
3552 //      OBJECTREF o1;
3553 //      OBJECTREF o2;
3554 //   } gc;
3555 //
3556 //   GCPROTECT_BEGIN(gc);
3557 //   ....
3558 //   GCPROTECT_END();
3559 //
3560 //
3561 // Notes:
3562 //
3563 //   - GCPROTECT_BEGININTERIOR() can be used in place of GCPROTECT_BEGIN()
3564 //     to handle the case where one or more of the OBJECTREFs is potentially
3565 //     an interior pointer.  This is a rare situation, because boxing would
3566 //     normally prevent us from encountering it.  Be aware that the OBJECTREFs
3567 //     we protect are not validated in this situation.
3568 //
3569 //   - GCPROTECT_ARRAY_BEGIN() can be used when an array of object references
3570 //     is allocated on the stack.  The pointer to the first element is passed
3571 //     along with the number of elements in the array.
3572 //
3573 //   - The argument to GCPROTECT_BEGIN should be an lvalue because it
3574 //     uses "sizeof" to count the OBJECTREF's.
3575 //
3576 //   - GCPROTECT_BEGIN spiritually violates our normal convention of not passing
3577 //     non-const refernce arguments. Unfortunately, this is necessary in
3578 //     order for the sizeof thing to work.
3579 //
3580 //   - GCPROTECT_BEGIN does _not_ zero out the OBJECTREF's. You must have
3581 //     valid OBJECTREF's when you invoke this macro.
3582 //
3583 //   - GCPROTECT_BEGIN begins a new C nesting block. Besides allowing
3584 //     GCPROTECT_BEGIN's to nest, it also has the advantage of causing
3585 //     a compiler error if you forget to code a maching GCPROTECT_END.
3586 //
3587 //   - If you are GCPROTECTing something, it means you are expecting a GC to occur.
3588 //     So we assert that GC is not forbidden. If you hit this assert, you probably need
3589 //     a HELPER_METHOD_FRAME to protect the region that can cause the GC.
3590 //------------------------------------------------------------------------
3591
3592 #ifndef DACCESS_COMPILE
3593
3594 #ifdef _PREFAST_
3595 // Suppress prefast warning #6384: Dividing sizeof a pointer by another value
3596 #pragma warning(disable:6384)
3597 #endif /*_PREFAST_ */
3598
3599 #define GCPROTECT_BEGIN(ObjRefStruct)                           do {    \
3600                 FrameWithCookie<GCFrame> __gcframe(                     \
3601                         (OBJECTREF*)&(ObjRefStruct),                    \
3602                         sizeof(ObjRefStruct)/sizeof(OBJECTREF),         \
3603                         FALSE);                                         \
3604                 /* work around unreachable code warning */              \
3605                 if (true) { DEBUG_ASSURE_NO_RETURN_BEGIN(GCPROTECT)
3606
3607 #define GCPROTECT_BEGIN_THREAD(pThread, ObjRefStruct)           do {    \
3608                 FrameWithCookie<GCFrame> __gcframe(                     \
3609                         pThread,                                        \
3610                         (OBJECTREF*)&(ObjRefStruct),                    \
3611                         sizeof(ObjRefStruct)/sizeof(OBJECTREF),         \
3612                         FALSE);                                         \
3613                 /* work around unreachable code warning */              \
3614                 if (true) { DEBUG_ASSURE_NO_RETURN_BEGIN(GCPROTECT)
3615
3616 #define GCPROTECT_ARRAY_BEGIN(ObjRefArray,cnt) do {                     \
3617                 FrameWithCookie<GCFrame> __gcframe(                     \
3618                         (OBJECTREF*)&(ObjRefArray),                     \
3619                         cnt * sizeof(ObjRefArray) / sizeof(OBJECTREF),  \
3620                         FALSE);                                         \
3621                 /* work around unreachable code warning */              \
3622                 if (true) { DEBUG_ASSURE_NO_RETURN_BEGIN(GCPROTECT)
3623
3624 #define GCPROTECT_BEGININTERIOR(ObjRefStruct)           do {            \
3625                 /* work around Wsizeof-pointer-div warning as we */     \
3626                 /* mean to capture pointer or object size */            \
3627                 UINT subjectSize = sizeof(ObjRefStruct);                \
3628                 FrameWithCookie<GCFrame> __gcframe(                     \
3629                         (OBJECTREF*)&(ObjRefStruct),                    \
3630                         subjectSize/sizeof(OBJECTREF),                  \
3631                         TRUE);                                          \
3632                 /* work around unreachable code warning */              \
3633                 if (true) { DEBUG_ASSURE_NO_RETURN_BEGIN(GCPROTECT)
3634
3635 #define GCPROTECT_BEGININTERIOR_ARRAY(ObjRefArray,cnt) do {             \
3636                 FrameWithCookie<GCFrame> __gcframe(                     \
3637                         (OBJECTREF*)&(ObjRefArray),                     \
3638                         cnt,                                            \
3639                         TRUE);                                          \
3640                 /* work around unreachable code warning */              \
3641                 if (true) { DEBUG_ASSURE_NO_RETURN_BEGIN(GCPROTECT)
3642
3643
3644 #define GCPROTECT_END()                                                 \
3645                 DEBUG_ASSURE_NO_RETURN_END(GCPROTECT) }                 \
3646                 __gcframe.Pop(); } while(0)
3647
3648
3649 #else // #ifndef DACCESS_COMPILE
3650
3651 #define GCPROTECT_BEGIN(ObjRefStruct)
3652 #define GCPROTECT_ARRAY_BEGIN(ObjRefArray,cnt)
3653 #define GCPROTECT_BEGININTERIOR(ObjRefStruct)
3654 #define GCPROTECT_END()
3655
3656 #endif // #ifndef DACCESS_COMPILE
3657
3658
3659 #define ASSERT_ADDRESS_IN_STACK(address) _ASSERTE (Thread::IsAddressInCurrentStack (address));
3660
3661 #if defined (_DEBUG) && !defined (DACCESS_COMPILE)
3662 #define ASSUME_BYREF_FROM_JIT_STACK_BEGIN(__objRef)                                      \
3663                 /* make sure we are only called inside an FCall */                       \
3664                 if (__me == 0) {};                                                       \
3665                 /* make sure the address is in stack. If the address is an interior */   \
3666                 /*pointer points to GC heap, the FCall still needs to protect it explicitly */             \
3667                 ASSERT_ADDRESS_IN_STACK (__objRef);                                      \
3668                 do {                                                                     \
3669                 FrameWithCookie<AssumeByrefFromJITStack> __dummyAssumeByrefFromJITStack ((__objRef));       \
3670                 __dummyAssumeByrefFromJITStack.Push ();                                  \
3671                 /* work around unreachable code warning */                               \
3672                 if (true) { DEBUG_ASSURE_NO_RETURN_BEGIN(GC_PROTECT)
3673
3674 #define ASSUME_BYREF_FROM_JIT_STACK_END()                                          \
3675                 DEBUG_ASSURE_NO_RETURN_END(GC_PROTECT) }                                            \
3676                 __dummyAssumeByrefFromJITStack.Pop(); } while(0)
3677 #else //defined (_DEBUG) && !defined (DACCESS_COMPILE)
3678 #define ASSUME_BYREF_FROM_JIT_STACK_BEGIN(__objRef)
3679 #define ASSUME_BYREF_FROM_JIT_STACK_END()    
3680 #endif //defined (_DEBUG) && !defined (DACCESS_COMPILE)
3681
3682 //------------------------------------------------------------------------
3683
3684 #if defined(FRAMES_TURNED_FPO_ON)
3685 #pragma optimize("", on)    // Go back to command line default optimizations
3686 #undef FRAMES_TURNED_FPO_ON
3687 #undef FPO_ON
3688 #endif
3689
3690 #include "crossloaderallocatorhash.inl"
3691
3692 #endif  //__frames_h__