diff options
author | Jiyoung Yun <jy910.yun@samsung.com> | 2017-02-10 20:35:12 +0900 |
---|---|---|
committer | Jiyoung Yun <jy910.yun@samsung.com> | 2017-02-10 20:35:12 +0900 |
commit | 4b11dc566a5bbfa1378d6266525c281b028abcc8 (patch) | |
tree | b48831a898906734f8884d08b6e18f1144ee2b82 /src/vm/jitinterface.cpp | |
parent | db20f3f1bb8595633a7e16c8900fd401a453a6b5 (diff) | |
download | coreclr-4b11dc566a5bbfa1378d6266525c281b028abcc8.tar.gz coreclr-4b11dc566a5bbfa1378d6266525c281b028abcc8.tar.bz2 coreclr-4b11dc566a5bbfa1378d6266525c281b028abcc8.zip |
Imported Upstream version 1.0.0.9910upstream/1.0.0.9910
Diffstat (limited to 'src/vm/jitinterface.cpp')
-rw-r--r-- | src/vm/jitinterface.cpp | 212 |
1 files changed, 153 insertions, 59 deletions
diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index 2f9db3d596..5afb89bd4b 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -2286,6 +2286,59 @@ BOOL CEEInfo::checkMethodModifier(CORINFO_METHOD_HANDLE hMethod, } /*********************************************************************/ +static unsigned ComputeGCLayout(MethodTable * pMT, BYTE* gcPtrs) +{ + STANDARD_VM_CONTRACT; + + unsigned result = 0; + + _ASSERTE(pMT->IsValueType()); + + // TODO: TypedReference should ideally be implemented as a by-ref-like struct containing a ByReference<T> field, in which + // case the check for g_TypedReferenceMT below would not be necessary + if (pMT == g_TypedReferenceMT || pMT->HasSameTypeDefAs(g_pByReferenceClass)) + { + if (gcPtrs[0] == TYPE_GC_NONE) + { + gcPtrs[0] = TYPE_GC_BYREF; + result++; + } + else if (gcPtrs[0] != TYPE_GC_BYREF) + { + COMPlusThrowHR(COR_E_BADIMAGEFORMAT); + } + return result; + } + + ApproxFieldDescIterator fieldIterator(pMT, ApproxFieldDescIterator::INSTANCE_FIELDS); + for (FieldDesc *pFD = fieldIterator.Next(); pFD != NULL; pFD = fieldIterator.Next()) + { + int fieldStartIndex = pFD->GetOffset() / sizeof(void*); + + if (pFD->GetFieldType() != ELEMENT_TYPE_VALUETYPE) + { + if (pFD->IsObjRef()) + { + if (gcPtrs[fieldStartIndex] == TYPE_GC_NONE) + { + gcPtrs[fieldStartIndex] = TYPE_GC_REF; + result++; + } + else if (gcPtrs[fieldStartIndex] != TYPE_GC_REF) + { + COMPlusThrowHR(COR_E_BADIMAGEFORMAT); + } + } + } + else + { + MethodTable * pFieldMT = pFD->GetApproxFieldTypeHandleThrowing().AsMethodTable(); + result += ComputeGCLayout(pFieldMT, gcPtrs + fieldStartIndex); + } + } + return result; +} + unsigned CEEInfo::getClassGClayout (CORINFO_CLASS_HANDLE clsHnd, BYTE* gcPtrs) { CONTRACTL { @@ -2305,6 +2358,8 @@ unsigned CEEInfo::getClassGClayout (CORINFO_CLASS_HANDLE clsHnd, BYTE* gcPtrs) if (pMT->IsByRefLike()) { + // TODO: TypedReference should ideally be implemented as a by-ref-like struct containing a ByReference<T> field, in + // which case the check for g_TypedReferenceMT below would not be necessary if (pMT == g_TypedReferenceMT) { gcPtrs[0] = TYPE_GC_BYREF; @@ -2313,10 +2368,12 @@ unsigned CEEInfo::getClassGClayout (CORINFO_CLASS_HANDLE clsHnd, BYTE* gcPtrs) } else { - // TODO-SPAN: Proper GC reporting memset(gcPtrs, TYPE_GC_NONE, - (VMClsHnd.GetSize() + sizeof(void*) -1)/ sizeof(void*)); - result = 0; + (VMClsHnd.GetSize() + sizeof(void*) - 1) / sizeof(void*)); + // Note: This case is more complicated than the TypedReference case + // due to ByRefLike structs being included as fields in other value + // types (TypedReference can not be.) + result = ComputeGCLayout(VMClsHnd.AsMethodTable(), gcPtrs); } } else if (VMClsHnd.IsNativeValueType()) @@ -5115,6 +5172,14 @@ void CEEInfo::getCallInfo( { // Pretend this was a "constrained. UnderlyingType" instruction prefix constrainedType = TypeHandle(MscorlibBinder::GetElementType(constrainedType.GetVerifierCorElementType())); + + // Native image signature encoder will use this field. It needs to match that pretended type, a bogus signature + // would be produced otherwise. + pConstrainedResolvedToken->hClass = (CORINFO_CLASS_HANDLE)constrainedType.AsPtr(); + + // Clear the token and typespec because of they do not match hClass anymore. + pConstrainedResolvedToken->token = mdTokenNil; + pConstrainedResolvedToken->pTypeSpec = NULL; } } @@ -7079,6 +7144,16 @@ bool getILIntrinsicImplementationForUnsafe(MethodDesc * ftn, methInfo->options = (CorInfoOptions)0; return true; } + else if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__BYREF_INIT_BLOCK_UNALIGNED)->GetMemberDef()) + { + static const BYTE ilcode[] = { CEE_LDARG_0, CEE_LDARG_1, CEE_LDARG_2, CEE_PREFIX1, (CEE_UNALIGNED & 0xFF), 0x01, CEE_PREFIX1, (CEE_INITBLK & 0xFF), CEE_RET }; + methInfo->ILCode = const_cast<BYTE*>(ilcode); + methInfo->ILCodeSize = sizeof(ilcode); + methInfo->maxStack = 3; + methInfo->EHcount = 0; + methInfo->options = (CorInfoOptions)0; + return true; + } return false; } @@ -8764,6 +8839,29 @@ CorInfoIntrinsics CEEInfo::getIntrinsicID(CORINFO_METHOD_HANDLE methodHnd, { result = ECall::GetIntrinsicID(method); } + else + { + MethodTable * pMT = method->GetMethodTable(); + if (pMT->IsByRefLike() && pMT->GetModule()->IsSystem()) + { + if (pMT->HasSameTypeDefAs(g_pByReferenceClass)) + { + // ByReference<T> has just two methods: constructor and Value property + if (method->IsCtor()) + { + result = CORINFO_INTRINSIC_ByReference_Ctor; + } + else + { + _ASSERTE(strcmp(method->GetName(), "get_Value") == 0); + result = CORINFO_INTRINSIC_ByReference_Value; + } + *pMustExpand = true; + } + + // TODO-SPAN: Span<T> intrinsics for optimizations + } + } EE_TO_JIT_TRANSITION(); @@ -9017,10 +9115,15 @@ CorInfoType CEEInfo::getFieldTypeInternal (CORINFO_FIELD_HANDLE fieldHnd, // <REVISIT_TODO>TODO should not burn the time to do this for anything but Value Classes</REVISIT_TODO> _ASSERTE(type != ELEMENT_TYPE_BYREF); - // For verifying code involving generics, use the class instantiation - // of the optional owner (to provide exact, not representative, - // type information) - SigTypeContext typeContext(field, (TypeHandle) owner); + if (type == ELEMENT_TYPE_I) + { + PTR_MethodTable enclosingMethodTable = field->GetApproxEnclosingMethodTable(); + if (enclosingMethodTable->IsByRefLike() && enclosingMethodTable->HasSameTypeDefAs(g_pByReferenceClass)) + { + _ASSERTE(field->GetOffset() == 0); + return CORINFO_TYPE_BYREF; + } + } if (!CorTypeInfo::IsPrimitiveType(type)) { @@ -9030,11 +9133,16 @@ CorInfoType CEEInfo::getFieldTypeInternal (CORINFO_FIELD_HANDLE fieldHnd, field->GetSig(&sig, &sigCount); - conv = (CorCallingConvention) CorSigUncompressCallingConv(sig); + conv = (CorCallingConvention)CorSigUncompressCallingConv(sig); _ASSERTE(isCallConv(conv, IMAGE_CEE_CS_CALLCONV_FIELD)); SigPointer ptr(sig, sigCount); + // For verifying code involving generics, use the class instantiation + // of the optional owner (to provide exact, not representative, + // type information) + SigTypeContext typeContext(field, (TypeHandle)owner); + clsHnd = ptr.GetTypeHandleThrowing(field->GetModule(), &typeContext); _ASSERTE(!clsHnd.IsNull()); @@ -10882,6 +10990,33 @@ void CEEJitInfo::CompressDebugInfo() EE_TO_JIT_TRANSITION(); } +void reservePersonalityRoutineSpace(ULONG &unwindSize) +{ +#if defined(_TARGET_X86_) + // Do nothing +#elif defined(_TARGET_AMD64_) + // Add space for personality routine, it must be 4-byte aligned. + // Everything in the UNWIND_INFO up to the variable-sized UnwindCodes + // array has already had its size included in unwindSize by the caller. + unwindSize += sizeof(ULONG); + + // Note that the count of unwind codes (2 bytes each) is stored as a UBYTE + // So the largest size could be 510 bytes, plus the header and language + // specific stuff. This can't overflow. + + _ASSERTE(FitsInU4(unwindSize + sizeof(ULONG))); + unwindSize = (ULONG)(ALIGN_UP(unwindSize, sizeof(ULONG))); +#elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) + // The JIT passes in a 4-byte aligned block of unwind data. + _ASSERTE(IS_ALIGNED(unwindSize, sizeof(ULONG))); + + // Add space for personality routine, it must be 4-byte aligned. + unwindSize += sizeof(ULONG); +#else + PORTABILITY_ASSERT("reservePersonalityRoutineSpace"); +#endif // !defined(_TARGET_AMD64_) + +} // Reserve memory for the method/funclet's unwind information. // Note that this must be called before allocMem. It should be // called once for the main method, once for every funclet, and @@ -10914,27 +11049,7 @@ void CEEJitInfo::reserveUnwindInfo(BOOL isFunclet, BOOL isColdCode, ULONG unwind ULONG currentSize = unwindSize; -#if defined(_TARGET_AMD64_) - // Add space for personality routine, it must be 4-byte aligned. - // Everything in the UNWIND_INFO up to the variable-sized UnwindCodes - // array has already had its size included in unwindSize by the caller. - currentSize += sizeof(ULONG); - - // Note that the count of unwind codes (2 bytes each) is stored as a UBYTE - // So the largest size could be 510 bytes, plus the header and language - // specific stuff. This can't overflow. - - _ASSERTE(FitsInU4(currentSize + sizeof(ULONG))); - currentSize = (ULONG)(ALIGN_UP(currentSize, sizeof(ULONG))); -#elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) - // The JIT passes in a 4-byte aligned block of unwind data. - _ASSERTE(IS_ALIGNED(currentSize, sizeof(ULONG))); - - // Add space for personality routine, it must be 4-byte aligned. - currentSize += sizeof(ULONG); -#else - PORTABILITY_ASSERT("CEEJitInfo::reserveUnwindInfo"); -#endif // !defined(_TARGET_AMD64_) + reservePersonalityRoutineSpace(currentSize); m_totalUnwindSize += currentSize; @@ -11019,27 +11134,7 @@ void CEEJitInfo::allocUnwindInfo ( UNWIND_INFO * pUnwindInfo = (UNWIND_INFO *) &(m_theUnwindBlock[m_usedUnwindSize]); m_usedUnwindSize += unwindSize; -#if defined(_TARGET_AMD64_) - // Add space for personality routine, it must be 4-byte aligned. - // Everything in the UNWIND_INFO up to the variable-sized UnwindCodes - // array has already had its size included in unwindSize by the caller. - m_usedUnwindSize += sizeof(ULONG); - - // Note that the count of unwind codes (2 bytes each) is stored as a UBYTE - // So the largest size could be 510 bytes, plus the header and language - // specific stuff. This can't overflow. - - _ASSERTE(FitsInU4(m_usedUnwindSize + sizeof(ULONG))); - m_usedUnwindSize = (ULONG)(ALIGN_UP(m_usedUnwindSize,sizeof(ULONG))); -#elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) - // The JIT passes in a 4-byte aligned block of unwind data. - _ASSERTE(IS_ALIGNED(m_usedUnwindSize, sizeof(ULONG))); - - // Add space for personality routine, it must be 4-byte aligned. - m_usedUnwindSize += sizeof(ULONG); -#else - PORTABILITY_ASSERT("CEEJitInfo::reserveUnwindInfo"); -#endif + reservePersonalityRoutineSpace(m_usedUnwindSize); _ASSERTE(m_usedUnwindSize <= m_totalUnwindSize); @@ -11082,7 +11177,7 @@ void CEEJitInfo::allocUnwindInfo ( RUNTIME_FUNCTION__SetBeginAddress(pRuntimeFunction, currentCodeOffset + startOffset); -#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) +#ifdef _TARGET_AMD64_ pRuntimeFunction->EndAddress = currentCodeOffset + endOffset; #endif @@ -11102,11 +11197,15 @@ void CEEJitInfo::allocUnwindInfo ( } #endif // _DEBUG -#if defined(_TARGET_AMD64_) - /* Copy the UnwindBlock */ memcpy(pUnwindInfo, pUnwindBlock, unwindSize); +#if defined(_TARGET_X86_) + + // Do NOTHING + +#elif defined(_TARGET_AMD64_) + pUnwindInfo->Flags = UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER; ULONG * pPersonalityRoutine = (ULONG*)ALIGN_UP(&(pUnwindInfo->UnwindCode[pUnwindInfo->CountOfUnwindCodes]), sizeof(ULONG)); @@ -11114,9 +11213,6 @@ void CEEJitInfo::allocUnwindInfo ( #elif defined(_TARGET_ARM64_) - /* Copy the UnwindBlock */ - memcpy(pUnwindInfo, pUnwindBlock, unwindSize); - *(LONG *)pUnwindInfo |= (1 << 20); // X bit ULONG * pPersonalityRoutine = (ULONG*)((BYTE *)pUnwindInfo + ALIGN_UP(unwindSize, sizeof(ULONG))); @@ -11124,13 +11220,11 @@ void CEEJitInfo::allocUnwindInfo ( #elif defined(_TARGET_ARM_) - /* Copy the UnwindBlock */ - memcpy(pUnwindInfo, pUnwindBlock, unwindSize); - *(LONG *)pUnwindInfo |= (1 << 20); // X bit ULONG * pPersonalityRoutine = (ULONG*)((BYTE *)pUnwindInfo + ALIGN_UP(unwindSize, sizeof(ULONG))); *pPersonalityRoutine = (TADDR)ProcessCLRException - baseAddress; + #endif #if defined(_TARGET_AMD64_) |