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//
5// ZapReadyToRun.cpp
6//
7
8//
9// Zapping of ready-to-run specific structures
10//
11// ======================================================================================
12
13#include "common.h"
14
15#include "zapreadytorun.h"
16
17#include "zapimport.h"
18
19#include "nativeformatwriter.h"
20
21#include "nibblestream.h"
22
23using namespace NativeFormat;
24
25void ZapReadyToRunHeader::Save(ZapWriter * pZapWriter)
26{
27 ZapImage * pImage = ZapImage::GetImage(pZapWriter);
28
29 READYTORUN_HEADER readyToRunHeader;
30
31 ZeroMemory(&readyToRunHeader, sizeof(readyToRunHeader));
32
33 readyToRunHeader.Signature = READYTORUN_SIGNATURE;
34 readyToRunHeader.MajorVersion = READYTORUN_MAJOR_VERSION;
35 readyToRunHeader.MinorVersion = READYTORUN_MINOR_VERSION;
36
37 if (pImage->m_ModuleDecoder.IsPlatformNeutral())
38 readyToRunHeader.Flags |= READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE;
39
40 // If all types loaded succesfully, set a flag to skip type loading sanity checks at runtime
41 if (pImage->GetCompileInfo()->AreAllClassesFullyLoaded(pImage->GetModuleHandle()))
42 readyToRunHeader.Flags |= READYTORUN_FLAG_SKIP_TYPE_VALIDATION;
43
44 readyToRunHeader.NumberOfSections = m_Sections.GetCount();
45
46 pZapWriter->Write(&readyToRunHeader, sizeof(readyToRunHeader));
47
48 qsort(&m_Sections[0], m_Sections.GetCount(), sizeof(Section), SectionCmp);
49
50 for(COUNT_T i = 0; i < m_Sections.GetCount(); i++)
51 {
52 READYTORUN_SECTION section;
53 section.Type = m_Sections[i].type;
54 ZapWriter::SetDirectoryData(&section.Section, m_Sections[i].pSection);
55 pZapWriter->Write(&section, sizeof(section));
56 }
57}
58
59class BlobVertex : public NativeFormat::Vertex
60{
61 int m_cbSize;
62
63public:
64 BlobVertex(int cbSize)
65 : m_cbSize(cbSize)
66 {
67 }
68
69 void * GetData()
70 {
71 return this + 1;
72 }
73
74 int GetSize()
75 {
76 return m_cbSize;
77 }
78
79 virtual void Save(NativeWriter * pWriter)
80 {
81 byte * pData = (byte *)GetData();
82 for (int i = 0; i < m_cbSize; i++)
83 pWriter->WriteByte(pData[i]);
84 }
85};
86
87class BlobVertexKey
88{
89 PVOID _pData;
90 int _cbSize;
91
92public:
93 BlobVertexKey(PVOID pData, int cbSize)
94 : _pData(pData), _cbSize(cbSize)
95 {
96 }
97
98 void * GetData()
99 {
100 return _pData;
101 }
102
103 int GetSize()
104 {
105 return _cbSize;
106 }
107};
108
109class BlobVertexSHashTraits : public DefaultSHashTraits<BlobVertex *>
110{
111public:
112 typedef BlobVertexKey key_t;
113
114 static key_t GetKey(element_t e)
115 {
116 LIMITED_METHOD_CONTRACT;
117 return key_t(e->GetData(), e->GetSize());
118 }
119 static BOOL Equals(key_t k1, key_t k2)
120 {
121 LIMITED_METHOD_CONTRACT;
122 if (k1.GetSize() != k2.GetSize())
123 return FALSE;
124 return memcmp(k1.GetData(), k2.GetData(), k1.GetSize()) == 0;
125 }
126 static count_t Hash(key_t k)
127 {
128 LIMITED_METHOD_CONTRACT;
129 count_t hash = 5381 + (count_t)(k.GetSize() << 7);
130
131 PBYTE pbData = (PBYTE)k.GetData();
132 PBYTE pbDataEnd = pbData + k.GetSize();
133
134 for (/**/ ; pbData < pbDataEnd; pbData++)
135 {
136 hash = ((hash << 5) + hash) ^ *pbData;
137 }
138 return hash;
139 }
140};
141
142
143class EntryPointVertex : public NativeFormat::Vertex
144{
145 DWORD m_methodIndex;
146 BlobVertex * m_pFixups;
147
148public:
149 EntryPointVertex(DWORD methodIndex, BlobVertex * pFixups)
150 : m_methodIndex(methodIndex), m_pFixups(pFixups)
151 {
152 }
153
154 virtual void Save(NativeWriter * pWriter)
155 {
156 if (m_pFixups != NULL)
157 {
158 int existingOffset = pWriter->GetCurrentOffset(m_pFixups);
159 if (existingOffset != -1)
160 {
161 pWriter->WriteUnsigned((m_methodIndex << 2) | 3);
162 pWriter->WriteUnsigned(pWriter->GetCurrentOffset() - existingOffset);
163 }
164 else
165 {
166 pWriter->WriteUnsigned((m_methodIndex << 2) | 1);
167 pWriter->SetCurrentOffset(m_pFixups);
168 m_pFixups->Save(pWriter);
169 }
170 }
171 else
172 {
173 pWriter->WriteUnsigned(m_methodIndex << 1);
174 }
175 }
176};
177
178class EntryPointWithBlobVertex : public EntryPointVertex
179{
180 BlobVertex * m_pBlob;
181
182public:
183 EntryPointWithBlobVertex(DWORD methodIndex, BlobVertex * pFixups, BlobVertex * pBlob)
184 : EntryPointVertex(methodIndex, pFixups), m_pBlob(pBlob)
185 {
186 }
187
188 virtual void Save(NativeWriter * pWriter)
189 {
190 m_pBlob->Save(pWriter);
191 EntryPointVertex::Save(pWriter);
192 }
193};
194
195void ZapImage::OutputEntrypointsTableForReadyToRun()
196{
197 BeginRegion(CORINFO_REGION_COLD);
198
199 NativeWriter arrayWriter;
200 NativeWriter hashtableWriter;
201
202 NativeSection * pArraySection = arrayWriter.NewSection();
203 NativeSection * pHashtableSection = hashtableWriter.NewSection();
204
205 VertexArray vertexArray(pArraySection);
206 pArraySection->Place(&vertexArray);
207 VertexHashtable vertexHashtable;
208 pHashtableSection->Place(&vertexHashtable);
209
210 bool fEmpty = true;
211
212 SHash< NoRemoveSHashTraits < BlobVertexSHashTraits > > fixupBlobs;
213
214 COUNT_T nCount = m_MethodCompilationOrder.GetCount();
215 for (COUNT_T i = 0; i < nCount; i++)
216 {
217 ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
218
219 mdMethodDef token = GetJitInfo()->getMethodDefFromMethod(pMethod->GetHandle());
220 CORINFO_SIG_INFO sig;
221 GetJitInfo()->getMethodSig(pMethod->GetHandle(), &sig);
222
223 int rid = RidFromToken(token);
224 _ASSERTE(rid != 0);
225
226 BlobVertex * pFixupBlob = NULL;
227
228 if (pMethod->m_pFixupList != NULL)
229 {
230 NibbleWriter writer;
231 m_pImportTable->PlaceFixups(pMethod->m_pFixupList, writer);
232
233 DWORD cbBlob;
234 PVOID pBlob = writer.GetBlob(&cbBlob);
235
236 pFixupBlob = fixupBlobs.Lookup(BlobVertexKey(pBlob, cbBlob));
237 if (pFixupBlob == NULL)
238 {
239 void * pMemory = new (GetHeap()) BYTE[sizeof(BlobVertex) + cbBlob];
240 pFixupBlob = new (pMemory) BlobVertex(cbBlob);
241 memcpy(pFixupBlob->GetData(), pBlob, cbBlob);
242
243 fixupBlobs.Add(pFixupBlob);
244 }
245 }
246
247 if (sig.sigInst.classInstCount > 0 || sig.sigInst.methInstCount > 0)
248 {
249 CORINFO_MODULE_HANDLE module = GetJitInfo()->getClassModule(pMethod->GetClassHandle());
250 _ASSERTE(GetCompileInfo()->IsInCurrentVersionBubble(module));
251 SigBuilder sigBuilder;
252 CORINFO_RESOLVED_TOKEN resolvedToken = {};
253 resolvedToken.tokenScope = module;
254 resolvedToken.token = token;
255 resolvedToken.hClass = pMethod->GetClassHandle();
256 resolvedToken.hMethod = pMethod->GetHandle();
257 GetCompileInfo()->EncodeMethod(module, pMethod->GetHandle(), &sigBuilder, NULL, NULL, &resolvedToken);
258
259 DWORD cbBlob;
260 PVOID pBlob = sigBuilder.GetSignature(&cbBlob);
261 void * pMemory = new (GetHeap()) BYTE[sizeof(BlobVertex) + cbBlob];
262 BlobVertex * pSigBlob = new (pMemory) BlobVertex(cbBlob);
263 memcpy(pSigBlob->GetData(), pBlob, cbBlob);
264
265 int dwHash = GetCompileInfo()->GetVersionResilientMethodHashCode(pMethod->GetHandle());
266 vertexHashtable.Append(dwHash, pHashtableSection->Place(new (GetHeap()) EntryPointWithBlobVertex(pMethod->GetMethodIndex(), pFixupBlob, pSigBlob)));
267 }
268 else
269 {
270 vertexArray.Set(rid - 1, new (GetHeap()) EntryPointVertex(pMethod->GetMethodIndex(), pFixupBlob));
271 }
272
273 fEmpty = false;
274 }
275
276 if (fEmpty)
277 return;
278
279 vertexArray.ExpandLayout();
280
281 vector<byte>& arrayBlob = arrayWriter.Save();
282 ZapNode * pArrayBlob = ZapBlob::NewBlob(this, &arrayBlob[0], arrayBlob.size());
283 m_pCodeMethodDescsSection->Place(pArrayBlob);
284
285 vector<byte>& hashtableBlob = hashtableWriter.Save();
286 ZapNode * pHashtableBlob = ZapBlob::NewBlob(this, &hashtableBlob[0], hashtableBlob.size());
287 m_pCodeMethodDescsSection->Place(pHashtableBlob);
288
289 ZapReadyToRunHeader * pReadyToRunHeader = GetReadyToRunHeader();
290 pReadyToRunHeader->RegisterSection(READYTORUN_SECTION_METHODDEF_ENTRYPOINTS, pArrayBlob);
291 pReadyToRunHeader->RegisterSection(READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS, pHashtableBlob);
292 pReadyToRunHeader->RegisterSection(READYTORUN_SECTION_RUNTIME_FUNCTIONS, m_pRuntimeFunctionSection);
293
294 if (m_pLazyMethodCallHelperSection->GetNodeCount() != 0)
295 pReadyToRunHeader->RegisterSection(READYTORUN_SECTION_DELAYLOAD_METHODCALL_THUNKS, m_pLazyMethodCallHelperSection);
296
297 if (m_pExceptionInfoLookupTable->GetSize() != 0)
298 pReadyToRunHeader->RegisterSection(READYTORUN_SECTION_EXCEPTION_INFO, m_pExceptionInfoLookupTable);
299
300 EndRegion(CORINFO_REGION_COLD);
301}
302
303class DebugInfoVertex : public NativeFormat::Vertex
304{
305 BlobVertex * m_pDebugInfo;
306
307public:
308 DebugInfoVertex(BlobVertex * pDebugInfo)
309 : m_pDebugInfo(pDebugInfo)
310 {
311 }
312
313 virtual void Save(NativeWriter * pWriter)
314 {
315 int existingOffset = pWriter->GetCurrentOffset(m_pDebugInfo);
316 if (existingOffset != -1)
317 {
318 _ASSERTE(pWriter->GetCurrentOffset() > existingOffset);
319 pWriter->WriteUnsigned(pWriter->GetCurrentOffset() - existingOffset);
320 }
321 else
322 {
323 pWriter->WriteUnsigned(0);
324 pWriter->SetCurrentOffset(m_pDebugInfo);
325 m_pDebugInfo->Save(pWriter);
326 }
327 }
328};
329
330void ZapImage::OutputDebugInfoForReadyToRun()
331{
332 NativeWriter writer;
333
334 NativeSection * pSection = writer.NewSection();
335
336 VertexArray vertexArray(pSection);
337 pSection->Place(&vertexArray);
338
339 bool fEmpty = true;
340
341 SHash< NoRemoveSHashTraits < BlobVertexSHashTraits > > debugInfoBlobs;
342
343 COUNT_T nCount = m_MethodCompilationOrder.GetCount();
344 for (COUNT_T i = 0; i < nCount; i++)
345 {
346 ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
347
348 ZapBlob * pDebugInfo = pMethod->GetDebugInfo();
349 if (pDebugInfo == NULL)
350 continue;
351
352 DWORD cbBlob = pDebugInfo->GetBlobSize();
353 PVOID pBlob = pDebugInfo->GetData();
354
355 BlobVertex * pDebugInfoBlob = debugInfoBlobs.Lookup(BlobVertexKey(pBlob, cbBlob));
356 if (pDebugInfoBlob == NULL)
357 {
358 void * pMemory = new (GetHeap()) BYTE[sizeof(BlobVertex) + cbBlob];
359 pDebugInfoBlob = new (pMemory) BlobVertex(cbBlob);
360 memcpy(pDebugInfoBlob->GetData(), pBlob, cbBlob);
361
362 debugInfoBlobs.Add(pDebugInfoBlob);
363 }
364
365 vertexArray.Set(pMethod->GetMethodIndex(), new (GetHeap()) DebugInfoVertex(pDebugInfoBlob));
366
367 fEmpty = false;
368 }
369
370 if (fEmpty)
371 return;
372
373 vertexArray.ExpandLayout();
374
375 vector<byte>& blob = writer.Save();
376
377 ZapNode * pBlob = ZapBlob::NewBlob(this, &blob[0], blob.size());
378 m_pDebugSection->Place(pBlob);
379
380 GetReadyToRunHeader()->RegisterSection(READYTORUN_SECTION_DEBUG_INFO, pBlob);
381}
382
383void ZapImage::OutputInliningTableForReadyToRun()
384{
385 SBuffer serializedInlineTrackingBuffer;
386 m_pPreloader->GetSerializedInlineTrackingMap(&serializedInlineTrackingBuffer);
387 ZapNode * pBlob = ZapBlob::NewAlignedBlob(this, (PVOID)(const BYTE*) serializedInlineTrackingBuffer, serializedInlineTrackingBuffer.GetSize(), 4);
388 m_pDebugSection->Place(pBlob);
389 GetReadyToRunHeader()->RegisterSection(READYTORUN_SECTION_INLINING_INFO, pBlob);
390}
391
392void ZapImage::OutputProfileDataForReadyToRun()
393{
394 if (m_pInstrumentSection != nullptr)
395 {
396 GetReadyToRunHeader()->RegisterSection(READYTORUN_SECTION_PROFILEDATA_INFO, m_pInstrumentSection);
397 }
398}
399
400void ZapImage::OutputTypesTableForReadyToRun(IMDInternalImport * pMDImport)
401{
402 NativeWriter writer;
403 VertexHashtable typesHashtable;
404
405 NativeSection * pSection = writer.NewSection();
406 pSection->Place(&typesHashtable);
407
408 // Note on duplicate types with same name: there is not need to perform that check when building
409 // the hashtable. If such types were encountered, the R2R compilation would fail before reaching here.
410
411 // Save the TypeDefs to the hashtable
412 {
413 HENUMInternalHolder hEnum(pMDImport);
414 hEnum.EnumAllInit(mdtTypeDef);
415
416 mdToken mdTypeToken;
417 while (pMDImport->EnumNext(&hEnum, &mdTypeToken))
418 {
419 mdTypeDef mdCurrentToken = mdTypeToken;
420 DWORD dwHash = GetCompileInfo()->GetVersionResilientTypeHashCode(GetModuleHandle(), mdTypeToken);
421
422 typesHashtable.Append(dwHash, pSection->Place(new UnsignedConstant(RidFromToken(mdTypeToken) << 1)));
423 }
424 }
425
426 // Save the ExportedTypes to the hashtable
427 {
428 HENUMInternalHolder hEnum(pMDImport);
429 hEnum.EnumInit(mdtExportedType, mdTokenNil);
430
431 mdToken mdTypeToken;
432 while (pMDImport->EnumNext(&hEnum, &mdTypeToken))
433 {
434 DWORD dwHash = GetCompileInfo()->GetVersionResilientTypeHashCode(GetModuleHandle(), mdTypeToken);
435
436 typesHashtable.Append(dwHash, pSection->Place(new UnsignedConstant((RidFromToken(mdTypeToken) << 1) | 1)));
437 }
438 }
439
440 vector<byte>& blob = writer.Save();
441
442 ZapNode * pBlob = ZapBlob::NewBlob(this, &blob[0], blob.size());
443 _ASSERTE(m_pAvailableTypesSection);
444 m_pAvailableTypesSection->Place(pBlob);
445
446 GetReadyToRunHeader()->RegisterSection(READYTORUN_SECTION_AVAILABLE_TYPES, pBlob);
447}
448
449
450//
451// Verify that data structures and flags shared between NGen and ReadyToRun are in sync
452//
453
454//
455// READYTORUN_IMPORT_SECTION
456//
457static_assert_no_msg(sizeof(READYTORUN_IMPORT_SECTION) == sizeof(CORCOMPILE_IMPORT_SECTION));
458
459static_assert_no_msg((int)READYTORUN_IMPORT_SECTION_TYPE_UNKNOWN == (int)CORCOMPILE_IMPORT_TYPE_UNKNOWN);
460
461static_assert_no_msg((int)READYTORUN_IMPORT_SECTION_FLAGS_EAGER == (int)CORCOMPILE_IMPORT_FLAGS_EAGER);
462
463//
464// READYTORUN_METHOD_SIG
465//
466static_assert_no_msg((int)READYTORUN_METHOD_SIG_UnboxingStub == (int)ENCODE_METHOD_SIG_UnboxingStub);
467static_assert_no_msg((int)READYTORUN_METHOD_SIG_InstantiatingStub == (int)ENCODE_METHOD_SIG_InstantiatingStub);
468static_assert_no_msg((int)READYTORUN_METHOD_SIG_MethodInstantiation == (int)ENCODE_METHOD_SIG_MethodInstantiation);
469static_assert_no_msg((int)READYTORUN_METHOD_SIG_SlotInsteadOfToken == (int)ENCODE_METHOD_SIG_SlotInsteadOfToken);
470static_assert_no_msg((int)READYTORUN_METHOD_SIG_MemberRefToken == (int)ENCODE_METHOD_SIG_MemberRefToken);
471static_assert_no_msg((int)READYTORUN_METHOD_SIG_Constrained == (int)ENCODE_METHOD_SIG_Constrained);
472static_assert_no_msg((int)READYTORUN_METHOD_SIG_OwnerType == (int)ENCODE_METHOD_SIG_OwnerType);
473
474//
475// READYTORUN_FIELD_SIG
476//
477static_assert_no_msg((int)READYTORUN_FIELD_SIG_IndexInsteadOfToken == (int)ENCODE_FIELD_SIG_IndexInsteadOfToken);
478static_assert_no_msg((int)READYTORUN_FIELD_SIG_MemberRefToken == (int)ENCODE_FIELD_SIG_MemberRefToken);
479static_assert_no_msg((int)READYTORUN_FIELD_SIG_OwnerType == (int)ENCODE_FIELD_SIG_OwnerType);
480
481//
482// READYTORUN_FIXUP
483//
484static_assert_no_msg((int)READYTORUN_FIXUP_ThisObjDictionaryLookup == (int)ENCODE_DICTIONARY_LOOKUP_THISOBJ);
485static_assert_no_msg((int)READYTORUN_FIXUP_TypeDictionaryLookup == (int)ENCODE_DICTIONARY_LOOKUP_TYPE);
486static_assert_no_msg((int)READYTORUN_FIXUP_MethodDictionaryLookup == (int)ENCODE_DICTIONARY_LOOKUP_METHOD);
487
488static_assert_no_msg((int)READYTORUN_FIXUP_TypeHandle == (int)ENCODE_TYPE_HANDLE);
489static_assert_no_msg((int)READYTORUN_FIXUP_MethodHandle == (int)ENCODE_METHOD_HANDLE);
490static_assert_no_msg((int)READYTORUN_FIXUP_FieldHandle == (int)ENCODE_FIELD_HANDLE);
491
492static_assert_no_msg((int)READYTORUN_FIXUP_MethodEntry == (int)ENCODE_METHOD_ENTRY);
493static_assert_no_msg((int)READYTORUN_FIXUP_MethodEntry_DefToken == (int)ENCODE_METHOD_ENTRY_DEF_TOKEN);
494static_assert_no_msg((int)READYTORUN_FIXUP_MethodEntry_RefToken == (int)ENCODE_METHOD_ENTRY_REF_TOKEN);
495
496static_assert_no_msg((int)READYTORUN_FIXUP_VirtualEntry == (int)ENCODE_VIRTUAL_ENTRY);
497static_assert_no_msg((int)READYTORUN_FIXUP_VirtualEntry_DefToken == (int)ENCODE_VIRTUAL_ENTRY_DEF_TOKEN);
498static_assert_no_msg((int)READYTORUN_FIXUP_VirtualEntry_RefToken == (int)ENCODE_VIRTUAL_ENTRY_REF_TOKEN);
499static_assert_no_msg((int)READYTORUN_FIXUP_VirtualEntry_Slot == (int)ENCODE_VIRTUAL_ENTRY_SLOT);
500
501static_assert_no_msg((int)READYTORUN_FIXUP_Helper == (int)ENCODE_READYTORUN_HELPER);
502static_assert_no_msg((int)READYTORUN_FIXUP_StringHandle == (int)ENCODE_STRING_HANDLE);
503
504static_assert_no_msg((int)READYTORUN_FIXUP_NewObject == (int)ENCODE_NEW_HELPER);
505static_assert_no_msg((int)READYTORUN_FIXUP_NewArray == (int)ENCODE_NEW_ARRAY_HELPER);
506
507static_assert_no_msg((int)READYTORUN_FIXUP_IsInstanceOf == (int)ENCODE_ISINSTANCEOF_HELPER);
508static_assert_no_msg((int)READYTORUN_FIXUP_ChkCast == (int)ENCODE_CHKCAST_HELPER);
509
510static_assert_no_msg((int)READYTORUN_FIXUP_FieldAddress == (int)ENCODE_FIELD_ADDRESS);
511static_assert_no_msg((int)READYTORUN_FIXUP_CctorTrigger == (int)ENCODE_CCTOR_TRIGGER);
512
513static_assert_no_msg((int)READYTORUN_FIXUP_StaticBaseNonGC == (int)ENCODE_STATIC_BASE_NONGC_HELPER);
514static_assert_no_msg((int)READYTORUN_FIXUP_StaticBaseGC == (int)ENCODE_STATIC_BASE_GC_HELPER);
515static_assert_no_msg((int)READYTORUN_FIXUP_ThreadStaticBaseNonGC == (int)ENCODE_THREAD_STATIC_BASE_NONGC_HELPER);
516static_assert_no_msg((int)READYTORUN_FIXUP_ThreadStaticBaseGC == (int)ENCODE_THREAD_STATIC_BASE_GC_HELPER);
517
518static_assert_no_msg((int)READYTORUN_FIXUP_FieldBaseOffset == (int)ENCODE_FIELD_BASE_OFFSET);
519static_assert_no_msg((int)READYTORUN_FIXUP_FieldOffset == (int)ENCODE_FIELD_OFFSET);
520
521static_assert_no_msg((int)READYTORUN_FIXUP_TypeDictionary == (int)ENCODE_TYPE_DICTIONARY);
522static_assert_no_msg((int)READYTORUN_FIXUP_MethodDictionary == (int)ENCODE_METHOD_DICTIONARY);
523
524static_assert_no_msg((int)READYTORUN_FIXUP_Check_TypeLayout == (int)ENCODE_CHECK_TYPE_LAYOUT);
525static_assert_no_msg((int)READYTORUN_FIXUP_Check_FieldOffset == (int)ENCODE_CHECK_FIELD_OFFSET);
526
527static_assert_no_msg((int)READYTORUN_FIXUP_DelegateCtor == (int)ENCODE_DELEGATE_CTOR);
528
529static_assert_no_msg((int)READYTORUN_FIXUP_DeclaringTypeHandle == (int)ENCODE_DECLARINGTYPE_HANDLE);
530
531//
532// READYTORUN_EXCEPTION
533//
534static_assert_no_msg(sizeof(READYTORUN_EXCEPTION_LOOKUP_TABLE_ENTRY) == sizeof(CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY));
535static_assert_no_msg(sizeof(READYTORUN_EXCEPTION_CLAUSE) == sizeof(CORCOMPILE_EXCEPTION_CLAUSE));
536