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(); }
TypeHandle Binder::LookupType(BinderTypeID id, BOOL fLoad) { _ASSERTE(m_pModule != NULL); _ASSERTE(id != TYPE__NIL); _ASSERTE(id <= m_cTypeHandles); THROWSCOMPLUSEXCEPTION(); TypeHandle th; const TypeDescription *d = m_typeDescriptions + id - 1; OBJECTREF pThrowable = NULL; GCPROTECT_BEGIN(pThrowable); NameHandle nh(d->type, TypeHandle(GetClass(d->classID)), d->rank); if (!fLoad) nh.SetTokenNotToLoad(tdAllTypes); th = m_pModule->GetClassLoader()->FindTypeHandle(&nh, &pThrowable); GCPROTECT_END(); if (th.IsNull()) { if (fLoad) COMPlusThrow(pThrowable); return TypeHandle(); } m_pTypeHandles[id-1] = th; return th; }
void QCALLTYPE COMDynamicWrite::TermCreateClass(QCall::ModuleHandle pModule, INT32 tk, QCall::ObjectHandleOnStack retType) { QCALL_CONTRACT; TypeHandle typeHnd; BEGIN_QCALL; _ASSERTE(pModule->GetReflectionModule()->GetClassWriter()); // Use the same service, regardless of whether we are generating a normal // class, or the special class for the module that holds global functions // & methods. pModule->GetReflectionModule()->AddClass(tk); // manually load the class if it is not the global type if (!IsNilToken(tk)) { TypeKey typeKey(pModule, tk); typeHnd = pModule->GetClassLoader()->LoadTypeHandleForTypeKey(&typeKey, TypeHandle()); } if (!typeHnd.IsNull()) { GCX_COOP(); retType.Set(typeHnd.GetManagedClassObject()); } END_QCALL; return; }
// 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_ }
TypeHandle Binder::RawGetType(BinderTypeID id) { CANNOTTHROWCOMPLUSEXCEPTION(); _ASSERTE(m_pModule != NULL); _ASSERTE(id != TYPE__NIL); _ASSERTE(id <= m_cTypeHandles); TypeHandle th = m_pTypeHandles[id-1]; _ASSERTE(!th.IsNull()); return th; }
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(); }
TypeHandle Binder::FetchType(BinderTypeID id) { THROWSCOMPLUSEXCEPTION(); _ASSERTE(id != TYPE__NIL); _ASSERTE(id <= m_cTypeHandles); TypeHandle th = m_pTypeHandles[id-1]; if (th.IsNull()) th = LookupType(id); return th; }
void ClassType::AddNestedType(const TypeHandle& nestedType) { if (nestedType.GetId() != 0) { nestedTypes_.push_back(nestedType); } }
NameHandle(DWORD kind, TypeHandle elemType, DWORD rank = 0) : Key1(kind | rank << 16), Key2((INT_PTR) elemType.AsPtr()), m_pTypeScope(NULL), m_mdType(mdTokenNil), m_mdTokenNotToLoad(tdNoTypes), m_WhichTable(nhConstructed), m_fDontRestore(FALSE), m_pBucket(NULL) {}
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)); }
CustomMarshalerInfo::CustomMarshalerInfo(BaseDomain *pDomain, TypeHandle hndCustomMarshalerType, TypeHandle hndManagedType, LPCUTF8 strCookie, DWORD cCookieStrBytes) : m_NativeSize(0) , m_hndManagedType(hndManagedType) , m_hndCustomMarshaler(NULL) , m_pMarshalNativeToManagedMD(NULL) , m_pMarshalManagedToNativeMD(NULL) , m_pCleanUpNativeDataMD(NULL) , m_pCleanUpManagedDataMD(NULL) , m_bDataIsByValue(FALSE) { CONTRACTL { THROWS; GC_TRIGGERS; MODE_COOPERATIVE; PRECONDITION(CheckPointer(pDomain)); } CONTRACTL_END; // Make sure the custom marshaller implements ICustomMarshaler. if (!hndCustomMarshalerType.GetMethodTable()->CanCastToNonVariantInterface(MscorlibBinder::GetClass(CLASS__ICUSTOM_MARSHALER))) { DefineFullyQualifiedNameForClassW() COMPlusThrow(kApplicationException, IDS_EE_ICUSTOMMARSHALERNOTIMPL, GetFullyQualifiedNameForClassW(hndCustomMarshalerType.GetMethodTable())); } // Determine if this type is a value class. m_bDataIsByValue = m_hndManagedType.GetMethodTable()->IsValueType(); // Custom marshalling of value classes is not currently supported. if (m_bDataIsByValue) COMPlusThrow(kNotSupportedException, W("NotSupported_ValueClassCM")); #ifndef CROSSGEN_COMPILE // Run the <clinit> on the marshaler since it might not have run yet. hndCustomMarshalerType.GetMethodTable()->EnsureInstanceActive(); hndCustomMarshalerType.GetMethodTable()->CheckRunClassInitThrowing(); // Create a COM+ string that will contain the string cookie. STRINGREF CookieStringObj = StringObject::NewString(strCookie, cCookieStrBytes); GCPROTECT_BEGIN(CookieStringObj); #endif // Load the method desc's for all the methods in the ICustomMarshaler interface. m_pMarshalNativeToManagedMD = GetCustomMarshalerMD(CustomMarshalerMethods_MarshalNativeToManaged, hndCustomMarshalerType); m_pMarshalManagedToNativeMD = GetCustomMarshalerMD(CustomMarshalerMethods_MarshalManagedToNative, hndCustomMarshalerType); m_pCleanUpNativeDataMD = GetCustomMarshalerMD(CustomMarshalerMethods_CleanUpNativeData, hndCustomMarshalerType); m_pCleanUpManagedDataMD = GetCustomMarshalerMD(CustomMarshalerMethods_CleanUpManagedData, hndCustomMarshalerType); // Load the method desc for the static method to retrieve the instance. MethodDesc *pGetCustomMarshalerMD = GetCustomMarshalerMD(CustomMarshalerMethods_GetInstance, hndCustomMarshalerType); // If the GetInstance method is generic, get an instantiating stub for it - // the CallDescr infrastructure doesn't know how to pass secret generic arguments. if (pGetCustomMarshalerMD->RequiresInstMethodTableArg()) { pGetCustomMarshalerMD = MethodDesc::FindOrCreateAssociatedMethodDesc( pGetCustomMarshalerMD, hndCustomMarshalerType.GetMethodTable(), FALSE, // forceBoxedEntryPoint Instantiation(), // methodInst FALSE, // allowInstParam FALSE); // forceRemotableMethod _ASSERTE(!pGetCustomMarshalerMD->RequiresInstMethodTableArg()); } #ifndef CROSSGEN_COMPILE MethodDescCallSite getCustomMarshaler(pGetCustomMarshalerMD, (OBJECTREF*)&CookieStringObj); pGetCustomMarshalerMD->EnsureActive(); // Prepare the arguments that will be passed to GetCustomMarshaler. ARG_SLOT GetCustomMarshalerArgs[] = { ObjToArgSlot(CookieStringObj) }; // Call the GetCustomMarshaler method to retrieve the custom marshaler to use. OBJECTREF CustomMarshalerObj = getCustomMarshaler.Call_RetOBJECTREF(GetCustomMarshalerArgs); if (!CustomMarshalerObj) { DefineFullyQualifiedNameForClassW() COMPlusThrow(kApplicationException, IDS_EE_NOCUSTOMMARSHALER, GetFullyQualifiedNameForClassW(hndCustomMarshalerType.GetMethodTable())); } m_hndCustomMarshaler = pDomain->CreateHandle(CustomMarshalerObj); // Retrieve the size of the native data. if (m_bDataIsByValue) { // <TODO>@TODO(DM): Call GetNativeDataSize() to retrieve the size of the native data.</TODO> _ASSERTE(!"Value classes are not yet supported by the custom marshaler!"); } else { m_NativeSize = sizeof(void *); } GCPROTECT_END(); #endif }
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); }
ETPureFunctionHint Eldritch2::Utf8Literal NameFromTypeHandle( TypeHandle typeHandle ) { const auto strippedName( FindLastInstance( typeHandle.GetName(), "::" ) ); return Utf8Literal( strippedName ? strippedName + 2 : typeHandle.GetName() ); }