[Tizen] Add RelativeFixupPrecode for arm64, which replaces FixupPrecode in FNV images
[platform/upstream/coreclr.git] / src / vm / arm64 / stubs.cpp
index 6805579..b25dc4d 100644 (file)
@@ -565,6 +565,18 @@ TADDR FixupPrecode::GetMethodDesc()
     return base + (m_MethodDescChunkIndex * MethodDesc::ALIGNMENT);
 }
 
+TADDR RelativeFixupPrecode::GetMethodDesc()
+{
+    LIMITED_METHOD_DAC_CONTRACT;
+
+    // This lookup is also manually inlined in PrecodeFixupThunk assembly code
+    TADDR baseAddr = GetBase();
+    TADDR base = *PTR_TADDR(baseAddr);
+    if (base == NULL)
+        return NULL;
+    return baseAddr + base + (m_MethodDescChunkIndex * MethodDesc::ALIGNMENT);
+}
+
 #ifdef DACCESS_COMPILE
 void FixupPrecode::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
 {
@@ -573,6 +585,14 @@ void FixupPrecode::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
 
        DacEnumMemoryRegion(GetBase(), sizeof(TADDR));
 }
+
+void RelativeFixupPrecode::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
+{
+       SUPPORTS_DAC;
+       DacEnumMemoryRegion(dac_cast<TADDR>(this), sizeof(RelativeFixupPrecode));
+
+       DacEnumMemoryRegion(GetBase(), sizeof(TADDR));
+}
 #endif // DACCESS_COMPILE
 
 #ifndef DACCESS_COMPILE
@@ -675,6 +695,39 @@ void FixupPrecode::Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator, int
     }
 }
 
+void RelativeFixupPrecode::Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator, int iMethodDescChunkIndex /*=0*/, int iPrecodeChunkIndex /*=0*/)
+{
+    WRAPPER_NO_CONTRACT;
+
+    InitCommon();
+
+    // Initialize chunk indices only if they are not initialized yet. This is necessary to make MethodDesc::Reset work.
+    if (m_PrecodeChunkIndex == 0)
+    {
+        _ASSERTE(FitsInU1(iPrecodeChunkIndex));
+        m_PrecodeChunkIndex = static_cast<BYTE>(iPrecodeChunkIndex);
+    }
+
+    if (iMethodDescChunkIndex != -1)
+    {
+        if (m_MethodDescChunkIndex == 0)
+        {
+            _ASSERTE(FitsInU1(iMethodDescChunkIndex));
+            m_MethodDescChunkIndex = static_cast<BYTE>(iMethodDescChunkIndex);
+        }
+
+        if (*(void**)GetBase() == NULL)
+            *(void**)GetBase() = (BYTE*)pMD - (iMethodDescChunkIndex * MethodDesc::ALIGNMENT) - GetBase();
+    }
+
+    _ASSERTE(GetMethodDesc() == (TADDR)pMD);
+
+    if (pLoaderAllocator != NULL)
+    {
+        m_pTargetOffset = GetEEFuncEntryPoint(PrecodeRelativeFixupThunk) - (TADDR)this - RelativeFixupPrecode::GetTargetOffset();
+    }
+}
+
 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
 // Partial initialization. Used to save regrouped chunks.
 void FixupPrecode::InitForSave(int iPrecodeChunkIndex)
@@ -688,10 +741,27 @@ void FixupPrecode::InitForSave(int iPrecodeChunkIndex)
     // The rest is initialized in code:FixupPrecode::Fixup
 }
 
