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