A
download codeman.h
Language: C++
Copyright: (c) 2006 Microsoft Corporation. All rights reserved.
LOC: 935
Project Info
Shared Source Common Language Infrastructure(sscli20)
Server: Shared Source Common Language Infrastructure
Type: filesystem
...sscli20\sscli20\clr\src\vm\
   appdomain.cpp
   appdomain.hpp
   appdomain.inl
   appdomainhelper.cpp
   appdomainhelper.h
   appdomainnative.cpp
   appdomainnative.hpp
   appdomainstack.cpp
   appdomainstack.h
   appdomainstack.inl
   argslot.h
   array.cpp
   array.h
   assembly.cpp
   assembly.hpp
   assemblyname.cpp
   assemblyname.hpp
   assemblynative.cpp
   assemblynative.hpp
   assemblysink.cpp
   assemblysink.h
   assemblyspec.cpp
   assemblyspec.hpp
   binder.cpp
   binder.h
   cachelinealloc.cpp
   cachelinealloc.h
   ceeload.cpp
   ceeload.h
   ceeload.inl
   ceemain.cpp
   ceemain.h
   certificatecache.cpp
   certificatecache.h
   cgensys.h
   class.cpp
   class.h
   class.inl
   classloadlevel.h
   classnames.h
   clrex.cpp
   clrex.h
   clsload.cpp
   clsload.hpp
   clsload.inl
   codeman.cpp
   codeman.h
   codeman.inl
   comarrayhelpers.cpp
   comarrayhelpers.h
   comarrayinfo.cpp
   comarrayinfo.h
   comcallablewrapper.cpp
   comcallablewrapper.h
   comcurrency.cpp
   comcurrency.h
   comdatetime.cpp
   comdatetime.h
   comdecimal.cpp
   comdecimal.h
   comdelegate.cpp
   comdelegate.h
   comdynamic.cpp
   comdynamic.h
   comisolatedstorage.cpp
   comisolatedstorage.h
   commemoryfailpoint.cpp
   commemoryfailpoint.h
   commethodrental.cpp
   commethodrental.h
   commodule.cpp
   commodule.h
   common.cpp
   common.h
   comnumber.cpp
   comnumber.h
   comobject.cpp
   comobject.h
   comreflectioncache.hpp
   comreflectioncommon.cpp
   comreflectioncommon.h
   comstreams.cpp
   comstreams.h
   comstring.cpp
   comstring.h
   comstringbuffer.cpp
   comstringbuffer.h
   comstringcommon.h
   comsynchronizable.cpp
   comsynchronizable.h
   comsystem.cpp
   comsystem.h
   comthreadpool.cpp
   comthreadpool.h
   comutilnative.cpp
   comutilnative.h
   comvarargs.cpp
   comvarargs.h
   comvariant.cpp
   comvariant.h
   comwaithandle.cpp
   comwaithandle.h
   confighelper.cpp
   confighelper.h
   ...inedexecutionregion.cpp
   ...rainedexecutionregion.h
   context.h
   contexts.cpp
   contractimpl.cpp
   contractimpl.h
   corhost.cpp
   crossdomaincalls.cpp
   crossdomaincalls.h
   crst.cpp
   crst.h
   cryptapis.h
   ctxtcall.h
   customattribute.cpp
   customattribute.h
   custommarshalerinfo.cpp
   custommarshalerinfo.h
   dbginterface.h
   debugdebugger.cpp
   debugdebugger.h
   debughelp.cpp
   debuginfostore.cpp
   debuginfostore.h
   decodemd.cpp
   decodemd.h
   delegateinfo.h
   dllimport.cpp
   dllimport.h
   dllimportcallback.cpp
   dllimportcallback.h
   domainfile.cpp
   domainfile.h
   domainfile.inl
   dynamicmethod.cpp
   dynamicmethod.h
   ecall.cpp
   ecall.h
   ecmakey.h
   eecallconv.h
   eeconfig.cpp
   eeconfig.h
   eeconfigfactory.cpp
   eeconfigfactory.h
   eecontract.cpp
   eecontract.h
   eecontract.inl
   eedbginterface.h
   eedbginterfaceimpl.cpp
   eedbginterfaceimpl.h
   eedbginterfaceimpl.inl
   eehash.cpp
   eehash.h
   eemessagebox.cpp
   eemessagebox.h
   eepolicy.cpp
   eepolicy.h
   eeprofinterfaces.h
   eeprofinterfaces.inl
   ...rofinterfacewrapper.inl
   eetwain.cpp
   encee.h
   eventstore.cpp
   eventstore.hpp
   excep.cpp
   excep.h
   exceptmacros.h
   exinfo.cpp
   exinfo.h
   exstate.cpp
   exstate.h
   exstatecommon.h
   fcall.cpp
   fcall.h
   field.cpp
   field.h
   fieldmarshaler.cpp
   fieldmarshaler.h
   fjit_eetwain.cpp
   fjit_eetwain.h
   fptrstubs.cpp
   fptrstubs.h
   frames.cpp
   frames.h
   fusionbind.cpp
   fusioninit.cpp
   fusionsink.cpp
   fusionwrap.cpp
   fusionwrap.h
   gc.h
   gccommon.cpp
   gcdecode.cpp
   gcdesc.h
   gcee.cpp
   gceesvr.cpp
   gceewks.cpp
   gchost.cpp
   gcimpl.h
   gcscan.cpp
   gcscan.h
   gcsmp.cpp
   gcsmppriv.h
   gcsvr.cpp
   gcwks.cpp
   genericdict.cpp
   genericdict.h
   generics.cpp
   generics.h
   genmeth.cpp
   gmheap.cpp
   gmheap.hpp
   gms.h
   h2inc.pl
   handletable.cpp
   handletable.h
   handletable.inl
   handletablecache.cpp
   handletablecore.cpp
   handletablepriv.h
   handletablescan.cpp
   hash.cpp
   hash.h
   hostexecutioncontext.cpp
   hostexecutioncontext.h
   hosting.cpp
   hosting.h
   ibclogger.h
   ildump.h
   ilmarshalers.cpp
   ilmarshalers.h
   ilstubcache.cpp
   ilstubcache.h
   ilstubresolver.cpp
   ilstubresolver.h
   instmethhash.cpp
   instmethhash.h
   interopconverter.cpp
   interopconverter.h
   interoputil.cpp
   interoputil.h
   ...lidoverlappedwrappers.h
   invokeutil.cpp
   invokeutil.h
   jithelpers.cpp
   jitinterface.cpp
   jitinterface.h
   jitinterfacegen.cpp
   list.cpp
   list.h
   listlock.cpp
   listlock.h
   listlock.inl
   makefile.inc
   managedmdimport.cpp
   managedmdimport.hpp
   marshaler.h
   marshalnative.cpp
   marshalnative.h
   mdaassistants.h
   mdaassistantsptr.h
   memberload.cpp
   memberload.h
   message.cpp
   message.h
   metasig.h
   method.cpp
   method.hpp
   method.inl
   methodimpl.cpp
   methodimpl.h
   methoditer.cpp
   methoditer.h
   methodtable.cpp
   methodtable.h
   methodtable.inl
   ml.cpp
   ml.h
   mlcache.cpp
   mlcache.h
   mlgen.cpp
   mlgen.h
   mlinfo.cpp
   mlinfo.h
   mlopdef.h
   mscorlib.h
   mtypes.h
   namespace.h
   nativeoverlapped.cpp
   nativeoverlapped.h
   newcompressedstack.cpp
   newcompressedstack.h
   nsenums.h
   object.cpp
   object.h
   object.inl
   objectclone.cpp
   objectclone.h
   objecthandle.cpp
   objecthandle.h
   objectlist.cpp
   objectlist.h
   olevariant.cpp
   olevariant.h
   pefile.cpp
   pefile.h
   pefile.inl
   peimage.cpp
   peimage.h
   peimage.inl
   peimagelayout.cpp
   peimagelayout.h
   peimagelayout.inl
   pendingload.cpp
   pendingload.h
   precode.cpp
   precode.h
   prestub.cpp
   proftoeeinterfaceimpl.cpp
   proftoeeinterfaceimpl.h
   reflectclasswriter.cpp
   reflectclasswriter.h
   reflectioninvocation.cpp
   reflectioninvocation.h
   remoting.cpp
   remoting.h
   rexcep.h
   runtimeexceptionkind.h
   runtimehandles.cpp
   runtimehandles.h
   rwlock.cpp
   rwlock.h
   safehandle.cpp
   security.h
   security.inl
   securityattributes.cpp
   securityattributes.h
   securityconfig.cpp
   securityconfig.h
   securitydeclarative.cpp
   securitydeclarative.h
   securitydescriptor.cpp
   securitydescriptor.h
   ...descriptorappdomain.cpp
   ...tydescriptorappdomain.h
   ...ydescriptorassembly.cpp
   ...itydescriptorassembly.h
   securityhostprotection.cpp
   securityhostprotection.h
   securityimperative.cpp
   securityimperative.h
   securitymeta.cpp
   securitymeta.h
   securitypolicy.cpp
   securitypolicy.h
   securitystackwalk.cpp
   securitystackwalk.h
   ...transparentassembly.cpp
   ...tytransparentassembly.h
   sigformat.cpp
   sigformat.h
   siginfo.cpp
   siginfo.hpp
   simplerwlock.cpp
   simplerwlock.hpp
   sourceline.cpp
   sourceline.h
   sources.dac
   sources.inc
   specialstatics.h
   spinlock.cpp
   spinlock.h
   stackbuildersink.cpp
   stackbuildersink.h
   stackcompressor.cpp
   stackcompressor.h
   stackingallocator.cpp
   stackingallocator.h
   stackprobe.h
   stackprobe.inl
   stackwalk.cpp
   stackwalk.h
   stackwalktypes.h
   stringliteralmap.cpp
   stringliteralmap.h
   strongname.cpp
   stubgen.h
   stublink.cpp
   stublink.h
   stublink.inl
   stubmgr.cpp
   stubmgr.h
   syncblk.cpp
   syncblk.h
   syncblk.inl
   syncclean.cpp
   syncclean.hpp
   synch.cpp
   synch.h
   ...zationcontextnative.cpp
   ...nizationcontextnative.h
   testhookmgr.cpp
   testhookmgr.h
   thekey.h
   threads.cpp
   threads.h
   threads.inl
   tokeniter.cpp
   tokeniter.hpp
   typectxt.cpp
   typectxt.h
   typedesc.cpp
   typedesc.h
   typedesc.inl
   typehandle.cpp
   typehandle.h
   typehandle.inl
   typehash.cpp
   typehash.h
   typekey.h
   typeparse.cpp
   typeparse.h
   typestring.cpp
   typestring.h
   umthunkhash.cpp
   umthunkhash.h
   util.cpp
   util.hpp
   validator.cpp
   vars.cpp
   vars.hpp
   verifier.cpp
   verifier.hpp
   veropcodes.hpp
   vertable.h
   virtualcallstub.cpp
   virtualcallstub.h
   vmholder.h
   win32threadpool.cpp
   win32threadpool.h
   wrappers.h

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
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
// ==++==
// 
//   
//    Copyright (c) 2006 Microsoft Corporation.  All rights reserved.
//   
//    The use and distribution terms for this software are contained in the file
//    named license.txt, which can be found in the root of this distribution.
//    By using this software in any fashion, you are agreeing to be bound by the
//    terms of this license.
//   
//    You must not remove this notice, or any other, from this software.
//   
// 
// ==--==
/******************************************************************************

Module Name:

    codeman.h

Abstract:

    Wrapper to facilitate multiple JITcompiler support in the COM+ Runtime

    The ExecutionManager is responsible for managing the RangeSections.
    Given an IP, it can find the RangeSection which holds that IP.

    RangeSections contain the JITed codes. Each RangeSection knows the 
    IJitManager which created it.

    An IJitManager knows about which method bodies live in each RangeSection.
    It can handle methods of one given CodeType. It can map a method body to
    a MethodDesc. It knows where the GCInfo about the method lives.
    Today, we have 3 IJitManagers viz.
    1. EEJitManager for JITcompiled code generated by mscorjit.dll
    2. MNativeJitManager for ngenned code. We should be able to replace
       this with EEJitManager

    An ICodeManager knows how to crack a specific format of GCInfo. There is
    a default format (handled by ExecutionManager::GetDefaultCodeManager())
    which can be shared by different IJitManagers/IJitCompilers.

    An ICorJitCompiler knows how to generate code for a method IL, and produce
    GCInfo in a format which the corresponding IJitManager's ICodeManager 
    can handle.

                                               ExecutionManager
                                                       |
                           +-----------+---------------+---------------+-----------+--- ...
                           |           |                               |           |
                        CodeType       |                            CodeType       |
                           |           |                               |           |
                           v           v                               v           v
+---------------+      +--------+<---- R    +---------------+      +--------+<---- R
|ICorJitCompiler|<---->|IJitMan |<---- R    |ICorJitCompiler|<---->|IJitMan |<---- R
+---------------+      +--------+<---- R    +---------------+      +--------+<---- R
                           |       x   .                               |       x   .
                           |        \  .                               |        \  .
                           v         \ .                               v         \ .
                       +--------+      R                           +--------+      R
                       |ICodeMan|                                  |ICodeMan|     (RangeSections)
                       +--------+                                  +--------+       

******************************************************************************/

