summaryrefslogtreecommitdiff
path: root/src/vm/newcompressedstack.h
blob: e3a639353de7b47ebc04b9e048b383886e00afd6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// 


//

#ifndef __newcompressedstack_h__
#define __newcompressedstack_h__
#ifdef FEATURE_COMPRESSEDSTACK

#include "objectlist.h"
// Returns true if the low bit in the ptr argument is set to 1
#define IS_LOW_BIT_SET(ptr) (((UINT_PTR)ptr) & 1)
// Sets the low bit in the ptr passed in
#define SET_LOW_BIT(ptr) (((UINT_PTR)ptr)|1)
// Reset the low bit to 0
#define UNSET_LOW_BIT(ptr) (((UINT_PTR)ptr)& ~((size_t)1))

class DomainCompressedStack;
class NewCompressedStack;



// This is the class that will contain an array of entries.
// All the entries will be for a single AppDomain
class DomainCompressedStack
{
    friend class NewCompressedStack;
public:
    ADID GetMyDomain()
    {
        // It is OK if m_DomainID gets set to -1 by ADU code and we return a valid AD.
        // (what that means is that tmp_adid is not invalid, but m_DomainID is set to invalid by ADU code
        // after we cached it)
        // Two cases:
        // 1. AD has set NoEnter
        // 1.a) current thread is finalizer: it will be allowed to enter the AD, but Destroy() takes a lock and checks again. So we're good
        // 1.b) current thread is not finalizer: it will not be allowed to enter AD and the value returned here will be NULL
        // 2. AD has not set NoEnter, but is in the process of CS processing at ADU
        //    A valid AD pointer is returned, which is all that this function is required to do. Since ADU unload is done handling this DCS, we'll not 
        //    enter that AD, but use the blob in the DCS.
        CONTRACTL
        {
            NOTHROW;
            GC_NOTRIGGER;
            MODE_COOPERATIVE;
            SO_TOLERANT;
        } 
        CONTRACTL_END;

        return m_DomainID;
    }
    // Construction and maintenence
    DomainCompressedStack(ADID domainID); //ctor
    BOOL IsAssemblyPresent(ISharedSecurityDescriptor* ssd);
    void AddEntry(void *ptr);
#ifndef DACCESS_COMPILE
    void AddFrameEntry(AppDomain * pAppDomain, FRAMESECDESCREF fsdRef, BOOL bIsAHDMFrame, OBJECTREF dynamicResolverRef);
#endif
    void Destroy(void);

    // Demand evaluation
    static FCDECL1(DWORD, GetDescCount, DomainCompressedStack* dcs);
    static FCDECL3(void, GetDomainPermissionSets, DomainCompressedStack* dcs, OBJECTREF* ppGranted, OBJECTREF* ppDenied);
    static FCDECL6(FC_BOOL_RET, GetDescriptorInfo, DomainCompressedStack* dcs, DWORD index, OBJECTREF* ppGranted, OBJECTREF* ppDenied, OBJECTREF* ppAssembly, OBJECTREF* ppFSD);
    static FCDECL1(FC_BOOL_RET, IgnoreDomain, DomainCompressedStack* dcs);
    OBJECTREF GetDomainCompressedStackInternal(AppDomain *pDomain);

    // AppDomain unload
    void ClearDomainInfo(void);
    static void AllHandleAppDomainUnload(AppDomain* pDomain, ADID domainId, ObjectList* list );
    static void ReleaseDomainCompressedStack( DomainCompressedStack* dcs ) { 
        WRAPPER_NO_CONTRACT;
        dcs->Destroy(); 
    };
    static DomainCompressedStack* GetNextEntryFromADList(AppDomain* pDomain, ObjectList::Iterator iter);
    void AppDomainUnloadDone(AppDomain* pDomain);



private:
    ArrayList m_EntryList;
    ADID m_DomainID; // either a valid domain ID or INVALID_APPDOMAIN_ID (set by unloading AppDomain to that value)
    BOOL m_ignoreAD; // Do not look at domain grant set since we have a CS at the threadbaseobject.
    DWORD m_dwOverridesCount;    
    DWORD m_dwAssertCount;
    BOOL m_Homogeneous;
    
    DWORD GetOverridesCount( void )
    {
        LIMITED_METHOD_CONTRACT;
        return m_dwOverridesCount;
    }
    
