JIT: Fix bug in finally cloning caused by unsound callfinally reordering
[platform/upstream/coreclr.git] / src / zap / zapimport.cpp
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 // ZapImport.cpp
6 //
7
8 //
9 // Zapping of soft bound references to elements outside the current module
10 //
11 // ======================================================================================
12
13 #include "common.h"
14
15 #include "zapimport.h"
16
17 #include "nibblestream.h"
18 #include "sigbuilder.h"
19
20 #if defined(FEATURE_READYTORUN_COMPILER)
21 // A flag to indicate that a helper call uses VSD
22 const DWORD READYTORUN_HELPER_FLAG_VSD = 0x10000000;
23 #endif
24
25 //
26 // ZapImportTable
27 //
28
29 void ZapImportTable::Save(ZapWriter * pZapWriter)
30 {
31     for (COUNT_T i = 0; i < m_modules.GetCount(); i++)
32     {
33         ModuleReferenceEntry * pModuleReference = m_modules[i];
34         _ASSERTE(pModuleReference != NULL);
35
36         CORCOMPILE_IMPORT_TABLE_ENTRY entry;
37
38         entry.wAssemblyRid = pModuleReference->m_wAssemblyRid;
39         entry.wModuleRid = pModuleReference->m_wModuleRid;
40
41         pZapWriter->Write(&entry, sizeof(entry));
42     }
43 }
44
45 ZapImportTable::ModuleReferenceEntry * ZapImportTable::GetModuleReference(CORINFO_MODULE_HANDLE handle)
46 {
47     ModuleReferenceEntry * pEntry = m_moduleReferences.Lookup(handle);
48
49     if (pEntry != NULL)
50         return pEntry;
51
52     if (!GetCompileInfo()->IsInCurrentVersionBubble(handle))
53     {
54         // FUTURE TODO: Version resilience
55         _ASSERTE(!"Invalid reference to module outside of current version bubble");
56         ThrowHR(E_FAIL);
57     }
58
59     pEntry = new (m_pImage->GetHeap()) ModuleReferenceEntry();
60     pEntry->m_module = handle;
61
62     DWORD assemblyIndex = 0;
63     DWORD moduleIndex = 0;
64     GetCompileInfo()->EncodeModuleAsIndexes(m_pImage->GetModuleHandle(), handle,
65                                                         &assemblyIndex, &moduleIndex,
66                                                         m_pImage->GetAssemblyEmit());
67     _ASSERTE(assemblyIndex <= USHRT_MAX);
68     _ASSERTE(moduleIndex <= USHRT_MAX);
69     pEntry->m_wAssemblyRid = (USHORT) assemblyIndex;
70     pEntry->m_wModuleRid = (USHORT) moduleIndex;
71
72     pEntry->m_index = m_modules.GetCount();
73     m_modules.Append(pEntry);
74
75     m_moduleReferences.Add(pEntry);
76
77     return pEntry;
78 }
79
80 ZapBlob * ZapImportTable::GetBlob(SigBuilder * pSigBuilder, BOOL fEager)
81 {
82     DWORD cbBlob;
83     PVOID pSignature = pSigBuilder->GetSignature(&cbBlob);
84
85     if (fEager)
86     {
87         // Use dedicated section for blobs of eager fixups
88         return ZapBlob::NewBlob(m_pImage, pSignature, cbBlob);
89     }
90
91     ZapBlob * pBlob = m_blobs.Lookup(ZapBlob::SHashKey(pSignature, cbBlob));
92
93     if (pBlob == NULL)
94     {
95         pBlob = ZapBlob::NewBlob(m_pImage, pSignature, cbBlob);
96
97         m_blobs.Add(pBlob);
98     }
99
100     return pBlob;
101 }
102
103 ZapBlob * ZapImportTable::PlaceImportBlob(ZapImport * pImport, BOOL fEager)
104 {
105     ZapBlob * pBlob;
106     if (pImport->HasBlob())
107     {
108         pBlob = pImport->GetBlob();
109     }
110     else
111     {
112         SigBuilder sigBuilder;
113         pImport->EncodeSignature(this, &sigBuilder);
114
115         pBlob = GetBlob(&sigBuilder, fEager);
116
117         pImport->SetBlob(pBlob);
118     }
119
120     if (!pBlob->IsPlaced())
121         PlaceBlob(pBlob, fEager);
122
123     return pBlob;
124 }
125
126 static const struct ImportSectionProperties 
127 {
128     BYTE                    Type;
129     BYTE                    EntrySize;
130     WORD                    Flags;
131 }   
132 c_ImportSectionProperties[ZapImportSectionType_Count] =
133 {
134     { /* ZapImportSectionType_Handle,       */ CORCOMPILE_IMPORT_TYPE_UNKNOWN,         0,              0                               },
135     { /* ZapImportSectionType_TypeHandle,   */ CORCOMPILE_IMPORT_TYPE_TYPE_HANDLE,     sizeof(TADDR),  0                               },
136     { /* ZapImportSectionType_MethodHandle, */ CORCOMPILE_IMPORT_TYPE_METHOD_HANDLE,   sizeof(TADDR),  0                               },
137 #ifdef _TARGET_ARM_
138     { /* ZapImportSectionType_PCode,        */ CORCOMPILE_IMPORT_TYPE_UNKNOWN,         0,              CORCOMPILE_IMPORT_FLAGS_PCODE   },
139 #endif
140     { /* ZapImportSectionType_StringHandle, */ CORCOMPILE_IMPORT_TYPE_STRING_HANDLE,   sizeof(TADDR),  0                               },
141 };
142
143 void ZapImportTable::PlaceImport(ZapImport * pImport)
144 {
145     BOOL fIsEager, fNeedsSignature;
146     ZapImportSectionType table = pImport->ComputePlacement(m_pImage, &fIsEager, &fNeedsSignature);
147
148     if (fIsEager)
149     {
150         table = ZapImportSectionType_Eager;
151     }
152     else
153     if (!m_pImage->IsCurrentCodeRegionHot())
154     {
155         table = (ZapImportSectionType)(table + ZapImportSectionType_Cold);
156     }
157
158     _ASSERTE(table < ZapImportSectionType_Total);
159
160
161     if (fNeedsSignature)
162     {
163         PlaceImportBlob(pImport, fIsEager);
164     }
165
166     ZapVirtualSection * pVirtualSection = m_pImage->m_pDelayLoadInfoTableSection[table];
167
168     if (m_nImportSectionSizes[table] == 0)
169     {
170         const ImportSectionProperties  * pProps = &c_ImportSectionProperties[table % ZapImportSectionType_Count];
171
172         WORD flags = pProps->Flags;
173
174         if (fIsEager)
175             flags |= CORCOMPILE_IMPORT_FLAGS_EAGER;
176
177         m_nImportSectionIndices[table] = m_pImage->GetImportSectionsTable()->Append(pProps->Type, flags, pProps->EntrySize,
178             pVirtualSection, m_pImage->m_pDelayLoadInfoDataTable[table]);
179     }
180
181     pImport->SetSectionIndexAndOffset(m_nImportSectionIndices[table], m_nImportSectionSizes[table]);
182
183     pVirtualSection->Place(pImport);
184
185     m_nImportSectionSizes[table] += pImport->GetSize();
186 }
187
188 // Sort ZapImport* by CorCompileTokenTable as primary key and offset within the table as secondary key
189 static int __cdecl fixupCmp(const void* a_, const void* b_)
190 {
191     ZapImport *a = *(ZapImport **)a_;
192     ZapImport *b = *(ZapImport **)b_;
193
194     int tableDiff = a->GetSectionIndex() - b->GetSectionIndex();
195     if (tableDiff != 0)
196         return tableDiff;
197
198     // Sort by offset within the table
199     return (a->GetOffset() - b->GetOffset());
200 }
201
202 void ZapImportTable::PlaceFixups(ZapImport ** pImports, NibbleWriter& writer)
203 {
204     COUNT_T nImports = 0;
205
206     for (;;)
207     {
208         ZapImport * pImport = pImports[nImports];
209         if (pImport == NULL) // end of the list
210             break;
211         if (!pImport->IsPlaced())
212             PlaceImport(pImport);
213         nImports++;
214     }
215
216     qsort(pImports, nImports, sizeof(ZapImport *), fixupCmp);
217
218     //
219     // Build the encoded fixup list
220     //
221
222     int curTableIndex = -1;
223     DWORD curOffset = 0;
224
225     for (COUNT_T iImport = 0; iImport < nImports; iImport++)
226     {
227         ZapImport * pImport = pImports[iImport];
228
229         int tableIndex = pImport->GetSectionIndex();
230         unsigned offset = pImport->GetOffset();
231
232         _ASSERTE(offset % sizeof(SIZE_T) == 0);
233         offset /= sizeof(SIZE_T);
234
235         if (tableIndex != curTableIndex)
236         {
237             // Write delta relative to the previous table index
238             _ASSERTE(tableIndex > curTableIndex);
239             if (curTableIndex != -1)
240             {
241                 writer.WriteEncodedU32(0); // table separator, so add except for the first entry
242                 writer.WriteEncodedU32(tableIndex - curTableIndex); // add table index delta
243             }
244             else
245             {
246                 writer.WriteEncodedU32(tableIndex);
247             }
248             curTableIndex = tableIndex;
249
250             // This is the first fixup in the current table.
251             // We will write it out completely (without delta-encoding)
252             writer.WriteEncodedU32(offset);
253         }
254         else
255         {
256             // This is not the first entry in the current table.
257             // We will write out the delta relative to the previous fixup value
258             int delta = offset - curOffset;
259             _ASSERTE(delta > 0);
260             writer.WriteEncodedU32(delta);
261         }
262
263         // future entries for this table would be relative to this rva
264         curOffset = offset;
265     }
266
267     writer.WriteEncodedU32(0); // table separator
268     writer.WriteEncodedU32(0); // fixup list ends
269
270     writer.Flush();
271 }
272
273 ZapFixupInfo * ZapImportTable::PlaceFixups(ZapImport ** pImports)
274 {
275     NibbleWriter writer;
276
277     PlaceFixups(pImports, writer);
278
279     DWORD cbBlob;
280     PVOID pBlob = writer.GetBlob(&cbBlob);
281
282     //
283     // Intern the fixup info
284     //
285
286     ZapFixupInfo * pFixupInfo = m_blobs.Lookup(ZapBlob::SHashKey(pBlob, cbBlob));
287
288     if (pFixupInfo == NULL)
289     {
290         // Fixup infos are mixed with other blobs
291         pFixupInfo = ZapBlob::NewBlob(m_pImage, pBlob, cbBlob);
292         m_blobs.Add(pFixupInfo);
293     }
294
295     if (!pFixupInfo->IsPlaced())
296         PlaceBlob(pFixupInfo);
297
298     return pFixupInfo;
299 }
300
301 void ZapImportTable::PlaceBlob(ZapBlob * pBlob, BOOL fEager)
302 {
303     ZapVirtualSection * pSection;
304     if (fEager)
305         pSection = m_pImage->m_pDelayLoadInfoDelayListSectionEager;
306     else
307     if (m_pImage->IsCurrentCodeRegionHot())
308         pSection = m_pImage->m_pDelayLoadInfoDelayListSectionHot;
309     else
310         pSection = m_pImage->m_pDelayLoadInfoDelayListSectionCold;
311     pSection->Place(pBlob);
312 }
313
314 // ======================================================================================
315 //
316 // Generic signatures
317 //
318 ZapGenericSignature * ZapImportTable::GetGenericSignature(PVOID signature, BOOL fMethod)
319 {
320 #ifdef  REDHAWK
321     _ASSERTE(!"NYI");
322     return NULL;
323 #else
324     SigBuilder sigBuilder;
325     GetCompileInfo()->EncodeGenericSignature(signature, fMethod, &sigBuilder, this, EncodeModuleHelper);
326
327     DWORD cbSig;
328     PVOID pSig = sigBuilder.GetSignature(&cbSig);
329
330     ZapGenericSignature * pGenericSignature = (ZapGenericSignature *)m_genericSignatures.Lookup(ZapBlob::SHashKey(pSig, cbSig));
331
332     if (pGenericSignature != NULL)
333         return pGenericSignature;
334
335     S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapGenericSignature)) + S_SIZE_T(cbSig);
336
337     if (cbAllocSize.IsOverflow())
338         ThrowHR(COR_E_OVERFLOW);
339
340     void * pMemory = new (m_pImage->GetHeap()) BYTE[cbAllocSize.Value()];
341
342     pGenericSignature = new (pMemory) ZapGenericSignature(cbSig);
343     memcpy((void *)(pGenericSignature + 1), pSig, cbSig);
344
345     m_genericSignatures.Add(pGenericSignature);
346
347     return pGenericSignature;
348 #endif // REDHAWK
349 }
350
351 // At ngen time Zapper::CompileModule PlaceFixups called from
352 //     code:ZapSig.GetSignatureForTypeHandle
353 //
354 /*static*/ DWORD ZapImportTable::EncodeModuleHelper( LPVOID compileContext,
355                                                 CORINFO_MODULE_HANDLE referencedModule)
356 {
357     ZapImportTable * pTable = (ZapImportTable *)compileContext;
358     return pTable->GetIndexOfModule(referencedModule);
359 }
360
361 void ZapImport::Save(ZapWriter * pZapWriter)
362 {
363     if (IsReadyToRunCompilation())
364     {
365         SIZE_T value = 0;
366         pZapWriter->Write(&value, sizeof(value));
367         return;
368     }
369
370     SIZE_T token = CORCOMPILE_TAG_TOKEN(GetBlob()->GetRVA());
371     pZapWriter->Write(&token, sizeof(token));
372 }
373
374 //
375 // CORCOMPILE_CODE_IMPORT_SECTION
376 //
377
378 COUNT_T ZapImportSectionsTable::Append(BYTE Type, USHORT Flags, BYTE EntrySize, ZapVirtualSection * pSection, ZapNode * pSignatures, ZapNode * pAuxiliaryData)
379 {
380     ImportSection entry;
381
382     entry.m_pSection = pSection;
383     entry.m_pSignatures = pSignatures;
384     entry.m_pAuxiliaryData = pAuxiliaryData;
385     entry.m_Flags = Flags;
386     entry.m_Type = Type;
387     entry.m_EntrySize = EntrySize;
388
389     m_ImportSectionsTable.Append(entry);
390
391     return m_ImportSectionsTable.GetCount() - 1;
392 }
393
394 DWORD ZapImportSectionsTable::GetSize()
395 {
396     return m_ImportSectionsTable.GetCount() * sizeof(CORCOMPILE_IMPORT_SECTION);
397 }
398
399 void ZapImportSectionsTable::Save(ZapWriter * pZapWriter)
400 {
401     COUNT_T nSections = m_ImportSectionsTable.GetCount();
402     for (COUNT_T iSection = 0; iSection < nSections; iSection++)
403     {
404         ImportSection * p = &m_ImportSectionsTable[iSection];
405
406         CORCOMPILE_IMPORT_SECTION entry;
407
408         ZapWriter::SetDirectoryData(&entry.Section, p->m_pSection);
409
410         entry.Flags = p->m_Flags;
411         entry.Type = p->m_Type;
412         entry.EntrySize = p->m_EntrySize;
413
414         entry.Signatures = (p->m_pSignatures != NULL) ? p->m_pSignatures->GetRVA() : NULL;
415         entry.AuxiliaryData = (p->m_pAuxiliaryData != NULL) ? p->m_pAuxiliaryData->GetRVA() : NULL;
416
417         pZapWriter->Write(&entry, sizeof(entry));
418     }
419 }
420
421
422 ZapImportSectionSignatures::ZapImportSectionSignatures(ZapImage * pImage, ZapVirtualSection * pImportSection, ZapVirtualSection * pGCSection)
423     : m_pImportSection(pImportSection), m_pImage(pImage)
424 {
425     if (pGCSection != NULL)
426     {
427         m_pGCRefMapTable = new (pImage->GetHeap()) ZapGCRefMapTable(pImage);
428         pGCSection->Place(m_pGCRefMapTable);
429     }
430 }
431
432 ZapImportSectionSignatures::~ZapImportSectionSignatures()
433 {
434     if (m_pGCRefMapTable != NULL)
435         m_pGCRefMapTable->~ZapGCRefMapTable();
436 }
437
438 DWORD ZapImportSectionSignatures::GetSize()
439 {
440     return m_pImportSection->GetNodeCount() * sizeof(DWORD);
441 }
442
443 void ZapImportSectionSignatures::Save(ZapWriter * pZapWriter)
444 {
445     COUNT_T nCount = m_pImportSection->GetNodeCount();
446     for (COUNT_T i = 0; i < nCount; i++)
447     {
448         ZapNode * pNode = m_pImportSection->GetNode(i);
449         DWORD dwRVA = ((ZapImport *)pNode)->GetBlob()->GetRVA();
450         pZapWriter->Write(&dwRVA, sizeof(dwRVA));
451     }
452 }
453
454 // ======================================================================================
455 //
456 // Special lazy imports for lazily resolved method calls
457 //
458
459 //
460 // External method thunk is a patchable thunk used for cross-module direct calls
461 //
462 class ZapExternalMethodThunk : public ZapImport
463 {
464 public:
465     ZapExternalMethodThunk()
466     {
467     }
468
469     CORINFO_METHOD_HANDLE GetMethod()
470     {
471         return (CORINFO_METHOD_HANDLE)GetHandle();
472     }
473
474     virtual DWORD GetSize()
475     {
476         return sizeof(CORCOMPILE_EXTERNAL_METHOD_THUNK);
477     }
478
479     virtual ZapNodeType GetType()
480     {
481         return ZapNodeType_ExternalMethodThunk;
482     }
483
484     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
485     {
486         CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)GetHandle();
487
488         CORINFO_MODULE_HANDLE referencingModule;
489         mdToken token = pTable->GetCompileInfo()->TryEncodeMethodAsToken(handle, NULL, &referencingModule);
490         if (token != mdTokenNil)
491         {
492             _ASSERTE(TypeFromToken(token) == mdtMethodDef || TypeFromToken(token) == mdtMemberRef);
493
494             pTable->EncodeModule(
495                 (TypeFromToken(token) == mdtMethodDef) ? ENCODE_METHOD_ENTRY_DEF_TOKEN : ENCODE_METHOD_ENTRY_REF_TOKEN,
496                 referencingModule, pSigBuilder);
497
498             pSigBuilder->AppendData(RidFromToken(token));
499         }
500         else
501         {
502             pTable->EncodeMethod(ENCODE_METHOD_ENTRY, handle, pSigBuilder);
503         }
504     }
505
506     virtual void Save(ZapWriter * pZapWriter);
507 };
508
509 void ZapExternalMethodThunk::Save(ZapWriter * pZapWriter)
510 {
511     ZapImage *             pImage  = ZapImage::GetImage(pZapWriter);
512     ZapNode *              helper  = pImage->GetHelperThunk(CORINFO_HELP_EE_EXTERNAL_FIXUP);
513
514     CORCOMPILE_EXTERNAL_METHOD_THUNK thunk;
515     memset(&thunk, DEFAULT_CODE_BUFFER_INIT, sizeof(thunk));
516 #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
517     thunk.callJmp[0]  = 0xE8;  // call rel32
518     pImage->WriteReloc(&thunk, 1, helper, 0, IMAGE_REL_BASED_REL32);
519     thunk.precodeType = _PRECODE_EXTERNAL_METHOD_THUNK;
520 #elif defined(_TARGET_ARM_) 
521     // Setup the call to ExternalMethodFixupStub
522     //
523     // mov r12, pc
524     //
525     // Per ARM architecture reference manual section A2.3,
526     // reading the value of PC register will read the address
527     // of the current instruction plus 4. In this case,
528     // R12 will containing the address of "F004" below once
529     // the "mov" is executed.
530     //
531     // Since this is 4 bytes ahead of the start of the thunk,
532     // the assembly helper we will call into will adjust this
533     // so that we point to the start of the thunk correctly.
534     thunk.m_rgCode[0] = 0x46fc;
535
536     // ldr pc, [pc, #4]
537     thunk.m_rgCode[1] = 0xf8df;
538     thunk.m_rgCode[2] = 0xf004;
539
540     // Setup the initial target to be our assembly helper.
541     pImage->WriteReloc(&thunk, offsetof(CORCOMPILE_EXTERNAL_METHOD_THUNK, m_pTarget), helper, 0, IMAGE_REL_BASED_PTR);
542 #elif defined(_TARGET_ARM64_)
543     
544     thunk.m_rgCode[0] = 0x1000000C; //adr       x12, #0
545     thunk.m_rgCode[1] = 0xF940098A; //ldr       x10, [x12, #16]
546     thunk.m_rgCode[2] = 0xD61F0140; //br        x10
547         
548     pImage->WriteReloc(&thunk, offsetof(CORCOMPILE_EXTERNAL_METHOD_THUNK, m_pTarget), helper, 0, IMAGE_REL_BASED_PTR);
549 #else
550     PORTABILITY_ASSERT("ZapExternalMethodThunk::Save");
551
552 #endif
553
554     pZapWriter->Write(&thunk,  sizeof(thunk));
555     _ASSERTE(sizeof(thunk) == GetSize());
556 }
557
558 void ZapImportSectionSignatures::PlaceExternalMethodThunk(ZapImport * pImport)
559 {
560     ZapExternalMethodThunk * pThunk = (ZapExternalMethodThunk *)pImport;
561
562     if (m_pImportSection->GetNodeCount() == 0)
563     {
564         m_dwIndex = m_pImage->GetImportSectionsTable()->Append(CORCOMPILE_IMPORT_TYPE_EXTERNAL_METHOD, CORCOMPILE_IMPORT_FLAGS_CODE,
565             sizeof(CORCOMPILE_EXTERNAL_METHOD_THUNK), m_pImportSection, this, m_pGCRefMapTable);
566
567         // Make sure the helper created
568         m_pImage->GetHelperThunk(CORINFO_HELP_EE_EXTERNAL_FIXUP);
569     }
570
571     // Add entry to both the the cell and data sections
572     m_pImportSection->Place(pThunk);
573
574     m_pImage->GetImportTable()->PlaceImportBlob(pThunk);
575
576     m_pGCRefMapTable->Append(pThunk->GetMethod());
577 }
578
579 ZapImport * ZapImportTable::GetExternalMethodThunk(CORINFO_METHOD_HANDLE handle)
580 {
581     return GetImport<ZapExternalMethodThunk, ZapNodeType_ExternalMethodThunk>((PVOID)handle);
582 }
583
584 //
585 // Stub dispatch cell is lazily initialized indirection used for virtual stub dispatch
586 //
587 class ZapStubDispatchCell : public ZapImport
588 {
589     ZapNode * m_pDelayLoadHelper;
590
591 public:
592     void SetDelayLoadHelper(ZapNode * pDelayLoadHelper)
593     {
594         _ASSERTE(m_pDelayLoadHelper == NULL);
595         m_pDelayLoadHelper = pDelayLoadHelper;
596     }
597
598     CORINFO_METHOD_HANDLE GetMethod()
599     {
600         return (CORINFO_METHOD_HANDLE)GetHandle();
601     }
602
603     CORINFO_CLASS_HANDLE GetClass()
604     {
605         return (CORINFO_CLASS_HANDLE)GetHandle2();
606     }
607
608     virtual DWORD GetSize()
609     {
610         return sizeof(TADDR);
611     }
612
613     virtual UINT GetAlignment()
614     {
615         return sizeof(TADDR);
616     }
617
618     virtual ZapNodeType GetType()
619     {
620         return ZapNodeType_StubDispatchCell;
621     }
622
623     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
624     {
625         CORINFO_MODULE_HANDLE referencingModule = pTable->GetJitInfo()->getClassModule(GetClass());
626         referencingModule = pTable->TryEncodeModule(ENCODE_VIRTUAL_ENTRY_SLOT, referencingModule, pSigBuilder);
627
628         DWORD slot = pTable->GetCompileInfo()->TryEncodeMethodSlot(GetMethod());
629
630         // We expect the encoding to always succeed
631         _ASSERTE(slot != (DWORD)-1);
632
633         pSigBuilder->AppendData(slot);
634
635         pTable->EncodeClassInContext(referencingModule, GetClass(), pSigBuilder);
636     }
637
638     virtual void Save(ZapWriter * pZapWriter)
639     {
640         ZapImage * pImage = ZapImage::GetImage(pZapWriter);
641
642         PVOID cell;
643         pImage->WriteReloc(&cell, 0, m_pDelayLoadHelper, 0, IMAGE_REL_BASED_PTR);
644         pZapWriter->Write(&cell, sizeof(cell));
645     }
646 };
647
648 ZapImport * ZapImportTable::GetStubDispatchCell(CORINFO_CLASS_HANDLE typeHnd, CORINFO_METHOD_HANDLE methHnd)
649 {
650     // Do not intern stub dispatch imports. Each callsite should get own cell.
651     ZapImport * pImport = new (m_pImage->GetHeap()) ZapStubDispatchCell();
652     pImport->SetHandle(methHnd);
653     pImport->SetHandle2(typeHnd);
654     return pImport;
655 }
656
657 void ZapImportSectionSignatures::PlaceStubDispatchCell(ZapImport * pImport)
658 {
659     ZapStubDispatchCell * pCell = (ZapStubDispatchCell *)pImport;
660
661     if (m_pImportSection->GetNodeCount() == 0)
662     {
663         m_dwIndex = m_pImage->GetImportSectionsTable()->Append(CORCOMPILE_IMPORT_TYPE_STUB_DISPATCH, CORCOMPILE_IMPORT_FLAGS_PCODE,
664             sizeof(TADDR), m_pImportSection, this, m_pGCRefMapTable);
665     }
666
667 #ifdef FEATURE_READYTORUN_COMPILER
668     if (IsReadyToRunCompilation())
669     {
670         // Create the delay load helper
671         ReadyToRunHelper helper = (ReadyToRunHelper)(READYTORUN_HELPER_DelayLoad_MethodCall | READYTORUN_HELPER_FLAG_VSD);
672         ZapNode * pDelayLoadHelper = m_pImage->GetImportTable()->GetPlacedIndirectHelperThunk(helper, (PVOID)(SIZE_T)m_dwIndex);
673         pCell->SetDelayLoadHelper(pDelayLoadHelper);
674     }
675     else
676 #endif
677     {
678         pCell->SetDelayLoadHelper(m_pImage->GetHelperThunk(CORINFO_HELP_EE_VSD_FIXUP));
679     }
680
681     // Add entry to both the cell and data sections
682     m_pImportSection->Place(pCell);
683
684     m_pImage->GetImportTable()->PlaceImportBlob(pCell);
685
686     m_pGCRefMapTable->Append(pCell->GetMethod());
687 }
688
689 //
690 // External method cell is lazily initialized indirection used for method calls
691 //
692 class ZapExternalMethodCell : public ZapImport
693 {
694     ZapNode * m_pDelayLoadHelper;
695
696 public:
697     void SetDelayLoadHelper(ZapNode * pDelayLoadHelper)
698     {
699         _ASSERTE(m_pDelayLoadHelper == NULL);
700         m_pDelayLoadHelper = pDelayLoadHelper;
701     }
702     CORINFO_METHOD_HANDLE GetMethod()
703     {
704         return (CORINFO_METHOD_HANDLE)GetHandle();
705     }
706
707     virtual DWORD GetSize()
708     {
709         return sizeof(TADDR);
710     }
711
712     virtual UINT GetAlignment()
713     {
714         return sizeof(TADDR);
715     }
716
717     virtual ZapNodeType GetType()
718     {
719         return ZapNodeType_ExternalMethodCell;
720     }
721
722     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
723     {
724         CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)GetHandle();
725
726         CORINFO_MODULE_HANDLE referencingModule;
727         mdToken token = pTable->GetCompileInfo()->TryEncodeMethodAsToken(handle, NULL, &referencingModule);
728         if (token != mdTokenNil)
729         {
730             _ASSERTE(TypeFromToken(token) == mdtMethodDef || TypeFromToken(token) == mdtMemberRef);
731
732             pTable->EncodeModule(
733                 (TypeFromToken(token) == mdtMethodDef) ? ENCODE_METHOD_ENTRY_DEF_TOKEN : ENCODE_METHOD_ENTRY_REF_TOKEN,
734                 referencingModule, pSigBuilder);
735
736             pSigBuilder->AppendData(RidFromToken(token));
737         }
738         else
739         {
740             pTable->EncodeMethod(ENCODE_METHOD_ENTRY, handle, pSigBuilder);
741         }
742     }
743
744     virtual void Save(ZapWriter * pZapWriter)
745     {
746         ZapImage * pImage = ZapImage::GetImage(pZapWriter);
747
748         PVOID cell;
749         pImage->WriteReloc(&cell, 0, m_pDelayLoadHelper, 0, IMAGE_REL_BASED_PTR);
750         pZapWriter->Write(&cell, sizeof(cell));
751     }
752 };
753
754 ZapImport * ZapImportTable::GetExternalMethodCell(CORINFO_METHOD_HANDLE handle)
755 {
756     return GetImport<ZapExternalMethodCell, ZapNodeType_ExternalMethodCell>((PVOID)handle);
757 }
758
759 void ZapImportSectionSignatures::PlaceExternalMethodCell(ZapImport * pImport)
760 {
761     ZapExternalMethodCell * pCell = (ZapExternalMethodCell *)pImport;
762
763     if (m_pImportSection->GetNodeCount() == 0)
764     {
765         m_dwIndex = m_pImage->GetImportSectionsTable()->Append(CORCOMPILE_IMPORT_TYPE_STUB_DISPATCH, CORCOMPILE_IMPORT_FLAGS_PCODE,
766             sizeof(TADDR), m_pImportSection, this, m_pGCRefMapTable);
767     }
768
769 #ifdef FEATURE_READYTORUN_COMPILER
770     if (IsReadyToRunCompilation())
771     {
772         // Create the delay load helper
773         ZapNode * pDelayLoadHelper = m_pImage->GetImportTable()->GetPlacedIndirectHelperThunk(READYTORUN_HELPER_DelayLoad_MethodCall, (PVOID)(SIZE_T)m_dwIndex);
774         pCell->SetDelayLoadHelper(pDelayLoadHelper);
775     }
776     else
777 #endif
778     {
779         pCell->SetDelayLoadHelper(m_pImage->GetHelperThunk(CORINFO_HELP_EE_EXTERNAL_FIXUP));
780     }
781
782     // Add entry to both the cell and data sections
783     m_pImportSection->Place(pCell);
784
785     m_pImage->GetImportTable()->PlaceImportBlob(pCell);
786
787     m_pGCRefMapTable->Append(pCell->GetMethod());
788 }
789
790 //
791 // Virtual import thunk is a patchable thunk used for cross-module virtual calls.
792 //
793 class ZapVirtualMethodThunk : public ZapImport
794 {
795 public:
796     virtual DWORD GetSize()
797     {
798         return sizeof(CORCOMPILE_VIRTUAL_IMPORT_THUNK);
799     }
800
801     virtual ZapNodeType GetType()
802     {
803         return ZapNodeType_VirtualMethodThunk;
804     }
805
806     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
807     {
808         // Virtual import thunks do not have signatures
809         _ASSERTE(false);
810     }
811
812     virtual void Save(ZapWriter * pZapWriter);
813 };
814
815 void ZapVirtualMethodThunk::Save(ZapWriter * pZapWriter)
816 {
817     ZapImage * pImage = ZapImage::GetImage(pZapWriter);
818
819     CORCOMPILE_VIRTUAL_IMPORT_THUNK thunk;
820     memset(&thunk, DEFAULT_CODE_BUFFER_INIT, sizeof(thunk));
821
822     // On ARM, the helper would already have the thumb-bit set. Refer to
823     // GetHelperThunk implementation.
824     ZapNode *  helper  = pImage->GetHelperThunk(CORINFO_HELP_EE_VTABLE_FIXUP);
825     _ASSERTE(FitsIn<UINT16>((SIZE_T)GetHandle2() - 1));
826     USHORT     slotNum = (USHORT)((SIZE_T)GetHandle2() - 1);
827
828 #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
829     thunk.callJmp[0] = 0xE8;        // call rel32
830     pImage->WriteReloc(&thunk, 1, helper, 0, IMAGE_REL_BASED_REL32);
831
832     // Mark this as a Virtual Import Thunk
833     thunk.precodeType = _PRECODE_VIRTUAL_IMPORT_THUNK;
834 #elif defined(_TARGET_ARM_)
835     // Setup the call to VirtualMethodFixupStub
836     //
837     // mov r12, pc
838     //
839     // Per ARM architecture reference manual section A2.3,
840     // reading the value of PC register will read the address
841     // of the current instruction plus 4. In this case,
842     // R12 will containing the address of "F004" below once
843     // the "mov" is executed.
844     //
845     // Since this is 4 bytes ahead of the start of the thunk,
846     // the assembly helper we will call into will adjust this
847     // so that we point to the start of the thunk correctly.
848     thunk.m_rgCode[0] = 0x46fc;
849
850     // ldr pc, [pc, #4]
851     thunk.m_rgCode[1] = 0xf8df;
852     thunk.m_rgCode[2] = 0xf004;
853
854     // Slot ID is setup below, so now setup the initial target
855     // to be our assembly helper.
856     pImage->WriteReloc(&thunk, offsetof(CORCOMPILE_VIRTUAL_IMPORT_THUNK, m_pTarget), helper, 0, IMAGE_REL_BASED_PTR);
857  #elif defined(_TARGET_ARM64_)
858
859     thunk.m_rgCode[0] = 0x1000000C; //adr       x12, #0
860     thunk.m_rgCode[1] = 0xF940098A; //ldr       x10, [x12, #16]
861     thunk.m_rgCode[2] = 0xD61F0140; //br        x10
862
863     // Slot ID is setup below, so now setup the initial target
864     // to be our assembly helper.
865     pImage->WriteReloc(&thunk, offsetof(CORCOMPILE_VIRTUAL_IMPORT_THUNK, m_pTarget), helper, 0, IMAGE_REL_BASED_PTR);
866 #else
867     PORTABILITY_ASSERT("ZapVirtualMethodThunk::Save");
868 #endif
869
870     thunk.slotNum = slotNum;
871
872     pZapWriter->Write(&thunk, sizeof(thunk));
873 }
874
875 void ZapImportTable::PlaceVirtualImportThunk(ZapImport * pVirtualImportThunk)
876 {
877     if (m_pImage->m_pVirtualImportThunkSection->GetNodeCount() == 0)
878     {
879         m_pImage->GetImportSectionsTable()->Append(CORCOMPILE_IMPORT_TYPE_VIRTUAL_METHOD, CORCOMPILE_IMPORT_FLAGS_CODE,
880             sizeof(CORCOMPILE_VIRTUAL_IMPORT_THUNK), m_pImage->m_pVirtualImportThunkSection);
881
882         // Make sure the helper created
883         m_pImage->GetHelperThunk(CORINFO_HELP_EE_VTABLE_FIXUP);
884     }
885
886     m_pImage->m_pVirtualImportThunkSection->Place(pVirtualImportThunk);
887 }
888
889 ZapImport * ZapImportTable::GetVirtualImportThunk(CORINFO_METHOD_HANDLE handle, int slot)
890 {
891     return GetImport<ZapVirtualMethodThunk, ZapNodeType_VirtualMethodThunk>(handle, (PVOID)(SIZE_T)(slot+1));
892 }
893
894 // ======================================================================================
895 //
896 // GCRefMapTable is used to encode for GC references locations for lazily resolved calls
897 //
898
899 void ZapGCRefMapTable::Append(CORINFO_METHOD_HANDLE handle)
900 {
901     m_pImage->GetCompileInfo()->GetCallRefMap(handle, &m_GCRefMapBuilder);
902     m_nCount++;
903 }
904
905 DWORD ZapGCRefMapTable::GetSize()
906 {
907     if (m_nCount == 0) return 0;
908
909     COUNT_T nLookupEntries = (1 + m_nCount / GCREFMAP_LOOKUP_STRIDE);
910
911     return (nLookupEntries * sizeof(DWORD)) + m_GCRefMapBuilder.GetBlobLength();
912 }
913
914 void ZapGCRefMapTable::Save(ZapWriter * pZapWriter)
915 {
916     if (m_nCount == 0) return;
917
918     COUNT_T nLookupEntries = (1 + m_nCount / GCREFMAP_LOOKUP_STRIDE);
919
920     DWORD dwBlobLength;
921     BYTE * pBlob = (BYTE *)m_GCRefMapBuilder.GetBlob(&dwBlobLength);
922
923     DWORD pos = 0;
924     COUNT_T iLookupEntry = 0;
925     for (;;)
926     {
927         DWORD relOfs = (nLookupEntries * sizeof(DWORD)) + pos;
928         pZapWriter->Write(&relOfs, sizeof(relOfs));
929         iLookupEntry++;
930
931         if (iLookupEntry >= nLookupEntries)
932             break;
933         
934         for (int i = 0; i < GCREFMAP_LOOKUP_STRIDE; i++)
935         {
936             while ((*(pBlob + pos) & 0x80) != 0)
937                 pos++;
938             pos++;
939
940             _ASSERTE(pos <= dwBlobLength);
941         }
942     }
943
944     pZapWriter->Write(pBlob, dwBlobLength);
945 }
946
947 // ======================================================================================
948 //
949 // Getters for existing imports.
950 //
951
952 ZapImport * ZapImportTable::GetExistingClassHandleImport(CORINFO_CLASS_HANDLE handle)
953 {
954     return GetExistingImport(ZapNodeType_Import_ClassHandle, handle);
955 }
956
957 ZapImport * ZapImportTable::GetExistingFieldHandleImport(CORINFO_FIELD_HANDLE handle)
958 {
959     return GetExistingImport(ZapNodeType_Import_FieldHandle, handle);
960 }
961
962 ZapImport * ZapImportTable::GetExistingMethodHandleImport(CORINFO_METHOD_HANDLE handle)
963 {
964     return GetExistingImport(ZapNodeType_Import_MethodHandle, handle);
965 }
966
967 CORINFO_MODULE_HANDLE ZapImportTable::TryEncodeModule(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_MODULE_HANDLE module, SigBuilder * pSigBuilder)
968 {
969     if (!GetCompileInfo()->IsInCurrentVersionBubble(module))
970         module = GetImage()->GetModuleHandle();
971
972     EncodeModule(kind, module, pSigBuilder);
973     return module;
974 }
975
976 void ZapImportTable::EncodeModule(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_MODULE_HANDLE module, SigBuilder * pSigBuilder)
977 {
978     if (module != GetImage()->GetModuleHandle())
979     {
980         pSigBuilder->AppendByte(kind | ENCODE_MODULE_OVERRIDE);
981         pSigBuilder->AppendData(GetIndexOfModule(module));
982     }
983     else
984     {
985         pSigBuilder->AppendByte(kind);
986     }
987 }
988
989 void ZapImportTable::EncodeClass(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_CLASS_HANDLE handle, SigBuilder * pSigBuilder)
990 {
991     CORINFO_MODULE_HANDLE referencingModule = GetJitInfo()->getClassModule(handle);
992     referencingModule = TryEncodeModule(kind, referencingModule, pSigBuilder);
993     GetCompileInfo()->EncodeClass(referencingModule, handle, pSigBuilder, this, EncodeModuleHelper);
994 }
995
996 void ZapImportTable::EncodeClassInContext(CORINFO_MODULE_HANDLE context, CORINFO_CLASS_HANDLE handle, SigBuilder * pSigBuilder)
997 {
998     GetCompileInfo()->EncodeClass(context, handle, pSigBuilder, this, EncodeModuleHelper);
999 }
1000
1001 void ZapImportTable::EncodeField(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, SigBuilder * pSigBuilder,
1002         CORINFO_RESOLVED_TOKEN * pResolvedToken, BOOL fEncodeUsingResolvedTokenSpecStreams)
1003 {
1004     CORINFO_CLASS_HANDLE clsHandle = GetJitInfo()->getFieldClass(handle);
1005     CORINFO_MODULE_HANDLE referencingModule = GetJitInfo()->getClassModule(clsHandle);
1006     referencingModule = TryEncodeModule(kind, referencingModule, pSigBuilder);
1007     GetCompileInfo()->EncodeField(referencingModule, handle, pSigBuilder, this, EncodeModuleHelper,
1008         pResolvedToken, fEncodeUsingResolvedTokenSpecStreams);
1009 }
1010
1011 void ZapImportTable::EncodeMethod(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, SigBuilder * pSigBuilder,
1012         CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken, BOOL fEncodeUsingResolvedTokenSpecStreams)
1013 {
1014     CORINFO_CLASS_HANDLE clsHandle = GetJitInfo()->getMethodClass(handle);
1015     CORINFO_MODULE_HANDLE referencingModule = GetJitInfo()->getClassModule(clsHandle);
1016     referencingModule = TryEncodeModule(kind, referencingModule, pSigBuilder);
1017     GetCompileInfo()->EncodeMethod(referencingModule, handle, pSigBuilder, this, EncodeModuleHelper,
1018         pResolvedToken, pConstrainedResolvedToken, fEncodeUsingResolvedTokenSpecStreams);
1019 }
1020
1021 // ======================================================================================
1022 //
1023 // Actual imports
1024 //
1025
1026 class ZapModuleHandleImport : public ZapImport
1027 {
1028 public:
1029     virtual ZapNodeType GetType()
1030     {
1031         return ZapNodeType_Import_ModuleHandle;
1032     }
1033
1034     virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature)
1035     {
1036         ZapImport::ComputePlacement(pImage, pfIsEager, pfNeedsSignature);
1037
1038          CORINFO_MODULE_HANDLE handle = (CORINFO_MODULE_HANDLE)GetHandle();
1039          if (pImage->m_pPreloader->CanEmbedModuleHandle(handle))
1040          {
1041             *pfIsEager = TRUE;
1042          }
1043
1044          return ZapImportSectionType_Handle;
1045     }
1046
1047     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
1048     {
1049         pTable->EncodeModule(ENCODE_MODULE_HANDLE, (CORINFO_MODULE_HANDLE)GetHandle(), pSigBuilder);
1050     }
1051 };
1052
1053 ZapImport * ZapImportTable::GetModuleHandleImport(CORINFO_MODULE_HANDLE handle)
1054 {
1055     return GetImport<ZapModuleHandleImport, ZapNodeType_Import_ModuleHandle>(handle);
1056 }
1057
1058 class ZapClassHandleImport : public ZapImport
1059 {
1060 public:
1061     virtual ZapNodeType GetType()
1062     {
1063         return ZapNodeType_Import_ClassHandle;
1064     }
1065
1066     virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature)
1067     {
1068         ZapImport::ComputePlacement(pImage, pfIsEager, pfNeedsSignature);
1069
1070         if (IsReadyToRunCompilation())
1071             return ZapImportSectionType_Handle;
1072
1073         CORINFO_CLASS_HANDLE handle = (CORINFO_CLASS_HANDLE)GetHandle();
1074         if (pImage->m_pPreloader->CanEmbedClassHandle(handle))
1075         {
1076             // We may have entries pointing to our module that exist in the handle table to trigger restore.
1077             if (pImage->GetCompileInfo()->GetLoaderModuleForEmbeddableType(handle) == pImage->GetModuleHandle())
1078             {
1079                 *pfNeedsSignature = FALSE;
1080             }
1081             else
1082             {
1083                 *pfIsEager = TRUE;
1084             }
1085          }
1086
1087         return ZapImportSectionType_TypeHandle;
1088     }
1089
1090     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
1091     {
1092         pTable->EncodeClass(ENCODE_TYPE_HANDLE, (CORINFO_CLASS_HANDLE)GetHandle(), pSigBuilder);
1093     }
1094
1095     virtual void Save(ZapWriter * pZapWriter)
1096     {
1097         ZapImage * pImage = ZapImage::GetImage(pZapWriter);
1098
1099         // We may have entries pointing to our module that exist in the handle table to trigger restore.
1100         if (!HasBlob())
1101         {
1102             PVOID cell;
1103             ZapNode handle(pImage->m_pPreloader->MapClassHandle((CORINFO_CLASS_HANDLE)GetHandle()));
1104             pImage->WriteReloc(&cell, 0, &handle, 0, IMAGE_REL_BASED_PTR);
1105             pZapWriter->Write(&cell, sizeof(cell));
1106         }
1107         else
1108         {
1109             ZapImport::Save(pZapWriter);
1110         }
1111     }
1112 };
1113
1114 ZapImport * ZapImportTable::GetClassHandleImport(CORINFO_CLASS_HANDLE handle, PVOID pUniqueId)
1115 {
1116     // pUniqueId is workaround for loading of generic parent method table. It would be nice to clean it up.
1117     if (pUniqueId != NULL)
1118     {
1119         return GetImport<ZapClassHandleImport, ZapNodeType_Import_ClassHandle>(handle, pUniqueId);
1120     }
1121
1122     ZapImport * pImport = GetImport<ZapClassHandleImport, ZapNodeType_Import_ClassHandle>(handle);
1123
1124     if (IsReadyToRunCompilation() && !pImport->HasBlob())
1125     {
1126         SigBuilder sigBuilder;
1127
1128         EncodeClass(ENCODE_TYPE_HANDLE, handle, &sigBuilder);
1129
1130         pImport->SetBlob(GetBlob(&sigBuilder));
1131     }
1132  
1133     return pImport;
1134 }
1135
1136 class ZapFieldHandleImport : public ZapImport
1137 {
1138 public:
1139     virtual ZapNodeType GetType()
1140     {
1141         return ZapNodeType_Import_FieldHandle;
1142     }
1143
1144     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
1145     {
1146         pTable->EncodeField(ENCODE_FIELD_HANDLE, (CORINFO_FIELD_HANDLE)GetHandle(), pSigBuilder);
1147     }
1148 };
1149
1150 ZapImport * ZapImportTable::GetFieldHandleImport(CORINFO_FIELD_HANDLE handle)
1151 {
1152     return GetImport<ZapFieldHandleImport, ZapNodeType_Import_FieldHandle>(handle);
1153 }
1154
1155 class ZapMethodHandleImport : public ZapImport
1156 {
1157 public:
1158     virtual ZapNodeType GetType()
1159     {
1160         return ZapNodeType_Import_MethodHandle;
1161     }
1162
1163     virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature)
1164     {
1165         ZapImport::ComputePlacement(pImage, pfIsEager, pfNeedsSignature);
1166
1167         if (IsReadyToRunCompilation())
1168             return ZapImportSectionType_Handle;
1169
1170         CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)GetHandle();
1171         if (pImage->m_pPreloader->CanEmbedMethodHandle(handle))
1172         {
1173             // We may have entries pointing to our module that exist in the handle table to trigger restore.
1174             if (pImage->GetCompileInfo()->GetLoaderModuleForEmbeddableMethod(handle) == pImage->GetModuleHandle())
1175             {
1176                 *pfNeedsSignature = FALSE;
1177             }
1178         }
1179
1180         return ZapImportSectionType_MethodHandle;
1181     }
1182
1183     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
1184     {
1185         pTable->EncodeMethod(ENCODE_METHOD_HANDLE, (CORINFO_METHOD_HANDLE)GetHandle(), pSigBuilder);
1186     }
1187
1188     virtual void Save(ZapWriter * pZapWriter)
1189     {
1190         ZapImage * pImage = ZapImage::GetImage(pZapWriter);
1191
1192         // We may have entries pointing to our module that exist in the handle table to trigger restore.
1193         if (!HasBlob())
1194         {
1195             PVOID cell;
1196             ZapNode handle(pImage->m_pPreloader->MapMethodHandle((CORINFO_METHOD_HANDLE)GetHandle()));
1197             pImage->WriteReloc(&cell, 0, &handle, 0, IMAGE_REL_BASED_PTR);
1198             pZapWriter->Write(&cell, sizeof(cell));
1199         }
1200         else
1201         {
1202             ZapImport::Save(pZapWriter);
1203         }
1204     }
1205 };
1206
1207 ZapImport * ZapImportTable::GetMethodHandleImport(CORINFO_METHOD_HANDLE handle)
1208 {
1209     return GetImport<ZapMethodHandleImport, ZapNodeType_Import_MethodHandle>(handle);
1210 }
1211
1212 class ZapStringHandleImport : public ZapImport
1213 {
1214 public:
1215     virtual ZapNodeType GetType()
1216     {
1217         return ZapNodeType_Import_StringHandle;
1218     }
1219
1220     virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature)
1221     {
1222         ZapImport::ComputePlacement(pImage, pfIsEager, pfNeedsSignature);
1223
1224         // Empty string
1225         if ((mdString)(size_t)GetHandle2() == mdtString)
1226         {
1227             *pfIsEager = TRUE;
1228             return ZapImportSectionType_Handle;
1229         }
1230
1231         return ZapImportSectionType_StringHandle;
1232     }
1233
1234     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
1235     {
1236         CORINFO_MODULE_HANDLE referencingModule = (CORINFO_MODULE_HANDLE)GetHandle();
1237
1238         pTable->EncodeModule(ENCODE_STRING_HANDLE, referencingModule, pSigBuilder);
1239
1240         mdString token = (mdString)(size_t)GetHandle2();
1241         pSigBuilder->AppendData(RidFromToken(token));
1242     }
1243 };
1244
1245 ZapImport * ZapImportTable::GetStringHandleImport(CORINFO_MODULE_HANDLE tokenScope, mdString metaTok)
1246 {
1247     return GetImport<ZapStringHandleImport, ZapNodeType_Import_StringHandle>(tokenScope, (PVOID)(size_t)metaTok);
1248 }
1249
1250 class ZapFunctionEntryImport : public ZapImport
1251 {
1252 public:
1253     virtual ZapNodeType GetType()
1254     {
1255         return ZapNodeType_Import_FunctionEntry;
1256     }
1257
1258 #ifdef _TARGET_ARM_
1259     virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature)
1260     {
1261         ZapImport::ComputePlacement(pImage, pfIsEager, pfNeedsSignature);
1262         return ZapImportSectionType_PCode;
1263     }
1264 #endif
1265
1266     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
1267     {
1268         CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)GetHandle();
1269
1270         CORINFO_MODULE_HANDLE referencingModule;
1271         mdToken token = pTable->GetCompileInfo()->TryEncodeMethodAsToken(handle, NULL, &referencingModule);
1272         if (token != mdTokenNil)
1273         {
1274             _ASSERTE(TypeFromToken(token) == mdtMethodDef || TypeFromToken(token) == mdtMemberRef);
1275             
1276             // It's a NativeCallable method , then encode it as ENCODE_METHOD_NATIVE_ENTRY
1277             if (pTable->GetCompileInfo()->IsNativeCallableMethod(handle))
1278             {
1279                 pTable->EncodeModule(ENCODE_METHOD_NATIVE_ENTRY, referencingModule, pSigBuilder);
1280             }
1281             else
1282             {
1283                 pTable->EncodeModule(
1284                     (TypeFromToken(token) == mdtMethodDef) ? ENCODE_METHOD_ENTRY_DEF_TOKEN : ENCODE_METHOD_ENTRY_REF_TOKEN,
1285                     referencingModule, pSigBuilder);
1286             }
1287
1288             pSigBuilder->AppendData(RidFromToken(token));
1289         }
1290         else
1291         {
1292             pTable->EncodeMethod(ENCODE_METHOD_ENTRY, handle, pSigBuilder);
1293         }
1294     }
1295
1296     virtual void Save(ZapWriter * pZapWriter)
1297     {
1298         SIZE_T token = CORCOMPILE_TAG_PCODE(GetBlob()->GetRVA());
1299         pZapWriter->Write(&token, sizeof(token));
1300     }
1301 };
1302
1303 ZapImport * ZapImportTable::GetFunctionEntryImport(CORINFO_METHOD_HANDLE handle)
1304 {
1305     return GetImport<ZapFunctionEntryImport, ZapNodeType_Import_FunctionEntry>(handle);
1306 }
1307
1308 class ZapStaticFieldAddressImport : public ZapImport
1309 {
1310 public:
1311     virtual ZapNodeType GetType()
1312     {
1313         return ZapNodeType_Import_StaticFieldAddress;
1314     }
1315
1316     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
1317     {
1318         pTable->EncodeField(ENCODE_STATIC_FIELD_ADDRESS, (CORINFO_FIELD_HANDLE)GetHandle(), pSigBuilder);
1319     }
1320
1321     virtual DWORD GetSize()
1322     {
1323         return 2 * sizeof(TADDR);
1324     }
1325
1326     virtual void Save(ZapWriter * pZapWriter)
1327     {
1328         ZapImport::Save(pZapWriter);
1329
1330         TADDR value = 0;
1331         pZapWriter->Write(&value, sizeof(value));
1332     }
1333 };
1334
1335 ZapImport * ZapImportTable::GetStaticFieldAddressImport(CORINFO_FIELD_HANDLE handle)
1336 {
1337     return GetImport<ZapStaticFieldAddressImport, ZapNodeType_Import_StaticFieldAddress>(handle);
1338 }
1339
1340 class ZapClassDomainIdImport : public ZapImport
1341 {
1342 public:
1343     virtual ZapNodeType GetType()
1344     {
1345         return ZapNodeType_Import_ClassDomainId;
1346     }
1347
1348     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
1349     {
1350         pTable->EncodeClass(ENCODE_CLASS_ID_FOR_STATICS, (CORINFO_CLASS_HANDLE)GetHandle(), pSigBuilder);
1351     }
1352 };
1353
1354 ZapImport * ZapImportTable::GetClassDomainIdImport(CORINFO_CLASS_HANDLE handle)
1355 {
1356     return GetImport<ZapClassDomainIdImport, ZapNodeType_Import_ClassDomainId>(handle);
1357 }
1358
1359 class ZapModuleDomainIdImport : public ZapImport
1360 {
1361 public:
1362     virtual ZapNodeType GetType()
1363     {
1364         return ZapNodeType_Import_ModuleDomainId;
1365     }
1366
1367     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
1368     {
1369         if (GetHandle() != NULL)
1370         {
1371             pTable->EncodeModule(ENCODE_MODULE_ID_FOR_STATICS, (CORINFO_MODULE_HANDLE)GetHandle(), pSigBuilder);
1372         }
1373         else
1374         {
1375             _ASSERTE(GetHandle2() != NULL);
1376
1377             pTable->EncodeClass(ENCODE_MODULE_ID_FOR_GENERIC_STATICS, (CORINFO_CLASS_HANDLE)GetHandle2(), pSigBuilder);
1378         }
1379     }
1380 };
1381
1382 ZapImport * ZapImportTable::GetModuleDomainIdImport(CORINFO_MODULE_HANDLE handleToModule, CORINFO_CLASS_HANDLE handleToClass)
1383 {
1384     _ASSERTE(((void *)handleToModule != (void *)handleToClass) && ((handleToModule == NULL) || (handleToClass == NULL)));
1385
1386     return GetImport<ZapModuleDomainIdImport, ZapNodeType_Import_ModuleDomainId>(handleToModule, handleToClass);
1387 }
1388
1389 class ZapSyncLockImport : public ZapImport
1390 {
1391 public:
1392     virtual ZapNodeType GetType()
1393     {
1394         return ZapNodeType_Import_SyncLock;
1395     }
1396
1397     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
1398     {
1399         pTable->EncodeClass(ENCODE_SYNC_LOCK, (CORINFO_CLASS_HANDLE)GetHandle(), pSigBuilder);
1400     }
1401 };
1402
1403 ZapImport * ZapImportTable::GetSyncLockImport(CORINFO_CLASS_HANDLE handle)
1404 {
1405     return GetImport<ZapSyncLockImport, ZapNodeType_Import_SyncLock>(handle);
1406 }
1407
1408 class ZapIndirectPInvokeTargetImport : public ZapImport
1409 {
1410 public:
1411     virtual ZapNodeType GetType()
1412     {
1413         return ZapNodeType_Import_IndirectPInvokeTarget;
1414     }
1415
1416     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
1417     {
1418         pTable->EncodeMethod(ENCODE_INDIRECT_PINVOKE_TARGET, (CORINFO_METHOD_HANDLE)GetHandle(), pSigBuilder);
1419     }
1420 };
1421
1422 ZapImport * ZapImportTable::GetIndirectPInvokeTargetImport(CORINFO_METHOD_HANDLE handle)
1423 {
1424     return GetImport<ZapIndirectPInvokeTargetImport, ZapNodeType_Import_IndirectPInvokeTarget>(handle);
1425 }
1426
1427 class ZapProfilingHandleImport : public ZapImport
1428 {
1429 public:
1430     virtual ZapNodeType GetType()
1431     {
1432         return ZapNodeType_Import_ProfilingHandle;
1433     }
1434
1435     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
1436     {
1437         pTable->EncodeMethod(ENCODE_PROFILING_HANDLE, (CORINFO_METHOD_HANDLE)GetHandle(), pSigBuilder);
1438     }
1439
1440     virtual DWORD GetSize()
1441     {
1442         // fixup cell, 3 pointers to interception method (Enter/Leave/Tailcall) and opaque handle
1443         return kZapProfilingHandleImportValueIndexCount * sizeof(TADDR);
1444     }
1445
1446     virtual void Save(ZapWriter * pZapWriter)
1447     {
1448         // Save fixup cell
1449         ZapImport::Save(pZapWriter);
1450
1451         // Save zeroes for the rest of the entries
1452         
1453         // If this assert fires, someone changed the
1454         // kZapProfilingHandleImportValueIndex... enum values without updating me!
1455         _ASSERTE(kZapProfilingHandleImportValueIndexCount == 5);
1456         
1457         TADDR value = 0;
1458         pZapWriter->Write(&value, sizeof(value));
1459         pZapWriter->Write(&value, sizeof(value));
1460         pZapWriter->Write(&value, sizeof(value));
1461         pZapWriter->Write(&value, sizeof(value));
1462     }
1463 };
1464
1465 ZapImport * ZapImportTable::GetProfilingHandleImport(CORINFO_METHOD_HANDLE handle)
1466 {
1467     return GetImport<ZapProfilingHandleImport, ZapNodeType_Import_ProfilingHandle>(handle);
1468 }
1469
1470 class ZapVarArgImport : public ZapImport
1471 {
1472 public:
1473     virtual ZapNodeType GetType()
1474     {
1475         return ZapNodeType_Import_VarArg;
1476     }
1477
1478     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
1479     {
1480         _ASSERTE((CORINFO_MODULE_HANDLE)GetHandle() == pTable->GetImage()->GetModuleHandle());
1481
1482         mdToken token = (mdToken)(size_t)GetHandle2();
1483         switch (TypeFromToken(token))
1484         {
1485         case mdtSignature:
1486             pSigBuilder->AppendByte(ENCODE_VARARGS_SIG);
1487             break;
1488
1489         case mdtMemberRef:
1490             pSigBuilder->AppendByte(ENCODE_VARARGS_METHODREF);
1491             break;
1492
1493         case mdtMethodDef:
1494             pSigBuilder->AppendByte(ENCODE_VARARGS_METHODDEF);
1495             break;
1496
1497         default:
1498             _ASSERTE(!"Bogus token for signature");
1499         }
1500
1501         pSigBuilder->AppendData(RidFromToken(token));
1502     }
1503 };
1504
1505 ZapImport * ZapImportTable::GetVarArgImport(CORINFO_MODULE_HANDLE handle, mdToken sigOrMemberRefOrDef)
1506 {
1507     return GetImport<ZapVarArgImport, ZapNodeType_Import_VarArg>(handle, (PVOID)(size_t)sigOrMemberRefOrDef);
1508 }
1509
1510 class ZapActiveDependencyImport : public ZapImport
1511 {
1512 public:
1513     virtual ZapNodeType GetType()
1514     {
1515         return ZapNodeType_Import_ActiveDependency;
1516     }
1517
1518     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
1519     {
1520         pTable->EncodeModule(ENCODE_ACTIVE_DEPENDENCY, (CORINFO_MODULE_HANDLE)GetHandle(), pSigBuilder);
1521         pSigBuilder->AppendData(pTable->GetIndexOfModule((CORINFO_MODULE_HANDLE)GetHandle2()));
1522     }
1523 };
1524
1525 ZapImport * ZapImportTable::GetActiveDependencyImport(CORINFO_MODULE_HANDLE moduleFrom, CORINFO_MODULE_HANDLE moduleTo)
1526 {
1527     return GetImport<ZapActiveDependencyImport, ZapNodeType_Import_ActiveDependency>(moduleFrom, moduleTo);
1528 }
1529
1530 ZapImport * ZapImportTable::GetClassImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_RESOLVED_TOKEN * pResolvedToken)
1531 {
1532     CORINFO_CLASS_HANDLE handle = (CORINFO_CLASS_HANDLE) pResolvedToken->hClass;
1533
1534     ZapImport * pImport = GetImport<ZapClassHandleImport, ZapNodeType_Import_ClassHandle>(handle, (PVOID)kind);
1535
1536     if (!pImport->HasBlob())
1537     {
1538         SigBuilder sigBuilder;
1539
1540         EncodeClass(kind, handle, &sigBuilder);
1541
1542         pImport->SetBlob(GetBlob(&sigBuilder));
1543     }
1544
1545     return pImport;
1546 }
1547
1548 ZapImport * ZapImportTable::GetMethodImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, 
1549     CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken /*=NULL*/)
1550 {
1551     SigBuilder sigBuilder;
1552     EncodeMethod(kind, handle, &sigBuilder, pResolvedToken, pConstrainedResolvedToken);
1553
1554     return GetImportForSignature<ZapMethodHandleImport, ZapNodeType_Import_MethodHandle>((PVOID)handle, &sigBuilder);
1555 }
1556
1557 ZapImport * ZapImportTable::GetFieldImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken)
1558 {
1559     SigBuilder sigBuilder;
1560     EncodeField(kind, handle, &sigBuilder, pResolvedToken);
1561
1562     return GetImportForSignature<ZapFieldHandleImport, ZapNodeType_Import_FieldHandle>((PVOID)handle, &sigBuilder);
1563 }
1564
1565 #ifdef FEATURE_READYTORUN_COMPILER
1566 ZapImport * ZapImportTable::GetCheckTypeLayoutImport(CORINFO_CLASS_HANDLE handle)
1567 {
1568     ZapImport * pImport = GetImport<ZapClassHandleImport, ZapNodeType_Import_ClassHandle>(handle, (PVOID)ENCODE_CHECK_TYPE_LAYOUT);
1569
1570     if (!pImport->HasBlob())
1571     {
1572         SigBuilder sigBuilder;
1573
1574         sigBuilder.AppendData(ENCODE_CHECK_TYPE_LAYOUT);
1575
1576         GetCompileInfo()->EncodeClass(m_pImage->GetModuleHandle(), handle, &sigBuilder, NULL, NULL);
1577
1578         GetCompileInfo()->EncodeTypeLayout(handle, &sigBuilder);
1579
1580         pImport->SetBlob(GetBlob(&sigBuilder));
1581     }
1582
1583     return pImport;
1584 }
1585
1586 ZapImport * ZapImportTable::GetCheckFieldOffsetImport(CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, DWORD offset)
1587 {
1588     SigBuilder sigBuilder;
1589
1590     sigBuilder.AppendData(ENCODE_CHECK_FIELD_OFFSET);
1591
1592     sigBuilder.AppendData(offset);
1593
1594     GetCompileInfo()->EncodeField(m_pImage->GetModuleHandle(), handle, &sigBuilder, NULL, NULL, pResolvedToken);
1595
1596     EncodeField(ENCODE_CHECK_FIELD_OFFSET, handle, &sigBuilder, pResolvedToken);
1597
1598     return GetImportForSignature<ZapFieldHandleImport, ZapNodeType_Import_FieldHandle>((PVOID)handle, &sigBuilder);
1599 }
1600 #endif // FEATURE_READYTORUN_COMPILER
1601
1602 ZapImport * ZapImportTable::GetStubDispatchCell(CORINFO_RESOLVED_TOKEN * pResolvedToken)
1603 {
1604     CORINFO_METHOD_HANDLE handle = pResolvedToken->hMethod;
1605
1606     SigBuilder sigBuilder;
1607
1608     DWORD slot = GetCompileInfo()->TryEncodeMethodSlot(handle);
1609     if (slot != (DWORD) -1)
1610     {
1611         CORINFO_CLASS_HANDLE clsHandle = pResolvedToken->hClass;
1612
1613         CORINFO_MODULE_HANDLE referencingModule = GetJitInfo()->getClassModule(clsHandle);
1614
1615         referencingModule = TryEncodeModule(ENCODE_VIRTUAL_ENTRY_SLOT, referencingModule, &sigBuilder);
1616
1617         sigBuilder.AppendData(slot);
1618
1619         EncodeClassInContext(referencingModule, clsHandle, &sigBuilder);
1620     }
1621     else
1622     {
1623         CORINFO_MODULE_HANDLE referencingModule;
1624         mdToken token = GetCompileInfo()->TryEncodeMethodAsToken(handle, pResolvedToken, &referencingModule);
1625         if (token != mdTokenNil)
1626         {
1627             _ASSERTE(TypeFromToken(token) == mdtMethodDef || TypeFromToken(token) == mdtMemberRef);
1628
1629             EncodeModule(
1630                 (TypeFromToken(token) == mdtMethodDef) ? ENCODE_VIRTUAL_ENTRY_DEF_TOKEN : ENCODE_VIRTUAL_ENTRY_REF_TOKEN,
1631                 referencingModule, &sigBuilder);
1632
1633             sigBuilder.AppendData(RidFromToken(token));
1634         }
1635         else
1636         {
1637             EncodeMethod(ENCODE_VIRTUAL_ENTRY, handle, &sigBuilder, pResolvedToken);
1638         }
1639     }
1640
1641     // For now, always optimize ready to run for size and startup performance - share cells between callsites
1642     return GetImportForSignature<ZapStubDispatchCell, ZapNodeType_StubDispatchCell>((PVOID)handle, &sigBuilder);
1643 }
1644
1645 ZapImport * ZapImportTable::GetExternalMethodCell(CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken)
1646 {
1647     SigBuilder sigBuilder;
1648
1649     CORINFO_MODULE_HANDLE referencingModule;
1650     mdToken token = GetCompileInfo()->TryEncodeMethodAsToken(handle, pResolvedToken, &referencingModule);
1651     if (token != mdTokenNil)
1652     {
1653         _ASSERTE(TypeFromToken(token) == mdtMethodDef || TypeFromToken(token) == mdtMemberRef);
1654
1655         EncodeModule(
1656             (TypeFromToken(token) == mdtMethodDef) ? ENCODE_METHOD_ENTRY_DEF_TOKEN : ENCODE_METHOD_ENTRY_REF_TOKEN,
1657             referencingModule, &sigBuilder);
1658
1659         sigBuilder.AppendData(RidFromToken(token));
1660     }
1661     else
1662     {
1663         EncodeMethod(ENCODE_METHOD_ENTRY, handle, &sigBuilder, pResolvedToken, pConstrainedResolvedToken);
1664     }
1665
1666     return GetImportForSignature<ZapExternalMethodCell, ZapNodeType_ExternalMethodCell>((PVOID)handle, &sigBuilder);
1667 }
1668
1669
1670 #ifdef FEATURE_READYTORUN_COMPILER
1671
1672 class ZapDynamicHelperCell : public ZapImport
1673 {
1674     ZapNode * m_pDelayLoadHelper;
1675
1676 public:
1677     void SetDelayLoadHelper(ZapNode * pDelayLoadHelper)
1678     {
1679         _ASSERTE(m_pDelayLoadHelper == NULL);
1680         m_pDelayLoadHelper = pDelayLoadHelper;
1681     }
1682
1683     virtual DWORD GetSize()
1684     {
1685         return sizeof(TADDR);
1686     }
1687
1688     virtual UINT GetAlignment()
1689     {
1690         return sizeof(TADDR);
1691     }
1692
1693     virtual ZapNodeType GetType()
1694     {
1695         return ZapNodeType_DynamicHelperCell;
1696     }
1697
1698     CORCOMPILE_FIXUP_BLOB_KIND GetKind()
1699     {
1700         int kind = (int)GetHandle();
1701
1702         if ((kind & 1) == 1)
1703         {
1704             return (CORCOMPILE_FIXUP_BLOB_KIND)(kind >> 1);
1705         }
1706         else
1707         {
1708             _ASSERTE(
1709                 (GetBlob()->GetSize() > 0) && (
1710                     GetBlob()->GetData()[0] == ENCODE_DICTIONARY_LOOKUP_THISOBJ ||
1711                     GetBlob()->GetData()[0] == ENCODE_DICTIONARY_LOOKUP_METHOD ||
1712                     GetBlob()->GetData()[0] == ENCODE_DICTIONARY_LOOKUP_TYPE));
1713
1714             return (CORCOMPILE_FIXUP_BLOB_KIND)GetBlob()->GetData()[0];
1715         }
1716     }
1717
1718     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
1719     {
1720         // Encode should be unreachable for ready-to-run cells
1721         _ASSERTE(false);
1722     }
1723
1724     virtual void Save(ZapWriter * pZapWriter)
1725     {
1726         ZapImage * pImage = ZapImage::GetImage(pZapWriter);
1727
1728         PVOID cell;
1729         pImage->WriteReloc(&cell, 0, m_pDelayLoadHelper, 0, IMAGE_REL_BASED_PTR);
1730         pZapWriter->Write(&cell, sizeof(cell));
1731     }
1732 };
1733
1734 static ReadyToRunHelper GetDelayLoadHelperForDynamicHelper(CORCOMPILE_FIXUP_BLOB_KIND kind)
1735 {
1736     switch (kind)
1737     {
1738     case ENCODE_NEW_HELPER:
1739     case ENCODE_NEW_ARRAY_HELPER:
1740     case ENCODE_STATIC_BASE_NONGC_HELPER:
1741     case ENCODE_STATIC_BASE_GC_HELPER:
1742     case ENCODE_THREAD_STATIC_BASE_NONGC_HELPER:
1743     case ENCODE_THREAD_STATIC_BASE_GC_HELPER:
1744     case ENCODE_CCTOR_TRIGGER:
1745     case ENCODE_FIELD_ADDRESS:
1746     case ENCODE_DICTIONARY_LOOKUP_THISOBJ:
1747     case ENCODE_DICTIONARY_LOOKUP_TYPE:
1748     case ENCODE_DICTIONARY_LOOKUP_METHOD:
1749         return READYTORUN_HELPER_DelayLoad_Helper;
1750
1751     case ENCODE_CHKCAST_HELPER:
1752     case ENCODE_ISINSTANCEOF_HELPER:
1753         return READYTORUN_HELPER_DelayLoad_Helper_Obj;
1754
1755     case ENCODE_VIRTUAL_ENTRY:
1756     // case ENCODE_VIRTUAL_ENTRY_DEF_TOKEN:
1757     // case ENCODE_VIRTUAL_ENTRY_REF_TOKEN:
1758     // case ENCODE_VIRTUAL_ENTRY_SLOT:
1759         return READYTORUN_HELPER_DelayLoad_Helper_Obj;
1760
1761     case ENCODE_DELEGATE_CTOR:
1762         return READYTORUN_HELPER_DelayLoad_Helper_ObjObj;
1763
1764     default:
1765         UNREACHABLE();
1766     }
1767 }
1768
1769 void ZapImportSectionSignatures::PlaceDynamicHelperCell(ZapImport * pImport)
1770 {
1771     ZapDynamicHelperCell * pCell = (ZapDynamicHelperCell *)pImport;
1772
1773     if (m_pImportSection->GetNodeCount() == 0)
1774     {
1775         m_dwIndex = m_pImage->GetImportSectionsTable()->Append(CORCOMPILE_IMPORT_TYPE_UNKNOWN, CORCOMPILE_IMPORT_FLAGS_PCODE,
1776             sizeof(TADDR), m_pImportSection, this, m_pGCRefMapTable);
1777     }
1778
1779     // Create the delay load helper
1780     ReadyToRunHelper helperNum = GetDelayLoadHelperForDynamicHelper(
1781         (CORCOMPILE_FIXUP_BLOB_KIND)(pCell->GetKind() & ~CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE));
1782
1783     ZapNode * pDelayLoadHelper = m_pImage->GetImportTable()->GetPlacedIndirectHelperThunk(helperNum, (PVOID)(SIZE_T)m_dwIndex, 
1784         (pCell->GetKind() & CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE) ? pCell : NULL);
1785
1786     pCell->SetDelayLoadHelper(pDelayLoadHelper);
1787
1788     // Add entry to both the the cell and data sections
1789     m_pImportSection->Place(pCell);
1790
1791     m_pImage->GetImportTable()->PlaceImportBlob(pCell);
1792 }
1793
1794 ZapImport * ZapImportTable::GetDictionaryLookupCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_LOOKUP_KIND * pLookup)
1795 {
1796     _ASSERTE(pLookup->needsRuntimeLookup);
1797
1798     SigBuilder sigBuilder;
1799
1800     sigBuilder.AppendData(kind & ~CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE);
1801
1802     if ((kind & ~CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE) == ENCODE_DICTIONARY_LOOKUP_THISOBJ)
1803     {
1804         CORINFO_CLASS_HANDLE hClassContext = GetJitInfo()->getMethodClass(pResolvedToken->tokenContext);
1805         GetCompileInfo()->EncodeClass(m_pImage->GetModuleHandle(), hClassContext, &sigBuilder, NULL, NULL);
1806     }
1807
1808     switch (pLookup->runtimeLookupFlags)
1809     {
1810     case READYTORUN_FIXUP_TypeHandle:
1811     case READYTORUN_FIXUP_DeclaringTypeHandle:
1812         {
1813             if (pResolvedToken->pTypeSpec == NULL)
1814             {
1815                 _ASSERTE(!"Invalid IL that directly references __Canon");
1816                 ThrowHR(E_NOTIMPL);
1817             }
1818
1819             if (pLookup->runtimeLookupFlags == READYTORUN_FIXUP_DeclaringTypeHandle)
1820             {
1821                 _ASSERTE(pLookup->runtimeLookupArgs != NULL);
1822                 sigBuilder.AppendData(ENCODE_DECLARINGTYPE_HANDLE);
1823                 GetCompileInfo()->EncodeClass(m_pImage->GetModuleHandle(), (CORINFO_CLASS_HANDLE)pLookup->runtimeLookupArgs, &sigBuilder, NULL, NULL);
1824             }
1825             else
1826             {
1827                 sigBuilder.AppendData(ENCODE_TYPE_HANDLE);
1828             }
1829
1830             if (pResolvedToken->tokenType == CORINFO_TOKENKIND_Newarr)
1831                 sigBuilder.AppendElementType(ELEMENT_TYPE_SZARRAY);
1832             sigBuilder.AppendBlob((PVOID)pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec);
1833         }
1834         break;
1835
1836     case READYTORUN_FIXUP_MethodHandle:
1837         EncodeMethod(ENCODE_METHOD_HANDLE, pResolvedToken->hMethod, &sigBuilder, pResolvedToken, NULL, TRUE);
1838         break;
1839
1840     case READYTORUN_FIXUP_MethodEntry:
1841         EncodeMethod(ENCODE_METHOD_ENTRY, pResolvedToken->hMethod, &sigBuilder, pResolvedToken, (CORINFO_RESOLVED_TOKEN*)pLookup->runtimeLookupArgs, TRUE);
1842         break;
1843
1844     case READYTORUN_FIXUP_VirtualEntry:
1845         EncodeMethod(ENCODE_VIRTUAL_ENTRY, pResolvedToken->hMethod, &sigBuilder, pResolvedToken, NULL, TRUE);
1846         break;
1847
1848     case READYTORUN_FIXUP_FieldHandle:
1849         EncodeField(ENCODE_FIELD_HANDLE, pResolvedToken->hField, &sigBuilder, pResolvedToken, TRUE);
1850         break;
1851
1852     default:
1853         _ASSERTE(!"Invalid R2R fixup kind!");
1854         ThrowHR(E_NOTIMPL);
1855     }
1856
1857     _ASSERTE(((DWORD)pResolvedToken->tokenContext & 1) == 0);
1858
1859     return GetImportForSignature<ZapDynamicHelperCell, ZapNodeType_DynamicHelperCell>((void*)pResolvedToken->tokenContext, &sigBuilder);
1860 }
1861
1862 ZapImport * ZapImportTable::GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_CLASS_HANDLE handle)
1863 {
1864     ZapImport * pImport = GetImport<ZapDynamicHelperCell, ZapNodeType_DynamicHelperCell>((void *)(uintptr_t)((kind << 1) | 1), handle);
1865
1866     if (!pImport->HasBlob())
1867     {
1868         SigBuilder sigBuilder;
1869
1870         sigBuilder.AppendData(kind & ~CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE);
1871
1872         GetCompileInfo()->EncodeClass(m_pImage->GetModuleHandle(), handle, &sigBuilder, NULL, NULL);
1873
1874         pImport->SetBlob(GetBlob(&sigBuilder));
1875     }
1876
1877     return pImport;
1878 }
1879
1880 ZapImport * ZapImportTable::GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, 
1881     CORINFO_CLASS_HANDLE delegateType /*=NULL*/)
1882 {
1883     SigBuilder sigBuilder;
1884
1885     EncodeMethod((CORCOMPILE_FIXUP_BLOB_KIND)(kind & ~CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE),
1886         handle, &sigBuilder, pResolvedToken);
1887
1888     if (delegateType != NULL)
1889     {
1890         _ASSERTE((CORCOMPILE_FIXUP_BLOB_KIND)(kind & ~CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE) == ENCODE_DELEGATE_CTOR);
1891         GetCompileInfo()->EncodeClass(m_pImage->GetModuleHandle(), delegateType, &sigBuilder, NULL, NULL);
1892     }
1893
1894     return GetImportForSignature<ZapDynamicHelperCell, ZapNodeType_DynamicHelperCell>((void *)(uintptr_t)((kind << 1) | 1), &sigBuilder);
1895 }
1896
1897 ZapImport * ZapImportTable::GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken)
1898 {
1899     SigBuilder sigBuilder;
1900
1901     EncodeField((CORCOMPILE_FIXUP_BLOB_KIND)(kind & ~CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE),
1902         handle, &sigBuilder, pResolvedToken);
1903
1904     return GetImportForSignature<ZapDynamicHelperCell, ZapNodeType_DynamicHelperCell>((void *)(uintptr_t)((kind << 1) | 1), &sigBuilder);
1905 }
1906
1907 class ZapIndirectHelperThunk : public ZapImport
1908 {
1909     DWORD SaveWorker(ZapWriter * pZapWriter);
1910
1911     ZapNode * m_pCell;
1912
1913 public:
1914     void SetCell(ZapNode * pCell)
1915     {
1916         m_pCell = pCell;
1917     }
1918
1919     ReadyToRunHelper GetReadyToRunHelper()
1920     {
1921         return (ReadyToRunHelper)((DWORD)GetHandle() & ~READYTORUN_HELPER_FLAG_VSD);
1922     }
1923
1924     DWORD GetSectionIndex()
1925     {
1926         return (DWORD)GetHandle2();
1927     }
1928
1929     BOOL IsDelayLoadHelper()
1930     {
1931         ReadyToRunHelper helper = GetReadyToRunHelper();
1932         return (helper == READYTORUN_HELPER_DelayLoad_MethodCall) ||
1933                (helper == READYTORUN_HELPER_DelayLoad_Helper) ||
1934                (helper == READYTORUN_HELPER_DelayLoad_Helper_Obj) ||
1935                (helper == READYTORUN_HELPER_DelayLoad_Helper_ObjObj);
1936     }
1937
1938     BOOL IsDelayLoadMethodCallHelper()
1939     {
1940         ReadyToRunHelper helper = GetReadyToRunHelper();
1941         return (helper == READYTORUN_HELPER_DelayLoad_MethodCall);
1942     }
1943
1944     BOOL IsVSD()
1945     {
1946         return ((DWORD)GetHandle() & READYTORUN_HELPER_FLAG_VSD) != 0;
1947     }
1948
1949     BOOL IsLazyHelper()
1950     {
1951         ReadyToRunHelper helper = GetReadyToRunHelper();
1952         return (helper == READYTORUN_HELPER_GetString);
1953     }
1954
1955     DWORD GetSize()
1956     {
1957         return SaveWorker(NULL);
1958     }
1959
1960     void Save(ZapWriter * pZapWriter)
1961     {
1962         SaveWorker(pZapWriter);
1963     }
1964
1965     virtual UINT GetAlignment()
1966     {
1967         return MINIMUM_CODE_ALIGN;
1968     }
1969
1970     virtual ZapNodeType GetType()
1971     {
1972         return ZapNodeType_IndirectHelperThunk;
1973     }
1974
1975     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
1976     {
1977         // Encode should be unreachable for ready-to-run cells
1978         _ASSERTE(false);
1979     }
1980 };
1981
1982 #ifdef _TARGET_ARM_
1983 static void MovRegImm(BYTE* p, int reg)
1984 {
1985     *(WORD *)(p + 0) = 0xF240;
1986     *(WORD *)(p + 2) = (UINT16)(reg << 8);
1987     *(WORD *)(p + 4) = 0xF2C0;
1988     *(WORD *)(p + 6) = (UINT16)(reg << 8);
1989 }
1990 #endif // _TARGET_ARM_
1991
1992 DWORD ZapIndirectHelperThunk::SaveWorker(ZapWriter * pZapWriter)
1993 {
1994     ZapImage * pImage = ZapImage::GetImage(pZapWriter);
1995
1996     BYTE buffer[44];
1997     BYTE * p = buffer;
1998
1999 #if defined(_TARGET_X86_)
2000     if (IsDelayLoadHelper())
2001     {
2002         // xor eax, eax
2003         *p++ = 0x33;
2004         *p++ = 0xC0;
2005
2006         // push index
2007         *p++ = 0x6A;
2008         _ASSERTE(GetSectionIndex() <= 0x7F);
2009         *p++ = (BYTE)GetSectionIndex();
2010
2011         // push [module]
2012         *p++ = 0xFF;
2013         *p++ = 0x35;
2014         if (pImage != NULL)
2015             pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_PTR);
2016         p += 4;
2017     }
2018     else
2019     if (IsLazyHelper())
2020     {
2021         // mov edx, [module]
2022         *p++ = 0x8B;
2023         *p++ = 0x15;
2024         if (pImage != NULL)
2025             pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_PTR);
2026         p += 4;
2027     }
2028
2029     // jmp [helper]
2030     *p++ = 0xFF;
2031     *p++ = 0x25;
2032     if (pImage != NULL)
2033         pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(GetReadyToRunHelper()), 0, IMAGE_REL_BASED_PTR);
2034     p += 4;
2035 #elif defined(_TARGET_AMD64_)
2036     if (IsDelayLoadHelper())
2037     {
2038         if (m_pCell != NULL)
2039         {
2040             // lea rax, [pCell]
2041             *p++ = 0x48;
2042             *p++ = 0x8D;
2043             *p++ = 0x05;
2044             if (pImage != NULL)
2045                 pImage->WriteReloc(buffer, (int)(p - buffer), m_pCell, 0, IMAGE_REL_BASED_REL32);
2046             p += 4;
2047         }
2048         else
2049         if (IsVSD())
2050         {
2051             // mov rax, r11
2052             *p++ = 0x49;
2053             *p++ = 0x8b;
2054             *p++ = 0xc3;
2055         }
2056         else
2057         {
2058             // xor eax, eax
2059             *p++ = 0x33;
2060             *p++ = 0xC0;
2061         }
2062
2063         // push index
2064         *p++ = 0x6A;
2065         _ASSERTE(GetSectionIndex() <= 0x7F);
2066         *p++ = (BYTE)GetSectionIndex();
2067
2068         // push [module]
2069         *p++ = 0xFF;
2070         *p++ = 0x35;
2071         if (pImage != NULL)
2072             pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_REL32);
2073         p += 4;
2074     }
2075     else
2076     if (IsLazyHelper())
2077     {
2078         *p++ = 0x48;
2079         *p++ = 0x8B;
2080 #ifdef UNIX_AMD64_ABI
2081         // mov rsi, [module]
2082         *p++ = 0x35;
2083 #else
2084         // mov rdx, [module]
2085         *p++ = 0x15;
2086 #endif
2087         if (pImage != NULL)
2088             pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_REL32);
2089         p += 4;
2090     }
2091
2092     // jmp [helper]
2093     *p++ = 0xFF;
2094     *p++ = 0x25;
2095     if (pImage != NULL)
2096         pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(GetReadyToRunHelper()), 0, IMAGE_REL_BASED_REL32);
2097     p += 4;
2098 #elif defined(_TARGET_ARM_)
2099     if (IsDelayLoadHelper())
2100     {
2101         // r4 contains indirection cell
2102         // push r4
2103         *(WORD *)(p + 0) = 0xB410;
2104         p += 2;
2105
2106         // mov r4, index
2107         _ASSERTE(GetSectionIndex() <= 0x7F);
2108         *(WORD *)(p + 0) = 0x2400 | (BYTE)GetSectionIndex();
2109         p += 2;
2110
2111         // push r4
2112         *(WORD *)(p + 0) = 0xB410;
2113         p += 2;
2114
2115         // mov r4, [module]
2116         MovRegImm(p, 4);
2117         if (pImage != NULL)
2118             pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_THUMB_MOV32);
2119         p += 8;
2120
2121         // ldr r4, [r4]
2122         *(WORD *)p = 0x6824;
2123         p += 2;
2124
2125         // push r4
2126         *(WORD *)(p + 0) = 0xB410;
2127         p += 2;
2128
2129         // mov r4, [helper]
2130         MovRegImm(p, 4);
2131         if (pImage != NULL)
2132             pImage->WriteReloc(buffer, (int)(p - buffer), pImage->GetImportTable()->GetHelperImport(GetReadyToRunHelper()), 0, IMAGE_REL_BASED_THUMB_MOV32);
2133         p += 8;
2134
2135         // ldr r4, [r4]
2136         *(WORD *)p = 0x6824;
2137         p += 2;
2138
2139         // bx r4
2140         *(WORD *)p = 0x4720;
2141         p += 2;
2142     }
2143     else
2144     {
2145         if (IsLazyHelper())
2146         {
2147             // mov r1, [helper]
2148             MovRegImm(p, 1);
2149             if (pImage != NULL)
2150                 pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_THUMB_MOV32);
2151             p += 8;
2152
2153             // ldr r1, [r1]
2154             *(WORD *)p = 0x6809;
2155             p += 2;
2156         }
2157
2158         // mov r12, [helper]
2159         MovRegImm(p, 12);
2160         if (pImage != NULL)
2161             pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(GetReadyToRunHelper()), 0, IMAGE_REL_BASED_THUMB_MOV32);
2162         p += 8;
2163
2164         // ldr r12, [r12]
2165         *(DWORD *)p = 0xC000F8DC;
2166         p += 4;
2167
2168         // bx r12
2169         *(WORD *)p = 0x4760;
2170         p += 2;
2171     }
2172 #elif defined(_TARGET_ARM64_)
2173     if (IsDelayLoadHelper())
2174     {
2175         // x11 contains indirection cell
2176         // Do nothing x11 contains our first param
2177
2178         //  movz x9, #index
2179         DWORD index = GetSectionIndex();
2180         _ASSERTE(index <= 0x7F);
2181         *(DWORD*)p = 0xd2800009 | (index << 5);
2182         p += 4;
2183
2184         // move Module* -> x10
2185         // ldr x10, [PC+0x14]
2186         *(DWORD*)p = 0x580000AA;
2187         p += 4;
2188
2189         //ldr x10, [x10]
2190         *(DWORD*)p = 0xf940014A;
2191         p += 4;
2192     }
2193     else
2194     if (IsLazyHelper())
2195     {
2196         // Move Module* -> x1
2197         // ldr x1, [PC+0x14]
2198         *(DWORD*)p = 0x580000A1;
2199         p += 4;
2200
2201         // ldr x1, [x1]
2202         *(DWORD*)p = 0xf9400021;
2203         p += 4;
2204     }
2205
2206     // branch to helper
2207     // ldr x12, [PC+0x14]
2208     *(DWORD*)p = 0x580000AC;
2209     p += 4;
2210
2211     // ldr x12, [x12]
2212     *(DWORD *)p = 0xf940018c;
2213     p += 4;
2214
2215     // br x12
2216     *(DWORD *)p = 0xd61f0180;
2217     p += 4;
2218
2219     // [Module*]
2220     if (pImage != NULL)
2221         pImage->WriteReloc(buffer, (int)(p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_PTR);
2222     p += 8;
2223
2224     // [helper]
2225     if (pImage != NULL)
2226         pImage->WriteReloc(buffer, (int)(p - buffer), pImage->GetImportTable()->GetHelperImport(GetReadyToRunHelper()), 0, IMAGE_REL_BASED_PTR);
2227     p += 8;
2228 #else
2229     PORTABILITY_ASSERT("ZapIndirectHelperThunk::SaveWorker");
2230 #endif
2231
2232     _ASSERTE(p - buffer <= sizeof(buffer));
2233
2234     if (pZapWriter != NULL)
2235         pZapWriter->Write(&buffer, (int)(p - buffer));
2236
2237     return (DWORD)(p - buffer);
2238 }
2239
2240 void ZapImportTable::PlaceIndirectHelperThunk(ZapNode * pImport)
2241 {
2242     ZapIndirectHelperThunk * pThunk = (ZapIndirectHelperThunk *)pImport;
2243
2244     if (pThunk->IsDelayLoadMethodCallHelper())
2245         m_pImage->m_pLazyMethodCallHelperSection->Place(pThunk);
2246     else
2247         m_pImage->m_pLazyHelperSection->Place(pThunk);
2248
2249     if (pThunk->IsDelayLoadHelper() || pThunk->IsLazyHelper())
2250        GetPlacedHelperImport(READYTORUN_HELPER_Module);
2251
2252     GetPlacedHelperImport(pThunk->GetReadyToRunHelper());
2253 }
2254
2255 ZapNode * ZapImportTable::GetIndirectHelperThunk(ReadyToRunHelper helperNum, PVOID pArg)
2256 {
2257     ZapNode * pImport = GetImport<ZapIndirectHelperThunk, ZapNodeType_IndirectHelperThunk>((void *)helperNum, pArg);
2258 #if defined(_TARGET_ARM_)
2259     pImport = m_pImage->GetInnerPtr(pImport, THUMB_CODE);
2260 #endif
2261     return pImport;
2262 }
2263
2264 ZapNode * ZapImportTable::GetPlacedIndirectHelperThunk(ReadyToRunHelper helperNum, PVOID pArg, ZapNode * pCell)
2265 {
2266     ZapNode * pImport;
2267     if (pCell != NULL)
2268     {
2269         ZapIndirectHelperThunk * pIndirectHelperThunk = new (m_pImage->GetHeap()) ZapIndirectHelperThunk();
2270         pIndirectHelperThunk->SetHandle((void *)helperNum);
2271         pIndirectHelperThunk->SetHandle2(pArg);
2272         pIndirectHelperThunk->SetCell(pCell);
2273         pImport = pIndirectHelperThunk;
2274     }
2275     else
2276     {
2277         pImport = GetImport<ZapIndirectHelperThunk, ZapNodeType_IndirectHelperThunk>((void *)helperNum, pArg);
2278     }
2279     if (!pImport->IsPlaced())
2280         PlaceIndirectHelperThunk(pImport);
2281 #if defined(_TARGET_ARM_)
2282     pImport = m_pImage->GetInnerPtr(pImport, THUMB_CODE);
2283 #endif
2284     return pImport;
2285 }
2286
2287 class ZapHelperImport : public ZapImport
2288 {
2289 public:
2290     virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature)
2291     {
2292         *pfIsEager = TRUE;
2293         *pfNeedsSignature = TRUE;
2294         return ZapImportSectionType_Handle;
2295     }
2296
2297     virtual ZapNodeType GetType()
2298     {
2299         return ZapNodeType_Import_Helper;
2300     }
2301
2302     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder)
2303     {
2304         // Encode should be unreachable for ready-to-run cells
2305         _ASSERTE(false);
2306     }
2307 };
2308
2309 ZapImport * ZapImportTable::GetHelperImport(ReadyToRunHelper helperNum)
2310 {
2311     ZapImport * pImport = GetImport<ZapHelperImport, ZapNodeType_Import_Helper>((void *)helperNum);
2312
2313     if (!pImport->HasBlob())
2314     {
2315         SigBuilder sigBuilder;
2316
2317         sigBuilder.AppendData(ENCODE_READYTORUN_HELPER);
2318         sigBuilder.AppendData(helperNum);
2319
2320         pImport->SetBlob(GetBlob(&sigBuilder));
2321     }
2322
2323     return pImport;
2324 }
2325
2326 ZapImport * ZapImportTable::GetPlacedHelperImport(ReadyToRunHelper helperNum)
2327 {
2328     ZapImport * pImport = GetHelperImport(helperNum);
2329     if (!pImport->IsPlaced())
2330         PlaceImport(pImport);
2331     return pImport;
2332 }
2333
2334 #endif // FEATURE_READYTORUN_COMPILER