FCIMPL1(void, ArrayNative::Initialize, ArrayBase* array) { FCALL_CONTRACT; if (array == NULL) { FCThrowVoid(kNullReferenceException); } MethodTable* pArrayMT = array->GetMethodTable(); TypeHandle thElem = pArrayMT->GetApproxArrayElementTypeHandle(); if (thElem.IsTypeDesc()) return; MethodTable * pElemMT = thElem.AsMethodTable(); if (!pElemMT->HasDefaultConstructor() || !pElemMT->IsValueType()) return; ARRAYBASEREF arrayRef (array); HELPER_METHOD_FRAME_BEGIN_1(arrayRef); ArrayInitializeWorker(&arrayRef, pArrayMT, pElemMT); HELPER_METHOD_FRAME_END(); }
// Some platforms have additional alignment requirements for arguments. This function adjusts the given arg // pointer to achieve such an alignment for the next argument on those platforms (otherwise it is a no-op). // NOTE: the debugger has its own implementation of this algorithm in Debug\DI\RsType.cpp, CordbType::RequiresAlign8() // so if you change this implementation be sure to update the debugger's version as well. static void AdjustArgPtrForAlignment(VARARGS *pData, size_t cbArg) { #ifdef _TARGET_ARM_ // Only 64-bit primitives or value types with embedded 64-bit primitives are aligned on 64-bit boundaries. if (cbArg < 8) return; // For the value type case we have to dig deeper and ask the typeloader whether the type requires // alignment. SigTypeContext typeContext; // This is an empty type context. This is OK because the vararg methods may not be generic. CorElementType et = pData->SigPtr.PeekElemTypeClosed(pData->ArgCookie->pModule, &typeContext); if (et == ELEMENT_TYPE_TYPEDBYREF) { return; } else if (et == ELEMENT_TYPE_VALUETYPE) { SigPointer tempSig(pData->SigPtr); TypeHandle valueType = tempSig.GetTypeHandleThrowing(pData->ArgCookie->pModule, &typeContext); if (!valueType.AsMethodTable()->RequiresAlign8()) return; } else { // One of the primitive 64-bit types } pData->ArgPtr = (BYTE*)ALIGN_UP(pData->ArgPtr, 8); #endif // _TARGET_ARM_ }
MethodTable *Binder::RawGetClass(BinderClassID id) { CANNOTTHROWCOMPLUSEXCEPTION(); _ASSERTE(m_pModule != NULL); _ASSERTE(id != CLASS__NIL); _ASSERTE(id <= m_cClassRIDs); TypeHandle th = m_pModule->LookupTypeDef(TokenFromRid(m_pClassRIDs[id-1], mdtTypeDef)); _ASSERTE(!th.IsNull()); _ASSERTE(th.IsUnsharedMT()); return th.AsMethodTable(); }
int GetVersionResilientTypeHashCode(TypeHandle type) { if (!type.IsTypeDesc()) { MethodTable *pMT = type.AsMethodTable(); _ASSERTE(!pMT->IsArray()); _ASSERTE(!IsNilToken(pMT->GetCl())); LPCUTF8 szNamespace; LPCUTF8 szName; IfFailThrow(pMT->GetMDImport()->GetNameOfTypeDef(pMT->GetCl(), &szName, &szNamespace)); int hashcode = ComputeNameHashCode(szNamespace, szName); MethodTable *pMTEnclosing = pMT->LoadEnclosingMethodTable(CLASS_LOAD_UNRESTOREDTYPEKEY); if (pMTEnclosing != NULL) { hashcode = ComputeNestedTypeHashCode(GetVersionResilientTypeHashCode(TypeHandle(pMTEnclosing)), hashcode); } if (!pMT->IsGenericTypeDefinition() && pMT->HasInstantiation()) { return ComputeGenericInstanceHashCode(hashcode, pMT->GetInstantiation().GetNumArgs(), pMT->GetInstantiation(), GetVersionResilientTypeHashCode); } else { return hashcode; } } else if (type.IsArray()) { ArrayTypeDesc *pArray = type.AsArray(); return ComputeArrayTypeHashCode(GetVersionResilientTypeHashCode(pArray->GetArrayElementTypeHandle()), pArray->GetRank()); } else if (type.IsPointer()) { return ComputePointerTypeHashCode(GetVersionResilientTypeHashCode(type.AsTypeDesc()->GetTypeParam())); } else if (type.IsByRef()) { return ComputeByrefTypeHashCode(GetVersionResilientTypeHashCode(type.AsTypeDesc()->GetTypeParam())); } assert(false); return 0; }
void Binder::CheckMscorlib() { const FieldOffsetCheck *pOffsets = MscorlibFieldOffsets; while (pOffsets->fieldID != FIELD__NIL) { FieldDesc *pFD = g_Mscorlib.FetchField(pOffsets->fieldID); DWORD offset = pFD->GetOffset(); if (!pFD->GetMethodTableOfEnclosingClass()->IsValueClass()) offset += sizeof(ObjHeader); _ASSERTE(offset == pOffsets->expectedOffset && "Managed class field offset does not match unmanaged class field offset"); pOffsets++; } const ClassSizeCheck *pSizes = MscorlibClassSizes; while (pSizes->classID != CLASS__NIL) { MethodTable *pMT = g_Mscorlib.FetchClass(pSizes->classID); DWORD size = pMT->GetClass()->GetNumInstanceFieldBytes(); DWORD expected = pSizes->expectedSize - sizeof(void*); _ASSERTE(size == expected && "Managed object size does not match unmanaged object size"); pSizes++; } // check the consistency of BCL and VM // note: it is not enabled by default because of it is time consuming and // changes the bootstrap sequence of the EE if (!g_pConfig->GetConfigDWORD(L"ConsistencyCheck", 0)) return; // // VM referencing BCL (mscorlib.h) // for (BinderClassID cID = (BinderClassID) 1; cID <= g_Mscorlib.m_cClassRIDs; cID = (BinderClassID) (cID + 1)) { if (g_Mscorlib.GetClassName(cID) != NULL) // Allow for CorSigElement entries with no classes g_Mscorlib.FetchClass(cID); } for (BinderMethodID mID = (BinderMethodID) 1; mID <= g_Mscorlib.m_cMethodRIDs; mID = (BinderMethodID) (mID + 1)) g_Mscorlib.FetchMethod(mID); for (BinderFieldID fID = (BinderFieldID) 1; fID <= g_Mscorlib.m_cFieldRIDs; fID = (BinderFieldID) (fID + 1)) g_Mscorlib.FetchField(fID); // // BCL referencing VM (ecall.cpp) // HRESULT hr = S_OK; Module *pModule = g_Mscorlib.m_pModule; IMDInternalImport *pInternalImport = pModule->GetMDImport(); HENUMInternal hEnum; // for all methods... IfFailGo(pInternalImport->EnumAllInit(mdtMethodDef, &hEnum)); for (;;) { mdTypeDef td; mdTypeDef tdClass; DWORD dwImplFlags; if (!pInternalImport->EnumNext(&hEnum, &td)) break; pInternalImport->GetMethodImplProps(td, NULL, &dwImplFlags); // ... that are internal calls ... if (!IsMiInternalCall(dwImplFlags)) continue; IfFailGo(pInternalImport->GetParentToken(td, &tdClass)); NameHandle className(pModule, tdClass); TypeHandle type; type = pModule->GetClassLoader()->LoadTypeHandle(&className, RETURN_ON_ERROR, FALSE); if (type.IsNull()) { LPCUTF8 pszName = pInternalImport->GetNameOfMethodDef(tdClass); OutputDebugStringA(pszName); OutputDebugStringA("\n"); _ASSERTE(false); } MethodDesc *pMD = type.AsMethodTable()->GetClass()->FindMethod(td);; _ASSERTE(pMD); // ... check that the method is in the fcall table. if (GetIDForMethod(pMD) == 0xffff) { LPCUTF8 pszName = pInternalImport->GetNameOfMethodDef(td); OutputDebugStringA(pszName); OutputDebugStringA("\n"); _ASSERTE(false); } } pInternalImport->EnumClose(&hEnum); ErrExit: _ASSERTE(SUCCEEDED(hr)); }
HRESULT STDMETHODCALLTYPE ICorDBPrivHelperImpl::CreateManagedObject( /*in*/ WCHAR *wszAssemblyName, /*in*/ WCHAR *wszModuleName, /*in*/ mdTypeDef classToken, /*in*/ void *rawData, /*out*/ IUnknown **ppUnk) { _ASSERTE(TypeFromToken((mdTypeDef)classToken) == mdtTypeDef); _ASSERTE(wszAssemblyName && wszModuleName && ppUnk); if (!wszAssemblyName || !wszModuleName || classToken == mdTokenNil) return E_INVALIDARG; if (!ppUnk) return E_POINTER; HRESULT hr = S_OK; BEGINCANNOTTHROWCOMPLUSEXCEPTION(); // This will set up a managed thread object if one does not already exist // for this particular thread. Thread* pThread = SetupThread(); if (pThread == NULL) { hr = E_OUTOFMEMORY; goto Exit; } // Start up COM Interop if (FAILED(hr = QuickCOMStartup())) goto Exit; { // Don't want to be interrupted... BOOL fWasGCEnabled = !pThread->PreemptiveGCDisabled(); if (fWasGCEnabled) pThread->DisablePreemptiveGC(); Assembly *pAssembly; Module *pModule; if (GetAppDomain() == NULL) hr = E_INVALIDARG; else { // Try and load the assembly, given the name provided. OBJECTREF pThrowable = NULL; GCPROTECT_BEGIN(pThrowable); hr = AssemblySpec::LoadAssembly(wszAssemblyName, &pAssembly, &pThrowable); GCPROTECT_END(); if (SUCCEEDED(hr)) { _ASSERTE(pAssembly); // Try and load the module, given the name provided. hr = pAssembly->GetModuleFromFilename(wszModuleName, &pModule); if (SUCCEEDED(hr)) { _ASSERTE(pModule); // If the class isn't known,then don't try and create it. if (!pModule->GetMDImport()->IsValidToken(classToken)) hr = E_INVALIDARG; else { COMPLUS_TRY { OBJECTREF obj = NULL; GCPROTECT_BEGIN(obj); // Now try and get the TypeHandle for the given token NameHandle nameHandle(pModule, classToken); TypeHandle typeHandle = pAssembly->LoadTypeHandle(&nameHandle, &obj); // If an exception was thrown at some point, convert // it to an HRESULT if (obj != NULL) hr = SecurityHelper::MapToHR(obj); // No longer need the object, can be GC'd if desired obj = NULL; if (SUCCEEDED(hr)) { _ASSERTE(typeHandle.AsMethodTable()); MethodTable *pMT = typeHandle.AsMethodTable(); if (!pMT->GetClass()->IsValueClass() || pMT->ContainsPointers()) hr = CORDBG_E_OBJECT_IS_NOT_COPYABLE_VALUE_CLASS; if (SUCCEEDED(hr)) { // Now run the class initialiser if (!pMT->CheckRunClassInit(&obj)) hr = SecurityHelper::MapToHR(obj); // No longer need the object, can be GC'd if // desired obj = NULL; if (SUCCEEDED(hr)) { // If successful, allocate an instance of // the class // This may throw an // OutOfMemoryException, but the below // COMPLUS_CATCH should handle it. If // the class is a ValueClass, the // created object will be a boxed // ValueClass. obj = AllocateObject(pMT); // Now create a COM wrapper around // this object. Note that this can // also throw. *ppUnk = GetComIPFromObjectRef(&obj); _ASSERTE(ppUnk); // This is the nasty part. We're gonna // copy the raw data we're given over // the new instance of the value // class... CopyValueClass(obj->UnBox(), rawData, pMT, obj->GetAppDomain()); // No longer need the object, can be GC'd // if desired obj = NULL; } } } GCPROTECT_END(); // obj } COMPLUS_CATCH { // If there's an exception, convert it to an HR hr = SecurityHelper::MapToHR(GETTHROWABLE()); } COMPLUS_END_CATCH } } } } if (fWasGCEnabled) pThread->EnablePreemptiveGC(); } Exit: ENDCANNOTTHROWCOMPLUSEXCEPTION(); return (hr); }