#ifndef __CODEMAN_HPP__

#define __CODEMAN_HPP__

// this is the define the make ejitted code recognizable from regular jit even though they are
// both IL.

#define   miManaged_IL_EJIT             (miMaxMethodImplVal + 1)

#include "crst.h"
#include "eetwain.h"
#ifdef FJIT
#include "fjit_eetwain.h"
#endif
#include "ceeload.h"
#include "jitinterface.h"
#include "debuginfostore.h"
#include "shash.h"

class MethodDesc;
class ICorJitCompiler;
class IJitManager;
class EEJitManager;
class ExecutionManager;
class Thread;
class CrawlFrame;
class MethodEntryChunk;
class IDebugInfoStore;
struct JitDebugInfo;
struct EE_ILEXCEPTION;
struct EE_ILEXCEPTION_CLAUSE;
typedef unsigned EH_CLAUSE_ENUMERATOR;

inline DWORD MIN (DWORD a, DWORD b);



// Note PAGE_SIZE is 0x1000 (4096) on X86 
//               and 0x2000 (8192) on IA64

#define PAGE_MASK               (PAGE_SIZE-1)
#define PAGE_ALIGN              ~(PAGE_MASK)
#define ROUND_DOWN_TO_PAGE(x)   ( (size_t) (x)              & PAGE_ALIGN)
#define ROUND_UP_TO_PAGE(x)     (((size_t) (x) + PAGE_MASK) & PAGE_ALIGN)


//-----------------------------------------------------------------------------
// Holds Jit (not ngen) debugging information manipulated by the EEJitManager.

typedef DPTR(struct JitDebugInfo) PTR_JitDebugInfo;

struct JitDebugInfo
{
    void Init()
    {
    }
    CompressDebugInfo::Boundaries m_bounds;
    CompressDebugInfo::Vars       m_vars;  

#ifdef DACCESS_COMPILE
    void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
#endif
};

//-----------------------------------------------------------------------------
// Method header which exists just before the code.
// Every IJitManager could have its own format for the header. However,
// everyone just used CodeHeader.
// MNativeJitManager use CORCOMPILE_METHOD_HEADER, however, that is a superset
// of CodeHeader, and we may eventually get rid of MNativeJitManager.

#ifdef USE_INDIRECT_CODEHEADER
typedef DPTR(struct _hpRealCodeHdr) PTR_RealCodeHeader;
typedef DPTR(struct _hpCodeHdr) PTR_CodeHeader;

#else // USE_INDIRECT_CODEHEADER
typedef DPTR(struct _hpCodeHdr) PTR_CodeHeader;

#endif // USE_INDIRECT_CODEHEADER