+// Partial initialization. Used to save regrouped chunks.
+void RelativeFixupPrecode::InitForSave(int iPrecodeChunkIndex)
+{
+    STANDARD_VM_CONTRACT;
+
+    InitCommon();
+
+    _ASSERTE(FitsInU1(iPrecodeChunkIndex));
+    m_PrecodeChunkIndex = static_cast<BYTE>(iPrecodeChunkIndex);
+    // The rest is initialized in code:RelativeFixupPrecode::Fixup
+}
+
 void FixupPrecode::Fixup(DataImage *image, MethodDesc * pMD)
 {
     STANDARD_VM_CONTRACT;
 
+#ifdef HAS_RELATIVE_FIXUP_PRECODE
+    // FixupPrecode is not saved to image in this case
+    _ASSERTE(!"FixupPrecode is not saved to NGENed image, RelativeFixupPrecode is instead");
+#else // HAS_RELATIVE_FIXUP_PRECODE
+
     // Note that GetMethodDesc() does not return the correct value because of 
     // regrouping of MethodDescs into hot and cold blocks. That's why the caller
     // has to supply the actual MethodDesc
@@ -716,6 +786,44 @@ void FixupPrecode::Fixup(DataImage *image, MethodDesc * pMD)
         image->FixupFieldToNode(this, (BYTE *)GetBase() - (BYTE *)this,
             pMDChunkNode, sizeof(MethodDescChunk));
     }
+#endif // HAS_RELATIVE_FIXUP_PRECODE
+}
+
+void RelativeFixupPrecode::Fixup(DataImage *image, MethodDesc * pMD)
+{
+    STANDARD_VM_CONTRACT;
+
+    // Note that GetMethodDesc() does not return the correct value because of
+    // regrouping of MethodDescs into hot and cold blocks. That's why the caller
+    // has to supply the actual MethodDesc
+
+    SSIZE_T mdChunkOffset;
+    ZapNode * pMDChunkNode = image->GetNodeForStructure(pMD, &mdChunkOffset);
+    ZapNode * pHelperThunk = image->GetHelperThunk(CORINFO_HELP_EE_PRECODE_FIXUP);
+
+    image->FixupFieldToNode(this,
+                            offsetof(RelativeFixupPrecode, m_pTargetOffset),
+                            pHelperThunk,
+                            offsetof(RelativeFixupPrecode, m_pTargetOffset) - RelativeFixupPrecode::GetTargetOffset(),
+                            IMAGE_REL_BASED_RELPTR);
+
+    // Set the actual chunk index
+    RelativeFixupPrecode * pNewPrecode = (RelativeFixupPrecode *)image->GetImagePointer(this);
+
+    size_t mdOffset = mdChunkOffset - sizeof(MethodDescChunk);
+    size_t chunkIndex = mdOffset / MethodDesc::ALIGNMENT;
+    _ASSERTE(FitsInU1(chunkIndex));
+    pNewPrecode->m_MethodDescChunkIndex = (BYTE)chunkIndex;
+
+    // Fixup the base of MethodDescChunk
+    if (m_PrecodeChunkIndex == 0)
+    {
+        image->FixupFieldToNode(this,
+                                (BYTE *)GetBase() - (BYTE *)this,
+                                pMDChunkNode,
+                                sizeof(MethodDescChunk),
+                                IMAGE_REL_BASED_RELPTR);
+    }
 }
 #endif // FEATURE_NATIVE_IMAGE_GENERATION
 
@@ -762,6 +870,21 @@ BOOL DoesSlotCallPrestub(PCODE pCode)
     }
 #endif
 
+    //RelativeFixupPrecode
+#if defined(HAS_RELATIVE_FIXUP_PRECODE)
+    if (RelativeFixupPrecode::IsRelativeFixupPrecodeByASM(pCode))
+    {
+        PCODE pTarget = dac_cast<PTR_RelativeFixupPrecode>(pInstr)->GetTarget();
+
+        if (isJump(pTarget))
+        {
+            pTarget = decodeJump(pTarget);
+        }
+
+        return pTarget == (TADDR)PrecodeRelativeFixupThunk;
+    }
+#endif // HAS_RELATIVE_FIXUP_PRECODE
+
     // StubPrecode
     if (pInstr[0] == 0x10000089 && // adr x9, #16
         pInstr[1] == 0xA940312A && // ldp x10,x12,[x9]