private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken, CORINFO_METHOD_STRUCT_* callerHandle, CORINFO_CALLINFO_FLAGS flags, ref CORINFO_CALL_INFO pResult) { #if DEBUG // In debug, write some bogus data to the struct to ensure we have filled everything // properly. fixed (CORINFO_CALL_INFO* tmp = &pResult) MemoryHelper.FillMemory((byte*)tmp, 0xcc, Marshal.SizeOf<CORINFO_CALL_INFO>()); #endif MethodDesc method = HandleToObject(pResolvedToken.hMethod); // Spec says that a callvirt lookup ignores static methods. Since static methods // can't have the exact same signature as instance methods, a lookup that found // a static method would have never found an instance method. if (method.Signature.IsStatic && (flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_CALLVIRT) != 0) { throw new BadImageFormatException(); } TypeDesc exactType = HandleToObject(pResolvedToken.hClass); TypeDesc constrainedType = null; if ((flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_CALLVIRT) != 0 && pConstrainedResolvedToken != null) { constrainedType = HandleToObject(pConstrainedResolvedToken->hClass); } bool resolvedConstraint = false; bool forceUseRuntimeLookup = false; MethodDesc methodAfterConstraintResolution = method; if (constrainedType == null) { pResult.thisTransform = CORINFO_THIS_TRANSFORM.CORINFO_NO_THIS_TRANSFORM; } else { // We have a "constrained." call. Try a partial resolve of the constraint call. Note that this // will not necessarily resolve the call exactly, since we might be compiling // shared generic code - it may just resolve it to a candidate suitable for // JIT compilation, and require a runtime lookup for the actual code pointer // to call. MethodDesc directMethod = constrainedType.GetClosestDefType().TryResolveConstraintMethodApprox(exactType, method, out forceUseRuntimeLookup); if (directMethod != null) { // Either // 1. no constraint resolution at compile time (!directMethod) // OR 2. no code sharing lookup in call // OR 3. we have have resolved to an instantiating stub methodAfterConstraintResolution = directMethod; Debug.Assert(!methodAfterConstraintResolution.OwningType.IsInterface); resolvedConstraint = true; pResult.thisTransform = CORINFO_THIS_TRANSFORM.CORINFO_NO_THIS_TRANSFORM; exactType = constrainedType; } else if (constrainedType.IsValueType) { pResult.thisTransform = CORINFO_THIS_TRANSFORM.CORINFO_BOX_THIS; } else { pResult.thisTransform = CORINFO_THIS_TRANSFORM.CORINFO_DEREF_THIS; } } MethodDesc targetMethod = methodAfterConstraintResolution; // TODO: Support Generics if (targetMethod.HasInstantiation) { pResult.contextHandle = contextFromMethod(targetMethod); } else { pResult.contextHandle = contextFromType(targetMethod.OwningType); } pResult._exactContextNeedsRuntimeLookup = 0; // // Determine whether to perform direct call // bool directCall = false; bool resolvedCallVirt = false; if (targetMethod.Signature.IsStatic) { // Static methods are always direct calls directCall = true; } else if (targetMethod.OwningType.IsInterface) { // Force all interface calls to be interpreted as if they are virtual. directCall = false; } else if ((flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_CALLVIRT) == 0 || resolvedConstraint) { directCall = true; } else { if (!targetMethod.IsVirtual || targetMethod.IsFinal || targetMethod.OwningType.IsSealed()) { resolvedCallVirt = true; directCall = true; } } pResult.codePointerOrStubLookup.lookupKind.needsRuntimeLookup = false; if (directCall) { MethodDesc directMethod = targetMethod; if (targetMethod.IsConstructor && targetMethod.OwningType.IsString) { // Calling a string constructor doesn't call the actual constructor. directMethod = targetMethod.GetStringInitializer(); } pResult.kind = CORINFO_CALL_KIND.CORINFO_CALL; pResult.codePointerOrStubLookup.constLookup.accessType = InfoAccessType.IAT_VALUE; pResult.codePointerOrStubLookup.constLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.MethodEntrypoint(directMethod)); pResult.nullInstanceCheck = resolvedCallVirt; } else if ((flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_LDFTN) != 0) { pResult.kind = CORINFO_CALL_KIND.CORINFO_VIRTUALCALL_LDVIRTFTN; pResult.codePointerOrStubLookup.constLookup.accessType = InfoAccessType.IAT_VALUE; pResult.codePointerOrStubLookup.constLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.ResolveVirtualFunction, targetMethod)); // The current CoreRT ReadyToRun helpers do not handle null thisptr - ask the JIT to emit explicit null checks // TODO: Optimize this pResult.nullInstanceCheck = true; } else { // CORINFO_CALL_CODE_POINTER tells the JIT that this is indirect // call that should not be inlined. pResult.kind = CORINFO_CALL_KIND.CORINFO_CALL_CODE_POINTER; pResult.codePointerOrStubLookup.constLookup.accessType = InfoAccessType.IAT_VALUE; var readyToRunHelper = targetMethod.OwningType.IsInterface ? ReadyToRunHelperId.InterfaceDispatch : ReadyToRunHelperId.VirtualCall; pResult.codePointerOrStubLookup.constLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(readyToRunHelper, targetMethod)); // The current CoreRT ReadyToRun helpers do not handle null thisptr - ask the JIT to emit explicit null checks // TODO: Optimize this pResult.nullInstanceCheck = true; } pResult.hMethod = ObjectToHandle(targetMethod); pResult.accessAllowed = CorInfoIsAccessAllowedResult.CORINFO_ACCESS_ALLOWED; // We're pretty much done at this point. Let's grab the rest of the information that the jit is going to // need. pResult.classFlags = getClassAttribsInternal(targetMethod.OwningType); pResult.methodFlags = getMethodAttribsInternal(targetMethod); Get_CORINFO_SIG_INFO(targetMethod.Signature, out pResult.sig); if ((flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_VERIFICATION) != 0) { if (pResult.hMethod != pResolvedToken.hMethod) { pResult.verMethodFlags = getMethodAttribsInternal(targetMethod); Get_CORINFO_SIG_INFO(targetMethod.Signature, out pResult.verSig); } else { pResult.verMethodFlags = pResult.methodFlags; pResult.verSig = pResult.sig; } } // TODO: Generics // pResult.instParamLookup }
private CORINFO_CLASS_STRUCT_* getTokenTypeAsHandle(IntPtr _this, ref CORINFO_RESOLVED_TOKEN pResolvedToken) { WellKnownType result = WellKnownType.RuntimeTypeHandle; if (pResolvedToken.hMethod != null) { result = WellKnownType.RuntimeMethodHandle; } else if (pResolvedToken.hField != null) { result = WellKnownType.RuntimeFieldHandle; } return ObjectToHandle(_compilation.TypeSystemContext.GetWellKnownType(result)); }
private CorInfoHelpFunc getCastingHelper(IntPtr _this, ref CORINFO_RESOLVED_TOKEN pResolvedToken, [MarshalAs(UnmanagedType.I1)]bool fThrowing) { throw new NotImplementedException("getCastingHelper"); }
private void getFieldInfo(IntPtr _this, ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_METHOD_STRUCT_* callerHandle, CORINFO_ACCESS_FLAGS flags, ref CORINFO_FIELD_INFO pResult) { #if DEBUG // In debug, write some bogus data to the struct to ensure we have filled everything // properly. fixed (CORINFO_FIELD_INFO* tmp = &pResult) MemoryHelper.FillMemory((byte*)tmp, 0xcc, Marshal.SizeOf<CORINFO_FIELD_INFO>()); #endif Debug.Assert(((int)flags & ((int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_GET | (int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_SET | (int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_ADDRESS | (int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_INIT_ARRAY)) != 0); var field = HandleToObject(pResolvedToken.hField); CORINFO_FIELD_ACCESSOR fieldAccessor; CORINFO_FIELD_FLAGS fieldFlags = (CORINFO_FIELD_FLAGS)0; if (field.IsStatic) { fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_STATIC; if (field.HasRva) { throw new NotSupportedException("getFieldInfo for RVA mapped field"); } fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER; pResult.helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE; ReadyToRunHelperId helperId; if (field.IsThreadStatic) { helperId = ReadyToRunHelperId.GetThreadStaticBase; } else if (field.HasGCStaticBase) { helperId = ReadyToRunHelperId.GetGCStaticBase; } else { helperId = ReadyToRunHelperId.GetNonGCStaticBase; } pResult.fieldLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(helperId, field.OwningType)); pResult.fieldLookup.accessType = InfoAccessType.IAT_VALUE; } else { fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_INSTANCE; } if (field.IsInitOnly) fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_FINAL; pResult.fieldAccessor = fieldAccessor; pResult.fieldFlags = fieldFlags; pResult.fieldType = getFieldType(_this, pResolvedToken.hField, ref pResult.structType, pResolvedToken.hClass); pResult.accessAllowed = CorInfoIsAccessAllowedResult.CORINFO_ACCESS_ALLOWED; pResult.offset = (uint)field.Offset; // TODO: We need to implement access checks for fields and methods. See JitInterface.cpp in mrtjit // and STS::AccessCheck::CanAccess. }
private void getCallInfo(IntPtr _this, ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken, CORINFO_METHOD_STRUCT_* callerHandle, CORINFO_CALLINFO_FLAGS flags, ref CORINFO_CALL_INFO pResult) { #if DEBUG // In debug, write some bogus data to the struct to ensure we have filled everything // properly. fixed (CORINFO_CALL_INFO* tmp = &pResult) MemoryHelper.FillMemory((byte*)tmp, 0xcc, Marshal.SizeOf<CORINFO_CALL_INFO>()); #endif MethodDesc method = HandleToObject(pResolvedToken.hMethod); // Spec says that a callvirt lookup ignores static methods. Since static methods // can't have the exact same signature as instance methods, a lookup that found // a static method would have never found an instance method. if (method.Signature.IsStatic && (flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_CALLVIRT) != 0) { throw new BadImageFormatException(); } TypeDesc exactType = HandleToObject(pResolvedToken.hClass); TypeDesc constrainedType = null; if ((flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_CALLVIRT) != 0 && pConstrainedResolvedToken != null) { constrainedType = HandleToObject(pConstrainedResolvedToken->hClass); } bool resolvedConstraint = false; bool forceUseRuntimeLookup = false; MethodDesc methodAfterConstraintResolution = method; if (constrainedType == null) { pResult.thisTransform = CORINFO_THIS_TRANSFORM.CORINFO_NO_THIS_TRANSFORM; } else { // We have a "constrained." call. Try a partial resolve of the constraint call. Note that this // will not necessarily resolve the call exactly, since we might be compiling // shared generic code - it may just resolve it to a candidate suitable for // JIT compilation, and require a runtime lookup for the actual code pointer // to call. MethodDesc directMethod = constrainedType.GetClosestMetadataType().TryResolveConstraintMethodApprox(exactType, method, out forceUseRuntimeLookup); if (directMethod != null) { // Either // 1. no constraint resolution at compile time (!directMethod) // OR 2. no code sharing lookup in call // OR 3. we have have resolved to an instantiating stub methodAfterConstraintResolution = directMethod; Debug.Assert(!methodAfterConstraintResolution.OwningType.IsInterface); resolvedConstraint = true; pResult.thisTransform = CORINFO_THIS_TRANSFORM.CORINFO_NO_THIS_TRANSFORM; exactType = constrainedType; } else if (constrainedType.IsValueType) { pResult.thisTransform = CORINFO_THIS_TRANSFORM.CORINFO_BOX_THIS; } else { pResult.thisTransform = CORINFO_THIS_TRANSFORM.CORINFO_DEREF_THIS; } } MethodDesc targetMethod = methodAfterConstraintResolution; // // Determine whether to perform direct call // bool directCall = false; bool resolvedCallVirt = false; if ((flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_LDFTN) != 0) { // Delegate targets are always treated as direct calls here. (It would be nice to clean it up...). directCall = true; } else if (targetMethod.Signature.IsStatic) { // Static methods are always direct calls directCall = true; } else if (targetMethod.OwningType.IsInterface) { // Force all interface calls to be interpreted as if they are virtual. directCall = false; } else if ((flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_CALLVIRT) == 0 || resolvedConstraint) { directCall = true; } else { if (!targetMethod.IsVirtual || targetMethod.IsFinal || targetMethod.OwningType.GetClosestMetadataType().IsSealed) { resolvedCallVirt = true; directCall = true; } } // TODO: Interface methods if (targetMethod.IsVirtual && targetMethod.OwningType.IsInterface) throw new NotImplementedException("Interface method"); pResult.hMethod = ObjectToHandle(targetMethod); pResult.methodFlags = getMethodAttribsInternal(targetMethod); pResult.classFlags = getClassAttribsInternal(targetMethod.OwningType); Get_CORINFO_SIG_INFO(targetMethod.Signature, out pResult.sig); // Get the required verification information in case it is needed by the verifier later if (pResult.hMethod != pResolvedToken.hMethod) { pResult.verMethodFlags = getMethodAttribsInternal(targetMethod); Get_CORINFO_SIG_INFO(targetMethod.Signature, out pResult.verSig); } else { pResult.verMethodFlags = pResult.methodFlags; pResult.verSig = pResult.sig; } pResult.accessAllowed = CorInfoIsAccessAllowedResult.CORINFO_ACCESS_ALLOWED; pResult.kind = CORINFO_CALL_KIND.CORINFO_CALL; pResult._nullInstanceCheck = (uint)(((flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_CALLVIRT) != 0) ? 1 : 0); // TODO: Generics // pResult.contextHandle; // pResult._exactContextNeedsRuntimeLookup // TODO: CORINFO_VIRTUALCALL_STUB // TODO: CORINFO_CALL_CODE_POINTER pResult.codePointerOrStubLookup.constLookup.accessType = InfoAccessType.IAT_VALUE; if (!directCall) { pResult.codePointerOrStubLookup.constLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.VirtualCall, targetMethod)); if ((pResult.methodFlags & (uint)CorInfoFlag.CORINFO_FLG_DELEGATE_INVOKE) != 0) { pResult._nullInstanceCheck = 1; } } else { if (targetMethod.IsConstructor && targetMethod.OwningType.IsString) { // Calling a string constructor doesn't call the actual constructor. targetMethod = IntrinsicMethods.GetStringInitializer(targetMethod); } pResult.codePointerOrStubLookup.constLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.MethodEntrypoint(targetMethod)); pResult.nullInstanceCheck = resolvedCallVirt; } // TODO: Generics // pResult.instParamLookup }
private object GetRuntimeDeterminedObjectForToken(ref CORINFO_RESOLVED_TOKEN pResolvedToken) { // Since RyuJIT operates on canonical types (as opposed to runtime determined ones), but the // dependency analysis operates on runtime determined ones, we convert the resolved token // to the runtime determined form (e.g. Foo<__Canon> becomes Foo<T__Canon>). var methodIL = (MethodIL)HandleToObject((IntPtr)pResolvedToken.tokenScope); if (methodIL.OwningMethod.IsSharedByGenericInstantiations) { MethodIL methodILUninstantiated = methodIL.GetMethodILDefinition(); MethodDesc sharedMethod = methodIL.OwningMethod.GetSharedRuntimeFormMethodTarget(); Instantiation typeInstantiation = sharedMethod.OwningType.Instantiation; Instantiation methodInstantiation = sharedMethod.Instantiation; object resultUninstantiated = methodILUninstantiated.GetObject((int)pResolvedToken.token); if (resultUninstantiated is MethodDesc) { return ((MethodDesc)resultUninstantiated).InstantiateSignature(typeInstantiation, methodInstantiation); } else if (resultUninstantiated is FieldDesc) { return ((FieldDesc)resultUninstantiated).InstantiateSignature(typeInstantiation, methodInstantiation); } else { TypeDesc result = ((TypeDesc)resultUninstantiated).InstantiateSignature(typeInstantiation, methodInstantiation); if (pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Newarr) result = result.MakeArrayType(); return result; } } return null; }
private bool tryResolveToken(ref CORINFO_RESOLVED_TOKEN pResolvedToken) { resolveToken(ref pResolvedToken); return true; }
public virtual void embedGenericHandle_wrapper(IntPtr _this, out IntPtr exception, ref CORINFO_RESOLVED_TOKEN pResolvedToken, [MarshalAs(UnmanagedType.Bool)]bool fEmbedParent, ref CORINFO_GENERICHANDLE_RESULT pResult) { exception = IntPtr.Zero; try { embedGenericHandle(ref pResolvedToken, fEmbedParent, ref pResult); return; } catch (Exception ex) { exception = AllocException(ex); } }
public virtual void getCallInfo_wrapper(IntPtr _this, out IntPtr exception, ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken, CORINFO_METHOD_STRUCT_* callerHandle, CORINFO_CALLINFO_FLAGS flags, ref CORINFO_CALL_INFO pResult) { exception = IntPtr.Zero; try { getCallInfo(ref pResolvedToken, pConstrainedResolvedToken, callerHandle, flags, ref pResult); return; } catch (Exception ex) { exception = AllocException(ex); } }
public virtual void getReadyToRunDelegateCtorHelper_wrapper(IntPtr _this, out IntPtr exception, ref CORINFO_RESOLVED_TOKEN pTargetMethod, CORINFO_CLASS_STRUCT_* delegateType, ref CORINFO_CONST_LOOKUP pLookup) { exception = IntPtr.Zero; try { getReadyToRunDelegateCtorHelper(ref pTargetMethod, delegateType, ref pLookup); return; } catch (Exception ex) { exception = AllocException(ex); } }
public virtual CorInfoIsAccessAllowedResult canAccessClass_wrapper(IntPtr _this, out IntPtr exception, ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_METHOD_STRUCT_* callerHandle, ref CORINFO_HELPER_DESC pAccessHelper) { exception = IntPtr.Zero; try { return canAccessClass(ref pResolvedToken, callerHandle, ref pAccessHelper); } catch (Exception ex) { exception = AllocException(ex); } return (CorInfoIsAccessAllowedResult)0; }
public virtual void getReadyToRunHelper_wrapper(IntPtr _this, out IntPtr exception, ref CORINFO_RESOLVED_TOKEN pResolvedToken, CorInfoHelpFunc id, ref CORINFO_CONST_LOOKUP pLookup) { exception = IntPtr.Zero; try { getReadyToRunHelper(ref pResolvedToken, id, ref pLookup); return; } catch (Exception ex) { exception = AllocException(ex); } }
public virtual CorInfoHelpFunc getCastingHelper_wrapper(IntPtr _this, out IntPtr exception, ref CORINFO_RESOLVED_TOKEN pResolvedToken, [MarshalAs(UnmanagedType.I1)]bool fThrowing) { exception = IntPtr.Zero; try { return getCastingHelper(ref pResolvedToken, fThrowing); } catch (Exception ex) { exception = AllocException(ex); } return (CorInfoHelpFunc)0; }
public virtual CorInfoHelpFunc getNewHelper_wrapper(IntPtr _this, out IntPtr exception, ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_METHOD_STRUCT_* callerHandle) { exception = IntPtr.Zero; try { return getNewHelper(ref pResolvedToken, callerHandle); } catch (Exception ex) { exception = AllocException(ex); } return (CorInfoHelpFunc)0; }
private void embedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken, [MarshalAs(UnmanagedType.Bool)]bool fEmbedParent, ref CORINFO_GENERICHANDLE_RESULT pResult) { #if DEBUG // In debug, write some bogus data to the struct to ensure we have filled everything // properly. fixed (CORINFO_GENERICHANDLE_RESULT* tmp = &pResult) MemoryHelper.FillMemory((byte*)tmp, 0xcc, Marshal.SizeOf<CORINFO_GENERICHANDLE_RESULT>()); #endif bool runtimeLookup; if (!fEmbedParent && pResolvedToken.hMethod != null) { MethodDesc md = HandleToObject(pResolvedToken.hMethod); TypeDesc td = HandleToObject(pResolvedToken.hClass); pResult.handleType = CorInfoGenericHandleType.CORINFO_HANDLETYPE_METHOD; Debug.Assert(md.OwningType == td); runtimeLookup = md.IsSharedByGenericInstantiations; pResult.compileTimeHandle = (CORINFO_GENERIC_STRUCT_*)ObjectToHandle(md); if (!runtimeLookup) { // TODO: LDTOKEN <method>? } else { pResult.lookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunFixupKind.MethodHandle; } } else if (!fEmbedParent && pResolvedToken.hField != null) { FieldDesc fd = HandleToObject(pResolvedToken.hField); TypeDesc td = HandleToObject(pResolvedToken.hClass); pResult.handleType = CorInfoGenericHandleType.CORINFO_HANDLETYPE_FIELD; pResult.compileTimeHandle = (CORINFO_GENERIC_STRUCT_*)pResolvedToken.hField; runtimeLookup = fd.IsStatic && td.IsCanonicalSubtype(CanonicalFormKind.Any); if (!runtimeLookup) { // TODO: Handle should actually point to a dependency node (we don't have one yet) pResult.lookup.constLookup.handle = (CORINFO_GENERIC_STRUCT_*)pResult.compileTimeHandle; } else { pResult.lookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunFixupKind.FieldHandle; } } else { TypeDesc td = HandleToObject(pResolvedToken.hClass); pResult.handleType = CorInfoGenericHandleType.CORINFO_HANDLETYPE_CLASS; pResult.compileTimeHandle = (CORINFO_GENERIC_STRUCT_*)pResolvedToken.hClass; runtimeLookup = td.IsCanonicalSubtype(CanonicalFormKind.Any); if (!runtimeLookup) { if (pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_NewObj) pResult.lookup.constLookup.handle = (CORINFO_GENERIC_STRUCT_*)ObjectToHandle(_compilation.NodeFactory.ConstructedTypeSymbol(td)); else pResult.lookup.constLookup.handle = (CORINFO_GENERIC_STRUCT_*)ObjectToHandle(_compilation.NodeFactory.NecessaryTypeSymbol(td)); } else { pResult.lookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunFixupKind.TypeHandle; } } Debug.Assert(pResult.compileTimeHandle != null); if (runtimeLookup) { pResult.lookup.lookupKind.needsRuntimeLookup = true; pResult.lookup.runtimeLookup.signature = null; pResult.lookup.runtimeLookup.indirections = CORINFO.USEHELPER; MethodDesc contextMethod = methodFromContext(pResolvedToken.tokenContext); // Do not bother computing the runtime lookup if we are inlining. The JIT is going // to abort the inlining attempt anyway. if (contextMethod != MethodBeingCompiled) return; pResult.lookup.lookupKind.runtimeLookupKind = GetGenericRuntimeLookupKind(contextMethod); } else { // If the target is not shared then we've already got our result and // can simply do a static look up pResult.lookup.lookupKind.needsRuntimeLookup = false; pResult.lookup.constLookup.accessType = InfoAccessType.IAT_VALUE; } }
public virtual void resolveToken_wrapper(IntPtr _this, out IntPtr exception, ref CORINFO_RESOLVED_TOKEN pResolvedToken) { exception = IntPtr.Zero; try { resolveToken(ref pResolvedToken); return; } catch (Exception ex) { exception = AllocException(ex); } }
private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken, CORINFO_METHOD_STRUCT_* callerHandle, CORINFO_CALLINFO_FLAGS flags, ref CORINFO_CALL_INFO pResult) { #if DEBUG // In debug, write some bogus data to the struct to ensure we have filled everything // properly. fixed (CORINFO_CALL_INFO* tmp = &pResult) MemoryHelper.FillMemory((byte*)tmp, 0xcc, Marshal.SizeOf<CORINFO_CALL_INFO>()); #endif MethodDesc method = HandleToObject(pResolvedToken.hMethod); // Spec says that a callvirt lookup ignores static methods. Since static methods // can't have the exact same signature as instance methods, a lookup that found // a static method would have never found an instance method. if (method.Signature.IsStatic && (flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_CALLVIRT) != 0) { throw new BadImageFormatException(); } TypeDesc exactType = HandleToObject(pResolvedToken.hClass); TypeDesc constrainedType = null; if ((flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_CALLVIRT) != 0 && pConstrainedResolvedToken != null) { constrainedType = HandleToObject(pConstrainedResolvedToken->hClass); } bool resolvedConstraint = false; bool forceUseRuntimeLookup = false; MethodDesc methodAfterConstraintResolution = method; if (constrainedType == null) { pResult.thisTransform = CORINFO_THIS_TRANSFORM.CORINFO_NO_THIS_TRANSFORM; } else { // We have a "constrained." call. Try a partial resolve of the constraint call. Note that this // will not necessarily resolve the call exactly, since we might be compiling // shared generic code - it may just resolve it to a candidate suitable for // JIT compilation, and require a runtime lookup for the actual code pointer // to call. MethodDesc directMethod = constrainedType.GetClosestDefType().TryResolveConstraintMethodApprox(exactType, method, out forceUseRuntimeLookup); if (directMethod != null) { // Either // 1. no constraint resolution at compile time (!directMethod) // OR 2. no code sharing lookup in call // OR 3. we have have resolved to an instantiating stub methodAfterConstraintResolution = directMethod; Debug.Assert(!methodAfterConstraintResolution.OwningType.IsInterface); resolvedConstraint = true; pResult.thisTransform = CORINFO_THIS_TRANSFORM.CORINFO_NO_THIS_TRANSFORM; exactType = constrainedType; } else if (constrainedType.IsValueType) { pResult.thisTransform = CORINFO_THIS_TRANSFORM.CORINFO_BOX_THIS; } else { pResult.thisTransform = CORINFO_THIS_TRANSFORM.CORINFO_DEREF_THIS; } } MethodDesc targetMethod = methodAfterConstraintResolution; // // Initialize callee context used for inlining and instantiation arguments // if (targetMethod.HasInstantiation) { pResult.contextHandle = contextFromMethod(targetMethod); pResult.exactContextNeedsRuntimeLookup = targetMethod.IsSharedByGenericInstantiations; } else { pResult.contextHandle = contextFromType(exactType); pResult.exactContextNeedsRuntimeLookup = exactType.IsCanonicalSubtype(CanonicalFormKind.Any); } // // Determine whether to perform direct call // bool directCall = false; bool resolvedCallVirt = false; if (targetMethod.Signature.IsStatic) { // Static methods are always direct calls directCall = true; } else if (targetMethod.OwningType.IsInterface) { // Force all interface calls to be interpreted as if they are virtual. directCall = false; } else if ((flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_CALLVIRT) == 0 || resolvedConstraint) { directCall = true; } else { if (!targetMethod.IsVirtual || targetMethod.IsFinal || targetMethod.OwningType.IsSealed()) { resolvedCallVirt = true; directCall = true; } } pResult.codePointerOrStubLookup.lookupKind.needsRuntimeLookup = false; if (directCall) { bool allowInstParam = (flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_ALLOWINSTPARAM) != 0; Debug.Assert(allowInstParam || !targetMethod.RequiresInstArg(), "Need an instantiating stub"); MethodDesc concreteMethod = targetMethod; targetMethod = targetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); MethodDesc directMethod = targetMethod; if (targetMethod.IsConstructor && targetMethod.OwningType.IsString) { // Calling a string constructor doesn't call the actual constructor. directMethod = targetMethod.GetStringInitializer(); concreteMethod = directMethod; } pResult.kind = CORINFO_CALL_KIND.CORINFO_CALL; pResult.codePointerOrStubLookup.constLookup.accessType = InfoAccessType.IAT_VALUE; if (pResult.exactContextNeedsRuntimeLookup) { // Nothing to do... The generic handle lookup gets embedded in to the codegen // during the jitting of the call. // (Note: The generic lookup in R2R is performed by a call to a helper at runtime, not by // codegen emitted at crossgen time) MethodDesc contextMethod = methodFromContext(pResolvedToken.tokenContext); // Do not bother capturing the runtime determined context if we're inlining. The JIT is going // to abort the inlining attempt if the inlinee does any generic lookups. bool inlining = contextMethod != MethodBeingCompiled; if (directMethod.IsSharedByGenericInstantiations && !inlining) { MethodDesc runtimeDeterminedMethod = (MethodDesc)GetRuntimeDeterminedObjectForToken(ref pResolvedToken); pResult.codePointerOrStubLookup.constLookup.addr = (void*)ObjectToHandle( _compilation.NodeFactory.RuntimeDeterminedMethod(runtimeDeterminedMethod)); } else { pResult.codePointerOrStubLookup.constLookup.addr = (void*)ObjectToHandle( _compilation.NodeFactory.MethodEntrypoint(directMethod)); } } else { ISymbolNode genericDictionary = null; if (targetMethod.RequiresInstMethodDescArg()) { genericDictionary = _compilation.NodeFactory.MethodGenericDictionary(concreteMethod); } else if (targetMethod.RequiresInstMethodTableArg()) { genericDictionary = _compilation.NodeFactory.TypeGenericDictionary(concreteMethod.OwningType); } if (genericDictionary != null) { pResult.instParamLookup.accessType = InfoAccessType.IAT_VALUE; pResult.instParamLookup.addr = (void*)ObjectToHandle(genericDictionary); pResult.codePointerOrStubLookup.constLookup.addr = (void*)ObjectToHandle( _compilation.NodeFactory.ShadowConcreteMethod(concreteMethod)); } else if (targetMethod.AcquiresInstMethodTableFromThis()) { pResult.codePointerOrStubLookup.constLookup.addr = (void*)ObjectToHandle( _compilation.NodeFactory.ShadowConcreteMethod(concreteMethod)); } else { pResult.codePointerOrStubLookup.constLookup.addr = (void*)ObjectToHandle( _compilation.NodeFactory.MethodEntrypoint(directMethod)); } } pResult.nullInstanceCheck = resolvedCallVirt; } else if ((flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_LDFTN) != 0) { pResult.kind = CORINFO_CALL_KIND.CORINFO_VIRTUALCALL_LDVIRTFTN; pResult.codePointerOrStubLookup.constLookup.accessType = InfoAccessType.IAT_VALUE; pResult.codePointerOrStubLookup.constLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.ResolveVirtualFunction, targetMethod)); // The current CoreRT ReadyToRun helpers do not handle null thisptr - ask the JIT to emit explicit null checks // TODO: Optimize this pResult.nullInstanceCheck = true; } else { // CORINFO_CALL_CODE_POINTER tells the JIT that this is indirect // call that should not be inlined. pResult.kind = CORINFO_CALL_KIND.CORINFO_CALL_CODE_POINTER; if (pResult.exactContextNeedsRuntimeLookup) { pResult.codePointerOrStubLookup.lookupKind.needsRuntimeLookup = true; pResult.codePointerOrStubLookup.lookupKind.runtimeLookupFlags = 0; pResult.codePointerOrStubLookup.runtimeLookup.indirections = CORINFO.USEHELPER; // Do not bother computing the runtime lookup if we are inlining. The JIT is going // to abort the inlining attempt anyway. MethodDesc contextMethod = methodFromContext(pResolvedToken.tokenContext); if (contextMethod != MethodBeingCompiled) { return; } pResult.codePointerOrStubLookup.lookupKind.runtimeLookupKind = GetGenericRuntimeLookupKind(contextMethod); pResult.codePointerOrStubLookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunFixupKind.VirtualEntry; } else { pResult.codePointerOrStubLookup.constLookup.accessType = InfoAccessType.IAT_VALUE; pResult.codePointerOrStubLookup.constLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.VirtualCall, targetMethod)); } // The current CoreRT ReadyToRun helpers do not handle null thisptr - ask the JIT to emit explicit null checks // TODO: Optimize this pResult.nullInstanceCheck = true; } pResult.hMethod = ObjectToHandle(targetMethod); pResult.accessAllowed = CorInfoIsAccessAllowedResult.CORINFO_ACCESS_ALLOWED; // We're pretty much done at this point. Let's grab the rest of the information that the jit is going to // need. pResult.classFlags = getClassAttribsInternal(targetMethod.OwningType); pResult.methodFlags = getMethodAttribsInternal(targetMethod); Get_CORINFO_SIG_INFO(targetMethod, out pResult.sig); if ((flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_VERIFICATION) != 0) { if (pResult.hMethod != pResolvedToken.hMethod) { pResult.verMethodFlags = getMethodAttribsInternal(targetMethod); Get_CORINFO_SIG_INFO(targetMethod, out pResult.verSig); } else { pResult.verMethodFlags = pResult.methodFlags; pResult.verSig = pResult.sig; } } pResult._secureDelegateInvoke = 0; }
public virtual CORINFO_CLASS_STRUCT_* getTokenTypeAsHandle_wrapper(IntPtr _this, out IntPtr exception, ref CORINFO_RESOLVED_TOKEN pResolvedToken) { exception = IntPtr.Zero; try { return getTokenTypeAsHandle(ref pResolvedToken); } catch (Exception ex) { exception = AllocException(ex); } return (CORINFO_CLASS_STRUCT_*)0; }
private void resolveToken(ref CORINFO_RESOLVED_TOKEN pResolvedToken) { var methodIL = (MethodIL)HandleToObject((IntPtr)pResolvedToken.tokenScope); var result = methodIL.GetObject((int)pResolvedToken.token); pResolvedToken.hClass = null; pResolvedToken.hMethod = null; pResolvedToken.hField = null; if (result is MethodDesc) { MethodDesc method = result as MethodDesc; pResolvedToken.hMethod = ObjectToHandle(method); pResolvedToken.hClass = ObjectToHandle(method.OwningType); } else if (result is FieldDesc) { FieldDesc field = result as FieldDesc; // References to literal fields from IL body should never resolve. // The CLR would throw a MissingFieldException while jitting and so should we. if (field.IsLiteral) throw new TypeSystemException.MissingFieldException(field.OwningType, field.Name); pResolvedToken.hField = ObjectToHandle(field); pResolvedToken.hClass = ObjectToHandle(field.OwningType); } else { TypeDesc type = (TypeDesc)result; if (pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Newarr) type = type.MakeArrayType(); pResolvedToken.hClass = ObjectToHandle(type); } pResolvedToken.pTypeSpec = null; pResolvedToken.cbTypeSpec = 0; pResolvedToken.pMethodSpec = null; pResolvedToken.cbMethodSpec = 0; }
private CorInfoHelpFunc getNewHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_METHOD_STRUCT_* callerHandle) { return CorInfoHelpFunc.CORINFO_HELP_NEWFAST; }
private CorInfoIsAccessAllowedResult canAccessClass(IntPtr _this, ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_METHOD_STRUCT_* callerHandle, ref CORINFO_HELPER_DESC pAccessHelper) { // TODO: Access check return CorInfoIsAccessAllowedResult.CORINFO_ACCESS_ALLOWED; }
private CorInfoHelpFunc getCastingHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, [MarshalAs(UnmanagedType.I1)]bool fThrowing) { // TODO: optimized helpers return fThrowing ? CorInfoHelpFunc.CORINFO_HELP_CHKCASTANY : CorInfoHelpFunc.CORINFO_HELP_ISINSTANCEOFANY; }
private void embedGenericHandle(IntPtr _this, ref CORINFO_RESOLVED_TOKEN pResolvedToken, [MarshalAs(UnmanagedType.Bool)]bool fEmbedParent, ref CORINFO_GENERICHANDLE_RESULT pResult) { #if DEBUG // In debug, write some bogus data to the struct to ensure we have filled everything // properly. fixed (CORINFO_GENERICHANDLE_RESULT* tmp = &pResult) MemoryHelper.FillMemory((byte*)tmp, 0xcc, Marshal.SizeOf<CORINFO_GENERICHANDLE_RESULT>()); #endif if (!fEmbedParent && pResolvedToken.hMethod != null) { throw new NotImplementedException("embedGenericHandle"); } else if (!fEmbedParent && pResolvedToken.hField != null) { pResult.handleType = CorInfoGenericHandleType.CORINFO_HANDLETYPE_FIELD; pResult.compileTimeHandle = (CORINFO_GENERIC_STRUCT_*)pResolvedToken.hField; // fRuntimeLookup = th.IsSharedByGenericInstantiations() && pFD->IsStatic(); } else { TypeDesc td = HandleToObject(pResolvedToken.hClass); pResult.handleType = CorInfoGenericHandleType.CORINFO_HANDLETYPE_CLASS; pResult.compileTimeHandle = (CORINFO_GENERIC_STRUCT_*)pResolvedToken.hClass; // TODO? If we're embedding a method handle for a method that points to a sub-class of the actual // class, we might need to embed the actual declaring type in compileTimeHandle. // IsSharedByGenericInstantiations would not work here. The runtime lookup is required // even for standalone generic variables that show up as __Canon here. //fRuntimeLookup = th.IsCanonicalSubtype(); } Debug.Assert(pResult.compileTimeHandle != null); // TODO: shared generics //if (...) //{ // ... //} // else { // If the target is not shared then we've already got our result and // can simply do a static look up pResult.lookup.lookupKind.needsRuntimeLookup = false; pResult.lookup.constLookup.handle = (CORINFO_GENERIC_STRUCT_*)pResult.compileTimeHandle; pResult.lookup.constLookup.accessType = InfoAccessType.IAT_VALUE; } }
private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_LOOKUP_KIND pGenericLookupKind, CorInfoHelpFunc id, ref CORINFO_CONST_LOOKUP pLookup) { pLookup.accessType = InfoAccessType.IAT_VALUE; switch (id) { case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_NEW: { var type = HandleToObject(pResolvedToken.hClass); Debug.Assert(type.IsDefType); if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) return false; pLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewHelper, type)); } break; case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_NEWARR_1: { var type = HandleToObject(pResolvedToken.hClass); Debug.Assert(type.IsSzArray); if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) return false; pLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewArr1, type)); } break; case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_ISINSTANCEOF: { var type = HandleToObject(pResolvedToken.hClass); if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) return false; pLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.IsInstanceOf, type)); } break; case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_CHKCAST: { var type = HandleToObject(pResolvedToken.hClass); if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) return false; pLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.CastClass, type)); } break; case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE: { var type = HandleToObject(pResolvedToken.hClass); if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) return false; pLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.GetNonGCStaticBase, type)); } break; case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_GENERIC_HANDLE: { Debug.Assert(pGenericLookupKind.needsRuntimeLookup); ReadyToRunFixupKind fixupKind = (ReadyToRunFixupKind)pGenericLookupKind.runtimeLookupFlags; object fixupTarget = GetRuntimeDeterminedObjectForToken(ref pResolvedToken); GenericLookupResult target = GetTargetForFixup(fixupTarget, fixupKind); ReadyToRunHelperId helper; TypeSystemEntity dictionaryOwner; if (pGenericLookupKind.runtimeLookupKind == CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_THISOBJ) { helper = ReadyToRunHelperId.GenericLookupFromThis; dictionaryOwner = MethodBeingCompiled.OwningType; } else if (pGenericLookupKind.runtimeLookupKind == CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_CLASSPARAM) { helper = ReadyToRunHelperId.GenericLookupFromDictionary; dictionaryOwner = MethodBeingCompiled.OwningType; } else { Debug.Assert(pGenericLookupKind.runtimeLookupKind == CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_METHODPARAM); helper = ReadyToRunHelperId.GenericLookupFromDictionary; dictionaryOwner = MethodBeingCompiled; } GenericLookupDescriptor lookup = new GenericLookupDescriptor(dictionaryOwner, target); pLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(helper, lookup)); } break; default: throw new NotImplementedException("ReadyToRun: " + id.ToString()); } return true; }
private void resolveToken(IntPtr _this, ref CORINFO_RESOLVED_TOKEN pResolvedToken) { var methodIL = (MethodIL)HandleToObject((IntPtr)pResolvedToken.tokenScope); var result = methodIL.GetObject((int)pResolvedToken.token); pResolvedToken.hClass = null; pResolvedToken.hMethod = null; pResolvedToken.hField = null; if (result is MethodDesc) { MethodDesc method = result as MethodDesc; pResolvedToken.hMethod = ObjectToHandle(method); pResolvedToken.hClass = ObjectToHandle(method.OwningType); } else if (result is FieldDesc) { FieldDesc field = result as FieldDesc; pResolvedToken.hField = ObjectToHandle(field); pResolvedToken.hClass = ObjectToHandle(field.OwningType); } else { TypeDesc type = (TypeDesc)result; if (pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Newarr) type = type.MakeArrayType(); pResolvedToken.hClass = ObjectToHandle(type); } pResolvedToken.pTypeSpec = null; pResolvedToken.cbTypeSpec = 0; pResolvedToken.pMethodSpec = null; pResolvedToken.cbMethodSpec = 0; }
private void getReadyToRunDelegateCtorHelper(ref CORINFO_RESOLVED_TOKEN pTargetMethod, CORINFO_CLASS_STRUCT_* delegateType, ref CORINFO_CONST_LOOKUP pLookup) { MethodDesc method = HandleToObject(pTargetMethod.hMethod); TypeDesc type = HandleToObject(delegateType); DelegateCreationInfo delegateInfo = _compilation.GetDelegateCtor(type, method); pLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.DelegateCtor, delegateInfo)); pLookup.accessType = InfoAccessType.IAT_VALUE; }
private CorInfoHelpFunc getNewHelper(IntPtr _this, ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_METHOD_STRUCT_* callerHandle) { throw new NotImplementedException("getNewHelper"); }
private void getFieldInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_METHOD_STRUCT_* callerHandle, CORINFO_ACCESS_FLAGS flags, ref CORINFO_FIELD_INFO pResult) { #if DEBUG // In debug, write some bogus data to the struct to ensure we have filled everything // properly. fixed (CORINFO_FIELD_INFO* tmp = &pResult) MemoryHelper.FillMemory((byte*)tmp, 0xcc, Marshal.SizeOf<CORINFO_FIELD_INFO>()); #endif Debug.Assert(((int)flags & ((int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_GET | (int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_SET | (int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_ADDRESS | (int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_INIT_ARRAY)) != 0); var field = HandleToObject(pResolvedToken.hField); CORINFO_FIELD_ACCESSOR fieldAccessor; CORINFO_FIELD_FLAGS fieldFlags = (CORINFO_FIELD_FLAGS)0; if (field.IsStatic) { fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_STATIC; if (field.HasRva) { fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_UNMANAGED; // TODO: Handle the case when the RVA is in the TLS range fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_RVA_ADDRESS; // We are not going through a helper. The constructor has to be triggered explicitly. if (_compilation.HasLazyStaticConstructor(field.OwningType)) { fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_INITCLASS; } } else { fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER; pResult.helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE; ReadyToRunHelperId helperId = ReadyToRunHelperId.Invalid; if (field.IsThreadStatic) { helperId = ReadyToRunHelperId.GetThreadStaticBase; } else if (field.HasGCStaticBase) { helperId = ReadyToRunHelperId.GetGCStaticBase; } else { var owningType = field.OwningType; if ((owningType.IsWellKnownType(WellKnownType.IntPtr) || owningType.IsWellKnownType(WellKnownType.UIntPtr)) && field.Name == "Zero") { fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_INTRINSIC_ZERO; } else { helperId = ReadyToRunHelperId.GetNonGCStaticBase; } } if (helperId != ReadyToRunHelperId.Invalid) { pResult.fieldLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(helperId, field.OwningType)); pResult.fieldLookup.accessType = InfoAccessType.IAT_VALUE; } } } else { fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_INSTANCE; } if (field.IsInitOnly) fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_FINAL; pResult.fieldAccessor = fieldAccessor; pResult.fieldFlags = fieldFlags; pResult.fieldType = getFieldType(pResolvedToken.hField, ref pResult.structType, pResolvedToken.hClass); pResult.accessAllowed = CorInfoIsAccessAllowedResult.CORINFO_ACCESS_ALLOWED; if (!field.IsStatic || !field.HasRva) pResult.offset = (uint)field.Offset; else pResult.offset = 0xBAADF00D; // TODO: We need to implement access checks for fields and methods. See JitInterface.cpp in mrtjit // and STS::AccessCheck::CanAccess. }
private void getReadyToRunHelper(IntPtr _this, ref CORINFO_RESOLVED_TOKEN pResolvedToken, CorInfoHelpFunc id, ref CORINFO_CONST_LOOKUP pLookup) { pLookup.accessType = InfoAccessType.IAT_VALUE; switch (id) { case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_NEW: { var type = HandleToObject(pResolvedToken.hClass); Debug.Assert(type is DefType); pLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewHelper, type)); } break; case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_NEWARR_1: { var type = HandleToObject(pResolvedToken.hClass); Debug.Assert(type.IsSzArray); pLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewArr1, type)); } break; case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_ISINSTANCEOF: { var type = HandleToObject(pResolvedToken.hClass); pLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.IsInstanceOf, type)); } break; case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_CHKCAST: { var type = HandleToObject(pResolvedToken.hClass); pLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.CastClass, type)); } break; case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE: { var type = HandleToObject(pResolvedToken.hClass); pLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.GetNonGCStaticBase, type)); } break; case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_DELEGATE_CTOR: { var method = HandleToObject(pResolvedToken.hMethod); DelegateInfo delegateInfo = _compilation.GetDelegateCtor(method); pLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.DelegateCtor, delegateInfo)); } break; default: throw new NotImplementedException("ReadyToRun: " + id.ToString()); } }
private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_LOOKUP_KIND pGenericLookupKind, CorInfoHelpFunc id, ref CORINFO_CONST_LOOKUP pLookup) { pLookup.accessType = InfoAccessType.IAT_VALUE; switch (id) { case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_NEW: { var type = HandleToObject(pResolvedToken.hClass); Debug.Assert(type.IsDefType); pLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewHelper, type)); } break; case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_NEWARR_1: { var type = HandleToObject(pResolvedToken.hClass); Debug.Assert(type.IsSzArray); pLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewArr1, type)); } break; case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_ISINSTANCEOF: { var type = HandleToObject(pResolvedToken.hClass); pLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.IsInstanceOf, type)); } break; case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_CHKCAST: { var type = HandleToObject(pResolvedToken.hClass); pLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.CastClass, type)); } break; case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE: { var type = HandleToObject(pResolvedToken.hClass); pLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.GetNonGCStaticBase, type)); } break; default: throw new NotImplementedException("ReadyToRun: " + id.ToString()); } return true; }