#ifdef USE_INDIRECT_CODEHEADER
typedef struct _hpRealCodeHdr
#else // USE_INDIRECT_CODEHEADER
typedef struct _hpCodeHdr
#endif // USE_INDIRECT_CODEHEADER
{
public:
    // On _Win64, this byte serves as padding to make
    // the layout of CodeHeader match that used by the _WIN64 implementation of CORCOMPILE_METHOD_HEADER
    PTR_JitDebugInfo     phdrDebugInfo;
    
    // Note - *(&(pCodeHeader->phdrJitEHInfo) - sizeof(size_t)) 
    // contains the number of EH clauses, See EEJitManager::allocEHInfo
    PTR_EE_ILEXCEPTION phdrJitEHInfo;
    BYTE *             phdrJitGCInfo;


    // Also see CORCOMPILE_METHOD_HEADER for the layout of the NGEN code header
    //
    PTR_MethodDesc   phdrMDesc;

public:
    //
    // Note: that the JITted code follows immediately after the MethodDesc*
    //
#ifndef USE_INDIRECT_CODEHEADER
    PTR_JitDebugInfo        GetDebugInfo()
    {
        return phdrDebugInfo;
    }
    PTR_EE_ILEXCEPTION      GetEHInfo()
    {
        return phdrJitEHInfo;
    }
    BYTE*                   GetGCInfo()
    {
        return phdrJitGCInfo;
    }
    PTR_MethodDesc          GetMethodDesc()
    {
        return phdrMDesc;
    }
    BYTE*                   GetCodeStartAddress()
    {
        return ((BYTE*)PTR_HOST_TO_TADDR(this) + sizeof(CodeHeader));
//        return (BYTE*)PTR_TO_TADDR(PTR_CodeHeader((CodeHeader*)this)) + sizeof(CodeHeader);
    }

    void SetRealCodeHeader(BYTE* pRCH)
    {
        // do nothing when we don't use an indirect header
        return;
    }

    void SetDebugInfo(PTR_JitDebugInfo pDI)
    {
        phdrDebugInfo = pDI;
    }
    void SetEHInfo(PTR_EE_ILEXCEPTION pEH)
    {
        phdrJitEHInfo = pEH;
    }
    void SetGCInfo(BYTE* pGC)
    {
        phdrJitGCInfo = pGC;
    }
    void SetMethodDesc(PTR_MethodDesc pMD)
    {
        phdrMDesc = pMD;
    }
#endif // !USE_INDIRECT_CODEHEADER

// if we're using the indirect codeheaders then all enumeration is done by the code header
#ifndef USE_INDIRECT_CODEHEADER
#ifdef DACCESS_COMPILE
    void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, IJitManager* pJitMan);
#endif  // DACCESS_COMPILE
#endif  // USE_INDIRECT_CODEHEADER
#ifdef USE_INDIRECT_CODEHEADER
} RealCodeHeader;
#else // USE_INDIRECT_CODEHEADER
} CodeHeader;
#endif // USE_INDIRECT_CODEHEADER

#ifdef USE_INDIRECT_CODEHEADER
typedef struct _hpCodeHdr
{
    PTR_RealCodeHeader   pRealCodeHeader;

public:
    PTR_JitDebugInfo        GetDebugInfo()
    {
        return pRealCodeHeader->phdrDebugInfo;
    }
    PTR_EE_ILEXCEPTION      GetEHInfo()
    {
        return pRealCodeHeader->phdrJitEHInfo;
    }
    BYTE*                   GetGCInfo()
    {
        return pRealCodeHeader->phdrJitGCInfo;
    }
    PTR_CodeHeader          GetNextFuncletHeader()
    {
        return pRealCodeHeader->pNextFuncletHeader;
    }
    PTR_RUNTIME_FUNCTION    GetUnwindInfo()
    {
        return pRealCodeHeader->pUnwindInfo;
    }
    PTR_MethodDesc          GetMethodDesc()
    {
        return pRealCodeHeader->phdrMDesc;
    }
    BYTE*                   GetCodeStartAddress()
    {        
        return ((BYTE*)PTR_HOST_TO_TADDR(this) + sizeof(CodeHeader));
    }
    PTR_CORCOMPILE_METHOD_COLD_HEADER GetColdHeader()
    {
        return pRealCodeHeader->pColdHeader;
    }

    void SetRealCodeHeader(BYTE* pRCH)
    {
        pRealCodeHeader = PTR_RealCodeHeader((RealCodeHeader*)pRCH);
    }

    void SetDebugInfo(PTR_JitDebugInfo pDI)
    {
        pRealCodeHeader->phdrDebugInfo = pDI;
    }
    void SetEHInfo(PTR_EE_ILEXCEPTION pEH)
    {
        pRealCodeHeader->phdrJitEHInfo = pEH;
    }
    void SetGCInfo(BYTE* pGC)
    {
        pRealCodeHeader->phdrJitGCInfo = pGC;
    }
    void SetNextFuncletHeader(PTR_CodeHeader pNext)
    {
        pRealCodeHeader->pNextFuncletHeader = pNext;
    }
    void SetUnwindInfo(PTR_RUNTIME_FUNCTION pUnwind)
    {
        pRealCodeHeader->pUnwindInfo = pUnwind;
    }
    void SetMethodDesc(PTR_MethodDesc pMD)
    {
        pRealCodeHeader->phdrMDesc = pMD;
    }
    void SetColdHeader(PTR_CORCOMPILE_METHOD_COLD_HEADER pColdHeader)
    {
        pRealCodeHeader->pColdHeader = pColdHeader;
    }

#ifdef DACCESS_COMPILE
    void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, IJitManager* pJitMan);
#endif  // DACCESS_COMPILE
} CodeHeader;
#endif // USE_INDIRECT_CODEHEADER


//-----------------------------------------------------------------------------
// This is a structure used to consolidate the information that we 
// need we creating new code heaps. 
// When creating new JumpStubs we have a constarint that the address used
// should be in the range [loAddr..hiAddr]
//
struct CodeHeapRequestInfo
{
    MethodDesc * m_pMD;
    BaseDomain * m_pDomain;
    const BYTE * m_loAddr;          // lowest address to use to satisfy our request (0 -- don't care)
    const BYTE * m_hiAddr;          // hihest address to use to satisfy our request (0 -- don't care)
    size_t       m_requestSize;     // minimum size that must be made available
    size_t       m_reserveSize;     // Amount that VirtualAlloc will reserved
    size_t       m_cacheSize;
    bool         m_isDynamicDomain;
    
    bool   IsDynamicDomain()                    { return m_isDynamicDomain;    }
    
    size_t getRequestSize()                     { return m_requestSize;        }
    void   setRequestSize(size_t requestSize)   { m_requestSize = requestSize; }
    
    size_t getReserveSize()                     { return m_reserveSize;        }
    void   setReserveSize(size_t reserveSize)   { m_reserveSize = reserveSize; }
    
    size_t getCacheSize()                       { return m_cacheSize;          }
    void   setCacheSize(size_t cacheSize)       { m_cacheSize = cacheSize;     }
    
    void   Init();
    
    CodeHeapRequestInfo(MethodDesc *pMD)
        : m_pMD(pMD), m_pDomain(0), 
          m_loAddr(0), m_hiAddr(0),
          m_requestSize(0), m_reserveSize(0), m_cacheSize(0)
    {   Init(); }
    
    CodeHeapRequestInfo(MethodDesc *pMD, BaseDomain *pDomain, size_t requestSize,
                        BYTE * loAddr, BYTE * hiAddr)
        : m_pMD(pMD), m_pDomain(pDomain), 
          m_loAddr(loAddr), m_hiAddr(hiAddr),
          m_requestSize(requestSize), m_reserveSize(0), m_cacheSize(0)
    {   Init(); }
};

//-----------------------------------------------------------------------------
//
// A CodeHeap is the abstraction the IJitManager uses to allocate memory
// needed to the jitting of a method.
// The CodeHeap works together with the HeapList to manage a contiguous block of memory.
// The CodeHeap is a non growable chunk of memory (it can be reserved and
// committed on demand).
//
// A CodeHeap is naturally protected from multiple threads by the code heap
// critical section - m_pCodeHeapCritSec - so if the implementation of the heap
// is only for the code manager, no locking needs to occur.
// It's important however that a delete operation on the CodeHeap (if any) happens
// via EEJitManager::ReleaseReferenceToHeap(CodeHeap*, MethodDesc*)
//
// The heap to be created depends on the MethodDesc that is being compiled. 
// Standard code uses the LoaderCodeHeap, a heap based on the LoaderHeap.
// DynamicMethods - and only those - use a HostCodeHeap, a heap that does
// normal Alloc/Free so reclamation can be performed. 
//
// The convention is that every heap implementation would have a static create
// function that returns a HeapList. The HeapList *must* be properly initialized
// on return except for the next pointer
//

