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