summaryrefslogtreecommitdiff
path: root/src/vm/cgensys.h
blob: d55d15dd7dd9e3d42bc3374e8e654dfc43463187 (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
// 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.
// CGENSYS.H -
//
// Generic header for choosing system-dependent helpers
//



#ifndef __cgensys_h__
#define __cgensys_h__

class MethodDesc;
class Stub;
class Thread;
class CrawlFrame;
struct EE_ILEXCEPTION_CLAUSE;
struct TransitionBlock;
struct VASigCookie;
struct CORCOMPILE_EXTERNAL_METHOD_THUNK;
class ComPlusCallMethodDesc;

#include <cgencpu.h>


#ifdef EnC_SUPPORTED
void ResumeAtJit(PT_CONTEXT pContext, LPVOID oldFP);
#endif

#if defined(_TARGET_X86_)
void ResumeAtJitEH   (CrawlFrame* pCf, BYTE* startPC, EE_ILEXCEPTION_CLAUSE *EHClausePtr, DWORD nestingLevel, Thread *pThread, BOOL unwindStack);
int  CallJitEHFilter (CrawlFrame* pCf, BYTE* startPC, EE_ILEXCEPTION_CLAUSE *EHClausePtr, DWORD nestingLevel, OBJECTREF thrownObj);
void CallJitEHFinally(CrawlFrame* pCf, BYTE* startPC, EE_ILEXCEPTION_CLAUSE *EHClausePtr, DWORD nestingLevel);
#endif // _TARGET_X86_


// get number of logical to physical processors.  Returns 1 on failure or non-intel x86 processors.
DWORD GetLogicalCpuCount();

//These are in util.cpp
extern size_t GetLogicalProcessorCacheSizeFromOS();
extern size_t GetIntelDeterministicCacheEnum();
extern size_t GetIntelDescriptorValuesCache();
extern DWORD GetLogicalCpuCountFromOS();
extern DWORD GetLogicalCpuCountFallback();


// Try to determine the largest last-level cache size of the machine - return 0 if unknown or no L2/L3 cache
size_t GetLargestOnDieCacheSize(BOOL bTrueSize = TRUE);


#ifdef FEATURE_COMINTEROP
extern "C" UINT32 STDCALL CLRToCOMWorker(TransitionBlock * pTransitionBlock, ComPlusCallMethodDesc * pMD);
extern "C" void GenericComPlusCallStub(void);

extern "C" void GenericComCallStub(void);
#endif // FEATURE_COMINTEROP

// Non-CPU-specific helper functions called by the CPU-dependent code
extern "C" PCODE STDCALL PreStubWorker(TransitionBlock * pTransitionBlock, MethodDesc * pMD);

extern "C" void STDCALL VarargPInvokeStubWorker(TransitionBlock * pTransitionBlock, VASigCookie * pVASigCookie, MethodDesc * pMD);
extern "C" void STDCALL VarargPInvokeStub(void);
extern "C" void STDCALL VarargPInvokeStub_RetBuffArg(void);

extern "C" void STDCALL GenericPInvokeCalliStubWorker(TransitionBlock * pTransitionBlock, VASigCookie * pVASigCookie, PCODE pUnmanagedTarget);
extern "C" void STDCALL GenericPInvokeCalliHelper(void);

extern "C" PCODE STDCALL ExternalMethodFixupWorker(TransitionBlock * pTransitionBlock, TADDR pIndirection, DWORD sectionIndex, Module * pModule);
extern "C" void STDCALL ExternalMethodFixupStub(void);
extern "C" void STDCALL ExternalMethodFixupPatchLabel(void);

extern "C" void STDCALL VirtualMethodFixupStub(void);
extern "C" void STDCALL VirtualMethodFixupPatchLabel(void);

extern "C" void STDCALL TransparentProxyStub(void);
extern "C" void STDCALL TransparentProxyStub_CrossContext();
extern "C" void STDCALL TransparentProxyStubPatchLabel(void);

#ifdef FEATURE_READYTORUN
extern "C" void STDCALL DelayLoad_MethodCall();

extern "C" void STDCALL DelayLoad_Helper();
extern "C" void STDCALL DelayLoad_Helper_Obj();
extern "C" void STDCALL DelayLoad_Helper_ObjObj();
#endif

// Returns information about the CPU processor.
// Note that this information may be the least-common-denominator in the
// case of a multi-proc machine.

#ifdef _TARGET_X86_
void GetSpecificCpuInfo(CORINFO_CPU * cpuInfo);
#else
inline void GetSpecificCpuInfo(CORINFO_CPU * cpuInfo)
{
    LIMITED_METHOD_CONTRACT;    
    cpuInfo->dwCPUType = 0;
    cpuInfo->dwFeatures = 0;
    cpuInfo->dwExtendedFeatures = 0;
}

#endif // !_TARGET_X86_

#if (defined(_TARGET_X86_) || defined(_TARGET_AMD64_)) && !defined(CROSSGEN_COMPILE)
extern "C" DWORD __stdcall getcpuid(DWORD arg, unsigned char result[16]);
extern "C" DWORD __stdcall getextcpuid(DWORD arg1, DWORD arg2, unsigned char result[16]);
extern "C" DWORD __stdcall xmmYmmStateSupport();
#endif

inline bool TargetHasAVXSupport()
{
#if (defined(_TARGET_X86_) || defined(_TARGET_AMD64_)) && !defined(CROSSGEN_COMPILE)
    unsigned char buffer[16];
    // All x86/AMD64 targets support cpuid.
    (void) getcpuid(1, buffer);
    // getcpuid executes cpuid with eax set to its first argument, and ecx cleared.
    // It returns the resulting eax, ebx, ecx and edx (in that order) in buffer[].
    // The AVX feature is ECX bit 28.
    return ((buffer[11] & 0x10) != 0);
#endif // (defined(_TARGET_X86_) || defined(_TARGET_AMD64_)) && !defined(CROSSGEN_COMPILE)
    return false;
}

#ifdef FEATURE_PREJIT
// Can code compiled for "minReqdCpuType" be used on "actualCpuType"
inline BOOL IsCompatibleCpuInfo(const CORINFO_CPU * actualCpuInfo,
                                const CORINFO_CPU * minReqdCpuInfo)
{
    LIMITED_METHOD_CONTRACT;
    return ((minReqdCpuInfo->dwFeatures & actualCpuInfo->dwFeatures) ==
             minReqdCpuInfo->dwFeatures);
}
#endif // FEATURE_PREJIT


#ifndef DACCESS_COMPILE
// Given an address in a slot, figure out if the prestub will be called
BOOL DoesSlotCallPrestub(PCODE pCode);
#endif

#ifdef DACCESS_COMPILE

// Used by dac/strike to make sense of non-jit/non-jit-helper call targets
// generated by the runtime.
BOOL GetAnyThunkTarget (T_CONTEXT *pctx, TADDR *pTarget, TADDR *pTargetMethodDesc);

#endif // DACCESS_COMPILE



//
// ResetProcessorStateHolder saves/restores processor state around calls to
// mscorlib during exception handling.
//
class ResetProcessorStateHolder
{
#if defined(_TARGET_AMD64_)
    ULONG m_mxcsr;
#endif

public:

    ResetProcessorStateHolder ()
    {
#if defined(_TARGET_AMD64_)
        m_mxcsr = _mm_getcsr();
        _mm_setcsr(0x1f80);
#endif // _TARGET_AMD64_
    }

    ~ResetProcessorStateHolder ()
    {
#if defined(_TARGET_AMD64_)
        _mm_setcsr(m_mxcsr);
#endif // _TARGET_AMD64_
    }
};


#endif // !__cgensys_h__