typedef VPTR(class CodeHeap) PTR_CodeHeap;

class CodeHeap
{
    VPTR_BASE_VTABLE_CLASS(CodeHeap)

public:

#ifdef DACCESS_COMPILE
    CodeHeap() {}
#endif

    // virtual dtor. Clean up heap
    virtual ~CodeHeap() {}

    // Alloc the specified numbers of bytes.
    // There are only 2 flavors of Alloc that the CodeHeap cares about: a throw and a non-throw.
    // We could combine them together and use a flag to call one or the other but the overall model
    // appears to favor explicit naming convention.
    virtual void* AllocMemory(size_t size, DWORD alignment) = 0;
    virtual void* AllocMemory_NoThrow(size_t size, DWORD alignment) = 0;

    // the inital address of the CodeHeap
    virtual void* GetHeapStartAddress() = 0;

#ifdef _DEBUG
    // for assert usage only. Return whatever internal data is used in the CodeHeap on return from Create.
    // Typically this value minus the start address in the HeapList should return the heap start address
    virtual size_t GetReservedPrivateData() = 0;
#endif

#ifdef DACCESS_COMPILE
    virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) = 0;
#endif

protected:
    friend class EEJitManager;
    // allows for reclamation of methods from the heap. Not every MethodDesc asks to be reclaimed
    // and a heap is free to ignore the request.
    // However for locking reasons is important this method is not called directly (hence protected) 
    // but always via the EEJitManager::ReleaseReferenceToHeap(CodeHeap*, MethodDesc*)
    virtual void ReleaseReferenceToHeap(MethodDesc* pMD) = 0;
    virtual void DestroyHeap() = 0;

};

//-----------------------------------------------------------------------------
// The HeapList works together with the CodeHeap to manage a contiguous block of memory.
//
// A single HeapList contains code only for a single AppDomain. EEJitManager uses
// EEJitManager::DomainCodeHeapList to keep a list of HeapLists for each AppDomain.

typedef DPTR(struct _HeapList) PTR_HeapList;

typedef struct _HeapList
{
    PTR_HeapList        hpNext;
    PTR_CodeHeap        pHeap;
    
    TADDR               startAddress;
    TADDR               endAddress;     // the current end of the used portion of the Heap

    // Counters which are incremented by writers.
    // Readers can check that changeEnd before the read is the same as
    // changeStart after the read to ensure that no writer was stomping
    // on the heap while they were reading it
    volatile PBYTE      changeStart;
    volatile PBYTE      changeEnd;

    TADDR               mapBase;        // "startAddress" rounded down to PAGE_SIZE. pHdrMap is relative to this address
    PTR_DWORD           pHdrMap;        // bit array used to find the start of methods

    size_t              maxCodeHeapSize;// Size of the entire contiguous block of memory
    DWORD               cBlocks;        // Number of allocations
    DWORD /*volatile*/  bFull;          // Heap is considered full do not use for new allocations
    
    // We have a hashtable cache to map from an address to a HeapList
    // This allows us to look up frequently used HeapLists faster.
    PBYTE               pCacheSpacePtr;
    size_t              bCacheSpaceSize;


    PTR_HeapList GetVolatile_hpNext()
    { return hpNext; }

    void SetVolatile_hpNext(PTR_HeapList next)
    { hpNext = next; }

    void SetHeapFull() 
    { *((volatile DWORD *) &bFull) = TRUE; }

    bool IsHeapFull() 
    { return (*((volatile DWORD *) &bFull) != 0); }

} HeapList;

//-----------------------------------------------------------------------------
// Implementation of the standard CodeHeap.
// Use the ExplicitControlLoaderHeap for allocations
// (Check the base class above - CodeHeap - for comments on the functions)
//
typedef VPTR(class LoaderCodeHeap) PTR_LoaderCodeHeap;

class LoaderCodeHeap : CodeHeap
{
#ifdef DACCESS_COMPILE
    friend class ClrDataAccess;
#endif
    
    VPTR_VTABLE_CLASS(LoaderCodeHeap, CodeHeap)

private:
    PTR_ExplicitControlLoaderHeap pLoaderHeap;

    LoaderCodeHeap(ExplicitControlLoaderHeap *pHeap)
    {
        LEAF_CONTRACT;
        pLoaderHeap = PTR_ExplicitControlLoaderHeap(pHeap);
    }

public:
    static HeapList* CreateCodeHeap(CodeHeapRequestInfo *pInfo, LoaderHeap *pJitMetaHeap);

public:
    virtual ~LoaderCodeHeap() 
    {
#ifndef DACCESS_COMPILE
        WRAPPER_CONTRACT;
        if (pLoaderHeap) 
            delete pLoaderHeap;
#endif
    }

    virtual void* AllocMemory(size_t size, DWORD alignment)
    {
#ifndef DACCESS_COMPILE
        WRAPPER_CONTRACT;
        return (void*)pLoaderHeap->AllocAlignedmem(size, alignment, FALSE);
#else
        return NULL;
#endif
    }

    virtual void* AllocMemory_NoThrow(size_t size, DWORD alignment)
    {
#ifndef DACCESS_COMPILE
        WRAPPER_CONTRACT;
        return (void*)pLoaderHeap->AllocAlignedmem_NoThrow(size, alignment, FALSE);
#else
        return NULL;
#endif
    }

    virtual void* GetHeapStartAddress() 
    {
        WRAPPER_CONTRACT;
        return pLoaderHeap->GetFirstBlockVirtualAddress();
    }

#ifdef _DEBUG
    virtual size_t GetReservedPrivateData()
    {
        LEAF_CONTRACT;
        return sizeof(HeapList) + sizeof(LoaderHeapBlock);
    }
#endif

#ifdef DACCESS_COMPILE
    virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
    {
        WRAPPER_CONTRACT;
        pLoaderHeap->EnumMemoryRegions(flags);
    }
#endif

protected:
    // the LoaderHeap does not allow for reclamation of methods
    virtual void ReleaseReferenceToHeap(MethodDesc* pMD) {LEAF_CONTRACT;}
    virtual void DestroyHeap() {LEAF_CONTRACT;}

};

//-----------------------------------------------------------------------------
// The ExecutionManager uses RangeSection ss the abstration of a contiguous
// address range to track the code heaps.

typedef DPTR(struct _rangesection) PTR_RangeSection;

typedef struct _rangesection
{
    TADDR               LowAddress;
    TADDR               HighAddress;

    PTR_IJitManager     pjit;           // The owner of this address range
    TADDR               ptable;

    PTR_RangeSection    pnext;          // link rangesections in a sorted list
    PTR_RangeSection    pLastUsed;      // for the head node only:  a link to rangesections that was used most recently

    DWORD               flags;
    PTR_RangeSection    pcold;          // pointer to cold range section (only present in hot range sections)
    PTR_Module          pModule;        // only valid for zapped images where a range section only contains code from one module

} RangeSection;

#define RANGE_SECTION_COLD  0x01

/*****************************************************************************/

#define FAILED_JIT      0x01
#define FAILED_EJIT     0x02

#define MIH_GC_OFFSET (offsetof(IMAGE_COR_MIH_ENTRY, MIHData) - offsetof(IMAGE_COR_MIH_ENTRY, Flags))

// METHODTOKEN == CORCOMPILE_METHOD_HEADER* for managed native code
//             == CodeHeader* for EEJitManager
typedef struct _METHODTOKEN {
    inline PTR_CodeHeader GetCodeHeader()
    {
        LEAF_CONTRACT;
        return PTR_CodeHeader((CodeHeader*)this);
    }
} *METHODTOKEN;

struct JumpStubBlockHeader;

//-----------------------------------------------------------------------------
//
// Manages the CodeHeap for some of the RangeSections in the ExecutionManager
//
//-----------------------------------------------------------------------------

class IJitManager 
{
    VPTR_BASE_VTABLE_CLASS(IJitManager)
    
public:

    struct MethodRegionInfo
    {
        BYTE *hotStartAddress;
        size_t hotSize;
        BYTE *coldStartAddress;
        size_t coldSize;
    };