    DWORD GetAssertCount( void )
    {
        LIMITED_METHOD_CONTRACT;
        return m_dwAssertCount;
    }

    BOOL IgnoreDomainInternal();
};
typedef Holder<DomainCompressedStack*, DoNothing< DomainCompressedStack* >, DomainCompressedStack::ReleaseDomainCompressedStack > DomainCompressedStackHolder;

class NewCompressedStack
{
    
private:
        DomainCompressedStack** m_DCSList;
        DWORD m_DCSListCount;
        DomainCompressedStack *m_currentDCS;
        Frame *m_pCtxTxFrame; // Be super careful where you use this. Remember that this is a stack location and is not always valid.
        ADID m_CSAD;
        AppDomainStack m_ADStack;
        DWORD adStackIndex;
        DWORD m_dwOverridesCount;
        DWORD m_dwAssertCount;

        
        void CreateDCS(ADID domainID);
        BOOL IsAssemblyPresent(ADID domainID, ISharedSecurityDescriptor* pSsd);
        BOOL IsDCSContained(DomainCompressedStack *pDCS);
        BOOL IsNCSContained(NewCompressedStack *pCS);
        void ProcessSingleDomainNCS(NewCompressedStack *pCS, AppDomain* pAppDomain);
public:
    DWORD GetDCSListCount(void)
    {
        // Returns # of non-NULL DCSList entries;
        LIMITED_METHOD_CONTRACT;
        return m_DCSListCount;
    }
    void Destroy( CLR_BOOL bEntriesOnly = FALSE);

    static void DestroyCompressedStack( NewCompressedStack* stack ) { 
        WRAPPER_NO_CONTRACT;
        stack->Destroy(); 
    };
    
    AppDomainStack& GetAppDomainStack( void )
    {
        LIMITED_METHOD_CONTRACT;
        return m_ADStack;
    }

    DWORD GetOverridesCount( void )
    {
        LIMITED_METHOD_CONTRACT;
        return m_dwOverridesCount;
    }
    
    DWORD GetAssertCount( void )
    {
        LIMITED_METHOD_CONTRACT;
        return m_dwAssertCount;
    }
    DWORD GetInnerAppDomainOverridesCount(void)
    {
        WRAPPER_NO_CONTRACT;
        return m_ADStack.GetInnerAppDomainOverridesCount();
    }
    DWORD GetInnerAppDomainAssertCount(void)
    {
        WRAPPER_NO_CONTRACT;
        return m_ADStack.GetInnerAppDomainAssertCount();
    }
    
    // This is called every time we hit a stack frame on a stack walk. it will be called with ASD, SSD, FSDs and this func will determine what
    // (if any) action needs to be performed. 
    // For example:
    // on seeing a new SSD, we'll add an entry to the current DCS
    // on seeing an SSD we've already seen, we'll do nothing
    // on seeing a new ASD, a new DCS will be created on this CS
#ifndef DACCESS_COMPILE
    void ProcessAppDomainTransition(void);
    DWORD ProcessFrame(AppDomain* pAppDomain, Assembly* pAssembly, MethodDesc* pFunc, ISharedSecurityDescriptor* pSsd, FRAMESECDESCREF* pFsdRef);
    void ProcessCS(AppDomain* pAppDomain, COMPRESSEDSTACKREF csRef, Frame *pFrame);

#endif 
    // ctor
    NewCompressedStack();
    OBJECTREF GetCompressedStackInner();

    // FCALLS
    static FCDECL1(DWORD, FCallGetDCSCount, SafeHandle* hcsUNSAFE);
    static FCDECL2(FC_BOOL_RET, FCallIsImmediateCompletionCandidate, SafeHandle* hcsUNSAFE, OBJECTREF *innerCS);
    static FCDECL2(Object*, GetDomainCompressedStack, SafeHandle* hcsUNSAFE, DWORD index);
    static FCDECL1(void, DestroyDCSList, SafeHandle* hcsUNSAFE);
    static FCDECL1(void, FCallGetHomogeneousPLS, Object* hgPLSUnsafe);

};
typedef Holder<NewCompressedStack*, DoNothing< NewCompressedStack* >, NewCompressedStack::DestroyCompressedStack > NewCompressedStackHolder;
#endif // #ifdef FEATURE_COMPRESSEDSTACK
#endif /* __newcompressedstack_h__ */