summaryrefslogtreecommitdiff
path: root/src/vm/common.h
blob: 1008533dddad4523b5742f8b7d3b4fd61e248c71 (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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
// 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.
//
// common.h - precompiled headers include for the COM+ Execution Engine
//

//


#ifndef _common_h_ 
#define _common_h_

#if defined(_MSC_VER) && defined(_X86_) && !defined(FPO_ON)
#pragma optimize("y", on)       // Small critical routines, don't put in EBP frame 
#define FPO_ON 1
#define COMMON_TURNED_FPO_ON 1
#endif

#define USE_COM_CONTEXT_DEF

#if defined(_DEBUG) && !defined(CROSSGEN_COMPILE)
#define DEBUG_REGDISPLAY
#endif

#ifdef _MSC_VER 

    // These don't seem useful, so turning them off is no big deal
#pragma warning(disable:4201)   // nameless struct/union
#pragma warning(disable:4510)   // can't generate default constructor
//#pragma warning(disable:4511)   // can't generate copy constructor
#pragma warning(disable:4512)   // can't generate assignment constructor
#pragma warning(disable:4610)   // user defined constructor required
#pragma warning(disable:4211)   // nonstandard extention used (char name[0] in structs)
#pragma warning(disable:4268)   // 'const' static/global data initialized with compiler generated default constructor fills the object with zeros
#pragma warning(disable:4238)   // nonstandard extension used : class rvalue used as lvalue
#pragma warning(disable:4291)   // no matching operator delete found
#pragma warning(disable:4345)   // behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized

    // Depending on the code base, you may want to not disable these
#pragma warning(disable:4245)   // assigning signed / unsigned
//#pragma warning(disable:4146)   // unary minus applied to unsigned
//#pragma warning(disable:4244)   // loss of data int -> char ..
#pragma warning(disable:4127)   // conditional expression is constant
#pragma warning(disable:4100)   // unreferenced formal parameter

#pragma warning(1:4189)   // local variable initialized but not used

#ifndef DEBUG 
#pragma warning(disable:4505)   // unreferenced local function has been removed
//#pragma warning(disable:4702)   // unreachable code
#pragma warning(disable:4313)   // 'format specifier' in format string conflicts with argument %d of type 'type'
#endif // !DEBUG

    // CONSIDER put these back in
#pragma warning(disable:4063)   // bad switch value for enum (only in Disasm.cpp)
#pragma warning(disable:4710)   // function not inlined
#pragma warning(disable:4527)   // user-defined destructor required
#pragma warning(disable:4513)   // destructor could not be generated

    // <TODO>TODO we really probably need this one put back in!!!</TODO>
//#pragma warning(disable:4701)   // local variable may be used without being initialized
#endif // _MSC_VER

#define _CRT_DEPENDENCY_   //this code depends on the crt file functions


#include <stdint.h>
#include <winwrap.h>


#include <windef.h>
#include <winnt.h>
#include <stdlib.h>
#include <wchar.h>
#include <objbase.h>
#include <stddef.h>
#include <float.h>
#include <math.h>
#include <time.h>
#include <limits.h>
#include <assert.h>

#include <olectl.h>

#ifdef _MSC_VER 
//non inline intrinsics are faster
#pragma function(memcpy,memcmp,strcmp,strcpy,strlen,strcat)
#endif // _MSC_VER

#include "volatile.h"

// make all the unsafe redefinitions available
#include "unsafe.h"

#include <../../debug/inc/dbgtargetcontext.h>

//-----------------------------------------------------------------------------------------------------------

#include "strongname.h"
#include "stdmacros.h"

#define POISONC ((UINT_PTR)((sizeof(int *) == 4)?0xCCCCCCCCL:I64(0xCCCCCCCCCCCCCCCC)))

#include "ndpversion.h"
#include "switches.h"
#include "holder.h"
#include "classnames.h"
#include "util.hpp"
#include "corpriv.h"
//#include "WarningControl.h"

#include <daccess.h>

typedef VPTR(class LoaderAllocator)     PTR_LoaderAllocator;
typedef VPTR(class AppDomain)           PTR_AppDomain;
typedef VPTR(class AppDomainBaseObject) PTR_AppDomainBaseObject;
typedef DPTR(class ArrayBase)           PTR_ArrayBase;
typedef DPTR(class ArrayTypeDesc)       PTR_ArrayTypeDesc;
typedef DPTR(class Assembly)            PTR_Assembly;
typedef DPTR(class AssemblyBaseObject)  PTR_AssemblyBaseObject;
typedef DPTR(class AssemblyNameBaseObject) PTR_AssemblyNameBaseObject;
typedef VPTR(class BaseDomain)          PTR_BaseDomain;
typedef DPTR(class ClassLoader)         PTR_ClassLoader;
typedef DPTR(class ComCallMethodDesc)   PTR_ComCallMethodDesc;
typedef VPTR(class CompilationDomain)   PTR_CompilationDomain;
typedef DPTR(class ComPlusCallMethodDesc) PTR_ComPlusCallMethodDesc;
typedef VPTR(class DebugInterface)      PTR_DebugInterface;
typedef DPTR(class Dictionary)          PTR_Dictionary;
typedef VPTR(class DomainAssembly)      PTR_DomainAssembly;
typedef VPTR(class DomainFile)          PTR_DomainFile;
typedef VPTR(class DomainModule)        PTR_DomainModule;
typedef DPTR(struct FailedAssembly)     PTR_FailedAssembly;
typedef VPTR(class EditAndContinueModule) PTR_EditAndContinueModule;
typedef DPTR(class EEClass)             PTR_EEClass;
typedef DPTR(class DelegateEEClass)     PTR_DelegateEEClass;
typedef DPTR(struct DomainLocalModule)  PTR_DomainLocalModule;
typedef VPTR(class EECodeManager)       PTR_EECodeManager;
typedef DPTR(class EEConfig)            PTR_EEConfig;
typedef VPTR(class EEDbgInterfaceImpl)  PTR_EEDbgInterfaceImpl;
typedef VPTR(class DebugInfoManager)    PTR_DebugInfoManager;
typedef DPTR(class FieldDesc)           PTR_FieldDesc;
typedef VPTR(class Frame)               PTR_Frame;
typedef VPTR(class ICodeManager)        PTR_ICodeManager;
typedef VPTR(class IJitManager)         PTR_IJitManager;
typedef VPTR(struct IUnknown)           PTR_IUnknown;
typedef DPTR(class InstMethodHashTable) PTR_InstMethodHashTable;
typedef DPTR(class MetaSig)             PTR_MetaSig;
typedef DPTR(class MethodDesc)          PTR_MethodDesc;
typedef DPTR(class MethodDescChunk)     PTR_MethodDescChunk;
typedef DPTR(class MethodImpl)          PTR_MethodImpl;
typedef DPTR(class MethodTable)         PTR_MethodTable;
typedef DPTR(class MscorlibBinder)      PTR_MscorlibBinder;
typedef VPTR(class Module)              PTR_Module;
typedef DPTR(class NDirectMethodDesc)   PTR_NDirectMethodDesc;
typedef VPTR(class Thread)              PTR_Thread;
typedef DPTR(class Object)              PTR_Object;
typedef DPTR(PTR_Object)                PTR_PTR_Object;
typedef DPTR(class ObjHeader)           PTR_ObjHeader;
typedef DPTR(class Precode)             PTR_Precode;
typedef VPTR(class ReflectionModule)    PTR_ReflectionModule;
typedef DPTR(class ReflectClassBaseObject) PTR_ReflectClassBaseObject;
typedef DPTR(class ReflectMethodObject) PTR_ReflectMethodObject;
typedef DPTR(class ReflectFieldObject)  PTR_ReflectFieldObject;
typedef DPTR(class ReflectModuleBaseObject) PTR_ReflectModuleBaseObject;
typedef DPTR(class ReJitManager)        PTR_ReJitManager;
typedef DPTR(struct ReJitInfo)          PTR_ReJitInfo;
typedef DPTR(struct SharedReJitInfo)    PTR_SharedReJitInfo;
typedef DPTR(class StringObject)        PTR_StringObject;
typedef DPTR(class StringBufferObject)  PTR_StringBufferObject;
typedef DPTR(class TypeHandle)          PTR_TypeHandle;
typedef VPTR(class VirtualCallStubManager) PTR_VirtualCallStubManager;
typedef VPTR(class VirtualCallStubManagerManager) PTR_VirtualCallStubManagerManager;
typedef VPTR(class IGCHeap)             PTR_IGCHeap;

//
// _UNCHECKED_OBJECTREF is for code that can't deal with DEBUG OBJECTREFs
//
typedef PTR_Object _UNCHECKED_OBJECTREF;
typedef DPTR(PTR_Object) PTR_UNCHECKED_OBJECTREF;

#ifdef USE_CHECKED_OBJECTREFS
class OBJECTREF;
#else
typedef PTR_Object OBJECTREF;
#endif
typedef DPTR(OBJECTREF) PTR_OBJECTREF;
typedef DPTR(PTR_OBJECTREF) PTR_PTR_OBJECTREF;

EXTERN_C Thread* STDCALL GetThread();
BOOL SetThread(Thread*);

// This is a mechanism by which macros can make the Thread pointer available to inner scopes
// that is robust to code changes.  If the outer Thread no longer is available for some reason
// (e.g. code refactoring), this GET_THREAD() macro will fall back to calling GetThread().
const bool CURRENT_THREAD_AVAILABLE = false;
Thread * const CURRENT_THREAD = NULL;
#define GET_THREAD() (CURRENT_THREAD_AVAILABLE ? CURRENT_THREAD : GetThread())

#define MAKE_CURRENT_THREAD_AVAILABLE() \
    Thread * __pThread = GET_THREAD(); \
    MAKE_CURRENT_THREAD_AVAILABLE_EX(__pThread)

#define MAKE_CURRENT_THREAD_AVAILABLE_EX(__pThread) \
    Thread * CURRENT_THREAD = __pThread; \
    const bool CURRENT_THREAD_AVAILABLE = true; \
    (void)CURRENT_THREAD_AVAILABLE; /* silence "local variable initialized but not used" warning */ \

#ifndef DACCESS_COMPILE
EXTERN_C AppDomain* STDCALL GetAppDomain();
#endif //!DACCESS_COMPILE

inline void RetailBreak()  
{
#ifdef _TARGET_X86_
    __asm int 3
#else
    DebugBreak();
#endif
}

extern BOOL isMemoryReadable(const TADDR start, unsigned len);

#ifndef memcpyUnsafe_f 
#define memcpyUnsafe_f

// use this when you want to memcpy something that contains GC refs
FORCEINLINE void* memcpyUnsafe(void *dest, const void *src, size_t len)
{
    WRAPPER_NO_CONTRACT;
    return memcpy(dest, src, len);
}

#endif // !memcpyUnsafe_f

//
// By default logging, and debug GC are enabled under debug
//
// These can be enabled in non-debug by removing the #ifdef _DEBUG
// allowing one to log/check_gc a free build.
//
#if defined(_DEBUG) && !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)

    //If memcpy has been defined to PAL_memcpy, we undefine it so that this case
    //can be covered by the if !defined(memcpy) block below
    #ifdef FEATURE_PAL
    #if IS_REDEFINED_IN_PAL(memcpy)
    #undef memcpy
    #endif //IS_REDEFINED_IN_PAL
    #endif //FEATURE_PAL

        // You should be using CopyValueClass if you are doing an memcpy
        // in the CG heap.
    #if !defined(memcpy)
    FORCEINLINE void* memcpyNoGCRefs(void * dest, const void * src, size_t len) {
            WRAPPER_NO_CONTRACT;

            #ifndef FEATURE_PAL
                return memcpy(dest, src, len);
            #else //FEATURE_PAL
                return PAL_memcpy(dest, src, len);
            #endif //FEATURE_PAL
            
        }
    extern "C" void *  __cdecl GCSafeMemCpy(void *, const void *, size_t);
    #define memcpy(dest, src, len) GCSafeMemCpy(dest, src, len)
    #endif // !defined(memcpy)
#else // !_DEBUG && !DACCESS_COMPILE && !CROSSGEN_COMPILE
    FORCEINLINE void* memcpyNoGCRefs(void * dest, const void * src, size_t len) {
            WRAPPER_NO_CONTRACT;
            
            return memcpy(dest, src, len);
        }
#endif // !_DEBUG && !DACCESS_COMPILE && !CROSSGEN_COMPILE

namespace Loader
{
    typedef enum 
    {
        Load, //should load
        DontLoad, //should not load
        SafeLookup  //take no locks, no allocations
    } LoadFlag;
}

// src/inc
#include "utilcode.h"
#include "log.h"
#include "loaderheap.h"
#include "fixuppointer.h"
#include "lazycow.h"

// src/vm
#include "gcenv.interlocked.h"
#include "gcenv.interlocked.inl"

#include "util.hpp"
#include "ibclogger.h"
#include "eepolicy.h"

#include "vars.hpp"
#include "crst.h"
#include "argslot.h"
#include "stublink.h"
#include "cgensys.h"
#include "ceemain.h"
#include "hash.h"
#include "eecontract.h"
#include "pedecoder.h"
#include "sstring.h"
#include "slist.h"
#include "yieldprocessornormalized.h"

#include "eeconfig.h"

#include "spinlock.h"
#include "declsec.h"

#ifdef FEATURE_COMINTEROP 
#include "stdinterfaces.h"
#endif

#include "typehandle.h"
#include "perfcounters.h"
#include "methodtable.h"
#include "typectxt.h"

#include "eehash.h"

#include "vars.hpp"
#include "eventstore.hpp"

#include "synch.h"
#include "regdisp.h"
#include "stackframe.h"
#include "gms.h"
#include "stackprobe.h"
#include "fcall.h"
#include "syncblk.h"
#include "gcdesc.h"
#include "specialstatics.h"
#include "object.h"  // <NICE> We should not really need to put this so early... </NICE>
#include "gchelpers.h"
#include "pefile.h"
#include "clrex.h"
#include "clsload.hpp"  // <NICE> We should not really need to put this so early... </NICE>
#include "siginfo.hpp"
#include "binder.h"
#include "jitinterface.h"  // <NICE> We should not really need to put this so early... </NICE>
#include "ceeload.h"
#include "memberload.h"
#include "genericdict.h"
#include "class.h"
#include "codeman.h"
#include "threads.h"
#include "clrex.inl"
#ifdef FEATURE_COMINTEROP
    #include "windowsruntime.h"
    #include "windowsstring.h"
#endif
#include "loaderallocator.hpp"
#include "appdomain.hpp"
#include "appdomain.inl"
#include "assembly.hpp"
#include "pefile.inl"
#include "excep.h"
#include "method.hpp"
#include "callingconvention.h"
#include "frames.h"
#include "qcall.h"
#include "callhelpers.h"

#include "stackwalk.h"
#include "stackingallocator.h"
#include "interoputil.h"
#include "wrappers.h"
#include "dynamicmethod.h"

#include "gcstress.h"

#ifndef DACCESS_COMPILE 

inline VOID UnsafeEEEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
{
    STATIC_CONTRACT_NOTHROW;
    STATIC_CONTRACT_GC_NOTRIGGER;
    STATIC_CONTRACT_CAN_TAKE_LOCK;

    UnsafeEnterCriticalSection(lpCriticalSection);
    INCTHREADLOCKCOUNT();
}

inline VOID UnsafeEELeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
{
    STATIC_CONTRACT_NOTHROW;
    STATIC_CONTRACT_GC_NOTRIGGER;

    UnsafeLeaveCriticalSection(lpCriticalSection);
    DECTHREADLOCKCOUNT();
}

inline BOOL UnsafeEETryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
{
    STATIC_CONTRACT_NOTHROW;
    STATIC_CONTRACT_GC_NOTRIGGER;
    STATIC_CONTRACT_CAN_TAKE_LOCK;

    BOOL fEnteredCriticalSection = UnsafeTryEnterCriticalSection(lpCriticalSection);
    if(fEnteredCriticalSection)
    {
        INCTHREADLOCKCOUNT();
    }
    return fEnteredCriticalSection;
}

#endif // !DACCESS_COMPILE

HRESULT EnsureRtlFunctions();
HINSTANCE GetModuleInst();

#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
//
// Strong memory model. No memory barrier necessary before writing object references into GC heap.
//
#define GCHeapMemoryBarrier()
#else
//
// The weak memory model forces us to raise memory barriers before writing object references into GC heap. This is required
// for both security and to make most managed code written against strong memory model work. Under normal circumstances, this memory 
// barrier is part of GC write barrier. However, there are a few places in the VM that set cards manually without going through 
// regular GC write barrier. These places need to this macro. This macro is usually used before memcpy-like operation followed 
// by SetCardsAfterBulkCopy.
//
#define GCHeapMemoryBarrier() MemoryBarrier()
#endif


// use this when you want to memcpy something that contains GC refs
void memmoveGCRefs(void *dest, const void *src, size_t len);


#if defined(_DEBUG)

// This catches CANNOTTHROW macros that occur outside the scope of a CONTRACT.
// Note that it's important for m_CannotThrowLineNums to be NULL.
struct DummyGlobalContract
{
    int    *m_CannotThrowLineNums; //= NULL;
    LPVOID *m_CannotThrowRecords; //= NULL;
};

extern DummyGlobalContract ___contract;

#endif // defined(_DEBUG)


// All files get to see all of these .inl files to make sure all files
// get the benefit of inlining.
#include "ceeload.inl"
#include "typedesc.inl"
#include "class.inl"
#include "methodtable.inl"
#include "typehandle.inl"
#include "object.inl"
#include "clsload.inl"
#include "domainfile.inl"
#include "method.inl"
#include "stackprobe.inl"
#include "syncblk.inl"
#include "threads.inl"
#include "eehash.inl"
#ifdef FEATURE_COMINTEROP
#include "WinRTRedirector.h"
#include "winrtredirector.inl"
#endif // FEATURE_COMINTEROP

#if defined(COMMON_TURNED_FPO_ON)
#pragma optimize("", on)        // Go back to command line default optimizations
#undef COMMON_TURNED_FPO_ON
#undef FPO_ON
#endif

extern INT64 g_PauseTime;          // Total duration of all pauses in the runtime
extern Volatile<BOOL> g_IsPaused;   // True if the runtime is Paused for FAS
extern CLREventStatic g_ClrResumeEvent;  // Event fired when the runtime is resumed after a Pause for FAS
INT64 AdditionalWait(INT64 sPauseTime, INT64 sTime, INT64 expDuration);

#endif // !_common_h_