    enum ScanFlag    {ScanReaderLock, ScanNoReaderLock};

#ifndef DACCESS_COMPILE
    IJitManager();
    virtual ~IJitManager();
#endif // #ifndef DACCESS_COMPILE

    // Get an DebugInfoStore, which lets us access jit information.
    virtual void GetDebugInfoStore(IDebugInfoStore ** ppStore) = 0;

#ifndef DACCESS_COMPILE   
    // Used to populate the info store.
    // The calls do not own the arrays passed in. It is expected that the implementations will compress
    // the arrays, and thus not need the uncompressed copy that was passed in.
    virtual void setVars(CodeHeader * pHeader, CORINFO_METHOD_HANDLE ftn, ULONG32 cVars, ICorDebugInfo::NativeVarInfo *vars) = 0;
    virtual void setBoundaries(CodeHeader * pHeader, CORINFO_METHOD_HANDLE ftn, ULONG32 cMap, ICorDebugInfo::OffsetMapping *pMap) = 0;
#endif    

    virtual void JitCodeToMethodInfo(
            SLOT currentPC,
            MethodDesc** ppMethodDesc,
            METHODTOKEN* pMethodToken = NULL,
            DWORD* pPCOffset = NULL,
            ScanFlag scanFlag = ScanReaderLock) = 0;

    virtual MethodDesc* JitTokenToMethodDesc(METHODTOKEN MethodToken)=0;
    virtual BYTE*       JitTokenToStartAddress(METHODTOKEN MethodToken, ScanFlag scanFlag=ScanReaderLock)=0;
    virtual size_t      JitTokenToMethodHotSize(METHODTOKEN MethodToken)=0;
    virtual void        JitTokenToMethodRegionInfo(METHODTOKEN MethodToken, MethodRegionInfo *methodRegionInfo) = 0;
    virtual unsigned    InitializeEHEnumeration(METHODTOKEN MethodToken, EH_CLAUSE_ENUMERATOR* pEnumState)=0;
    virtual EE_ILEXCEPTION_CLAUSE* GetNextEHClause(METHODTOKEN MethodToken,
                                        EH_CLAUSE_ENUMERATOR* pEnumState, 
                                        EE_ILEXCEPTION_CLAUSE* pEHclause)=0; 
#ifndef DACCESS_COMPILE    
    virtual TypeHandle  ResolveEHClause(METHODTOKEN MethodToken,
                                        EH_CLAUSE_ENUMERATOR* pEnumState, 
                                        EE_ILEXCEPTION_CLAUSE* pEHClauseOut,
                                        CrawlFrame *pCf)=0;
#endif // #ifndef DACCESS_COMPILE
    virtual void*       GetGCInfo(METHODTOKEN MethodToken)=0;
#ifndef DACCESS_COMPILE
    virtual void        RemoveJitData(METHODTOKEN MethodToken, size_t GCinfo_len, size_t EHinfo_len)=0;
    virtual void        Unload(AppDomain *pDomain)=0;   // for appdomain unloading
    virtual BOOL        LoadJIT(LPCWSTR szJITdll);
    virtual void        ResumeAtJitEH   (CrawlFrame* pCf, EE_ILEXCEPTION_CLAUSE *EHClausePtr, DWORD nestingLevel, Thread *pThread, BOOL unwindStack)=0;
    virtual int         CallJitEHFilter (CrawlFrame* pCf, EE_ILEXCEPTION_CLAUSE *EHClausePtr, DWORD nestingLevel, OBJECTREF thrownObj)=0;
    virtual void        CallJitEHFinally(CrawlFrame* pCf, EE_ILEXCEPTION_CLAUSE *EHClausePtr, DWORD nestingLevel)=0;

    virtual CodeHeader*         allocCode(MethodDesc* pFD, size_t blockSize, CorJitAllocMemFlag flag)=0;
#endif // #ifndef DACCESS_COMPILE


#ifndef DACCESS_COMPILE
    virtual BYTE *              allocGCInfo(CodeHeader* pCodeHeader, DWORD blockSize, size_t * pAllocationSize)=0;
    virtual EE_ILEXCEPTION*     allocEHInfo(CodeHeader* pCodeHeader, unsigned numClauses, size_t * pAllocationSize)=0;
    virtual JumpStubBlockHeader* allocJumpStubBlock(MethodDesc* pMD, DWORD numJumps, 
                                                    BYTE * loAddr, BYTE * hiAddr,
                                                    BaseDomain *pDomain)=0;
#endif // #ifndef DACCESS_COMPILE

#ifndef DACCESS_COMPILE
    virtual BYTE* GetNativeEntry(BYTE* startAddress)=0;
#endif // #ifndef DACCESS_COMPILE

    static ScanFlag GetScanFlags();



#ifdef DACCESS_COMPILE
    virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
#endif

#ifndef DACCESS_COMPILE
    void SetCodeManager(ICodeManager *codeMgr, BOOL bIsDefault)
    {
        LEAF_CONTRACT;

        m_runtimeSupport = codeMgr;
        m_IsDefaultCodeMan = bIsDefault;
        return;
    }
#endif

    ICodeManager *GetCodeManager() 
    {
        LEAF_CONTRACT;

        return m_runtimeSupport;
    }

    void SetCodeType(DWORD type)
    {
        LEAF_CONTRACT;

        m_CodeType = type;
        return;
    }

    DWORD GetCodeType()
    {
        LEAF_CONTRACT;

        return(m_CodeType);
    }

    BOOL IsJitForType(DWORD type)
    {
        LEAF_CONTRACT;

        if (type == m_CodeType)
            return TRUE;
        else
            return FALSE;
    }
    
    BOOL IsJitLoaded()
    {
        LEAF_CONTRACT;

        return (m_jit != NULL);
    }

    VOID ClearCache()
    {
        if( m_jit != NULL )
        {
            m_jit->clearCache();
        }
    }

    BOOL IsCacheCleanupRequired()
    {
        if( m_jit != NULL )
        {
            return m_jit->isCacheCleanupRequired();
        }

        return FALSE;
    }

    ICorJitCompiler *  m_jit;
    PTR_IJitManager    m_next;

protected:

    DWORD            m_CodeType;
    DWORD            m_IsDefaultCodeMan;
    PTR_ICodeManager m_runtimeSupport;
    HINSTANCE        m_JITCompiler;
};

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

struct JumpStubBlockHeader
{
    JumpStubBlockHeader *  m_next;
    UINT32                 m_used;
    UINT32                 m_allocated;
    BaseDomain *           m_domain;
    UINT64                 m_zero;
};

//-----------------------------------------------------------------------------
// Ideally, EEJitManager would just implement IDebugInfoStore directly, but DAC
// doesn't support multiple inheritence.
// The only thing in here is a VTable.
// This is conceptually an extension to EEJitManager

class EEJitDebugInfoStore : public IDebugInfoStore
{
public:
    VPTR_VTABLE_CLASS(EEJitDebugInfoStore, IDebugInfoStore)

    EEJitDebugInfoStore() { }
    
    static CodeHeader * EEJitDebugInfoStore::GetCodeHeaderFromJitRequest(const DebugInfoRequest & request);

    virtual HRESULT GetVars(
        const DebugInfoRequest & request,
        IN FP_IDS_NEW fpNew, IN void * pNewData,
        OUT ULONG32 * pcVars, 
        OUT ICorDebugInfo::NativeVarInfo ** ppVars);
    virtual HRESULT GetBoundaries(
        const DebugInfoRequest & request,
        IN FP_IDS_NEW fpNew, IN void * pNewData,
        OUT ULONG32 * pcMap, 
        OUT ICorDebugInfo::OffsetMapping ** ppMap);

#ifdef DACCESS_COMPILE
    virtual void EnumMemoryRegionsForMethodDebugInfo(CLRDataEnumMemoryFlags flags, MethodDesc * pMD);
#endif        
};


/*****************************************************************************/

#if defined (_MSC_VER) && _MSC_VER <= 1300
template void DoNothing(EEJitManager*);
template BOOL CompareDefault(EEJitManager*,EEJitManager*);
typedef DacHolder<EEJitManager *, DoNothing, DoNothing> HACKEEJitManagerLockHolder;
#endif

