public void GetCallRefMap(MethodDesc method) { TransitionBlock transitionBlock = TransitionBlock.FromTarget(method.Context.Target); bool hasThis = (method.Signature.Flags & MethodSignatureFlags.Static) == 0; bool isVarArg = false; TypeHandle returnType = new TypeHandle(method.Signature.ReturnType); TypeHandle[] parameterTypes = new TypeHandle[method.Signature.Length]; for (int parameterIndex = 0; parameterIndex < parameterTypes.Length; parameterIndex++) { parameterTypes[parameterIndex] = new TypeHandle(method.Signature[parameterIndex]); } CallingConventions callingConventions = (hasThis ? CallingConventions.ManagedInstance : CallingConventions.ManagedStatic); bool hasParamType = method.GetCanonMethodTarget(CanonicalFormKind.Specific).RequiresInstArg(); bool extraFunctionPointerArg = false; bool[] forcedByRefParams = new bool[parameterTypes.Length]; bool skipFirstArg = false; bool extraObjectFirstArg = false; ArgIteratorData argIteratorData = new ArgIteratorData(hasThis, isVarArg, parameterTypes, returnType); ArgIterator argit = new ArgIterator( method.Context, argIteratorData, callingConventions, hasParamType, extraFunctionPointerArg, forcedByRefParams, skipFirstArg, extraObjectFirstArg); if (argit.HasIndeterminateSize()) { // Flush an empty GC ref map block so that the list of methods remains in sync with the list of GC ref map records Flush(); return; } int nStackBytes = argit.SizeOfFrameArgumentArray(); // Allocate a fake stack CORCOMPILE_GCREFMAP_TOKENS[] fakeStack = new CORCOMPILE_GCREFMAP_TOKENS[transitionBlock.SizeOfTransitionBlock + nStackBytes]; // Fill it in FakeGcScanRoots(method, argit, fakeStack); // Encode the ref map uint nStackSlots; if (_factory.Target.Architecture == TargetArchitecture.X86) { uint cbStackPop = argit.CbStackPop(); WriteStackPop(cbStackPop / (uint)_factory.Target.PointerSize); nStackSlots = (uint)(nStackBytes / _factory.Target.PointerSize + _transitionBlock.NumArgumentRegisters); } else { nStackSlots = (uint)((transitionBlock.SizeOfTransitionBlock + nStackBytes - _transitionBlock.OffsetOfFirstGCRefMapSlot) / _factory.Target.PointerSize); } for (uint pos = 0; pos < nStackSlots; pos++) { int ofs; if (_factory.Target.Architecture == TargetArchitecture.X86) { ofs = (int)(pos < _transitionBlock.NumArgumentRegisters ? _transitionBlock.OffsetOfArgumentRegisters + _transitionBlock.SizeOfArgumentRegisters - (pos + 1) * _factory.Target.PointerSize : _transitionBlock.OffsetOfArgs + (pos - _transitionBlock.NumArgumentRegisters) * _factory.Target.PointerSize); } else { ofs = (int)(_transitionBlock.OffsetOfFirstGCRefMapSlot + pos * _factory.Target.PointerSize); } CORCOMPILE_GCREFMAP_TOKENS token = fakeStack[ofs]; if (token != CORCOMPILE_GCREFMAP_TOKENS.GCREFMAP_SKIP) { WriteToken(pos, (byte)token); } } Flush(); }