typedef VPTR(class EEJitManager) PTR_EEJitManager;

class EEJitManager :public IJitManager
{
#ifdef DACCESS_COMPILE
    friend class ClrDataAccess;
#endif
    friend class CheckDuplicatedStructLayouts;
    friend class EEJitDebugInfoStore;

    VPTR_VTABLE_CLASS(EEJitManager, IJitManager)
    
public:

#ifndef DACCESS_COMPILE
    EEJitManager();

    // No destructor necessary. Only one instance of this class that is destroyed at process shutdown.
    // ~EEJitManager();
#endif // #ifndef DACCESS_COMPILE

    // Used to get a reader interface for the stores.
    virtual void GetDebugInfoStore(IDebugInfoStore ** ppStore);

#ifndef DACCESS_COMPILE       
    // Used to populate the info store.
    virtual void setVars(CodeHeader * pHeader, CORINFO_METHOD_HANDLE ftn, ULONG32 cVars, ICorDebugInfo::NativeVarInfo *vars);
    virtual void setBoundaries(CodeHeader * pHeader, CORINFO_METHOD_HANDLE ftn, ULONG32 cMap, ICorDebugInfo::OffsetMapping *pMap);
#endif
    
    virtual void JitCodeToMethodInfo(SLOT currentPC, 
                                     MethodDesc** ppMethodDesc, 
                                     METHODTOKEN* pMethodToken=NULL, 
                                     DWORD* pPCOffset=NULL, 
                                     ScanFlag scanFlag=ScanReaderLock);
    virtual MethodDesc* JitTokenToMethodDesc(METHODTOKEN MethodToken);
    static  BYTE*       JitTokenToStartAddressStatic(METHODTOKEN MethodToken, ScanFlag scanFlag=ScanReaderLock);
    virtual BYTE*       JitTokenToStartAddress(METHODTOKEN MethodToken, ScanFlag scanFlag=ScanReaderLock);
    virtual size_t      JitTokenToMethodHotSize(METHODTOKEN MethodToken);
    virtual void        JitTokenToMethodRegionInfo(METHODTOKEN MethodToken, MethodRegionInfo *methodRegionInfo);

    virtual unsigned    InitializeEHEnumeration(METHODTOKEN MethodToken, EH_CLAUSE_ENUMERATOR* pEnumState);
    virtual EE_ILEXCEPTION_CLAUSE*      GetNextEHClause(METHODTOKEN MethodToken,
                                        EH_CLAUSE_ENUMERATOR* pEnumState, 
                                        EE_ILEXCEPTION_CLAUSE* pEHclause); 
#ifndef DACCESS_COMPILE    
    virtual TypeHandle  ResolveEHClause(METHODTOKEN MethodToken,
                                        EH_CLAUSE_ENUMERATOR* pEnumState, 
                                        EE_ILEXCEPTION_CLAUSE* pEHClauseOut,
                                        CrawlFrame *pCf);
#endif // #ifndef DACCESS_COMPILE
    void*               GetGCInfo(METHODTOKEN MethodToken);
#ifndef DACCESS_COMPILE
    virtual void        RemoveJitData(METHODTOKEN MethodToken, size_t GCinfo_len, size_t EHinfo_len);

    virtual void        Unload(AppDomain *pDomain);
    virtual void        ResumeAtJitEH   (CrawlFrame* pCf, EE_ILEXCEPTION_CLAUSE *EHClausePtr, DWORD nestingLevel, Thread *pThread, BOOL unwindStack);
    virtual int         CallJitEHFilter (CrawlFrame* pCf, EE_ILEXCEPTION_CLAUSE *EHClausePtr, DWORD nestingLevel, OBJECTREF thrownObj);
    virtual void        CallJitEHFinally(CrawlFrame* pCf, EE_ILEXCEPTION_CLAUSE *EHClausePtr, DWORD nestingLevel);

    CodeHeader*         allocCode(MethodDesc* pFD, size_t blockSize, CorJitAllocMemFlag flag);
    void                allocEntryChunk(MethodDescChunk *pMDChunk);
    BYTE *              allocGCInfo(CodeHeader* pCodeHeader, DWORD blockSize, size_t * pAllocationSize);
    EE_ILEXCEPTION*     allocEHInfo(CodeHeader* pCodeHeader, unsigned numClauses, size_t * pAllocationSize);
    JumpStubBlockHeader* allocJumpStubBlock(MethodDesc* pMD, DWORD numJumps, 
                                            BYTE * loAddr, BYTE * hiAddr,
                                            BaseDomain *pDomain);

#endif // #ifndef DACCESS_COMPILE

    inline virtual BOOL IsStub(const BYTE* address)
    { // This is needed by the debugger, this code manager does not produce stubs, so always return false 
        LEAF_CONTRACT;
        return false;
    }

    inline virtual const BYTE* FollowStub(const BYTE* address)
    {
        LEAF_CONTRACT;
        _ASSERTE(!"Should not be called");
        return NULL;
    }


#ifdef DACCESS_COMPILE
    virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
#endif
    
    // Heap Management functions
    static void NibbleMapSet(DWORD *pMap, size_t delta, BOOL bSet = TRUE);
    static size_t FindMethodCode(PTR_DWORD pMap, TADDR delta);

    inline virtual BYTE* GetNativeEntry(BYTE* startAddress)
    {
        LEAF_CONTRACT;
        return startAddress;
    }

/* =========== NOT CURRENTLY USED =====================
    void *NewNativeHeap(DWORD startAddr, DWORD length);
    BOOL IsJITforCurrentIP(DWORD currentPC);
   =========== NOT CURRENTLY USED ===================*/

#ifndef DACCESS_COMPILE
    void        ReleaseReferenceToHeap(CodeHeap *pCodeHeap, MethodDesc *pMD);
    void        ReleaseHeap(CodeHeap *pCodeHeap);
    void        DeleteCodeHeap(HeapList *pHeapList);
    void        RemoveCodeHeapFromDomainList(CodeHeap *pHeap, BaseDomain *pDomain);

#endif

private :
    struct DomainCodeHeapList {
        BaseDomain *m_pDomain;
        CDynArray<HeapList *> m_CodeHeapList;
        DomainCodeHeapList();
        ~DomainCodeHeapList();
    };
#ifndef DACCESS_COMPILE
    HeapList*   NewCodeHeap(CodeHeapRequestInfo *pInfo, DomainCodeHeapList *pADHeapList); 
    HeapList*   GetCodeHeap(CodeHeapRequestInfo *pInfo);
    void*       allocCodeRaw(CodeHeapRequestInfo *pInfo, 
                             size_t blockSize, unsigned align,
                             HeapList ** ppCodeHeap /* Writeback, Can be null */ );

    DomainCodeHeapList *GetCodeHeapList(MethodDesc *pMD, BaseDomain *pDomain);
    LoaderHeap* GetJitMetaHeap(MethodDesc *pMD);

protected :    
    void *      allocEHInfoRaw(CodeHeader* pCodeHeader, DWORD blockSize, size_t * pAllocationSize);
private :       
#endif // #ifndef DACCESS_COMPILE

    static CodeHeader * GetCodeHeaderFromAddr(TADDR startAddress)
    {
        LEAF_CONTRACT;
        //return PTR_CodeHeader((PTR_HOST_TO_TADDR(startAddress) & ~3) - sizeof(CodeHeader));
        return PTR_CodeHeader((startAddress & ~3) - sizeof(CodeHeader));
    }

    PTR_HeapList m_pCodeHeap;

    PTR_HeapList GetVolatile_pCodeHeap()
    { return m_pCodeHeap; }
    
    void SetVolatile_pCodeHeap(PTR_HeapList value)
    { m_pCodeHeap = value; }
    
protected :    
    CrstExplicitInit    m_CodeHeapCritSec;
private :    
    EEJitDebugInfoStore m_DebugInfoStore;

    // must hold critical section to access this structure.
    CUnorderedArray<DomainCodeHeapList *, 5> m_DomainCodeHeaps;
    CUnorderedArray<DomainCodeHeapList *, 5> m_DynamicDomainCodeHeaps;

    // infrastructure to manage readers so we can lock them out and delete domain data
    volatile LONG        m_dwReaderCount;
    volatile LONG        m_dwWriterLock;

    MethodDesc* JitCodeToMethodDescWrapper( SLOT currentPC, 
                                            METHODTOKEN* pMethodToken=NULL, 
                                            DWORD* pPCOffset=NULL
                                            );

    void AddRangeToJitHeapCache (TADDR startAddr, TADDR endAddr, HeapList* pHp);
    void DeleteJitHeapCache (HeapList *pHeapList);
    size_t GetCodeHeapCacheSize (size_t bAllocationRequest);

    const static DWORD  HASH_BUCKETS       = 256;

    const static size_t CACHE_BLOCK_SIZE   = 0x00010000;                          // ( 64 KB )
    const static size_t CACHE_BLOCK_MASK   = CACHE_BLOCK_SIZE-1;                  // 0x0000ffff
    const static size_t CACHE_BLOCK_ALIGN  = ~CACHE_BLOCK_MASK;                   // 0xffff0000
    const static size_t CACHE_INDEX_MASK   = (HASH_BUCKETS-1) * CACHE_BLOCK_SIZE; // 0x00ff0000
    const static DWORD  CACHE_INDEX_RSHIFT = 16;

    inline DWORD GET_CACHE_INDEX(size_t addr)
    { return ((DWORD)(addr & CACHE_INDEX_MASK)) >> CACHE_INDEX_RSHIFT; }

    inline size_t COMPUTE_HASH_KEY(size_t addr)
    { return (addr & CACHE_BLOCK_ALIGN); }

    typedef struct _HashEntry
    {
        size_t hashKey;      // Key stored as COMPUTE_HASH_KEY(currentPC), hash is computed GET_CACHE_INDEX(hashKey)
        PTR_HeapList pHp;    // Value points to the HeapList's node
        DPTR(struct _HashEntry) pNext;
    } HashEntry;
    typedef DPTR(HashEntry) PTR_HashEntry;
    PTR_HashEntry m_JitCodeHashTable[HASH_BUCKETS];
    HashEntry *m_pJitHeapCacheUnlinkedList;
#ifdef _DEBUG
    BOOL DebugContainedInHeapList (HeapList *pHashEntryHp);
    void DebugCheckJitHeapCacheValidity ();
#endif // _DEBUG

    static void IncrementReader(EEJitManager *pMgr);
    static void DecrementReader(EEJitManager *pMgr);
    static void TakeWriter(EEJitManager *pMgr);
    static void ReleaseWriter(EEJitManager *pMgr);

    typedef DacHolder<EEJitManager *, EEJitManager::IncrementReader, EEJitManager::DecrementReader> ReaderLockHolder;
    typedef DacHolder<EEJitManager *, EEJitManager::TakeWriter, EEJitManager::ReleaseWriter> WriterLockHolder;
};


//*****************************************************************************
//
// This class manages IJitManagers and ICorJitCompilers.  It has only static
// members.  It should never be constucted.
//
//*****************************************************************************

#if defined (_MSC_VER) && _MSC_VER <= 1300
template void DoNothing(ExecutionManager*);
template BOOL CompareDefault(ExecutionManager*,ExecutionManager*);
typedef DacHolder<ExecutionManager *, DoNothing, DoNothing> HACKExecutionManagerLockHolder;
#endif

class ExecutionManager
{
    friend class CorExternalDataAccess;

#ifdef DACCESS_COMPILE
    friend class ClrDataAccess;
#endif

    friend bool decodeMethodEntryPoint(const BYTE* pBuffer, BYTE epSize, const BYTE** pTarget, SSIZE_T* pMDOffset, bool fHasLock);

    static IJitManager*   FindJitManNonZeroWrapper(SLOT currentPC);
    static IJitManager*   FindJitManNonZero(SLOT currentPC, IJitManager::ScanFlag scanFlag=IJitManager::ScanReaderLock);
public :

    static void Init();

    // this gets called a lot for stackwalking, so inline the zero case
    static IJitManager*   FindJitMan(SLOT currentPC, IJitManager::ScanFlag scanFlag=IJitManager::ScanReaderLock)
    {
        CONTRACTL {
            NOTHROW;
            GC_NOTRIGGER;
            SO_TOLERANT;
        } CONTRACTL_END;
 
        return (currentPC ? FindJitManNonZero(currentPC, scanFlag) : NULL);
    }

    static IJitManager*   FindJitManPCOnly(SLOT currentPC)
    {
        CONTRACTL {
            NOTHROW;
            GC_NOTRIGGER;
            SO_TOLERANT;
        } CONTRACTL_END;
 
        return (currentPC ? FindJitManNonZeroWrapper(currentPC) : NULL);
    }

    // Find a code manager from the current locations of the IP
    static ICodeManager*  FindCodeMan(SLOT currentPC, IJitManager::ScanFlag scanFlag=IJitManager::ScanReaderLock) 
    {
        CONTRACTL {
            NOTHROW;
            GC_NOTRIGGER;
            SO_TOLERANT;
        } CONTRACTL_END;
 
        IJitManager * pJitMan = FindJitMan(currentPC, scanFlag);
        return pJitMan != NULL ? pJitMan->GetCodeManager() : NULL;
    }

    // Use JitCodeToMethodOffset() to get the offset relative to the start of the method.
    static DWORD          JitCodeToOffset(TADDR currentPC);
        

    static IJitManager*   FindJitForType(DWORD Flags);
    static void ClearCaches( void );
    static BOOL IsCacheCleanupRequired();

    static LPWSTR         GetJitName();
    static IJitManager*   GetJitForType(DWORD Flags, bool dontLoadJit = false);

    static void           Unload(AppDomain *pDomain);
    static BOOL           PatchEntryPoint(BYTE* pBuffer, BYTE epSize, 
                                          BYTE* target, MethodDesc * methodDesc);

    static void           AddJitManager(IJitManager * newjitmgr);
    static RangeSection * AddCodeRange(TADDR StartRange, TADDR EndRange,
                                       IJitManager* pJit, TADDR Table,
                                       DWORD flags=0,
                                       RangeSection *pColdRangeSection=NULL,
                                       Module* pModule=NULL);
    static void           DeleteCodeRange(TADDR StartRange);
    static RangeSection * AddDataRange(TADDR StartRange, TADDR EndRange,
                                       Module* pModule=NULL);
    static void           DeleteDataRange(TADDR StartRange);

    static void           ReleaseReferenceToHeap(EEJitManager *pJitManager, CodeHeap *pCodeHeap, MethodDesc *pMethod);
    static void           ReleaseHeap(EEJitManager *pJitManager, CodeHeap *pCodeHeap);

#ifndef FJITONLY
    static ICodeManager*  GetDefaultCodeManager()
    {
        LEAF_CONTRACT;
        return (ICodeManager *)m_pDefaultCodeMan;    
    }
#endif

    static Module* FindZapModule(TADDR currentData);

    // NOTE: This will only work well for NGEN'd images
    static Module* FindZapModuleForNativeCode(TADDR currentCode);


    static RangeSection*             GetRangeSection(RangeSection *pRS, TADDR addr);
    static RangeSection*             GetRangeSectionAndPrev(RangeSection *pRS, TADDR addr, RangeSection **ppPrev);

    static RangeSection*             GetRangeSectionForAddress(TADDR startAddress);
        
#ifdef DACCESS_COMPILE
    static void EnumRangeList(RangeSection* list,
                              CLRDataEnumMemoryFlags flags);
    static void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
#endif

#ifndef DACCESS_COMPILE
    static void    preallocatedJumpStubBlock(BYTE * mem, DWORD blockSize, BaseDomain *pDomain);
    static void    unlinkPreallocatedJumpStubBlock(BYTE * mem, DWORD blockSize, BaseDomain *pDomain);
    static void    deleteJumpStubBlock(HeapList *pHeapList);
    static void    deleteJumpStubBlockHelper(TADDR startAddr, TADDR endAddr);

    static JumpStubBlockHeader * recoverJumpStubBlockHeader(BYTE * jumpStub);

    static BYTE *  jumpStub(MethodDesc* pMD,
                            BYTE * target,
                            BYTE * loAddr,
                            BYTE * hiAddr,
                            BaseDomain *pDomain = NULL);
#endif
    
private : 

    SPTR_DECL(RangeSection,  m_CodeRangeList);
    SPTR_DECL(RangeSection,  m_DataRangeList);
    SPTR_DECL(IJitManager,   m_pJitList);
#ifndef FJITONLY
    SPTR_DECL(EECodeManager, m_pDefaultCodeMan);
#endif
    static CrstStatic       m_ExecutionManagerCrst;
    static CrstStatic       m_JumpStubCrst;
    static CrstStatic       m_RangeCrst;        // Aquire before writing into m_CodeRangeList and m_DataRangeList
    static BYTE             m_fFailedToLoad;

    // infrastructure to manage readers so we can lock them out and delete domain data
    // make ReaderCount volatile because we have order dependency in READER_INCREMENT
#ifndef DACCESS_COMPILE
    static volatile LONG   m_dwReaderCount;
    static volatile LONG   m_dwWriterLock;
#else
    SVAL_DECL(LONG, m_dwReaderCount);
    SVAL_DECL(LONG, m_dwWriterLock);
#endif

#ifdef DACCESS_COMPILE
    static bool IsSafe(void)
    {
        return m_dwWriterLock == 0;
    }
#endif
    
    static void IncrementReader(ExecutionManager *pMgr);
    static void DecrementReader(ExecutionManager *pMgr);
    static void TakeWriter(ExecutionManager *pMgr);
    static void ReleaseWriter(ExecutionManager *pMgr);

    typedef DacHolder<ExecutionManager *, ExecutionManager::IncrementReader, ExecutionManager::DecrementReader, 0, NoNull<ExecutionManager *> > ReaderLockHolder; 
    typedef DacHolder<ExecutionManager *, ExecutionManager::TakeWriter, ExecutionManager::ReleaseWriter, 0, NoNull<ExecutionManager *> > WriterLockHolder; 

    static RangeSection * AddRangeHelper(RangeSection** ppRangeList,
                                         TADDR StartRange,
                                         TADDR EndRange,
                                         IJitManager* pJit, 
                                         TADDR Table, 
                                         DWORD flags=0, 
                                         RangeSection *pColdRangeSection=NULL,
                                         Module* pModule=NULL);
    static void DeleteRangeHelper(RangeSection** ppRangeList,
                                  TADDR StartRange);

#ifndef DACCESS_COMPILE
    static BYTE * getNextJumpStub(MethodDesc* pMD,
                                  IJitManager* pJitMan,
                                  BYTE * target,
                                  BYTE * loAddr,  BYTE * hiAddr,
                                  BaseDomain *pDomain);
#endif    

private:
    static JumpStubBlockHeader *  m_jumpStubBlock;

    // ***************************************************************************
    // Hashtable for JumpStubs for jitted code

    struct JumpStubEntry {
        BYTE*       m_target;
        BYTE*       m_jumpStub;
    };

    class JumpStubTraits : public DefaultSHashTraits<JumpStubEntry>
    {
    public:
        typedef BYTE* key_t;

        static key_t GetKey(element_t e)
        {
            LEAF_CONTRACT;
            return e.m_target;
        }
        static BOOL Equals(key_t k1, key_t k2)
        {
            LEAF_CONTRACT;
            return k1 == k2;
        }
        static count_t Hash(key_t k)
        {
            LEAF_CONTRACT;
            return (count_t)(size_t)k;
        }

        static const element_t Null() { LEAF_CONTRACT; JumpStubEntry e; e.m_target = NULL; return e; }
        static bool IsNull(const element_t &e) { LEAF_CONTRACT; return e.m_target == NULL; }
        static const element_t Deleted() { LEAF_CONTRACT; JumpStubEntry e; e.m_target = (BYTE*)-1; return e; }
        static bool IsDeleted(const element_t &e) { LEAF_CONTRACT; return e.m_target == (BYTE*)-1; }
    };
    typedef SHash<JumpStubTraits> JumpStubTable;

    static JumpStubTable *        m_jumpStubTable;
};

//-----------------------------------------------------------------------------
    
inline
/* static */ DWORD ExecutionManager::JitCodeToOffset(TADDR currentPC)
{
    CONTRACTL {
        NOTHROW;
        GC_NOTRIGGER;
    } CONTRACTL_END;

    DWORD offset;
    IJitManager *pJitMan = FindJitMan((SLOT)currentPC);
    _ASSERTE(pJitMan != NULL);

    pJitMan->JitCodeToMethodInfo((SLOT)currentPC, 
                                 NULL, 
                                 NULL, 
                                 &offset
                                 );
    return offset;
}
        

//-----------------------------------------------------------------------------
// this is only called from a couple of places, but inlining helps EH perf

inline void* EEJitManager::GetGCInfo(METHODTOKEN MethodToken)
{
    CONTRACTL {
        NOTHROW;
        GC_NOTRIGGER;
    } CONTRACTL_END;

    CodeHeader* pHeader = MethodToken->GetCodeHeader();

    return pHeader->GetGCInfo();
}

inline BYTE* EEJitManager::JitTokenToStartAddress(METHODTOKEN MethodToken, IJitManager::ScanFlag scanFlag)
{
    CONTRACTL {
        NOTHROW;
        GC_NOTRIGGER;
    } CONTRACTL_END;

    return JitTokenToStartAddressStatic(MethodToken, scanFlag);
}

inline BYTE* EEJitManager::JitTokenToStartAddressStatic(METHODTOKEN MethodToken, IJitManager::ScanFlag scanFlag)
{ 
    CONTRACTL {
        NOTHROW;
        GC_NOTRIGGER;
        WIN64_ONLY(PRECONDITION(!MethodToken->IsFuncletMethodToken()));
    } CONTRACTL_END;

    if (MethodToken)
    {
        return MethodToken->GetCodeHeader()->GetCodeStartAddress();
    }
    return NULL;
}

inline size_t EEJitManager::JitTokenToMethodHotSize(METHODTOKEN MethodToken)
{
    CONTRACTL {
        NOTHROW;
        GC_NOTRIGGER;
    } CONTRACTL_END;

    return GetCodeManager()->GetFunctionSize(GetGCInfo(MethodToken));
}

inline void EEJitManager::JitTokenToMethodRegionInfo(METHODTOKEN MethodToken, MethodRegionInfo *methodRegionInfo)
{
    CONTRACTL {
        NOTHROW;
        GC_NOTRIGGER;
        PRECONDITION(methodRegionInfo != NULL);
        WIN64_ONLY(PRECONDITION(!MethodToken->IsFuncletMethodToken()));
    } CONTRACTL_END;

    methodRegionInfo->hotStartAddress  = JitTokenToStartAddress(MethodToken);
    methodRegionInfo->hotSize          = JitTokenToMethodHotSize(MethodToken);
    methodRegionInfo->coldStartAddress = 0;
    methodRegionInfo->coldSize         = 0;
}


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

//*****************************************************************************
// Implementation of the ICodeInfo interface

class EECodeInfo : public ICodeInfo
{
public:

    EECodeInfo(METHODTOKEN token, IJitManager * pJM);
    EECodeInfo(METHODTOKEN token, IJitManager * pJM, MethodDesc * pMD);

    const char*  __stdcall getMethodName(const char **moduleName /* OUT */ );
    void         __stdcall getMethodSig(CORINFO_SIG_HANDLE    *phsig,     /* OUT */
                                        DWORD                 *pcbSigSize,/* OUT */
                                        CORINFO_MODULE_HANDLE *phscope);  /* OUT */
    virtual LPVOID       __stdcall getStartAddress();
    IJitManager* __stdcall getJitManager() { LEAF_CONTRACT; return m_pJM; };
    bool         __stdcall IsSynchronized();
    bool         __stdcall AcquiresInstMethodTableFromThis();
    bool         __stdcall RequiresInstArg();

    METHODTOKEN         m_methodToken;
    MethodDesc         *m_pMD;
    IJitManager        *m_pJM;

    static inline CEEInfo* GetCEEInfo()
        { LEAF_CONTRACT;  return (CEEInfo*)&s_ceeInfoMemory; }
    static BYTE s_ceeInfoMemory[sizeof(CEEInfo)];

#ifndef DACCESS_COMPILE
    static void Init();
#endif
};

#endif // !__CODEMAN_HPP__

About Koders | Resources | Downloads | Support | Black Duck | Terms of Service | DMCA | Privacy Policy | Contact Us