From 8ae8594b4f0730b7ba1b8a3a7d46069cfbbe5d7c Mon Sep 17 00:00:00 2001 From: Steve Date: Tue, 11 Feb 2025 17:48:15 +0900 Subject: [PATCH 01/20] NativeAOT: Cover more opcodes in type preinitializer (#112073) --- .../Compiler/TypePreinit.cs | 57 +++- .../Preinitialization/Preinitialization.cs | 291 ++++++++++++++++-- 2 files changed, 324 insertions(+), 24 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs index a5851aba72f2fe..8a437f66bce9c7 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs @@ -835,6 +835,8 @@ private Status TryScanMethod(MethodIL methodIL, Value[] parameters, Stack -42; + private static long GetLong() => -42; + private static float GetFloat() => -42; + private static double GetDouble() => -42; + private static nint GetNativeInt() => -42; + + class IntConversions + { + internal static byte s_byte; + internal static sbyte s_sbyte; + internal static short s_short; + internal static ushort s_ushort; + internal static uint s_uint; + internal static long s_long; + internal static ulong s_ulong; + internal static float s_float; + internal static double s_double; + internal static nint s_nint; + internal static nuint s_nuint; + + static IntConversions() + { + s_byte = unchecked((byte)GetInt()); + s_sbyte = unchecked((sbyte)GetInt()); + s_short = unchecked((short)GetInt()); + s_ushort = unchecked((ushort)GetInt()); + s_uint = unchecked((uint)GetInt()); + s_long = unchecked((long)GetInt()); + s_ulong = unchecked((ulong)GetInt()); + s_float = unchecked((float)GetInt()); + s_double = unchecked(GetInt()); + s_nint = unchecked((nint)GetInt()); + s_nuint = unchecked((nuint)GetInt()); + } + } + + class LongConversions + { + internal static byte s_byte; + internal static sbyte s_sbyte; + internal static short s_short; + internal static ushort s_ushort; + internal static int s_int; + internal static uint s_uint; + internal static ulong s_ulong; + internal static float s_float; + internal static double s_double; + internal static nint s_nint; + internal static nuint s_nuint; + + static LongConversions() + { + s_byte = unchecked((byte)GetLong()); + s_sbyte = unchecked((sbyte)GetLong()); + s_short = unchecked((short)GetLong()); + s_ushort = unchecked((ushort)GetLong()); + s_int = unchecked((int)GetLong()); + s_uint = unchecked((uint)GetLong()); + s_ulong = unchecked((ulong)GetLong()); + s_float = unchecked((float)GetLong()); + s_double = unchecked((double)GetLong()); + s_nint = unchecked((nint)GetLong()); + s_nuint = unchecked((nuint)GetLong()); + } + } + + class FloatConversions + { + internal static byte s_byte; + internal static sbyte s_sbyte; + internal static short s_short; + internal static ushort s_ushort; + internal static int s_int; + internal static uint s_uint; + internal static long s_long; + internal static ulong s_ulong; + internal static double s_double; + internal static nint s_nint; + internal static nuint s_nuint; + + static FloatConversions() + { + s_byte = unchecked((byte)GetFloat()); + s_sbyte = unchecked((sbyte)GetFloat()); + s_short = unchecked((short)GetFloat()); + s_ushort = unchecked((ushort)GetFloat()); + s_int = unchecked((int)GetFloat()); + s_uint = unchecked((uint)GetFloat()); + s_long = unchecked((long)GetFloat()); + s_ulong = unchecked((ulong)GetFloat()); + s_double = unchecked((double)GetFloat()); + s_nint = unchecked((nint)GetFloat()); + s_nuint = unchecked((nuint)GetFloat()); + } + } + + class DoubleConversions + { + internal static byte s_byte; + internal static sbyte s_sbyte; + internal static short s_short; + internal static ushort s_ushort; + internal static int s_int; + internal static uint s_uint; + internal static long s_long; + internal static ulong s_ulong; + internal static float s_float; + internal static nint s_nint; + internal static nuint s_nuint; + + static DoubleConversions() + { + s_byte = unchecked((byte)GetDouble()); + s_sbyte = unchecked((sbyte)GetDouble()); + s_short = unchecked((short)GetDouble()); + s_ushort = unchecked((ushort)GetDouble()); + s_int = unchecked((int)GetDouble()); + s_uint = unchecked((uint)GetDouble()); + s_long = unchecked((long)GetDouble()); + s_ulong = unchecked((ulong)GetDouble()); + s_float = unchecked((float)GetDouble()); + s_nint = unchecked((nint)GetDouble()); + s_nuint = unchecked((nuint)GetDouble()); + } + } + + class NativeIntConversions + { + internal static byte s_byte; + internal static sbyte s_sbyte; + internal static short s_short; + internal static ushort s_ushort; + internal static int s_int; + internal static uint s_uint; + internal static long s_long; + internal static ulong s_ulong; + internal static float s_float; + internal static double s_double; + internal static nuint s_nuint; + + static NativeIntConversions() + { + s_byte = unchecked((byte)GetNativeInt()); + s_sbyte = unchecked((sbyte)GetNativeInt()); + s_short = unchecked((short)GetNativeInt()); + s_ushort = unchecked((ushort)GetNativeInt()); + s_int = unchecked((int)GetNativeInt()); + s_uint = unchecked((uint)GetNativeInt()); + s_long = unchecked((long)GetNativeInt()); + s_ulong = unchecked((ulong)GetNativeInt()); + s_float = unchecked((float)GetNativeInt()); + s_double = unchecked((double)GetNativeInt()); + s_nuint = unchecked((nuint)GetNativeInt()); + } + } + + public static void Run() + { + Assert.IsPreinitialized(typeof(IntConversions)); + Assert.AreEqual(unchecked((byte)GetInt()), IntConversions.s_byte); + Assert.AreEqual(unchecked((sbyte)GetInt()), IntConversions.s_sbyte); + Assert.AreEqual(unchecked((short)GetInt()), IntConversions.s_short); + Assert.AreEqual(unchecked((ushort)GetInt()), IntConversions.s_ushort); + Assert.AreEqual(unchecked((uint)GetInt()), IntConversions.s_uint); + Assert.AreEqual(unchecked((long)GetInt()), IntConversions.s_long); + Assert.AreEqual(unchecked((ulong)GetInt()), IntConversions.s_ulong); + Assert.AreEqual(unchecked((float)GetInt()), IntConversions.s_float); + Assert.AreEqual(unchecked((double)GetInt()), IntConversions.s_double); + Assert.AreEqual(unchecked((nint)GetInt()), IntConversions.s_nint); + Assert.AreEqual(unchecked((nuint)GetInt()), IntConversions.s_nuint); + + Assert.IsPreinitialized(typeof(LongConversions)); + Assert.AreEqual(unchecked((byte)GetLong()), LongConversions.s_byte); + Assert.AreEqual(unchecked((sbyte)GetLong()), LongConversions.s_sbyte); + Assert.AreEqual(unchecked((short)GetLong()), LongConversions.s_short); + Assert.AreEqual(unchecked((ushort)GetLong()), LongConversions.s_ushort); + Assert.AreEqual(unchecked((int)GetLong()), LongConversions.s_int); + Assert.AreEqual(unchecked((uint)GetLong()), LongConversions.s_uint); + Assert.AreEqual(unchecked((ulong)GetLong()), LongConversions.s_ulong); + Assert.AreEqual(unchecked((float)GetLong()), LongConversions.s_float); + Assert.AreEqual(unchecked((double)GetLong()), LongConversions.s_double); + Assert.AreEqual(unchecked((nint)GetLong()), LongConversions.s_nint); + Assert.AreEqual(unchecked((nuint)GetLong()), LongConversions.s_nuint); + + Assert.IsPreinitialized(typeof(FloatConversions)); + Assert.AreEqual(unchecked((byte)GetFloat()), FloatConversions.s_byte); + Assert.AreEqual(unchecked((sbyte)GetFloat()), FloatConversions.s_sbyte); + Assert.AreEqual(unchecked((short)GetFloat()), FloatConversions.s_short); + Assert.AreEqual(unchecked((ushort)GetFloat()), FloatConversions.s_ushort); + Assert.AreEqual(unchecked((int)GetFloat()), FloatConversions.s_int); + Assert.AreEqual(unchecked((uint)GetFloat()), FloatConversions.s_uint); + Assert.AreEqual(unchecked((long)GetFloat()), FloatConversions.s_long); + Assert.AreEqual(unchecked((ulong)GetFloat()), FloatConversions.s_ulong); + Assert.AreEqual(unchecked((double)GetFloat()), FloatConversions.s_double); + Assert.AreEqual(unchecked((nint)GetFloat()), FloatConversions.s_nint); + Assert.AreEqual(unchecked((nuint)GetFloat()), FloatConversions.s_nuint); + + Assert.IsPreinitialized(typeof(DoubleConversions)); + Assert.AreEqual(unchecked((byte)GetDouble()), DoubleConversions.s_byte); + Assert.AreEqual(unchecked((sbyte)GetDouble()), DoubleConversions.s_sbyte); + Assert.AreEqual(unchecked((short)GetDouble()), DoubleConversions.s_short); + Assert.AreEqual(unchecked((ushort)GetDouble()), DoubleConversions.s_ushort); + Assert.AreEqual(unchecked((int)GetDouble()), DoubleConversions.s_int); + Assert.AreEqual(unchecked((uint)GetDouble()), DoubleConversions.s_uint); + Assert.AreEqual(unchecked((long)GetDouble()), DoubleConversions.s_long); + Assert.AreEqual(unchecked((ulong)GetDouble()), DoubleConversions.s_ulong); + Assert.AreEqual(unchecked((float)GetDouble()), DoubleConversions.s_float); + Assert.AreEqual(unchecked((nint)GetDouble()), DoubleConversions.s_nint); + Assert.AreEqual(unchecked((nuint)GetDouble()), DoubleConversions.s_nuint); + + Assert.IsPreinitialized(typeof(NativeIntConversions)); + Assert.AreEqual(unchecked((byte)GetNativeInt()), NativeIntConversions.s_byte); + Assert.AreEqual(unchecked((sbyte)GetNativeInt()), NativeIntConversions.s_sbyte); + Assert.AreEqual(unchecked((short)GetNativeInt()), NativeIntConversions.s_short); + Assert.AreEqual(unchecked((ushort)GetNativeInt()), NativeIntConversions.s_ushort); + Assert.AreEqual(unchecked((int)GetNativeInt()), NativeIntConversions.s_int); + Assert.AreEqual(unchecked((uint)GetNativeInt()), NativeIntConversions.s_uint); + Assert.AreEqual(unchecked((long)GetNativeInt()), NativeIntConversions.s_long); + Assert.AreEqual(unchecked((ulong)GetNativeInt()), NativeIntConversions.s_ulong); + Assert.AreEqual(unchecked((float)GetNativeInt()), NativeIntConversions.s_float); + Assert.AreEqual(unchecked((double)GetNativeInt()), NativeIntConversions.s_double); + Assert.AreEqual(unchecked((nuint)GetNativeInt()), NativeIntConversions.s_nuint); + } +} + + static class Assert { [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", @@ -1438,69 +1667,87 @@ private static bool HasCctor(Type type) return type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Static, null, Type.EmptyTypes, null) != null; } - public static void IsPreinitialized(Type type) + public static void IsPreinitialized(Type type, [CallerLineNumber] int line = 0) { if (HasCctor(type)) - throw new Exception(); + throw new Exception($"{type} is not preinitialized. At line {line}."); } - public static void IsLazyInitialized(Type type) + public static void IsLazyInitialized(Type type, [CallerLineNumber] int line = 0) { if (!HasCctor(type)) - throw new Exception(); + throw new Exception($"{type} is not lazy initialized. At line {line}."); } - public static unsafe void AreEqual(void* v1, void* v2) + public static unsafe void AreEqual(void* v1, void* v2, [CallerLineNumber] int line = 0) { if (v1 != v2) - throw new Exception(); + throw new Exception($"Expect {(nint)v1}, but get {(nint)v2}. At line {line}."); } - public static unsafe void AreEqual(bool v1, bool v2) + public static unsafe void AreEqual(bool v1, bool v2, [CallerLineNumber] int line = 0) { if (v1 != v2) - throw new Exception(); + throw new Exception($"Expect {v1}, but get {v2}. At line {line}."); } - public static unsafe void AreEqual(int v1, int v2) + public static unsafe void AreEqual(int v1, int v2, [CallerLineNumber] int line = 0) { if (v1 != v2) - throw new Exception(); + throw new Exception($"Expect {v1}, but get {v2}. At line {line}."); } - public static void AreEqual(string v1, string v2) + public static void AreEqual(string v1, string v2, [CallerLineNumber] int line = 0) { if (v1 != v2) - throw new Exception(); + throw new Exception($"Expect {v1}, but get {v2}. At line {line}."); } - public static unsafe void AreEqual(long v1, long v2) + public static unsafe void AreEqual(long v1, long v2, [CallerLineNumber] int line = 0) { if (v1 != v2) - throw new Exception(); + throw new Exception($"Expect {v1}, but get {v2}. At line {line}."); } - public static unsafe void AreEqual(float v1, float v2) + public static unsafe void AreEqual(ulong v1, ulong v2, [CallerLineNumber] int line = 0) { if (v1 != v2) - throw new Exception(); + throw new Exception($"Expect {v1}, but get {v2}. At line {line}."); } - public static unsafe void AreEqual(double v1, double v2) + public static unsafe void AreEqual(float v1, float v2, [CallerLineNumber] int line = 0) { if (v1 != v2) - throw new Exception(); + throw new Exception($"Expect {v1}, but get {v2}. At line {line}."); } - public static void True(bool v) + public static unsafe void AreEqual(double v1, double v2, [CallerLineNumber] int line = 0) + { + if (v1 != v2) + throw new Exception($"Expect {v1}, but get {v2}. At line {line}."); + } + + public static unsafe void AreEqual(nint v1, nint v2, [CallerLineNumber] int line = 0) + { + if (v1 != v2) + throw new Exception($"Expect {v1}, but get {v2}. At line {line}."); + } + + public static unsafe void AreEqual(nuint v1, nuint v2, [CallerLineNumber] int line = 0) + { + if (v1 != v2) + throw new Exception($"Expect {v1}, but get {v2}. At line {line}."); + } + + public static void True(bool v, [CallerLineNumber] int line = 0) { if (!v) - throw new Exception(); + throw new Exception($"Expect True, but get {v}. At line {line}."); } - public static void AreSame(T v1, T v2) where T : class + public static void AreSame(T v1, T v2, [CallerLineNumber] int line = 0) where T : class { if (v1 != v2) - throw new Exception(); + throw new Exception($"{v1} and {v2} is not the same. At line {line}."); } } From 8a22b878d004cfa55994af9672c7cfecd5357969 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Tue, 11 Feb 2025 10:32:09 +0100 Subject: [PATCH 02/20] JIT: Optimize struct parameter register accesses in the backend (#110819) This PR adds an optimization in lowering to utilize the new parameter register to local mappings added in #110795. The optimization detects IR that is going to result in stack spills/loads and instead replaces them with scalar locals that will be able to stay in registers. Physical promotion benefits especially from this as it creates the kind of IR that the optimization ends up kicking in for. The heuristics of physical promotion are updated to account for the fact that the backend is now able to do this optimization, making physical promotion more likely to promote struct parameters. --- src/coreclr/jit/codegen.h | 2 + src/coreclr/jit/codegenarm.cpp | 24 +++ src/coreclr/jit/codegencommon.cpp | 31 +++- src/coreclr/jit/compiler.cpp | 2 +- src/coreclr/jit/compiler.h | 2 +- src/coreclr/jit/compiler.hpp | 5 +- src/coreclr/jit/lclvars.cpp | 20 +- src/coreclr/jit/lower.cpp | 297 ++++++++++++++++++++++++++++-- src/coreclr/jit/lower.h | 6 +- src/coreclr/jit/lsra.cpp | 3 +- src/coreclr/jit/lsraarmarch.cpp | 12 +- src/coreclr/jit/lsrabuild.cpp | 40 ++-- src/coreclr/jit/promotion.cpp | 66 ++++++- 13 files changed, 469 insertions(+), 41 deletions(-) diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index b8f4d99353208a..2520864b707421 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -444,6 +444,8 @@ class CodeGen final : public CodeGenInterface void genPopFltRegs(regMaskTP regMask); regMaskTP genStackAllocRegisterMask(unsigned frameSize, regMaskTP maskCalleeSavedFloat); + regMaskTP genPrespilledUnmappedRegs(); + regMaskTP genJmpCallArgMask(); void genFreeLclFrame(unsigned frameSize, diff --git a/src/coreclr/jit/codegenarm.cpp b/src/coreclr/jit/codegenarm.cpp index 92d6bc8635224e..26975c0130ab9c 100644 --- a/src/coreclr/jit/codegenarm.cpp +++ b/src/coreclr/jit/codegenarm.cpp @@ -2102,6 +2102,30 @@ regMaskTP CodeGen::genStackAllocRegisterMask(unsigned frameSize, regMaskTP maskC } } +//----------------------------------------------------------------------------------- +// genPrespilledUnmappedRegs: Get a mask of the registers that are prespilled +// and also not mapped to any locals. +// +// Returns: +// Mask of those registers. These registers can be used safely in prolog as +// they won't be needed after prespilling. +// +regMaskTP CodeGen::genPrespilledUnmappedRegs() +{ + regMaskTP regs = regSet.rsMaskPreSpillRegs(false); + + if (compiler->m_paramRegLocalMappings != nullptr) + { + for (int i = 0; i < compiler->m_paramRegLocalMappings->Height(); i++) + { + const ParameterRegisterLocalMapping& mapping = compiler->m_paramRegLocalMappings->BottomRef(i); + regs &= ~mapping.RegisterSegment->GetRegisterMask(); + } + } + + return regs; +} + //----------------------------------------------------------------------------------- // instGen_MemoryBarrier: Emit a MemoryBarrier instruction // diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 2318d4223ad812..5b280951178aff 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -3411,6 +3411,12 @@ void CodeGen::genHomeRegisterParams(regNumber initReg, bool* initRegStillZeroed) // top of the underlying registers. RegGraph graph(compiler); + // Add everything to the graph, or spill directly to stack when needed. + // Note that some registers may be homed in multiple (stack) places. + // Particularly if there is a mapping to a local that does not share its + // (stack) home with the parameter local, in which case we will home it + // both into the parameter local's stack home (if it is used), but also to + // the mapping target. for (unsigned lclNum = 0; lclNum < compiler->info.compArgsCount; lclNum++) { LclVarDsc* lclDsc = compiler->lvaGetDesc(lclNum); @@ -3426,11 +3432,26 @@ void CodeGen::genHomeRegisterParams(regNumber initReg, bool* initRegStillZeroed) const ParameterRegisterLocalMapping* mapping = compiler->FindParameterRegisterLocalMappingByRegister(segment.GetRegister()); + bool spillToBaseLocal = true; if (mapping != nullptr) { genSpillOrAddRegisterParam(mapping->LclNum, mapping->Offset, lclNum, segment, &graph); + + // If home is shared with base local, then skip spilling to the + // base local. + if (lclDsc->lvPromoted) + { + spillToBaseLocal = false; + } } - else + +#ifdef TARGET_ARM + // For arm32 the spills to the base local happen as part of + // prespilling sometimes, so skip it in that case. + spillToBaseLocal &= (regSet.rsMaskPreSpillRegs(false) & segment.GetRegisterMask()) == 0; +#endif + + if (spillToBaseLocal) { genSpillOrAddRegisterParam(lclNum, segment.Offset, lclNum, segment, &graph); } @@ -3915,7 +3936,7 @@ void CodeGen::genCheckUseBlockInit() // must force spill R4/R5/R6 so that we can use them during // zero-initialization process. // - int forceSpillRegCount = genCountBits(maskCalleeRegArgMask & ~regSet.rsMaskPreSpillRegs(false)) - 1; + int forceSpillRegCount = genCountBits(maskCalleeRegArgMask & ~genPrespilledUnmappedRegs()) - 1; if (forceSpillRegCount > 0) regSet.rsSetRegsModified(RBM_R4); if (forceSpillRegCount > 1) @@ -5347,7 +5368,7 @@ void CodeGen::genFnProlog() // These registers will be available to use for the initReg. We just remove // all of these registers from the rsCalleeRegArgMaskLiveIn. // - intRegState.rsCalleeRegArgMaskLiveIn &= ~regSet.rsMaskPreSpillRegs(false); + intRegState.rsCalleeRegArgMaskLiveIn &= ~genPrespilledUnmappedRegs(); #endif /* Choose the register to use for zero initialization */ @@ -5751,6 +5772,10 @@ void CodeGen::genFnProlog() #else genEnregisterOSRArgsAndLocals(); #endif + // OSR functions take no parameters in registers. Ensure no mappings + // are present. + // assert((compiler->m_paramRegLocalMappings == nullptr) || compiler->m_paramRegLocalMappings->Empty()); + compiler->lvaUpdateArgsWithInitialReg(); } else diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 811fa2d56035a9..ed6852d138bd17 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -10419,7 +10419,7 @@ JITDBGAPI void __cdecl dVN(ValueNum vn) cVN(JitTls::GetCompiler(), vn); } -JITDBGAPI void __cdecl dRegMask(regMaskTP mask) +JITDBGAPI void __cdecl dRegMask(const regMaskTP& mask) { static unsigned sequenceNumber = 0; // separate calls with a number to indicate this function has been called printf("===================================================================== dRegMask %u\n", sequenceNumber++); diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 2f5d219ed94d43..e3077cfac9ac12 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -4202,7 +4202,7 @@ class Compiler #ifdef DEBUG void lvaDumpRegLocation(unsigned lclNum); - void lvaDumpFrameLocation(unsigned lclNum); + void lvaDumpFrameLocation(unsigned lclNum, int minLength); void lvaDumpEntry(unsigned lclNum, FrameLayoutState curState, size_t refCntWtdWidth = 6); void lvaTableDump(FrameLayoutState curState = NO_FRAME_LAYOUT); // NO_FRAME_LAYOUT means use the current frame // layout state defined by lvaDoneFrameLayout diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index ef00369ea1b309..1738810e149b4b 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -4260,8 +4260,9 @@ inline void Compiler::CLR_API_Leave(API_ICorJitInfo_Names ename) bool Compiler::fgVarIsNeverZeroInitializedInProlog(unsigned varNum) { LclVarDsc* varDsc = lvaGetDesc(varNum); - bool result = varDsc->lvIsParam || lvaIsOSRLocal(varNum) || (varNum == lvaGSSecurityCookie) || - (varNum == lvaInlinedPInvokeFrameVar) || (varNum == lvaStubArgumentVar) || (varNum == lvaRetAddrVar); + bool result = varDsc->lvIsParam || varDsc->lvIsParamRegTarget || lvaIsOSRLocal(varNum) || + (varNum == lvaGSSecurityCookie) || (varNum == lvaInlinedPInvokeFrameVar) || + (varNum == lvaStubArgumentVar) || (varNum == lvaRetAddrVar); #ifdef TARGET_ARM64 result = result || (varNum == lvaFfrRegister); diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index f9d84a12bc9a28..5b2308634fad83 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -4939,8 +4939,8 @@ void Compiler::lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers) // that was set by past phases. if (!isRecompute) { - varDsc->lvSingleDef = varDsc->lvIsParam; - varDsc->lvSingleDefRegCandidate = varDsc->lvIsParam; + varDsc->lvSingleDef = varDsc->lvIsParam || varDsc->lvIsParamRegTarget; + varDsc->lvSingleDefRegCandidate = varDsc->lvIsParam || varDsc->lvIsParamRegTarget; varDsc->lvAllDefsAreNoGc = (varDsc->lvImplicitlyReferenced == false); } @@ -5033,6 +5033,11 @@ void Compiler::lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers) varDsc->incRefCnts(BB_UNITY_WEIGHT, this); } } + else if (varDsc->lvIsParamRegTarget && (varDsc->lvRefCnt() > 0)) + { + varDsc->incRefCnts(BB_UNITY_WEIGHT, this); + varDsc->incRefCnts(BB_UNITY_WEIGHT, this); + } // If we have JMP, all arguments must have a location // even if we don't use them inside the method @@ -7370,7 +7375,7 @@ void Compiler::lvaDumpRegLocation(unsigned lclNum) * in its home location. */ -void Compiler::lvaDumpFrameLocation(unsigned lclNum) +void Compiler::lvaDumpFrameLocation(unsigned lclNum, int minLength) { int offset; regNumber baseReg; @@ -7383,7 +7388,12 @@ void Compiler::lvaDumpFrameLocation(unsigned lclNum) baseReg = EBPbased ? REG_FPBASE : REG_SPBASE; #endif - printf("[%2s%1s0x%02X] ", getRegName(baseReg), (offset < 0 ? "-" : "+"), (offset < 0 ? -offset : offset)); + int printed = + printf("[%2s%1s0x%02X] ", getRegName(baseReg), (offset < 0 ? "-" : "+"), (offset < 0 ? -offset : offset)); + if ((printed >= 0) && (printed < minLength)) + { + printf("%*s", minLength - printed, ""); + } } /***************************************************************************** @@ -7474,7 +7484,7 @@ void Compiler::lvaDumpEntry(unsigned lclNum, FrameLayoutState curState, size_t r // location. Otherwise, it's always on the stack. if (lvaDoneFrameLayout != NO_FRAME_LAYOUT) { - lvaDumpFrameLocation(lclNum); + lvaDumpFrameLocation(lclNum, (int)strlen("zero-ref ")); } } } diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index eee9a5859ecb43..dfd489eac21b88 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -7901,6 +7901,11 @@ PhaseStatus Lowering::DoPhase() comp->lvSetMinOptsDoNotEnreg(); } + if (comp->opts.OptimizationEnabled()) + { + MapParameterRegisterLocals(); + } + for (BasicBlock* const block : comp->Blocks()) { /* Make the block publicly available */ @@ -7916,11 +7921,6 @@ PhaseStatus Lowering::DoPhase() LowerBlock(block); } - if (comp->opts.OptimizationEnabled()) - { - MapParameterRegisterLocals(); - } - #ifdef DEBUG JITDUMP("Lower has completed modifying nodes.\n"); if (VERBOSE) @@ -8030,12 +8030,16 @@ void Lowering::MapParameterRegisterLocals() comp->m_paramRegLocalMappings->Emplace(&segment, fieldLclNum, segment.Offset - fieldDsc->lvFldOffset); } - LclVarDsc* fieldLclDsc = comp->lvaGetDesc(fieldLclNum); - assert(!fieldLclDsc->lvIsParamRegTarget); - fieldLclDsc->lvIsParamRegTarget = true; + assert(!fieldDsc->lvIsParamRegTarget); + fieldDsc->lvIsParamRegTarget = true; } } + if (!comp->opts.IsOSR()) + { + FindInducedParameterRegisterLocals(); + } + #ifdef DEBUG if (comp->verbose) { @@ -8043,14 +8047,285 @@ void Lowering::MapParameterRegisterLocals() for (int i = 0; i < comp->m_paramRegLocalMappings->Height(); i++) { const ParameterRegisterLocalMapping& mapping = comp->m_paramRegLocalMappings->BottomRef(i); - printf(" "); - mapping.RegisterSegment->Dump(); - printf(" -> V%02u\n", mapping.LclNum); + printf(" %s -> V%02u+%u\n", getRegName(mapping.RegisterSegment->GetRegister()), mapping.LclNum, + mapping.Offset); } } #endif } +//------------------------------------------------------------------------ +// Lowering::FindInducedParameterRegisterLocals: +// Find locals that would be profitable to map from parameter registers, +// based on IR in the initialization block. +// +void Lowering::FindInducedParameterRegisterLocals() +{ +#ifdef TARGET_ARM + // On arm32 the profiler hook does not preserve arg registers, so + // parameters are prespilled and cannot stay enregistered. + if (comp->compIsProfilerHookNeeded()) + { + JITDUMP("Skipping FindInducedParameterRegisterLocals on arm32 with profiler hook\n"); + return; + } +#endif + + // Check if we possibly have any parameters we can induce new register + // locals from. + bool anyCandidates = false; + for (unsigned lclNum = 0; lclNum < comp->info.compArgsCount; lclNum++) + { + LclVarDsc* lcl = comp->lvaGetDesc(lclNum); + if (lcl->lvPromoted || !lcl->lvDoNotEnregister) + { + continue; + } + + const ABIPassingInformation& abiInfo = comp->lvaGetParameterABIInfo(lclNum); + if (!abiInfo.HasAnyRegisterSegment()) + { + continue; + } + + anyCandidates = true; + break; + } + + if (!anyCandidates) + { + return; + } + + bool hasRegisterKill = false; + LocalSet storedToLocals(comp->getAllocator(CMK_ABI)); + // Now look for optimization opportunities in the first block: places where + // we read fields out of struct parameters that can be mapped cleanly. This + // is frequently created by physical promotion. + for (GenTree* node : LIR::AsRange(comp->fgFirstBB)) + { + hasRegisterKill |= node->IsCall(); + + GenTreeLclVarCommon* storeLcl; + if (node->DefinesLocal(comp, &storeLcl)) + { + storedToLocals.Emplace(storeLcl->GetLclNum(), true); + continue; + } + + if (node->OperIs(GT_LCL_ADDR)) + { + storedToLocals.Emplace(node->AsLclVarCommon()->GetLclNum(), true); + continue; + } + + if (!node->OperIs(GT_LCL_FLD)) + { + continue; + } + + GenTreeLclFld* fld = node->AsLclFld(); + if (fld->GetLclNum() >= comp->info.compArgsCount) + { + continue; + } + + LclVarDsc* paramDsc = comp->lvaGetDesc(fld); + if (paramDsc->lvPromoted) + { + // These are complicated to reason about since they may be + // defined/used through their fields, so just skip them. + continue; + } + + if (fld->TypeIs(TYP_STRUCT)) + { + continue; + } + + if (storedToLocals.Lookup(fld->GetLclNum())) + { + // LCL_FLD does not necessarily take the value of the parameter + // anymore. + continue; + } + + const ABIPassingInformation& dataAbiInfo = comp->lvaGetParameterABIInfo(fld->GetLclNum()); + const ABIPassingSegment* regSegment = nullptr; + for (const ABIPassingSegment& segment : dataAbiInfo.Segments()) + { + if (!segment.IsPassedInRegister()) + { + continue; + } + + assert(fld->GetLclOffs() <= comp->lvaLclExactSize(fld->GetLclNum())); + unsigned structAccessedSize = + min(genTypeSize(fld), comp->lvaLclExactSize(fld->GetLclNum()) - fld->GetLclOffs()); + if ((segment.Offset != fld->GetLclOffs()) || (structAccessedSize > segment.Size) || + (varTypeUsesIntReg(fld) != genIsValidIntReg(segment.GetRegister()))) + { + continue; + } + + // This is a match, but check if it is already remapped. + // TODO-CQ: If it is already remapped, we can reuse the value from + // the remapping. + if (comp->FindParameterRegisterLocalMappingByRegister(segment.GetRegister()) == nullptr) + { + regSegment = &segment; + } + + break; + } + + if (regSegment == nullptr) + { + continue; + } + + JITDUMP("LCL_FLD use [%06u] of unenregisterable parameter corresponds to ", Compiler::dspTreeID(fld)); + DBEXEC(VERBOSE, regSegment->Dump()); + JITDUMP("\n"); + + // Now see if we want to introduce a new local for this value, or if we + // can reuse one because this is the source of a store (frequently + // created by physical promotion). + LIR::Use use; + if (!LIR::AsRange(comp->fgFirstBB).TryGetUse(fld, &use)) + { + JITDUMP(" ..but no use was found\n"); + continue; + } + + unsigned remappedLclNum = TryReuseLocalForParameterAccess(use, storedToLocals); + + if (remappedLclNum == BAD_VAR_NUM) + { + // If we have seen register kills then avoid creating a new local. + // The local is going to have to move from the parameter register + // into a callee saved register, and the callee saved register will + // need to be saved/restored to/from stack anyway. + if (hasRegisterKill) + { + JITDUMP(" ..but use happens after a call and is deemed unprofitable to create a local for\n"); + continue; + } + + remappedLclNum = comp->lvaGrabTemp( + false DEBUGARG(comp->printfAlloc("V%02u.%s", fld->GetLclNum(), getRegName(regSegment->GetRegister())))); + comp->lvaGetDesc(remappedLclNum)->lvType = fld->TypeGet(); + JITDUMP("Created new local V%02u for the mapping\n", remappedLclNum); + } + else + { + JITDUMP("Reusing local V%02u for store from struct parameter register %s. Store:\n", remappedLclNum, + getRegName(regSegment->GetRegister())); + DISPTREERANGE(LIR::AsRange(comp->fgFirstBB), use.User()); + + // The store will be a no-op, so get rid of it + LIR::AsRange(comp->fgFirstBB).Remove(use.User(), true); + use = LIR::Use(); + +#ifdef DEBUG + LclVarDsc* remappedLclDsc = comp->lvaGetDesc(remappedLclNum); + remappedLclDsc->lvReason = + comp->printfAlloc("%s%sV%02u.%s", remappedLclDsc->lvReason == nullptr ? "" : remappedLclDsc->lvReason, + remappedLclDsc->lvReason == nullptr ? "" : " ", fld->GetLclNum(), + getRegName(regSegment->GetRegister())); +#endif + } + + comp->m_paramRegLocalMappings->Emplace(regSegment, remappedLclNum, 0); + comp->lvaGetDesc(remappedLclNum)->lvIsParamRegTarget = true; + + JITDUMP("New mapping: "); + DBEXEC(VERBOSE, regSegment->Dump()); + JITDUMP(" -> V%02u\n", remappedLclNum); + + // Insert explicit normalization for small types (the LCL_FLD we + // are replacing comes with this normalization). + if (varTypeIsSmall(fld)) + { + GenTree* lcl = comp->gtNewLclvNode(remappedLclNum, genActualType(fld)); + GenTree* normalizeLcl = comp->gtNewCastNode(TYP_INT, lcl, false, fld->TypeGet()); + GenTree* storeNormalizedLcl = comp->gtNewStoreLclVarNode(remappedLclNum, normalizeLcl); + LIR::AsRange(comp->fgFirstBB).InsertAtBeginning(LIR::SeqTree(comp, storeNormalizedLcl)); + + JITDUMP("Parameter normalization:\n"); + DISPTREERANGE(LIR::AsRange(comp->fgFirstBB), storeNormalizedLcl); + } + + // If we still have a valid use, then replace the LCL_FLD with a + // LCL_VAR of the remapped parameter register local. + if (use.IsInitialized()) + { + GenTree* lcl = comp->gtNewLclvNode(remappedLclNum, genActualType(fld)); + LIR::AsRange(comp->fgFirstBB).InsertAfter(fld, lcl); + use.ReplaceWith(lcl); + LowerNode(lcl); + JITDUMP("New user tree range:\n"); + DISPTREERANGE(LIR::AsRange(comp->fgFirstBB), use.User()); + } + + fld->gtBashToNOP(); + } +} + +//------------------------------------------------------------------------ +// Lowering::TryReuseLocalForParameterAccess: +// Try to figure out if a LCL_FLD that corresponds to a parameter register is +// being stored directly to a LCL_VAR, and in that case whether it would be +// profitable to reuse that local as the parameter register. +// +// Parameters: +// use - The use of the LCL_FLD +// storedToLocals - Map of locals that have had potential definitions to them +// up until the use +// +// Returns: +// The local number to reuse, or BAD_VAR_NUM to create a new local instead. +// +unsigned Lowering::TryReuseLocalForParameterAccess(const LIR::Use& use, const LocalSet& storedToLocals) +{ + GenTree* useNode = use.User(); + + if (!useNode->OperIs(GT_STORE_LCL_VAR)) + { + return BAD_VAR_NUM; + } + + LclVarDsc* destLclDsc = comp->lvaGetDesc(useNode->AsLclVarCommon()); + + if (destLclDsc->lvIsParamRegTarget) + { + return BAD_VAR_NUM; + } + + if (destLclDsc->lvIsStructField) + { + return BAD_VAR_NUM; + } + + if (destLclDsc->TypeGet() == TYP_STRUCT) + { + return BAD_VAR_NUM; + } + + if (destLclDsc->lvDoNotEnregister) + { + return BAD_VAR_NUM; + } + + if (storedToLocals.Lookup(useNode->AsLclVarCommon()->GetLclNum())) + { + // Destination may change value before this access + return BAD_VAR_NUM; + } + + return useNode->AsLclVarCommon()->GetLclNum(); +} + #ifdef DEBUG //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/lower.h b/src/coreclr/jit/lower.h index 7fa3aca9e98511..86b336c517f3c1 100644 --- a/src/coreclr/jit/lower.h +++ b/src/coreclr/jit/lower.h @@ -133,7 +133,11 @@ class Lowering final : public Phase static bool CheckBlock(Compiler* compiler, BasicBlock* block); #endif // DEBUG - void MapParameterRegisterLocals(); + typedef JitHashTable, bool> LocalSet; + + void MapParameterRegisterLocals(); + void FindInducedParameterRegisterLocals(); + unsigned TryReuseLocalForParameterAccess(const LIR::Use& use, const LocalSet& storedToLocals); void LowerBlock(BasicBlock* block); GenTree* LowerNode(GenTree* node); diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index dc4f2c312045e4..3958dd2df29d77 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -1484,7 +1484,8 @@ void LinearScan::identifyCandidatesExceptionDataflow() assert(varDsc->lvLiveInOutOfHndlr); - if (varTypeIsGC(varDsc) && VarSetOps::IsMember(compiler, finallyVars, varIndex) && !varDsc->lvIsParam) + if (varTypeIsGC(varDsc) && VarSetOps::IsMember(compiler, finallyVars, varIndex) && !varDsc->lvIsParam && + !varDsc->lvIsParamRegTarget) { assert(varDsc->lvMustInit); } diff --git a/src/coreclr/jit/lsraarmarch.cpp b/src/coreclr/jit/lsraarmarch.cpp index 518ae815f867c8..b3c6c7d4cf788d 100644 --- a/src/coreclr/jit/lsraarmarch.cpp +++ b/src/coreclr/jit/lsraarmarch.cpp @@ -457,13 +457,19 @@ int LinearScan::BuildPutArgSplit(GenTreePutArgSplit* argNode) // go into registers. for (unsigned regIndex = 0; regIndex < currentRegCount; regIndex++) { - SingleTypeRegSet sourceMask = RBM_NONE; if (sourceRegCount < argNode->gtNumRegs) { - sourceMask = genSingleTypeRegMask((regNumber)((unsigned)argReg + sourceRegCount)); + regNumber nextArgReg = (regNumber)((unsigned)argReg + sourceRegCount); + SingleTypeRegSet sourceMask = genSingleTypeRegMask(nextArgReg); + BuildUse(node, sourceMask, regIndex); + placedArgRegs.AddRegNumInMask(nextArgReg); } + else + { + BuildUse(node, RBM_NONE, regIndex); + } + sourceRegCount++; - BuildUse(node, sourceMask, regIndex); } } srcCount += sourceRegCount; diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 25964ec22f24fb..a3a0ad88b80f4a 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -2066,7 +2066,7 @@ void LinearScan::insertZeroInitRefPositions() while (iter.NextElem(&varIndex)) { LclVarDsc* varDsc = compiler->lvaGetDescByTrackedIndex(varIndex); - if (!varDsc->lvIsParam && isCandidateVar(varDsc)) + if (!varDsc->lvIsParam && !varDsc->lvIsParamRegTarget && isCandidateVar(varDsc)) { JITDUMP("V%02u is a finally var:", compiler->lvaTrackedIndexToLclNum(varIndex)); Interval* interval = getIntervalForLocalVar(varIndex); @@ -2188,6 +2188,7 @@ void LinearScan::buildIntervals() // locals we are expecting to store the registers into in the prolog. for (unsigned lclNum = 0; lclNum < compiler->info.compArgsCount; lclNum++) { + LclVarDsc* lcl = compiler->lvaGetDesc(lclNum); const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(lclNum); for (const ABIPassingSegment& seg : abiInfo.Segments()) { @@ -2199,18 +2200,35 @@ void LinearScan::buildIntervals() const ParameterRegisterLocalMapping* mapping = compiler->FindParameterRegisterLocalMappingByRegister(seg.GetRegister()); - unsigned mappedLclNum = mapping != nullptr ? mapping->LclNum : lclNum; - JITDUMP("Arg V%02u in reg %s\n", mappedLclNum, getRegName(seg.GetRegister())); - LclVarDsc* argDsc = compiler->lvaGetDesc(mappedLclNum); - if (argDsc->lvTracked && !compiler->compJmpOpUsed && (argDsc->lvRefCnt() == 0) && - !compiler->opts.compDbgCode) + bool isParameterLive = !lcl->lvTracked || compiler->compJmpOpUsed || (lcl->lvRefCnt() != 0); + bool isLive; + if (mapping != nullptr) { - // Not live - continue; + LclVarDsc* mappedLcl = compiler->lvaGetDesc(mapping->LclNum); + bool isMappedLclLive = !mappedLcl->lvTracked || compiler->compJmpOpUsed || (mappedLcl->lvRefCnt() != 0); + if (mappedLcl->lvIsStructField) + { + // Struct fields are not saved into their parameter local + isLive = isMappedLclLive; + } + else + { + isLive = isParameterLive || isMappedLclLive; + } + } + else + { + isLive = isParameterLive; } - RegState* regState = genIsValidFloatReg(seg.GetRegister()) ? floatRegState : intRegState; - regState->rsCalleeRegArgMaskLiveIn |= seg.GetRegisterMask(); + JITDUMP("Arg V%02u is %s in reg %s\n", mapping != nullptr ? mapping->LclNum : lclNum, + isLive ? "live" : "dead", getRegName(seg.GetRegister())); + + if (isLive) + { + RegState* regState = genIsValidFloatReg(seg.GetRegister()) ? floatRegState : intRegState; + regState->rsCalleeRegArgMaskLiveIn |= seg.GetRegisterMask(); + } } } @@ -4468,7 +4486,7 @@ int LinearScan::BuildPutArgReg(GenTreeUnOp* node) SingleTypeRegSet argMask = genSingleTypeRegMask(argReg); RefPosition* use = BuildUse(op1, argMask); - // Record that this register is occupied by a register now. + // Record that this register is occupied by an argument now. placedArgRegs.AddRegNumInMask(argReg); if (supportsSpecialPutArg() && isCandidateLocalRef(op1) && ((op1->gtFlags & GTF_VAR_DEATH) == 0)) diff --git a/src/coreclr/jit/promotion.cpp b/src/coreclr/jit/promotion.cpp index 43ae688490615e..7db809bc5cadf8 100644 --- a/src/coreclr/jit/promotion.cpp +++ b/src/coreclr/jit/promotion.cpp @@ -767,12 +767,34 @@ class LocalUses unsigned countReadBacks = 0; weight_t countReadBacksWtd = 0; - // For parameters or OSR locals we always need one read back. - if (lcl->lvIsParam || lcl->lvIsOSRLocal) + + // For OSR locals we always need one read back. + if (lcl->lvIsOSRLocal) { countReadBacks++; countReadBacksWtd += comp->fgFirstBB->getBBWeight(comp); } + else if (lcl->lvIsParam) + { + // For parameters, the backend may be able to map it directly from a register. + if (MapsToRegister(comp, access, lclNum)) + { + // No promotion will result in a store to stack in the prolog. + costWithout += COST_STRUCT_ACCESS_CYCLES * comp->fgFirstBB->getBBWeight(comp); + sizeWithout += COST_STRUCT_ACCESS_SIZE; + + // Promotion we cost like the normal reg accesses above + costWith += COST_REG_ACCESS_CYCLES * comp->fgFirstBB->getBBWeight(comp); + sizeWith += COST_REG_ACCESS_SIZE; + } + else + { + // Otherwise we expect no prolog work to be required if we + // don't promote, and we need a read back from the stack. + countReadBacks++; + countReadBacksWtd += comp->fgFirstBB->getBBWeight(comp); + } + } // If the struct is stored from a call (either due to a multireg // return or by being passed as the retbuffer) then we need a readback @@ -1000,6 +1022,46 @@ class LocalUses return nullptr; } + + //------------------------------------------------------------------------ + // MapsToRegister: + // Check if a specific access in the specified parameter local is + // expected to map to a register. + // + // Parameters: + // comp - Compiler instance + // access - Access in the local + // lclNum - Parameter lcl num + // + // Returns: + // Pointer to a matching access, or nullptr if no match was found. + // + bool MapsToRegister(Compiler* comp, const Access& access, unsigned lclNum) + { + assert(lclNum < comp->info.compArgsCount); + + if (comp->lvaIsImplicitByRefLocal(lclNum)) + { + return false; + } + + const ABIPassingInformation& abiInfo = comp->lvaGetParameterABIInfo(lclNum); + if (abiInfo.HasAnyStackSegment()) + { + return false; + } + + for (const ABIPassingSegment& seg : abiInfo.Segments()) + { + if ((access.Offset == seg.Offset) && (genTypeSize(access.AccessType) == seg.Size) && + (varTypeUsesIntReg(access.AccessType) == genIsValidIntReg(seg.GetRegister()))) + { + return true; + } + } + + return false; + } }; // Struct used to save all struct stores involving physical promotion candidates. From 771539182c280c9933ad57422583f1380541eda1 Mon Sep 17 00:00:00 2001 From: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Date: Tue, 11 Feb 2025 11:40:48 +0100 Subject: [PATCH 03/20] Add optional hooks for debugging OpenSSL memory allocations (#111539) * add hooks to debug OpenSSL memory * opensslshim * 1.x * 1.0.1 * android * Collections * unsafe * build * feedback * update * feedback * feedback * feedback * fix build * gcc * gcc * Update src/native/libs/System.Security.Cryptography.Native/openssl.c Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> * Move init to Interop.Crypto * Fix data race on GetIncrementalAllocations * Use modern tuple type * Fix typo * Move functionality to separate file * Revert unnecessary changes * WIP tracking in native code * Improvements * Reintroduce rw lock * Add readme * Fix build * Code review feedback * code review changes - cont. * More code review feedback * Expose the "API" via system.security.cryptography * Fix infinite link list traversal * Fix memory accounting for realloc * Refactoring * Improve comments * Improve Readme * Simplify implementation * Don't use CRYPTO_atomic_add * Readme fixes * Fix build * Fix compilation, attempt 2 * Fix build - attemt no 3 * Apply suggestions from code review Co-authored-by: Jeremy Barton * Feedback --------- Co-authored-by: wfurt Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> Co-authored-by: Jeremy Barton --- .../Interop.Crypto.cs | 50 +++ .../README.md | 77 +++++ .../ILLink.Descriptors.LibraryBuild.xml | 12 + .../CMakeLists.txt | 1 + .../apibridge.h | 6 + .../entrypoints.c | 4 + .../memory_debug.c | 308 ++++++++++++++++++ .../memory_debug.h | 12 + .../openssl.c | 6 + .../opensslshim.h | 2 + 10 files changed, 478 insertions(+) create mode 100644 src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/README.md create mode 100644 src/libraries/System.Security.Cryptography/src/ILLink/ILLink.Descriptors.LibraryBuild.xml create mode 100644 src/native/libs/System.Security.Cryptography.Native/memory_debug.c create mode 100644 src/native/libs/System.Security.Cryptography.Native/memory_debug.h diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs index 27b047b8308ed3..ff72852caa75c6 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs @@ -3,10 +3,13 @@ using System; using System.Diagnostics; +using System.Globalization; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; +using TrackedAllocationDelegate = System.Action; + internal static partial class Interop { internal static partial class Crypto @@ -164,5 +167,52 @@ internal static byte[] GetDynamicBuffer(NegativeSizeReadMethod return bytes; } + + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetMemoryUse")] + private static partial void GetMemoryUse(ref long memoryUse, ref long allocationCount); + + internal static long GetOpenSslAllocatedMemory() + { + long used = 0; + long count = 0; + GetMemoryUse(ref used, ref count); + return used; + } + + internal static long GetOpenSslAllocationCount() + { + long used = 0; + long count = 0; + GetMemoryUse(ref used, ref count); + return count; + } + + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EnableMemoryTracking")] + internal static unsafe partial void EnableMemoryTracking(int enable); + + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ForEachTrackedAllocation")] + private static unsafe partial void ForEachTrackedAllocation(delegate* unmanaged callback, IntPtr ctx); + + internal static unsafe void ForEachTrackedAllocation(TrackedAllocationDelegate callback) + { + ForEachTrackedAllocation(&MemoryTrackingCallback, (IntPtr)(&callback)); + } + + [UnmanagedCallersOnly] + private static unsafe void MemoryTrackingCallback(IntPtr ptr, ulong size, char* file, int line, IntPtr ctx) + { + TrackedAllocationDelegate callback = *(TrackedAllocationDelegate*)ctx; + callback(ptr, size, (IntPtr)file, line); + } + + internal static unsafe void EnableMemoryTracking() + { + EnableMemoryTracking(1); + } + + internal static unsafe void DisableMemoryTracking() + { + EnableMemoryTracking(0); + } } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/README.md b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/README.md new file mode 100644 index 00000000000000..8d081002ad1a9d --- /dev/null +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/README.md @@ -0,0 +1,77 @@ +# System.Security.Cryptography.Native + +This folder contains C# bindings for native shim (libSystem.Security.Cryptography.Native.OpenSsl.so), shimming functionality provided by the OpenSSL library. + +## Memory allocation hooks + +One extra feature exposed by the native shim is tracking of memory used by +OpenSSL by hooking the memory allocation routines via +`CRYPTO_set_mem_functions`. + +The functionality is enabled by setting +`DOTNET_OPENSSL_MEMORY_DEBUG` to 1. This environment +variable must be set before launching the program (calling +`Environment.SetEnvironmentVariable` at the start of the program is not +sufficient). The diagnostic API is not officially exposed and needs to be +accessed via private reflection on the `Interop.Crypto` type located in the +`System.Security.Cryptography` assembly. On this type, you can use following static +methods: + +- `int GetOpenSslAllocatedMemory()` + - Gets the total amount of memory allocated by OpenSSL +- `int GetOpenSslAllocationCount()` + - Gets the number of allocations made by OpenSSL +- `void EnableMemoryTracking()`/`void DisableMemoryTracking()` + - toggles tracking of individual live allocations via internal data + structures. I.e. will keep track of live memory allocated since the start of + tracking. +- `void ForEachTrackedAllocation(Action callback)` + - Accepts an callback and calls it for each allocation performed since the + last `EnableMemoryTracking` call. The order of reported information does not + correspond to the order of allocation. This method holds an internal lock + which prevents other threads from allocating any memory from OpenSSL. + - Callback parameters are + - IntPtr - The pointer to the allocated object + - ulong - size of the allocation in bytes + - IntPtr - Pointer to a null-terminated string (`const char*`) containing the name of the file from which the allocation was made. + - int - line number within the file specified by the previous parameter where the allocation was called from. + +The debug functionality brings some overhead (header for each allocation, +locks/synchronization during each allocation) and may cause performance penalty. + +### Example usage + +```cs +// all above mentioned APIs are accessible via "private reflection" +BindingFlags flags = BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Static; +var cryptoInterop = typeof(RandomNumberGenerator).Assembly.GetTypes().First(t => t.Name == "Crypto"); + +// enable tracking, this clears up any previously tracked allocations +cryptoInterop.InvokeMember("EnableMemoryTracking", flags, null, null, null); + +// do some work that includes OpenSSL +HttpClient client = new HttpClient(); +await client.GetAsync("https://www.microsoft.com"); + +// stop tracking (this step is optional) +cryptoInterop.InvokeMember("DisableMemoryTracking", flags, null, null, null); + +using var process = Process.GetCurrentProcess(); +Console.WriteLine($"Bytes known to GC [{GC.GetTotalMemory(false)}], process working set [{process.WorkingSet64}]"); +Console.WriteLine("OpenSSL - currently allocated memory: {0} B", cryptoInterop.InvokeMember("GetOpenSslAllocatedMemory", flags, null, null, null)); +Console.WriteLine("OpenSSL - total allocations since start: {0}", cryptoInterop.InvokeMember("GetOpenSslAllocationCount", flags, null, null, null)); + +Dictionary<(IntPtr file, int line), ulong> allAllocations = new(); +Action callback = (ptr, size, namePtr, line) => +{ + CollectionsMarshal.GetValueRefOrAddDefault(allAllocations, (namePtr, line), out _) += size; +}; +cryptoInterop.InvokeMember("ForEachTrackedAllocation", flags, null, null, [callback]); + +Console.WriteLine("Total allocated OpenSSL memory by location"); +foreach (var ((filenameptr, line), total) in allAllocations.OrderByDescending(kvp => kvp.Value).Take(10)) +{ + string filename = Marshal.PtrToStringUTF8(filenameptr); + Console.WriteLine($"{total:N0} B from {filename}:{line}"); +} +``` \ No newline at end of file diff --git a/src/libraries/System.Security.Cryptography/src/ILLink/ILLink.Descriptors.LibraryBuild.xml b/src/libraries/System.Security.Cryptography/src/ILLink/ILLink.Descriptors.LibraryBuild.xml new file mode 100644 index 00000000000000..6a151eaf89bdcb --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/ILLink/ILLink.Descriptors.LibraryBuild.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/native/libs/System.Security.Cryptography.Native/CMakeLists.txt b/src/native/libs/System.Security.Cryptography.Native/CMakeLists.txt index ca536c1697a601..4a1d2e9e5e8e61 100644 --- a/src/native/libs/System.Security.Cryptography.Native/CMakeLists.txt +++ b/src/native/libs/System.Security.Cryptography.Native/CMakeLists.txt @@ -21,6 +21,7 @@ include_directories(${OPENSSL_INCLUDE_DIR}) set(NATIVECRYPTO_SOURCES apibridge.c apibridge_30.c + memory_debug.c openssl.c pal_asn1.c pal_bignum.c diff --git a/src/native/libs/System.Security.Cryptography.Native/apibridge.h b/src/native/libs/System.Security.Cryptography.Native/apibridge.h index 06bfa4c2fe8fb9..ae305b977629dd 100644 --- a/src/native/libs/System.Security.Cryptography.Native/apibridge.h +++ b/src/native/libs/System.Security.Cryptography.Native/apibridge.h @@ -65,3 +65,9 @@ int32_t local_X509_get_version(const X509* x509); int32_t local_X509_up_ref(X509* x509); typedef void (*SSL_CTX_keylog_cb_func)(const SSL *ssl, const char *line); void local_SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb); + +typedef void *(*CRYPTO_malloc_fn)(size_t num, const char *file, int line); +typedef void *(*CRYPTO_realloc_fn)(void *addr, size_t num, const char *file, int line); +typedef void (*CRYPTO_free_fn)(void *addr, const char *file, int line); + +int CRYPTO_set_mem_functions(CRYPTO_malloc_fn malloc_fn, CRYPTO_realloc_fn realloc_fn, CRYPTO_free_fn free_fn); diff --git a/src/native/libs/System.Security.Cryptography.Native/entrypoints.c b/src/native/libs/System.Security.Cryptography.Native/entrypoints.c index 329d0932ecf72e..7d59afc0d33d1b 100644 --- a/src/native/libs/System.Security.Cryptography.Native/entrypoints.c +++ b/src/native/libs/System.Security.Cryptography.Native/entrypoints.c @@ -5,6 +5,7 @@ // Include System.Security.Cryptography.Native headers #include "openssl.h" +#include "memory_debug.h" #include "pal_asn1.h" #include "pal_bignum.h" #include "pal_bio.h" @@ -188,6 +189,9 @@ static const Entry s_cryptoNative[] = DllImportEntry(CryptoNative_GetECKeyParameters) DllImportEntry(CryptoNative_GetMaxMdSize) DllImportEntry(CryptoNative_GetMemoryBioSize) + DllImportEntry(CryptoNative_GetMemoryUse) + DllImportEntry(CryptoNative_EnableMemoryTracking) + DllImportEntry(CryptoNative_ForEachTrackedAllocation) DllImportEntry(CryptoNative_GetObjectDefinitionByName) DllImportEntry(CryptoNative_GetOcspRequestDerSize) DllImportEntry(CryptoNative_GetPkcs7Certificates) diff --git a/src/native/libs/System.Security.Cryptography.Native/memory_debug.c b/src/native/libs/System.Security.Cryptography.Native/memory_debug.c new file mode 100644 index 00000000000000..ed24da7086028a --- /dev/null +++ b/src/native/libs/System.Security.Cryptography.Native/memory_debug.c @@ -0,0 +1,308 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "opensslshim.h" +#include "memory_debug.h" + +#include +#include +#include +#include + +// +// OpenSSL memory tracking/debugging facilities. +// +// We can use CRYPTO_set_mem_functions to replace allocation routines in +// OpenSSL. This allows us to prepend each allocated memory with a header that +// contains the size and source of the allocation, which allows us to track how +// much memory is OpenSSL consuming (not including malloc overhead). +// +// Additionally, if requested, we can track all allocations over a period of +// time and present them to managed code for analysis (via reflection APIs). +// +// Given that there is an overhead associated with tracking, the feature is +// gated behind the DOTNET_OPENSSL_MEMORY_DEBUG environment variable and should +// not be enabled by default in production. +// +// To track all allocated objects in a given period, the allocated objects are +// stringed in a circular, doubly-linked list. This allows us to do O(1) +// insertion and deletion. All operations are done under lock to prevent data +// corruption. To prevent lock contention over a single list, we maintain +// multiple lists, each with its own lock and allocate them round-robin. +// + +// helper macro for getting the pointer to containing type from a pointer to a member +#define container_of(ptr, type, member) ((type*)((char*)(ptr) - offsetof(type, member))) + +typedef struct link_t +{ + struct link_t* next; + struct link_t* prev; +} link_t; + +typedef struct list_t +{ + link_t head; + pthread_mutex_t lock; +} list_t; + +// Whether outstanding allocations should be tracked +static int32_t g_trackingEnabled = 0; +// Static lists of tracked allocations. +static list_t* g_trackedMemory = NULL; +// Number of partitions (distinct lists in g_trackedMemory) to track outstanding +// allocations in. +static uint32_t kPartitionCount = 32; + +// header for each tracked allocation +typedef struct header_t +{ + // link for the circular list + struct link_t link; + + // size of the allocation (of the data field) + uint64_t size; + + // filename from where the allocation was made + const char* file; + + // line number in the file where the allocation was made + int32_t line; + + // index of the list where this entry is stored + uint32_t index; + + // the start of actual allocated memory + __attribute__((aligned(8))) uint8_t data[]; +} header_t; + +static uint64_t g_allocatedMemory; +static uint64_t g_allocationCount; + +static void list_link_init(link_t* link) +{ + link->next = link; + link->prev = link; +} + +static void list_init(list_t* list) +{ + list_link_init(&list->head); + + int res = pthread_mutex_init(&list->lock, NULL); + assert(res == 0); +} + +static void list_insert_link(link_t* item, link_t* prev, link_t* next) +{ + next->prev = item; + item->next = next; + item->prev = prev; + prev->next = item; +} + +static void list_unlink_item(link_t* item) +{ + link_t* prev = item->prev; + link_t* next = item->next; + + prev->next = next; + next->prev = prev; + + list_link_init(item); +} + +static void init_memory_entry(header_t* entry, size_t size, const char* file, int32_t line) +{ + uint64_t newCount = __atomic_fetch_add(&g_allocationCount, 1, __ATOMIC_SEQ_CST); + + entry->size = size; + entry->line = line; + entry->file = file; + list_link_init(&entry->link); + entry->index = (uint32_t)(newCount % kPartitionCount); +} + +static list_t* get_item_bucket(header_t* entry) +{ + uint32_t index = entry->index % kPartitionCount; + return &g_trackedMemory[index]; +} + +static void do_track_entry(header_t* entry, int32_t add) +{ + __atomic_fetch_add(&g_allocatedMemory, (add != 0 ? entry->size : -entry->size), __ATOMIC_SEQ_CST); + + if (add != 0 && !g_trackingEnabled) + { + // don't track this (new) allocation individually + return; + } + + if (add == 0 && entry->link.next == &entry->link) + { + // freeing allocation, which is not in any list, skip taking the lock + return; + } + + list_t* list = get_item_bucket(entry); + int res = pthread_mutex_lock(&list->lock); + assert (res == 0); + + if (add != 0) + { + list_insert_link(&entry->link, &list->head, list->head.next); + } + else + { + list_unlink_item(&entry->link); + } + + res = pthread_mutex_unlock(&list->lock); + assert (res == 0); +} + +static void* mallocFunction(size_t size, const char *file, int line) +{ + header_t* entry = malloc(size + sizeof(header_t)); + if (entry != NULL) + { + init_memory_entry(entry, size, file, line); + do_track_entry(entry, 1); + } + + return (void*)(&entry->data); +} + +static void* reallocFunction (void *ptr, size_t size, const char *file, int line) +{ + struct header_t* entry = NULL; + + if (ptr != NULL) + { + entry = container_of(ptr, header_t, data); + + // untrack the item as realloc will free the memory and copy the contents elsewhere + do_track_entry(entry, 0); + } + + void* toReturn = NULL; + header_t* newEntry = (header_t*) realloc((void*)entry, size + sizeof(header_t)); + if (newEntry != NULL) + { + entry = newEntry; + + init_memory_entry(entry, size, file, line); + toReturn = (void*)(&entry->data); + } + + // either track the new memory, or add back the original one if realloc failed + if (entry) + { + do_track_entry(entry, 1); + } + + return toReturn; +} + +static void freeFunction(void *ptr, const char *file, int line) +{ + (void)file; + (void)line; + + if (ptr != NULL) + { + header_t* entry = container_of(ptr, header_t, data); + do_track_entry(entry, 0); + free(entry); + } +} + +void CryptoNative_GetMemoryUse(uint64_t* totalUsed, uint64_t* allocationCount) +{ + assert(totalUsed != NULL); + assert(allocationCount != NULL); + + *totalUsed = g_allocatedMemory; + *allocationCount = g_allocationCount; +} + +void CryptoNative_EnableMemoryTracking(int32_t enable) +{ + if (g_trackedMemory == NULL) + { + return; + } + + if (enable) + { + // Clear the lists by unlinking the list heads, any existing items in + // the list will become orphaned in a "floating" circular list. + // we will keep removing items from the list as they are freed + for (uint32_t i = 0; i < kPartitionCount; i++) + { + list_t* list = &g_trackedMemory[i]; + + pthread_mutex_lock(&list->lock); + + list_unlink_item(&list->head); + + pthread_mutex_unlock(&list->lock); + } + } + + g_trackingEnabled = enable; +} + +void CryptoNative_ForEachTrackedAllocation(void (*callback)(void* ptr, uint64_t size, const char* file, int32_t line, void* ctx), void* ctx) +{ + assert(callback != NULL); + + if (g_trackedMemory == NULL) + { + return; + } + + for (uint32_t i = 0; i < kPartitionCount; i++) + { + list_t* list = &g_trackedMemory[i]; + + pthread_mutex_lock(&list->lock); + for (link_t* node = list->head.next; node != &list->head; node = node->next) + { + header_t* entry = container_of(node, header_t, link); + callback(entry->data, entry->size, entry->file, entry->line, ctx); + } + pthread_mutex_unlock(&list->lock); + } +} + +static void init_tracking_lists(void) +{ + g_trackedMemory = malloc(kPartitionCount * sizeof(list_t)); + for (uint32_t i = 0; i < kPartitionCount; i++) + { + list_init(&g_trackedMemory[i]); + } +} + +void InitializeMemoryDebug(void) +{ + const char* debug = getenv("DOTNET_OPENSSL_MEMORY_DEBUG"); + if (debug != NULL && strcmp(debug, "1") == 0) + { +#ifdef FEATURE_DISTRO_AGNOSTIC_SSL + if (API_EXISTS(CRYPTO_set_mem_functions)) + { + // This should cover 1.1.1+ + CRYPTO_set_mem_functions(mallocFunction, reallocFunction, freeFunction); + init_tracking_lists(); + } +#elif OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_1_1_1_RTM + // OpenSSL 1.0 has different prototypes and it is out of support so we enable this only + // on 1.1.1+ + CRYPTO_set_mem_functions(mallocFunction, reallocFunction, freeFunction); + init_tracking_lists(); +#endif + } +} diff --git a/src/native/libs/System.Security.Cryptography.Native/memory_debug.h b/src/native/libs/System.Security.Cryptography.Native/memory_debug.h new file mode 100644 index 00000000000000..38572ea227651e --- /dev/null +++ b/src/native/libs/System.Security.Cryptography.Native/memory_debug.h @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "pal_types.h" + +void InitializeMemoryDebug(void); + +PALEXPORT void CryptoNative_EnableMemoryTracking(int32_t enable); + +PALEXPORT void CryptoNative_ForEachTrackedAllocation(void (*callback)(void* ptr, uint64_t size, const char* file, int32_t line, void* ctx), void* ctx); + +PALEXPORT void CryptoNative_GetMemoryUse(uint64_t* totalUsed, uint64_t* allocationCount); diff --git a/src/native/libs/System.Security.Cryptography.Native/openssl.c b/src/native/libs/System.Security.Cryptography.Native/openssl.c index d63481421a1323..f752da891b287c 100644 --- a/src/native/libs/System.Security.Cryptography.Native/openssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/openssl.c @@ -7,6 +7,7 @@ #include "pal_safecrt.h" #include "pal_x509.h" #include "pal_ssl.h" +#include "memory_debug.h" #include "openssl.h" #ifdef FEATURE_DISTRO_AGNOSTIC_SSL @@ -1508,7 +1509,12 @@ static int32_t EnsureOpenSslInitializedCore(void) // Otherwise call the 1.1 one. #ifdef FEATURE_DISTRO_AGNOSTIC_SSL InitializeOpenSSLShim(); +#endif + // This needs to be done before any allocation is done e.g. EnsureOpenSsl* is called. + // And it also needs to be after the pointers are loaded for DISTRO_AGNOSTIC_SSL + InitializeMemoryDebug(); +#ifdef FEATURE_DISTRO_AGNOSTIC_SSL if (API_EXISTS(SSL_state)) { ret = EnsureOpenSsl10Initialized(); diff --git a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h index 9f7228d06e13ca..400ecf9275b6d3 100644 --- a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h +++ b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h @@ -313,6 +313,7 @@ extern bool g_libSslUses32BitTime; REQUIRED_FUNCTION(CRYPTO_malloc) \ LEGACY_FUNCTION(CRYPTO_num_locks) \ LEGACY_FUNCTION(CRYPTO_set_locking_callback) \ + REQUIRED_FUNCTION(CRYPTO_set_mem_functions) \ REQUIRED_FUNCTION(d2i_OCSP_RESPONSE) \ REQUIRED_FUNCTION(d2i_PKCS12_fp) \ REQUIRED_FUNCTION(d2i_PKCS7) \ @@ -861,6 +862,7 @@ extern TYPEOF(OPENSSL_gmtime)* OPENSSL_gmtime_ptr; #define CRYPTO_malloc CRYPTO_malloc_ptr #define CRYPTO_num_locks CRYPTO_num_locks_ptr #define CRYPTO_set_locking_callback CRYPTO_set_locking_callback_ptr +#define CRYPTO_set_mem_functions CRYPTO_set_mem_functions_ptr #define d2i_OCSP_RESPONSE d2i_OCSP_RESPONSE_ptr #define d2i_PKCS12_fp d2i_PKCS12_fp_ptr #define d2i_PKCS7 d2i_PKCS7_ptr From 6649e7f1f941d869498ecbf8710623ac86d9d115 Mon Sep 17 00:00:00 2001 From: Katelyn Gadd Date: Tue, 11 Feb 2025 05:02:50 -0800 Subject: [PATCH 04/20] Guard members of MonoType union & fix related bugs (#111645) * Guard members of MonoType union behind type check helpers * Add _unchecked to call sites that are obviously guarded correctly * Fix type confusion in bulk_type_log_single_type * Fix genericinst fallthrough treating a MonoGenericClass ptr as a MonoClass ptr * Fix type confusion in amd64 mini * Fix type confusion in aot-runtime-wasm * Prune a dead goto to make unchecked safe * Fix two cases where we were partially initializing a stack-allocated MonoType instead of fully initializing it * See https://github.com/dotnet/runtime/issues/112395 for detailed list of bugs fixed --- src/mono/mono/component/debugger-agent.c | 82 +++---- src/mono/mono/component/marshal-ilgen.c | 20 +- .../eventpipe/ep-rt-mono-runtime-provider.c | 29 ++- src/mono/mono/metadata/class-init.c | 33 +-- src/mono/mono/metadata/class-internals.h | 4 +- src/mono/mono/metadata/class.c | 201 ++++++++-------- src/mono/mono/metadata/custom-attrs.c | 41 ++-- src/mono/mono/metadata/debug-helpers.c | 20 +- src/mono/mono/metadata/icall.c | 49 ++-- src/mono/mono/metadata/marshal-lightweight.c | 10 +- src/mono/mono/metadata/marshal-shared.c | 10 +- src/mono/mono/metadata/marshal.c | 57 +++-- src/mono/mono/metadata/metadata-internals.h | 118 ++++++++- src/mono/mono/metadata/metadata.c | 227 +++++++++--------- src/mono/mono/metadata/object.c | 20 +- src/mono/mono/metadata/reflection.c | 22 +- src/mono/mono/metadata/sre-encode.c | 10 +- src/mono/mono/metadata/sre.c | 43 ++-- src/mono/mono/mini/aot-compiler.c | 28 +-- src/mono/mono/mini/aot-runtime-wasm.c | 7 +- src/mono/mono/mini/aot-runtime.c | 32 +-- src/mono/mono/mini/calls.c | 6 +- src/mono/mono/mini/interp/interp.c | 36 +-- src/mono/mono/mini/interp/transform-simd.c | 6 +- src/mono/mono/mini/interp/transform.c | 12 +- src/mono/mono/mini/intrinsics.c | 8 +- src/mono/mono/mini/method-to-ir.c | 28 +-- src/mono/mono/mini/mini-amd64.c | 33 +-- src/mono/mono/mini/mini-generic-sharing.c | 51 ++-- src/mono/mono/mini/mini-llvm.c | 6 +- src/mono/mono/mini/mini.c | 20 +- src/mono/mono/profiler/aot.c | 2 +- 32 files changed, 709 insertions(+), 562 deletions(-) diff --git a/src/mono/mono/component/debugger-agent.c b/src/mono/mono/component/debugger-agent.c index 323f5e277c6767..4ada4f89fdafdb 100644 --- a/src/mono/mono/component/debugger-agent.c +++ b/src/mono/mono/component/debugger-agent.c @@ -779,11 +779,11 @@ mono_debugger_agent_init_internal (void) mono_de_init (&cbs); transport_init (); - + start_debugger_thread_func = start_debugger_thread; suspend_vm_func = suspend_vm; suspend_current_func = suspend_current; - + /* Need to know whenever a thread has acquired the loader mutex */ mono_loader_lock_track_ownership (TRUE); @@ -1627,7 +1627,7 @@ mono_init_debugger_agent_common (MonoProfilerHandle *prof) mono_profiler_set_thread_started_callback (*prof, thread_startup); mono_profiler_set_thread_stopped_callback (*prof, thread_end); mono_profiler_set_jit_done_callback (*prof, jit_done); - + mono_native_tls_alloc (&debugger_tls_id, NULL); /* Needed by the hash_table_new_type () call below */ @@ -2634,7 +2634,7 @@ resume_vm (void) mono_loader_unlock (); #else resumed_from_wasi = TRUE; -#endif +#endif } /* @@ -3122,7 +3122,7 @@ compute_frame_info (MonoInternalThread *thread, DebuggerTlsData *tls, gboolean f #else tls->frame_count = 0; return; -#endif +#endif } new_frame_count = g_slist_length (user_data.frames); @@ -4629,7 +4629,7 @@ ensure_runtime_is_suspended (void) { #ifdef HOST_WASI return ERR_NONE; -#endif +#endif if (suspend_count == 0) return ERR_NOT_SUSPENDED; @@ -5291,7 +5291,7 @@ buffer_add_value_full (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain, continue; if (CHECK_ICORDBG (TRUE)) buffer_add_int (buf, mono_class_get_field_token (f)); - if (mono_vtype_get_field_addr (addr, f) == addr && mono_class_from_mono_type_internal (t) == mono_class_from_mono_type_internal (f->type) && !boxed_vtype) //to avoid infinite recursion + if (mono_vtype_get_field_addr (addr, f) == addr && mono_class_from_mono_type_internal (t) == mono_class_from_mono_type_internal (f->type) && !boxed_vtype) //to avoid infinite recursion { gssize val = *(gssize*)addr; if (CHECK_ICORDBG (TRUE)) @@ -5351,7 +5351,7 @@ obj_is_of_type (MonoObject *obj, MonoType *t) static ErrorCode decode_value (MonoType *t, MonoDomain *domain, gpointer void_addr, gpointer void_buf, guint8 **endbuf, guint8 *limit, gboolean check_field_datatype, guint8 **extra_space, gboolean from_by_ref_value_type); -static int +static int decode_value_compute_size (MonoType *t, int type, MonoDomain *domain, guint8 *buf, guint8 **endbuf, guint8 *limit, gboolean from_by_ref_value_type); static ErrorCode @@ -5419,7 +5419,7 @@ decode_vtype (MonoType *t, MonoDomain *domain, gpointer void_addr, gpointer void return ERR_NONE; } -static ErrorCode +static ErrorCode decode_fixed_size_array_internal (MonoType *t, int type, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8 **endbuf, guint8 *limit, gboolean check_field_datatype) { ErrorCode err = ERR_NONE; @@ -5475,7 +5475,7 @@ decode_fixed_size_array_internal (MonoType *t, int type, MonoDomain *domain, gui } -static int +static int decode_fixed_size_array_compute_size_internal (MonoType *t, int type, MonoDomain *domain, guint8 *buf, guint8 **endbuf, guint8 *limit) { int ret = 0; @@ -5510,7 +5510,7 @@ decode_fixed_size_array_compute_size_internal (MonoType *t, int type, MonoDomain ret += sizeof(guint32); break; case MONO_TYPE_I8: - case MONO_TYPE_U8: + case MONO_TYPE_U8: case MONO_TYPE_R8: decode_long (buf, &buf, limit); ret += sizeof(guint64); @@ -5561,7 +5561,7 @@ decode_vtype_compute_size (MonoType *t, MonoDomain *domain, gpointer void_buf, g continue; if (mono_field_is_deleted (f)) continue; - + gboolean cur_field_in_extra_space = from_by_ref_value_type; gboolean members_in_extra_space = cur_field_in_extra_space || m_type_is_byref (f->type) || m_class_is_byreflike (mono_class_from_mono_type_internal (f->type)); int field_size = decode_value_compute_size (f->type, 0, domain, buf, &buf, limit, members_in_extra_space); @@ -5587,7 +5587,7 @@ decode_vtype_compute_size (MonoType *t, MonoDomain *domain, gpointer void_buf, g return ret; } -static int +static int decode_value_compute_size (MonoType *t, int type, MonoDomain *domain, guint8 *buf, guint8 **endbuf, guint8 *limit, gboolean from_by_ref_value_type) { if (type == 0) @@ -5632,12 +5632,12 @@ decode_value_compute_size (MonoType *t, int type, MonoDomain *domain, guint8 *bu break; case MONO_TYPE_I4: case MONO_TYPE_U4: - case MONO_TYPE_R4: + case MONO_TYPE_R4: decode_int (buf, &buf, limit); ret += sizeof(guint32); break; case MONO_TYPE_I8: - case MONO_TYPE_U8: + case MONO_TYPE_U8: case MONO_TYPE_R8: decode_long (buf, &buf, limit); ret += sizeof(guint64); @@ -5693,8 +5693,8 @@ decode_value_compute_size (MonoType *t, int type, MonoDomain *domain, guint8 *bu goto end; } } else if ((t->type == MONO_TYPE_GENERICINST) && - mono_metadata_generic_class_is_valuetype (t->data.generic_class) && - m_class_is_enumtype (t->data.generic_class->container_class)){ + mono_metadata_generic_class_is_valuetype (m_type_data_get_generic_class_unchecked (t)) && + m_class_is_enumtype (m_type_data_get_generic_class_unchecked (t)->container_class)){ ret += decode_vtype_compute_size (t, domain, buf, &buf, limit, from_by_ref_value_type); } else { NOT_IMPLEMENTED; @@ -5916,8 +5916,8 @@ decode_value_internal (MonoType *t, int type, MonoDomain *domain, guint8 *addr, return ERR_INVALID_ARGUMENT; } } else if ((t->type == MONO_TYPE_GENERICINST) && - mono_metadata_generic_class_is_valuetype (t->data.generic_class) && - m_class_is_enumtype (t->data.generic_class->container_class)){ + mono_metadata_generic_class_is_valuetype (m_type_data_get_generic_class_unchecked (t)) && + m_class_is_enumtype (m_type_data_get_generic_class_unchecked (t)->container_class)){ err = decode_vtype (t, domain, addr, buf, &buf, limit, check_field_datatype, extra_space, from_by_ref_value_type); if (err != ERR_NONE) return err; @@ -5944,7 +5944,7 @@ decode_value (MonoType *t, MonoDomain *domain, gpointer void_addr, gpointer void int type = decode_byte (buf, &buf, limit); if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type_internal (t))) { - MonoType *targ = t->data.generic_class->context.class_inst->type_argv [0]; + MonoType *targ = m_type_data_get_generic_class_unchecked (t)->context.class_inst->type_argv [0]; guint8 *nullable_buf; /* @@ -6359,7 +6359,7 @@ mono_do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, gu MonoDomain *domain; guint8 *this_buf; guint8 *extra_space = NULL; - int extra_space_size = 0; + int extra_space_size = 0; #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED MonoLMFExt ext; #endif @@ -7099,7 +7099,7 @@ find_assembly_by_name (char* assembly_name) //resolve the assembly MonoImageOpenStatus status; MonoAssemblyName* aname = mono_assembly_name_new (lookup_name); - g_free (lookup_name); + g_free (lookup_name); if (!aname) { PRINT_DEBUG_MSG (1, "Could not resolve assembly %s\n", assembly_name); return NULL; @@ -7518,7 +7518,7 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf) guint8* memory = (guint8*)GINT_TO_POINTER (decode_long (p, &p, end)); int size = decode_int (p, &p, end); if (!valid_memory_address(memory, size)) - return ERR_INVALID_ARGUMENT; + return ERR_INVALID_ARGUMENT; PRINT_DEBUG_MSG (1, "MDBGPROT_CMD_VM_READ_MEMORY - [%p] - size - %d\n", memory, size); buffer_add_byte_array (buf, memory, size); break; @@ -7595,7 +7595,7 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf) break; case MONO_TYPE_I8: buffer_add_typeid (buf, mono_get_root_domain (), mono_get_int64_class ()); - break; + break; case MONO_TYPE_U8: buffer_add_typeid (buf, mono_get_root_domain (), mono_get_uint64_class ()); break; @@ -7642,7 +7642,7 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf) symfile_size = ppdb_compressed_size; pdb_bytes = ppdb_data; } - } + } } m_dbgprot_buffer_init (buf, assembly_size + symfile_size + 1024); m_dbgprot_buffer_add_byte_array (buf, (uint8_t *) assembly_bytes, assembly_size); @@ -7805,7 +7805,7 @@ event_commands (int command, guint8 *p, guint8 *end, Buffer *buf) if (req->event_kind == EVENT_KIND_BREAKPOINT) { g_assert (method); - + req->info = mono_de_set_breakpoint (method, location, req, error); if (!is_ok (error)) { g_free (req); @@ -8064,7 +8064,7 @@ domain_commands (int command, guint8 *p, guint8 *end, Buffer *buf) klass = decode_typeid (p, &p, end, NULL, &err); int rank = decode_int (p, &p, end); uintptr_t *lengths = g_newa (uintptr_t, rank); - intptr_t *lower_bounds = g_newa (intptr_t, rank); + intptr_t *lower_bounds = g_newa (intptr_t, rank); for (int i = 0 ; i < rank; i++) { lengths [i] = decode_int (p, &p, end); @@ -8628,10 +8628,10 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint { if (type->type == MONO_TYPE_FNPTR) { - buffer_add_int (buf, 1 + type->data.method->param_count); - buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (type->data.method->ret)); - for (int j = 0; j < type->data.method->param_count; ++j) { - buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (type->data.method->params[j])); + buffer_add_int (buf, 1 + m_type_data_get_method_unchecked (type)->param_count); + buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (m_type_data_get_method_unchecked (type)->ret)); + for (int j = 0; j < m_type_data_get_method_unchecked (type)->param_count; ++j) { + buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (m_type_data_get_method_unchecked (type)->params[j])); } } else { buffer_add_int (buf, 0); @@ -8830,7 +8830,7 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint } case MDBGPROT_CMD_TYPE_SET_VALUES_BY_FIELD_TOKEN: { len = 0; - gpointer iter = NULL; + gpointer iter = NULL; len = decode_int (p, &p, end); int field_token = decode_int (p, &p, end); while ((f = mono_class_get_fields_internal (klass, &iter))) { @@ -9122,18 +9122,18 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint g_free (type_argv); break; } - case MDBGPROT_CMD_TYPE_ELEMENT_TYPE: + case MDBGPROT_CMD_TYPE_ELEMENT_TYPE: { buffer_add_int (buf, m_class_get_byval_arg (klass)->type); buffer_add_byte (buf, GINT_TO_UINT8 (MONO_TYPE_ISSTRUCT (m_class_get_byval_arg (klass)))); break; } - case MDBGPROT_CMD_TYPE_RANK: + case MDBGPROT_CMD_TYPE_RANK: { buffer_add_byte (buf, m_class_get_rank (klass)); break; } - case MDBGPROT_CMD_TYPE_GET_FIELD_RVA: + case MDBGPROT_CMD_TYPE_GET_FIELD_RVA: { gpointer iter = NULL; int field_token = decode_int (p, &p, end); @@ -9683,9 +9683,9 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g MonoGenericContext *context; GString *res; res = g_string_new (""); - mono_type_get_desc (res, m_class_get_byval_arg (type->data.generic_class->container_class), TRUE); + mono_type_get_desc (res, m_class_get_byval_arg (m_type_data_get_generic_class_unchecked (type)->container_class), TRUE); buffer_add_string (buf, (g_string_free (res, FALSE))); - context = &type->data.generic_class->context; + context = &m_type_data_get_generic_class_unchecked (type)->context; if (context->class_inst) buffer_add_int (buf, context->class_inst->type_argc); else @@ -9892,7 +9892,7 @@ thread_commands (int command, guint8 *p, guint8 *end, Buffer *buf) if (suspend_count) wait_for_suspend (); } -#endif +#endif /* if (suspend_count) wait_for_suspend (); @@ -10548,7 +10548,7 @@ object_commands (int command, guint8 *p, guint8 *end, Buffer *buf) break; } } - //Above for loop might end if 'k' is null , ensure 'k' is not + //Above for loop might end if 'k' is null , ensure 'k' is not //null before passing it to mono_class_get_fields_internal to avoid crash while (k && (f = mono_class_get_fields_internal (k, &iter))) { if (mono_class_get_field_token (f) == field_token) { @@ -10699,7 +10699,7 @@ object_commands (int command, guint8 *p, guint8 *end, Buffer *buf) break; case MDBGPROT_CMD_OBJECT_IS_DELEGATE: { MonoType *type = m_class_get_byval_arg (obj_type); - if (m_class_is_delegate (obj_type) || (type->type == MONO_TYPE_GENERICINST && m_class_is_delegate (type->data.generic_class->container_class))) + if (m_class_is_delegate (obj_type) || (type->type == MONO_TYPE_GENERICINST && m_class_is_delegate (m_type_data_get_generic_class_unchecked (type)->container_class))) buffer_add_byte (buf, TRUE); else buffer_add_byte (buf, FALSE); @@ -11156,7 +11156,7 @@ gboolean mono_debugger_agent_receive_and_process_command (void) Buffer buf; ErrorCode err; gboolean no_reply; - + gboolean log_each_step = g_hasenv ("MONO_DEBUGGER_LOG_AFTER_COMMAND"); while (TRUE) { diff --git a/src/mono/mono/component/marshal-ilgen.c b/src/mono/mono/component/marshal-ilgen.c index 5848f22c87c413..9a74df582f6afd 100644 --- a/src/mono/mono/component/marshal-ilgen.c +++ b/src/mono/mono/component/marshal-ilgen.c @@ -54,11 +54,11 @@ static MonoComponentMarshalILgen component_func_table = { &ilgen_init_internal, &emit_marshal_ilgen, &ilgen_install_callbacks_mono, -}; +}; MonoComponentMarshalILgen* -mono_component_marshal_ilgen_init (void) +mono_component_marshal_ilgen_init (void) { return &component_func_table; } @@ -842,7 +842,7 @@ emit_marshal_ptr_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, case MARSHAL_ACTION_CONV_IN: /* MS seems to allow this in some cases, ie. bxc #158 */ /* - if (MONO_TYPE_ISSTRUCT (t->data.type) && !mono_class_from_mono_type_internal (t->data.type)->blittable) { + if (MONO_TYPE_ISSTRUCT (m_type_data_get_type (t)) && !mono_class_from_mono_type_internal (m_type_data_get_type (t))->blittable) { char *msg = g_strdup_printf ("Can not marshal 'parameter #%d': Pointers can not reference marshaled structures. Use byref instead.", argnum + 1); cb_to_mono->methodBuilder.emit_exception_marshal_directive (m->mb, msg); } @@ -1965,7 +1965,7 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, * leak the handle. We should move the allocation of the SafeHandle to the * input marshalling code to prevent that. */ - ctor = mono_class_get_method_from_name_checked (t->data.klass, ".ctor", 0, 0, local_error); + ctor = mono_class_get_method_from_name_checked (m_type_data_get_klass (t), ".ctor", 0, 0, local_error); if (ctor == NULL || !is_ok (local_error)){ cb_to_mono->methodBuilder.emit_exception (mb, "MissingMethodException", "parameterless constructor required"); mono_error_cleanup (local_error); @@ -2003,13 +2003,15 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, MonoMethod *ctor = NULL; int intptr_handle_slot; - if (mono_class_is_abstract (t->data.klass)) { + MonoClass *klass_of_t = m_type_data_get_klass (t); + + if (mono_class_is_abstract (klass_of_t)) { cb_to_mono->methodBuilder.emit_byte (mb, CEE_POP); cb_to_mono->methodBuilder.emit_exception_marshal_directive (mb, g_strdup ("Returned SafeHandles should not be abstract")); break; } - ctor = mono_class_get_method_from_name_checked (t->data.klass, ".ctor", 0, 0, error); + ctor = mono_class_get_method_from_name_checked (klass_of_t, ".ctor", 0, 0, error); if (ctor == NULL || !is_ok (error)){ mono_error_cleanup (error); cb_to_mono->methodBuilder.emit_byte (mb, CEE_POP); @@ -2628,7 +2630,7 @@ emit_marshal_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, switch (t->type) { case MONO_TYPE_VALUETYPE: - if (t->data.klass == cb_to_mono->class_try_get_handleref_class ()) + if (m_type_data_get_klass_unchecked (t) == cb_to_mono->class_try_get_handleref_class ()) return emit_marshal_handleref_ilgen (m, argnum, t, spec, conv_arg, conv_arg_type, action); return emit_marshal_vtype_ilgen (m, argnum, t, spec, conv_arg, conv_arg_type, action); @@ -2636,8 +2638,8 @@ emit_marshal_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, return emit_marshal_string_ilgen (m, argnum, t, spec, conv_arg, conv_arg_type, action); case MONO_TYPE_CLASS: case MONO_TYPE_OBJECT: - if (cb_to_mono->try_get_safehandle_class () != NULL && t->data.klass && - cb_to_mono->is_subclass_of_internal (t->data.klass, cb_to_mono->try_get_safehandle_class (), FALSE)) + if (cb_to_mono->try_get_safehandle_class () != NULL && m_type_data_get_klass_unchecked (t) && + cb_to_mono->is_subclass_of_internal (m_type_data_get_klass_unchecked (t), cb_to_mono->try_get_safehandle_class (), FALSE)) return emit_marshal_safehandle_ilgen (m, argnum, t, spec, conv_arg, conv_arg_type, action); return emit_marshal_object_ilgen (m, argnum, t, spec, conv_arg, conv_arg_type, action); diff --git a/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c b/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c index 379b7bde8a1cae..930933b22ab9f3 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c +++ b/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c @@ -1554,20 +1554,27 @@ bulk_type_log_single_type ( // Sets val variable sized parameter type data, type_parameters_count, and mono_type_parameters associated // with arrays or generics to be recursively batched in the same ep_rt_mono_log_type_and_parameters call switch (mono_underlying_type->type) { - case MONO_TYPE_ARRAY: case MONO_TYPE_SZARRAY: + { + // FIXME: Previously was handled by below ARRAY block but that is incorrect; this implementation is speculative -kg + val->fixed_sized_data.flags |= TYPE_FLAGS_ARRAY; + // mono arrays are always arrays of by value types + val->mono_type_parameters = mono_mempool_alloc0 (type_logger->mem_pool, 1 * sizeof (MonoType*)); + *val->mono_type_parameters = m_class_get_byval_arg (m_type_data_get_klass_unchecked (mono_underlying_type)); + val->type_parameters_count++; + break; + } + case MONO_TYPE_ARRAY: { MonoArrayType *mono_array_type = mono_type_get_array_type (mono_type); val->fixed_sized_data.flags |= TYPE_FLAGS_ARRAY; - if (mono_underlying_type->type == MONO_TYPE_ARRAY) { - // Only ranks less than TypeFlagsArrayRankMax are supported. - // Fortunately TypeFlagsArrayRankMax should be greater than the - // number of ranks the type loader will support - uint32_t rank = mono_array_type->rank; - if (rank < TYPE_FLAGS_ARRAY_RANK_MAX) { - rank <<= 8; - val->fixed_sized_data.flags |= rank; - } + // Only ranks less than TypeFlagsArrayRankMax are supported. + // Fortunately TypeFlagsArrayRankMax should be greater than the + // number of ranks the type loader will support + uint32_t rank = mono_array_type->rank; + if (rank < TYPE_FLAGS_ARRAY_RANK_MAX) { + rank <<= 8; + val->fixed_sized_data.flags |= rank; } // mono arrays are always arrays of by value types @@ -1578,7 +1585,7 @@ bulk_type_log_single_type ( } case MONO_TYPE_GENERICINST: { - MonoGenericInst *class_inst = mono_type->data.generic_class->context.class_inst; + MonoGenericInst *class_inst = m_type_data_get_generic_class_unchecked (mono_type)->context.class_inst; val->type_parameters_count = class_inst->type_argc; val->mono_type_parameters = mono_mempool_alloc0 (type_logger->mem_pool, val->type_parameters_count * sizeof (MonoType*)); memcpy (val->mono_type_parameters, class_inst->type_argv, val->type_parameters_count * sizeof (MonoType*)); diff --git a/src/mono/mono/metadata/class-init.c b/src/mono/mono/metadata/class-init.c index 6a43869672e572..624fd9989efe4f 100644 --- a/src/mono/mono/metadata/class-init.c +++ b/src/mono/mono/metadata/class-init.c @@ -524,7 +524,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError mono_class_set_generic_container (klass, generic_container); MonoType *canonical_inst = &((MonoClassGtd*)klass)->canonical_inst; canonical_inst->type = MONO_TYPE_GENERICINST; - canonical_inst->data.generic_class = mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE); + m_type_data_set_generic_class_unchecked (canonical_inst, mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE)); enable_gclass_recording (); } @@ -535,10 +535,10 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) { /*WARNING: this must satisfy mono_metadata_type_hash*/ klass->this_arg.byref__ = 1; - klass->this_arg.data.klass = klass; klass->this_arg.type = MONO_TYPE_CLASS; - klass->_byval_arg.data.klass = klass; + m_type_data_set_klass_unchecked (&klass->this_arg, klass); klass->_byval_arg.type = MONO_TYPE_CLASS; + m_type_data_set_klass_unchecked (&klass->_byval_arg, klass); } parent = mono_class_get_checked (image, parent_token, error); if (parent && context) /* Always inflate */ @@ -937,7 +937,8 @@ mono_class_create_generic_inst (MonoGenericClass *gclass) klass->_byval_arg.type = MONO_TYPE_GENERICINST; klass->this_arg.type = m_class_get_byval_arg (klass)->type; - klass->this_arg.data.generic_class = klass->_byval_arg.data.generic_class = gclass; + m_type_data_set_generic_class_unchecked (&klass->this_arg, gclass); + m_type_data_set_generic_class_unchecked (&klass->_byval_arg, gclass); klass->this_arg.byref__ = TRUE; klass->is_inlinearray = gklass->is_inlinearray; mono_class_set_inlinearray_value(klass, mono_class_get_inlinearray_value(gklass)); @@ -1218,13 +1219,13 @@ mono_class_create_bounded_array (MonoClass *eclass, guint32 rank, gboolean bound if ((rank > 1) || bounded) { MonoArrayType *at = mm ? (MonoArrayType *)mono_mem_manager_alloc0 (mm, sizeof (MonoArrayType)) : (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType)); klass->_byval_arg.type = MONO_TYPE_ARRAY; - klass->_byval_arg.data.array = at; + m_type_data_set_array_unchecked (&klass->_byval_arg, at); at->eklass = eclass; at->rank = GUINT32_TO_UINT8 (rank); /* FIXME: complete.... */ } else { klass->_byval_arg.type = MONO_TYPE_SZARRAY; - klass->_byval_arg.data.klass = eclass; + m_type_data_set_klass_unchecked (&klass->_byval_arg, eclass); } klass->this_arg = klass->_byval_arg; klass->this_arg.byref__ = 1; @@ -1398,8 +1399,8 @@ make_generic_param_class (MonoGenericParam *param) MonoTypeEnum t = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR; klass->_byval_arg.type = t; klass->this_arg.type = t; - CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param ); - CHECKED_METADATA_WRITE_PTR ( klass->_byval_arg.data.generic_param , param ); + CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data__.generic_param , param ); + CHECKED_METADATA_WRITE_PTR ( klass->_byval_arg.data__.generic_param , param ); klass->this_arg.byref__ = TRUE; /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */ @@ -1543,7 +1544,8 @@ mono_class_create_ptr (MonoType *type) class_composite_fixup_cast_class (result, TRUE); result->this_arg.type = result->_byval_arg.type = MONO_TYPE_PTR; - result->this_arg.data.type = result->_byval_arg.data.type = m_class_get_byval_arg (el_class); + m_type_data_set_type_unchecked (&result->this_arg, m_class_get_byval_arg (el_class)); + m_type_data_set_type_unchecked (&result->_byval_arg, m_class_get_byval_arg (el_class)); result->this_arg.byref__ = TRUE; mono_class_setup_supertypes (result); @@ -1609,7 +1611,8 @@ mono_class_create_fnptr (MonoMethodSignature *sig) result->min_align = sizeof (gpointer); result->cast_class = result->element_class = result; result->this_arg.type = result->_byval_arg.type = MONO_TYPE_FNPTR; - result->this_arg.data.method = result->_byval_arg.data.method = sig; + m_type_data_set_method_unchecked (&result->this_arg, sig); + m_type_data_set_method_unchecked (&result->_byval_arg, sig); result->this_arg.byref__ = TRUE; result->blittable = TRUE; result->inited = TRUE; @@ -1887,7 +1890,7 @@ type_has_references (MonoClass *klass, MonoType *ftype) if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type_internal (ftype))))) return TRUE; if (!m_type_is_byref (ftype) && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) { - MonoGenericParam *gparam = ftype->data.generic_param; + MonoGenericParam *gparam = m_type_data_get_generic_param_unchecked (ftype); if (gparam->gshared_constraint) return class_has_references (mono_class_from_mono_type_internal (gparam->gshared_constraint)); @@ -1935,7 +1938,7 @@ mono_class_is_gparam_with_nonblittable_parent (MonoClass *klass) { MonoType *type = m_class_get_byval_arg (klass); g_assert (mono_type_is_generic_parameter (type)); - MonoGenericParam *gparam = type->data.generic_param; + MonoGenericParam *gparam = m_type_data_get_generic_param_unchecked (type); if ((mono_generic_param_info (gparam)->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0) return TRUE; if ((mono_generic_param_info (gparam)->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0) @@ -2699,7 +2702,7 @@ setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **met if (mono_class_is_gtd (iface)) { MonoType *ty = mono_class_gtd_get_canonical_inst (iface); g_assert (ty->type == MONO_TYPE_GENERICINST); - gclass = ty->data.generic_class; + gclass = m_type_data_get_generic_class_unchecked (ty); } else gclass = mono_class_get_generic_class (iface); @@ -3325,10 +3328,10 @@ mono_class_setup_mono_type (MonoClass *klass) gboolean is_corlib = mono_is_corlib_image (klass->image); klass->this_arg.byref__ = 1; - klass->this_arg.data.klass = klass; klass->this_arg.type = MONO_TYPE_CLASS; - klass->_byval_arg.data.klass = klass; klass->_byval_arg.type = MONO_TYPE_CLASS; + m_type_data_set_klass_unchecked (&klass->this_arg, klass); + m_type_data_set_klass_unchecked (&klass->_byval_arg, klass); if (is_corlib && !strcmp (nspace, "System")) { if (!strcmp (name, "ValueType")) { diff --git a/src/mono/mono/metadata/class-internals.h b/src/mono/mono/metadata/class-internals.h index 5cd05e50edf801..5fa79bcca9c6e7 100644 --- a/src/mono/mono/metadata/class-internals.h +++ b/src/mono/mono/metadata/class-internals.h @@ -545,13 +545,13 @@ mono_generic_param_name (MonoGenericParam *p) static inline MonoGenericContainer * mono_type_get_generic_param_owner (MonoType *t) { - return mono_generic_param_owner (t->data.generic_param); + return mono_generic_param_owner (m_type_data_get_generic_param (t)); } static inline guint16 mono_type_get_generic_param_num (MonoType *t) { - return mono_generic_param_num (t->data.generic_param); + return mono_generic_param_num (m_type_data_get_generic_param (t)); } /* diff --git a/src/mono/mono/metadata/class.c b/src/mono/mono/metadata/class.c index c74c5c12e00cfd..1e71f0a2b9dde3 100644 --- a/src/mono/mono/metadata/class.c +++ b/src/mono/mono/metadata/class.c @@ -354,14 +354,14 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed, switch (type->type) { case MONO_TYPE_ARRAY: { - int i, rank = type->data.array->rank; + int i, rank = m_type_data_get_array_unchecked (type)->rank; MonoTypeNameFormat nested_format; nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ? MONO_TYPE_NAME_FORMAT_FULL_NAME : format; mono_type_get_name_recurse ( - m_class_get_byval_arg (type->data.array->eklass), str, FALSE, nested_format); + m_class_get_byval_arg (m_type_data_get_array_unchecked (type)->eklass), str, FALSE, nested_format); g_string_append_c (str, '['); if (rank == 1) g_string_append_c (str, '*'); @@ -376,7 +376,7 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed, mono_type_name_check_byref (type, str); if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) - _mono_type_get_assembly_name (type->data.array->eklass, str); + _mono_type_get_assembly_name (m_type_data_get_array_unchecked (type)->eklass, str); break; } case MONO_TYPE_SZARRAY: { @@ -386,13 +386,13 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed, MONO_TYPE_NAME_FORMAT_FULL_NAME : format; mono_type_get_name_recurse ( - m_class_get_byval_arg (type->data.klass), str, FALSE, nested_format); + m_class_get_byval_arg (m_type_data_get_klass_unchecked (type)), str, FALSE, nested_format); g_string_append (str, "[]"); mono_type_name_check_byref (type, str); if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) - _mono_type_get_assembly_name (type->data.klass, str); + _mono_type_get_assembly_name (m_type_data_get_klass_unchecked (type), str); break; } case MONO_TYPE_PTR: { @@ -402,21 +402,21 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed, MONO_TYPE_NAME_FORMAT_FULL_NAME : format; mono_type_get_name_recurse ( - type->data.type, str, FALSE, nested_format); + m_type_data_get_type_unchecked (type), str, FALSE, nested_format); g_string_append_c (str, '*'); mono_type_name_check_byref (type, str); if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) - _mono_type_get_assembly_name (mono_class_from_mono_type_internal (type->data.type), str); + _mono_type_get_assembly_name (mono_class_from_mono_type_internal (m_type_data_get_type_unchecked (type)), str); break; } case MONO_TYPE_VAR: case MONO_TYPE_MVAR: - if (!mono_generic_param_name (type->data.generic_param)) - g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num); + if (!mono_generic_param_name (m_type_data_get_generic_param_unchecked (type))) + g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", m_type_data_get_generic_param_unchecked (type)->num); else - g_string_append (str, mono_generic_param_name (type->data.generic_param)); + g_string_append (str, mono_generic_param_name (m_type_data_get_generic_param_unchecked (type))); mono_type_name_check_byref (type, str); @@ -427,12 +427,12 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed, nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ? MONO_TYPE_NAME_FORMAT_FULL_NAME : format; - mono_type_get_name_recurse (type->data.method->ret, str, FALSE, nested_format); + mono_type_get_name_recurse (m_type_data_get_method_unchecked (type)->ret, str, FALSE, nested_format); g_string_append_c (str, '('); - for (int i = 0; i < type->data.method->param_count; ++i) { - mono_type_get_name_recurse (type->data.method->params[i], str, FALSE, nested_format); - if (i != type->data.method->param_count - 1) + for (int i = 0; i < m_type_data_get_method_unchecked (type)->param_count; ++i) { + mono_type_get_name_recurse (m_type_data_get_method_unchecked (type)->params[i], str, FALSE, nested_format); + if (i != m_type_data_get_method_unchecked (type)->param_count - 1) g_string_append (str, ", "); } g_string_append_c (str, ')'); @@ -592,10 +592,10 @@ mono_type_get_name (MonoType *type) MonoType* mono_type_get_underlying_type (MonoType *type) { - if (type->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (type->data.klass) && !m_type_is_byref (type)) - return mono_class_enum_basetype_internal (type->data.klass); - if (type->type == MONO_TYPE_GENERICINST && m_class_is_enumtype (type->data.generic_class->container_class) && !m_type_is_byref (type)) - return mono_class_enum_basetype_internal (type->data.generic_class->container_class); + if (type->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_type_data_get_klass_unchecked (type)) && !m_type_is_byref (type)) + return mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (type)); + if (type->type == MONO_TYPE_GENERICINST && m_class_is_enumtype (m_type_data_get_generic_class_unchecked (type)->container_class) && !m_type_is_byref (type)) + return mono_class_enum_basetype_internal (m_type_data_get_generic_class_unchecked (type)->container_class); return type; } @@ -619,16 +619,16 @@ mono_class_is_open_constructed_type (MonoType *t) case MONO_TYPE_MVAR: return TRUE; case MONO_TYPE_SZARRAY: - return mono_class_is_open_constructed_type (m_class_get_byval_arg (t->data.klass)); + return mono_class_is_open_constructed_type (m_class_get_byval_arg (m_type_data_get_klass_unchecked (t))); case MONO_TYPE_ARRAY: - return mono_class_is_open_constructed_type (m_class_get_byval_arg (t->data.array->eklass)); + return mono_class_is_open_constructed_type (m_class_get_byval_arg (m_type_data_get_array_unchecked (t)->eklass)); case MONO_TYPE_PTR: - return mono_class_is_open_constructed_type (t->data.type); + return mono_class_is_open_constructed_type (m_type_data_get_type_unchecked (t)); case MONO_TYPE_GENERICINST: - return t->data.generic_class->context.class_inst->is_open; + return m_type_data_get_generic_class_unchecked (t)->context.class_inst->is_open; case MONO_TYPE_CLASS: case MONO_TYPE_VALUETYPE: - return mono_class_is_gtd (t->data.klass); + return mono_class_is_gtd (m_type_data_get_klass_unchecked (t)); default: return FALSE; } @@ -659,7 +659,7 @@ can_inflate_gparam_with (MonoGenericParam *gparam, MonoType *type) MonoGenericParamInfo *info = mono_generic_param_info (gparam); if (info && (info->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)) { if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) { - MonoGenericParam *inst_gparam = type->data.generic_param; + MonoGenericParam *inst_gparam = m_type_data_get_generic_param_unchecked (type); if (inst_gparam->gshared_constraint && inst_gparam->gshared_constraint->type == MONO_TYPE_OBJECT) return FALSE; } @@ -702,7 +702,7 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont else return type; } - MonoGenericParam *gparam = type->data.generic_param; + MonoGenericParam *gparam = m_type_data_get_generic_param_unchecked (type); if (num >= inst->type_argc) { const char *pname = mono_generic_param_name (gparam); mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations", @@ -736,7 +736,7 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont else return type; } - MonoGenericParam *gparam = type->data.generic_param; + MonoGenericParam *gparam = m_type_data_get_generic_param_unchecked (type); if (num >= inst->type_argc) { const char *pname = mono_generic_param_name (gparam); mono_error_set_bad_image (error, image, "VAR %hu (%s) cannot be expanded in this context with %d instantiations", @@ -776,31 +776,31 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont return nt; } case MONO_TYPE_SZARRAY: { - MonoClass *eclass = type->data.klass; + MonoClass *eclass = m_type_data_get_klass_unchecked (type); MonoType *nt, *inflated = inflate_generic_type (NULL, m_class_get_byval_arg (eclass), context, error); if ((!inflated && !changed) || !is_ok (error)) return NULL; if (!inflated) return type; nt = mono_metadata_type_dup (image, type); - nt->data.klass = mono_class_from_mono_type_internal (inflated); + m_type_data_set_klass (nt, mono_class_from_mono_type_internal (inflated)); mono_metadata_free_type (inflated); return nt; } case MONO_TYPE_ARRAY: { - MonoClass *eclass = type->data.array->eklass; + MonoClass *eclass = m_type_data_get_array_unchecked (type)->eklass; MonoType *nt, *inflated = inflate_generic_type (NULL, m_class_get_byval_arg (eclass), context, error); if ((!inflated && !changed) || !is_ok (error)) return NULL; if (!inflated) return type; nt = mono_metadata_type_dup (image, type); - nt->data.array->eklass = mono_class_from_mono_type_internal (inflated); + m_type_data_get_array (nt)->eklass = mono_class_from_mono_type_internal (inflated); mono_metadata_free_type (inflated); return nt; } case MONO_TYPE_GENERICINST: { - MonoGenericClass *gclass = type->data.generic_class; + MonoGenericClass *gclass = m_type_data_get_generic_class_unchecked (type); MonoGenericInst *inst; MonoType *nt; if (!gclass->context.class_inst->is_open) { @@ -816,7 +816,7 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont if (inst != gclass->context.class_inst) gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic); - if (gclass == type->data.generic_class) { + if (gclass == m_type_data_get_generic_class_unchecked (type)) { if (!changed) return NULL; else @@ -824,12 +824,12 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont } nt = mono_metadata_type_dup (image, type); - nt->data.generic_class = gclass; + m_type_data_set_generic_class (nt, gclass); return nt; } case MONO_TYPE_CLASS: case MONO_TYPE_VALUETYPE: { - MonoClass *klass = type->data.klass; + MonoClass *klass = m_type_data_get_klass_unchecked (type); MonoGenericContainer *container = mono_class_try_get_generic_container (klass); MonoGenericInst *inst; MonoGenericClass *gclass = NULL; @@ -857,21 +857,21 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont nt = mono_metadata_type_dup (image, type); nt->type = MONO_TYPE_GENERICINST; - nt->data.generic_class = gclass; + m_type_data_set_generic_class_unchecked (nt, gclass); return nt; } case MONO_TYPE_PTR: { - MonoType *nt, *inflated = inflate_generic_type (image, type->data.type, context, error); + MonoType *nt, *inflated = inflate_generic_type (image, m_type_data_get_type_unchecked (type), context, error); if ((!inflated && !changed) || !is_ok (error)) return NULL; if (!inflated && changed) return type; nt = mono_metadata_type_dup (image, type); - nt->data.type = inflated; + m_type_data_set_type (nt, inflated); return nt; } case MONO_TYPE_FNPTR: { - MonoMethodSignature *in_sig = type->data.method; + MonoMethodSignature *in_sig = m_type_data_get_method_unchecked (type); // quick bail out - if there are no type variables anywhere in the signature, // there's nothing that could get inflated. if (!in_sig->has_type_parameters) { @@ -892,7 +892,7 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont return type; } MonoType *nt = mono_metadata_type_dup (image, type); - nt->data.method = new_sig; + m_type_data_set_method (nt, new_sig); return nt; } default: @@ -1671,11 +1671,11 @@ mono_type_has_exceptions (MonoType *type) case MONO_TYPE_CLASS: case MONO_TYPE_VALUETYPE: case MONO_TYPE_SZARRAY: - return mono_class_has_failure (type->data.klass); + return mono_class_has_failure (m_type_data_get_klass_unchecked (type)); case MONO_TYPE_ARRAY: - return mono_class_has_failure (type->data.array->eklass); + return mono_class_has_failure (m_type_data_get_array_unchecked (type)->eklass); case MONO_TYPE_GENERICINST: - return mono_class_has_failure (mono_class_create_generic_inst (type->data.generic_class)); + return mono_class_has_failure (mono_class_create_generic_inst (m_type_data_get_generic_class_unchecked (type))); default: return FALSE; } @@ -1747,7 +1747,7 @@ mono_type_get_basic_type_from_generic (MonoType *type) { /* When we do generic sharing we let type variables stand for reference/primitive types. */ if (!m_type_is_byref (type) && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) && - (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT)) + (!m_type_data_get_generic_param_unchecked (type)->gshared_constraint || m_type_data_get_generic_param_unchecked (type)->gshared_constraint->type == MONO_TYPE_OBJECT)) return mono_get_object_type (); return type; } @@ -2265,65 +2265,54 @@ mono_class_from_mono_type (MonoType *type) MonoClass * mono_class_from_mono_type_internal (MonoType *type) { + +#define CASE_KLASS_OR_DEFAULT_FOR_TYPE(enum_value, default_expr) \ + case enum_value: \ + return m_type_data_get_klass_unchecked (type) ? m_type_data_get_klass_unchecked (type) : default_expr; + g_assert (type); switch (type->type) { - case MONO_TYPE_OBJECT: - return type->data.klass? type->data.klass: mono_defaults.object_class; - case MONO_TYPE_VOID: - return type->data.klass? type->data.klass: mono_defaults.void_class; - case MONO_TYPE_BOOLEAN: - return type->data.klass? type->data.klass: mono_defaults.boolean_class; - case MONO_TYPE_CHAR: - return type->data.klass? type->data.klass: mono_defaults.char_class; - case MONO_TYPE_I1: - return type->data.klass? type->data.klass: mono_defaults.sbyte_class; - case MONO_TYPE_U1: - return type->data.klass? type->data.klass: mono_defaults.byte_class; - case MONO_TYPE_I2: - return type->data.klass? type->data.klass: mono_defaults.int16_class; - case MONO_TYPE_U2: - return type->data.klass? type->data.klass: mono_defaults.uint16_class; - case MONO_TYPE_I4: - return type->data.klass? type->data.klass: mono_defaults.int32_class; - case MONO_TYPE_U4: - return type->data.klass? type->data.klass: mono_defaults.uint32_class; - case MONO_TYPE_I: - return type->data.klass? type->data.klass: mono_defaults.int_class; - case MONO_TYPE_U: - return type->data.klass? type->data.klass: mono_defaults.uint_class; - case MONO_TYPE_I8: - return type->data.klass? type->data.klass: mono_defaults.int64_class; - case MONO_TYPE_U8: - return type->data.klass? type->data.klass: mono_defaults.uint64_class; - case MONO_TYPE_R4: - return type->data.klass? type->data.klass: mono_defaults.single_class; - case MONO_TYPE_R8: - return type->data.klass? type->data.klass: mono_defaults.double_class; - case MONO_TYPE_STRING: - return type->data.klass? type->data.klass: mono_defaults.string_class; - case MONO_TYPE_TYPEDBYREF: - return type->data.klass? type->data.klass: mono_defaults.typed_reference_class; + CASE_KLASS_OR_DEFAULT_FOR_TYPE(MONO_TYPE_OBJECT, mono_defaults.object_class); + CASE_KLASS_OR_DEFAULT_FOR_TYPE(MONO_TYPE_VOID, mono_defaults.void_class); + CASE_KLASS_OR_DEFAULT_FOR_TYPE(MONO_TYPE_BOOLEAN, mono_defaults.boolean_class); + CASE_KLASS_OR_DEFAULT_FOR_TYPE(MONO_TYPE_CHAR, mono_defaults.char_class); + CASE_KLASS_OR_DEFAULT_FOR_TYPE(MONO_TYPE_I1, mono_defaults.sbyte_class); + CASE_KLASS_OR_DEFAULT_FOR_TYPE(MONO_TYPE_U1, mono_defaults.byte_class); + CASE_KLASS_OR_DEFAULT_FOR_TYPE(MONO_TYPE_I2, mono_defaults.int16_class); + CASE_KLASS_OR_DEFAULT_FOR_TYPE(MONO_TYPE_U2, mono_defaults.uint16_class); + CASE_KLASS_OR_DEFAULT_FOR_TYPE(MONO_TYPE_I4, mono_defaults.int32_class); + CASE_KLASS_OR_DEFAULT_FOR_TYPE(MONO_TYPE_U4, mono_defaults.uint32_class); + CASE_KLASS_OR_DEFAULT_FOR_TYPE(MONO_TYPE_I, mono_defaults.int_class); + CASE_KLASS_OR_DEFAULT_FOR_TYPE(MONO_TYPE_U, mono_defaults.uint_class); + CASE_KLASS_OR_DEFAULT_FOR_TYPE(MONO_TYPE_I8, mono_defaults.int64_class); + CASE_KLASS_OR_DEFAULT_FOR_TYPE(MONO_TYPE_U8, mono_defaults.uint64_class); + CASE_KLASS_OR_DEFAULT_FOR_TYPE(MONO_TYPE_R4, mono_defaults.single_class); + CASE_KLASS_OR_DEFAULT_FOR_TYPE(MONO_TYPE_R8, mono_defaults.double_class); + CASE_KLASS_OR_DEFAULT_FOR_TYPE(MONO_TYPE_STRING, mono_defaults.string_class); + CASE_KLASS_OR_DEFAULT_FOR_TYPE(MONO_TYPE_TYPEDBYREF, mono_defaults.typed_reference_class); case MONO_TYPE_ARRAY: - return mono_class_create_bounded_array (type->data.array->eklass, type->data.array->rank, TRUE); + return mono_class_create_bounded_array (m_type_data_get_array_unchecked (type)->eklass, m_type_data_get_array_unchecked (type)->rank, TRUE); case MONO_TYPE_PTR: - return mono_class_create_ptr (type->data.type); + return mono_class_create_ptr (m_type_data_get_type_unchecked (type)); case MONO_TYPE_FNPTR: - return mono_class_create_fnptr (type->data.method); + return mono_class_create_fnptr (m_type_data_get_method_unchecked (type)); case MONO_TYPE_SZARRAY: - return mono_class_create_array (type->data.klass, 1); + return mono_class_create_array (m_type_data_get_klass_unchecked (type), 1); case MONO_TYPE_CLASS: case MONO_TYPE_VALUETYPE: - return type->data.klass; + return m_type_data_get_klass_unchecked (type); case MONO_TYPE_GENERICINST: - return mono_class_create_generic_inst (type->data.generic_class); + return mono_class_create_generic_inst (m_type_data_get_generic_class_unchecked (type)); case MONO_TYPE_MVAR: case MONO_TYPE_VAR: - return mono_class_create_generic_parameter (type->data.generic_param); + return mono_class_create_generic_parameter (m_type_data_get_generic_param_unchecked (type)); default: g_warning ("mono_class_from_mono_type_internal: implement me 0x%02x\n", type->type); g_assert_not_reached (); } +#undef CASE_KLASS_OR_DEFAULT_FOR_TYPE + // Yes, this returns NULL, even if it is documented as not doing so, but there // is no way for the code to make it this far, due to the assert above. return NULL; @@ -3717,7 +3706,7 @@ mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, g if (check_for_reference_conv && mono_type_is_generic_argument (m_class_get_byval_arg (target)) && mono_type_is_generic_argument (m_class_get_byval_arg (candidate))) { - MonoGenericParam *gparam = m_class_get_byval_arg (candidate)->data.generic_param; + MonoGenericParam *gparam = m_type_data_get_generic_param_unchecked (m_class_get_byval_arg (candidate)); MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam); if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0) @@ -3796,8 +3785,8 @@ mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate) if (target_byval_arg->type != candidate_byval_arg->type) return FALSE; - gparam = target_byval_arg->data.generic_param; - ogparam = candidate_byval_arg->data.generic_param; + gparam = m_type_data_get_generic_param (target_byval_arg); + ogparam = m_type_data_get_generic_param (candidate_byval_arg); tinfo = mono_generic_param_info (gparam); cinfo = mono_generic_param_info (ogparam); @@ -3888,10 +3877,10 @@ mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate) static MonoType* mono_type_get_underlying_type_ignore_byref (MonoType *type) { - if (type->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (type->data.klass)) - return mono_class_enum_basetype_internal (type->data.klass); - if (type->type == MONO_TYPE_GENERICINST && m_class_is_enumtype (type->data.generic_class->container_class)) - return mono_class_enum_basetype_internal (type->data.generic_class->container_class); + if (type->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_type_data_get_klass_unchecked (type))) + return mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (type)); + if (type->type == MONO_TYPE_GENERICINST && m_class_is_enumtype (m_type_data_get_generic_class_unchecked (type)->container_class)) + return mono_class_enum_basetype_internal (m_type_data_get_generic_class_unchecked (type)->container_class); return type; } @@ -3921,7 +3910,7 @@ mono_byref_type_is_assignable_from (MonoType *type, MonoType *ctype, gboolean si if (mono_type_is_primitive (t)) { return mono_type_is_primitive (ot) && m_class_get_instance_size (klass) == m_class_get_instance_size (klassc); } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) { - return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num; + return t->type == ot->type && m_type_data_get_generic_param_unchecked (t)->num == m_type_data_get_generic_param_unchecked (ot)->num; } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) { return t->type == ot->type; } else { @@ -4138,7 +4127,7 @@ mono_class_is_assignable_from_general (MonoClass *klass, MonoClass *oklass, gboo * In this case, Foo is assignable from T1. */ if (mono_type_is_generic_argument (oklass_byval_arg)) { - MonoGenericParam *gparam = oklass_byval_arg->data.generic_param; + MonoGenericParam *gparam = m_type_data_get_generic_param_unchecked (oklass_byval_arg); MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints; int i; @@ -4306,7 +4295,7 @@ mono_class_is_assignable_from_general (MonoClass *klass, MonoClass *oklass, gboo if (MONO_CLASS_IS_INTERFACE_INTERNAL (eclass)) { MonoType *eoclass_byval_arg = m_class_get_byval_arg (eoclass); if (mono_type_is_generic_argument (eoclass_byval_arg)) { - MonoGenericParam *eoparam = eoclass_byval_arg->data.generic_param; + MonoGenericParam *eoparam = m_type_data_get_generic_param_unchecked (eoclass_byval_arg); MonoGenericParamInfo *eoinfo = mono_generic_param_info (eoparam); int eomask = eoinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK; // check for class constraint @@ -4337,7 +4326,7 @@ mono_class_is_assignable_from_general (MonoClass *klass, MonoClass *oklass, gboo } if (m_class_get_byval_arg (klass)->type == MONO_TYPE_FNPTR) { - if (mono_metadata_signature_equal (klass_byval_arg->data.method, oklass_byval_arg->data.method)) { + if (mono_metadata_signature_equal (m_type_data_get_method (klass_byval_arg), m_type_data_get_method (oklass_byval_arg))) { *result = TRUE; return; } @@ -4653,7 +4642,7 @@ mono_generic_param_get_base_type (MonoClass *klass) MonoType *type = m_class_get_byval_arg (klass); g_assert (mono_type_is_generic_argument (type)); - MonoGenericParam *gparam = type->data.generic_param; + MonoGenericParam *gparam = m_type_data_get_generic_param_unchecked (type); g_assert (gparam->owner && !gparam->owner->is_anonymous); @@ -4671,7 +4660,7 @@ mono_generic_param_get_base_type (MonoClass *klass) MonoType *constraint_type = m_class_get_byval_arg (constraint); if (mono_type_is_generic_argument (constraint_type)) { - MonoGenericParam *constraint_param = constraint_type->data.generic_param; + MonoGenericParam *constraint_param = m_type_data_get_generic_param_unchecked (constraint_type); MonoGenericParamInfo *constraint_info = mono_generic_param_info (constraint_param); if ((constraint_info->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0 && (constraint_info->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) == 0) @@ -4826,14 +4815,14 @@ mono_class_array_element_size (MonoClass *klass) case MONO_TYPE_R8: return 8; case MONO_TYPE_VALUETYPE: - if (m_class_is_enumtype (type->data.klass)) { - type = mono_class_enum_basetype_internal (type->data.klass); + if (m_class_is_enumtype (m_type_data_get_klass_unchecked (type))) { + type = mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (type)); klass = m_class_get_element_class (klass); goto handle_enum; } return mono_class_value_size (klass, NULL); case MONO_TYPE_GENERICINST: - type = m_class_get_byval_arg (type->data.generic_class->container_class); + type = m_class_get_byval_arg (m_type_data_get_generic_class_unchecked (type)->container_class); goto handle_enum; case MONO_TYPE_VAR: case MONO_TYPE_MVAR: { @@ -6323,15 +6312,15 @@ can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst) MonoType *type = ginst->type_argv[i]; switch (type->type) { case MONO_TYPE_SZARRAY: - if (!can_access_type (access_klass, type->data.klass)) + if (!can_access_type (access_klass, m_type_data_get_klass_unchecked (type))) return FALSE; break; case MONO_TYPE_ARRAY: - if (!can_access_type (access_klass, type->data.array->eklass)) + if (!can_access_type (access_klass, m_type_data_get_array_unchecked (type)->eklass)) return FALSE; break; case MONO_TYPE_PTR: - if (!can_access_type (access_klass, mono_class_from_mono_type_internal (type->data.type))) + if (!can_access_type (access_klass, mono_class_from_mono_type_internal (m_type_data_get_type_unchecked (type)))) return FALSE; break; case MONO_TYPE_CLASS: @@ -6930,7 +6919,7 @@ mono_method_get_base_method (MonoMethod *method, gboolean definition, MonoError * up the class hierarchy. */ MonoType *ty = mono_class_gtd_get_canonical_inst (klass); g_assert (ty->type == MONO_TYPE_GENERICINST); - MonoGenericClass *gklass = ty->data.generic_class; + MonoGenericClass *gklass = m_type_data_get_generic_class_unchecked (ty); generic_inst = mono_generic_class_get_context (gklass); klass = gklass->container_class; } else if (mono_class_is_ginst (klass)) { diff --git a/src/mono/mono/metadata/custom-attrs.c b/src/mono/mono/metadata/custom-attrs.c index abdd89a19c372f..e0e485dd3e4a44 100644 --- a/src/mono/mono/metadata/custom-attrs.c +++ b/src/mono/mono/metadata/custom-attrs.c @@ -115,9 +115,9 @@ get_attr_ctor_method_from_handle (MonoReflectionCustomAttrHandle cattr, MonoRefl * \param ctor_method (out param) the custom attribute constructor as MonoMethod if the custom attribute is visible, otherwise NULL * * \returns TRUE if the custom attribute is visible on a decorated type, otherwise FALSE - * + * * Determines if a custom attribute is visible for a decorated target \p target_image - * + * * FIXME: the return value is also TRUE when custom attribute constructor is NULL, which is probably a bug */ static gboolean @@ -312,7 +312,7 @@ load_cattr_value (MonoImage *image, MonoType *t, MonoObject **out_obj, const cha { int type = t->type; guint32 slen; - MonoClass *tklass = t->data.klass; + MonoClass *tklass = m_type_data_get_klass (t); if (out_obj) *out_obj = NULL; @@ -320,7 +320,7 @@ load_cattr_value (MonoImage *image, MonoType *t, MonoObject **out_obj, const cha error_init (error); if (type == MONO_TYPE_GENERICINST) { - MonoGenericClass * mgc = t->data.generic_class; + MonoGenericClass * mgc = m_type_data_get_generic_class_unchecked (t); MonoClass * cc = mgc->container_class; if (m_class_is_enumtype (cc)) { tklass = m_class_get_element_class (cc); @@ -332,6 +332,8 @@ load_cattr_value (MonoImage *image, MonoType *t, MonoObject **out_obj, const cha } handle_enum: + // the _unchecked MonoType accessors are not used here because the gotos to handle_enum doesn't necessarily keep + // type and t in sync so it's not guaranteed that accessing the union members is safe switch (type) { case MONO_TYPE_U1: case MONO_TYPE_I1: @@ -388,15 +390,16 @@ load_cattr_value (MonoImage *image, MonoType *t, MonoObject **out_obj, const cha *end = p + 8; return val; } - case MONO_TYPE_VALUETYPE: - if (m_class_is_enumtype (t->data.klass)) { - type = mono_class_enum_basetype_internal (t->data.klass)->type; + case MONO_TYPE_VALUETYPE: { + MonoClass *klass_of_t = m_type_data_get_klass (t); + if (m_class_is_enumtype (klass_of_t)) { + type = mono_class_enum_basetype_internal (klass_of_t)->type; goto handle_enum; } else { - g_error ("generic valutype %s not handled in custom attr value decoding", m_class_get_name (t->data.klass)); + g_error ("generic valutype %s not handled in custom attr value decoding", m_class_get_name (klass_of_t)); } break; - + } case MONO_TYPE_STRING: { if (!bcheck_blob (p, 0, boundp, error)) return NULL; @@ -525,7 +528,7 @@ MONO_RESTORE_WARNING basetype = mono_class_enum_basetype_internal (tklass)->type; if (basetype == MONO_TYPE_GENERICINST) { - MonoGenericClass * mgc = m_class_get_byval_arg (tklass)->data.generic_class; + MonoGenericClass * mgc = m_type_data_get_generic_class (m_class_get_byval_arg (tklass)); MonoClass * cc = mgc->container_class; if (m_class_is_enumtype (cc)) { basetype = m_class_get_byval_arg (m_class_get_element_class (cc))->type; @@ -637,14 +640,14 @@ load_cattr_value_noalloc (MonoImage *image, MonoType *t, const char *p, const ch { int type = t->type; guint32 slen; - MonoClass *tklass = t->data.klass; + MonoClass *tklass = m_type_data_get_klass (t); MonoCustomAttrValue* result = (MonoCustomAttrValue *)g_malloc (sizeof (MonoCustomAttrValue)); g_assert (boundp); error_init (error); if (type == MONO_TYPE_GENERICINST) { - MonoGenericClass * mgc = t->data.generic_class; + MonoGenericClass * mgc = m_type_data_get_generic_class (t); MonoClass * cc = mgc->container_class; if (m_class_is_enumtype (cc)) { tklass = m_class_get_element_class (cc); @@ -657,6 +660,8 @@ load_cattr_value_noalloc (MonoImage *image, MonoType *t, const char *p, const ch result->type = type; handle_enum: + // the _unchecked MonoType accessors are not used here because the gotos to handle_enum doesn't necessarily keep + // type and t in sync so it's not guaranteed that accessing the union members is safe switch (type) { case MONO_TYPE_U1: case MONO_TYPE_I1: @@ -718,14 +723,16 @@ load_cattr_value_noalloc (MonoImage *image, MonoType *t, const char *p, const ch result->value.primitive = val; return result; } - case MONO_TYPE_VALUETYPE: - if (m_class_is_enumtype (t->data.klass)) { - type = mono_class_enum_basetype_internal (t->data.klass)->type; + case MONO_TYPE_VALUETYPE: { + MonoClass *klass_of_t = m_type_data_get_klass (t); + if (m_class_is_enumtype (klass_of_t)) { + type = mono_class_enum_basetype_internal (klass_of_t)->type; goto handle_enum; } else { - g_error ("generic valutype %s not handled in custom attr value decoding", m_class_get_name (t->data.klass)); + g_error ("generic valutype %s not handled in custom attr value decoding", m_class_get_name (klass_of_t)); } break; + } case MONO_TYPE_STRING: { const char *start = p; @@ -2062,7 +2069,7 @@ mono_method_get_unsafe_accessor_attr_data (MonoMethod *method, int *accessor_kin } MonoDecodeCustomAttr *decoded_args = mono_reflection_create_custom_attr_data_args_noalloc (m_class_get_image (attr->ctor->klass), attr->ctor, attr->data, attr->data_size, error); - + if (!is_ok (error)) { mono_error_cleanup (error); mono_reflection_free_custom_attr_data_args_noalloc (decoded_args); diff --git a/src/mono/mono/metadata/debug-helpers.c b/src/mono/mono/metadata/debug-helpers.c index 7ef728eadd5fa8..90da5042827680 100644 --- a/src/mono/mono/metadata/debug-helpers.c +++ b/src/mono/mono/metadata/debug-helpers.c @@ -170,30 +170,30 @@ mono_type_get_desc (GString *res, MonoType *type, gboolean include_namespace) case MONO_TYPE_OBJECT: g_string_append (res, "object"); break; case MONO_TYPE_PTR: - mono_type_get_desc (res, type->data.type, include_namespace); + mono_type_get_desc (res, m_type_data_get_type_unchecked (type), include_namespace); g_string_append_c (res, '*'); break; case MONO_TYPE_ARRAY: - mono_type_get_desc (res, &type->data.array->eklass->_byval_arg, include_namespace); + mono_type_get_desc (res, &m_type_data_get_array_unchecked (type)->eklass->_byval_arg, include_namespace); g_string_append_c (res, '['); - for (guint8 i = 1; i < type->data.array->rank; ++i) + for (guint8 i = 1; i < m_type_data_get_array_unchecked (type)->rank; ++i) g_string_append_c (res, ','); g_string_append_c (res, ']'); break; case MONO_TYPE_SZARRAY: - mono_type_get_desc (res, &type->data.klass->_byval_arg, include_namespace); + mono_type_get_desc (res, &m_type_data_get_klass_unchecked (type)->_byval_arg, include_namespace); g_string_append (res, "[]"); break; case MONO_TYPE_CLASS: case MONO_TYPE_VALUETYPE: - append_class_name (res, type->data.klass, include_namespace); + append_class_name (res, m_type_data_get_klass_unchecked (type), include_namespace); break; case MONO_TYPE_GENERICINST: { MonoGenericContext *context; - mono_type_get_desc (res, &type->data.generic_class->container_class->_byval_arg, include_namespace); + mono_type_get_desc (res, &m_type_data_get_generic_class_unchecked (type)->container_class->_byval_arg, include_namespace); g_string_append (res, "<"); - context = &type->data.generic_class->context; + context = &m_type_data_get_generic_class_unchecked (type)->context; if (context->class_inst) { for (guint i = 0; i < context->class_inst->type_argc; ++i) { if (i > 0) @@ -215,12 +215,12 @@ mono_type_get_desc (GString *res, MonoType *type, gboolean include_namespace) } case MONO_TYPE_VAR: case MONO_TYPE_MVAR: - if (type->data.generic_param) { - const char *name = mono_generic_param_name (type->data.generic_param); + if (m_type_data_get_generic_param_unchecked (type)) { + const char *name = mono_generic_param_name (m_type_data_get_generic_param_unchecked (type)); if (name) g_string_append (res, name); else - g_string_append_printf (res, "%s%hu", type->type == MONO_TYPE_VAR ? "!" : "!!", mono_generic_param_num (type->data.generic_param)); + g_string_append_printf (res, "%s%hu", type->type == MONO_TYPE_VAR ? "!" : "!!", mono_generic_param_num (m_type_data_get_generic_param_unchecked (type))); } else { g_string_append (res, ""); } diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index a5ba24a6883114..b838ec465f821c 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -483,8 +483,9 @@ array_set_value_impl (MonoArray *arr, MonoObjectHandle value_handle, guint32 pos vsize = mono_class_value_size (vc, NULL); - et_isenum = et == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_class_get_byval_arg (ec)->data.klass); - vt_isenum = vt == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_class_get_byval_arg (vc)->data.klass); + // et/vt = m_class_get_byval_arg (ec/vc)->type so get_klass_unchecked is safe here + et_isenum = et == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_type_data_get_klass_unchecked (m_class_get_byval_arg (ec))); + vt_isenum = vt == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_type_data_get_klass_unchecked (m_class_get_byval_arg (vc))); if (strict_enums && et_isenum && !vt_isenum) { INVALID_CAST; @@ -492,10 +493,10 @@ array_set_value_impl (MonoArray *arr, MonoObjectHandle value_handle, guint32 pos } if (et_isenum) - et = mono_class_enum_basetype_internal (m_class_get_byval_arg (ec)->data.klass)->type; + et = mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (m_class_get_byval_arg (ec)))->type; if (vt_isenum) - vt = mono_class_enum_basetype_internal (m_class_get_byval_arg (vc)->data.klass)->type; + vt = mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (m_class_get_byval_arg (vc)))->type; // Treat MONO_TYPE_U/I as MONO_TYPE_U8/I8/U4/I4 #if SIZEOF_VOID_P == 8 @@ -2033,8 +2034,8 @@ static MonoType* get_generic_argument_type (MonoType* type, unsigned int generic_argument_position) { g_assert (type->type == MONO_TYPE_GENERICINST); - g_assert (type->data.generic_class->context.class_inst->type_argc > generic_argument_position); - return type->data.generic_class->context.class_inst->type_argv [generic_argument_position]; + g_assert (m_type_data_get_generic_class_unchecked (type)->context.class_inst->type_argc > generic_argument_position); + return m_type_data_get_generic_class_unchecked (type)->context.class_inst->type_argv [generic_argument_position]; } MonoArrayHandle @@ -2212,7 +2213,7 @@ ves_icall_RuntimeFieldInfo_SetValueInternal (MonoReflectionFieldHandle field, Mo isref = TRUE; break; case MONO_TYPE_GENERICINST: { - MonoGenericClass *gclass = type->data.generic_class; + MonoGenericClass *gclass = m_type_data_get_generic_class_unchecked (type); g_assert (!gclass->context.class_inst->is_open); isref = !m_class_is_valuetype (gclass->container_class); @@ -2872,14 +2873,14 @@ ves_icall_RuntimeType_GetCallingConventionFromFunctionPointerInternal (MonoQCall MonoType *type = type_handle.type; g_assert (type->type == MONO_TYPE_FNPTR); // FIXME: Once we address: https://github.com/dotnet/runtime/issues/90308 this should not be needed anymore - return GUINT_TO_INT8 (mono_method_signature_has_ext_callconv (type->data.method, MONO_EXT_CALLCONV_SUPPRESS_GC_TRANSITION) ? MONO_CALL_UNMANAGED_MD : type->data.method->call_convention); + return GUINT_TO_INT8 (mono_method_signature_has_ext_callconv (m_type_data_get_method_unchecked (type), MONO_EXT_CALLCONV_SUPPRESS_GC_TRANSITION) ? MONO_CALL_UNMANAGED_MD : m_type_data_get_method_unchecked (type)->call_convention); } MonoBoolean ves_icall_RuntimeType_IsUnmanagedFunctionPointerInternal (MonoQCallTypeHandle type_handle) { MonoType *type = type_handle.type; - return type->type == MONO_TYPE_FNPTR && type->data.method->pinvoke; + return type->type == MONO_TYPE_FNPTR && m_type_data_get_method_unchecked (type)->pinvoke; } void @@ -2888,7 +2889,7 @@ ves_icall_RuntimeTypeHandle_GetElementType (MonoQCallTypeHandle type_handle, Mon MonoType *type = type_handle.type; if (!m_type_is_byref (type) && type->type == MONO_TYPE_SZARRAY) { - HANDLE_ON_STACK_SET (res, mono_type_get_object_checked (m_class_get_byval_arg (type->data.klass), error)); + HANDLE_ON_STACK_SET (res, mono_type_get_object_checked (m_class_get_byval_arg (m_type_data_get_klass_unchecked (type)), error)); return; } @@ -2929,7 +2930,7 @@ ves_icall_RuntimeTypeHandle_GetCorElementType (MonoQCallTypeHandle type_handle) MonoType *type = type_handle.type; // Enums in generic classes should still return VALUETYPE - if (type->type == MONO_TYPE_GENERICINST && m_class_is_enumtype (type->data.generic_class->container_class) && !m_type_is_byref (type)) + if (type->type == MONO_TYPE_GENERICINST && m_class_is_enumtype (m_type_data_get_generic_class_unchecked (type)->container_class) && !m_type_is_byref (type)) return MONO_TYPE_VALUETYPE; if (m_type_is_byref (type)) @@ -2968,11 +2969,12 @@ ves_icall_RuntimeType_FunctionPointerReturnAndParameterTypes (MonoQCallTypeHandl MonoType *type = type_handle.type; GPtrArray *res_array = g_ptr_array_new (); + MonoMethodSignature *sig = m_type_data_get_method (type); - g_ptr_array_add (res_array, type->data.method->ret); + g_ptr_array_add (res_array, sig->ret); - for (int i = 0; i < type->data.method->param_count; ++i) - g_ptr_array_add (res_array, type->data.method->params[i]); + for (int i = 0; i < sig->param_count; ++i) + g_ptr_array_add (res_array, sig->params[i]); return res_array; } @@ -2983,11 +2985,11 @@ ves_icall_RuntimeType_GetFunctionPointerTypeModifiers (MonoQCallTypeHandle type_ MonoType *type = type_handle.type; g_assert (type->type == MONO_TYPE_FNPTR); if (position == 0) { - return type_array_from_modifiers (type->data.method->ret, optional, error); + return type_array_from_modifiers (m_type_data_get_method_unchecked (type)->ret, optional, error); } else { - g_assert (type->data.method->param_count > position - 1); - return type_array_from_modifiers (type->data.method->params[position - 1], optional, error); + g_assert (m_type_data_get_method_unchecked (type)->param_count > position - 1); + return type_array_from_modifiers (m_type_data_get_method_unchecked (type)->params[position - 1], optional, error); } } @@ -3277,7 +3279,7 @@ MonoGenericParamInfo * ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoQCallTypeHandle type_handle, MonoError *error) { MonoType *type = type_handle.type; - return mono_generic_param_info (type->data.generic_param); + return mono_generic_param_info (m_type_data_get_generic_param (type)); } MonoReflectionMethodHandle @@ -6577,15 +6579,14 @@ static void mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type) { type->type = blob_type; - type->data.klass = NULL; if (blob_type == MONO_TYPE_CLASS) - type->data.klass = mono_defaults.object_class; - else if (real_type->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (real_type->data.klass)) { + m_type_data_set_klass_unchecked (type, mono_defaults.object_class); + else if (real_type->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_type_data_get_klass_unchecked (real_type))) { /* For enums, we need to use the base type */ type->type = MONO_TYPE_VALUETYPE; - type->data.klass = mono_class_from_mono_type_internal (real_type); + m_type_data_set_klass_unchecked (type, mono_class_from_mono_type_internal (real_type)); } else - type->data.klass = mono_class_from_mono_type_internal (real_type); + m_type_data_set_klass (type, mono_class_from_mono_type_internal (real_type)); } MonoObjectHandle @@ -6593,7 +6594,7 @@ ves_icall_property_info_get_default_value (MonoReflectionPropertyHandle property { MonoReflectionProperty* property = MONO_HANDLE_RAW (property_handle); - MonoType blob_type; + MonoType blob_type = { 0 }; MonoProperty *prop = property->property; MonoType *type = get_property_type (prop); MonoTypeEnum def_type; diff --git a/src/mono/mono/metadata/marshal-lightweight.c b/src/mono/mono/metadata/marshal-lightweight.c index 2095334a818afe..54e8db81929eb3 100644 --- a/src/mono/mono/metadata/marshal-lightweight.c +++ b/src/mono/mono/metadata/marshal-lightweight.c @@ -344,12 +344,12 @@ emit_invoke_call (MonoMethodBuilder *mb, MonoMethod *method, break; } - t = m_class_get_byval_arg (t->data.generic_class->container_class); + t = m_class_get_byval_arg (m_type_data_get_generic_class (t)->container_class); type = t->type; goto handle_enum; case MONO_TYPE_VALUETYPE: - if (type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (t->data.klass)) { - type = mono_class_enum_basetype_internal (t->data.klass)->type; + if (type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_type_data_get_klass (t))) { + type = mono_class_enum_basetype_internal (m_type_data_get_klass (t))->type; goto handle_enum; } mono_mb_emit_no_nullcheck (mb); @@ -1009,9 +1009,9 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi case MONO_TYPE_VOID: break; case MONO_TYPE_VALUETYPE: - klass = sig->ret->data.klass; + klass = m_type_data_get_klass (sig->ret); if (m_class_is_enumtype (klass)) { - type = mono_class_enum_basetype_internal (sig->ret->data.klass)->type; + type = mono_class_enum_basetype_internal (m_type_data_get_klass (sig->ret))->type; goto handle_enum; } mono_emit_marshal (&m, 0, sig->ret, spec, 0, NULL, MARSHAL_ACTION_CONV_RESULT); diff --git a/src/mono/mono/metadata/marshal-shared.c b/src/mono/mono/metadata/marshal-shared.c index 75d95a799ef817..7a6beef71a7406 100644 --- a/src/mono/mono/metadata/marshal-shared.c +++ b/src/mono/mono/metadata/marshal-shared.c @@ -507,7 +507,7 @@ mono_marshal_shared_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *ty int esize; if (type->type == MONO_TYPE_SZARRAY) { - eklass = type->data.klass; + eklass = m_type_data_get_klass_unchecked (type); } else { g_assert_not_reached (); } @@ -873,8 +873,8 @@ mono_marshal_shared_emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *kla MonoType *etype; int len; - if (t == MONO_TYPE_VALUETYPE && m_class_is_enumtype (ftype->data.klass)) { - ftype = mono_class_enum_basetype_internal (ftype->data.klass); + if (t == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_type_data_get_klass_unchecked (ftype))) { + ftype = mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (ftype)); goto handle_enum; } @@ -1060,9 +1060,9 @@ mono_marshal_shared_emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *ty int esize; if (type->type == MONO_TYPE_SZARRAY) { - eklass = type->data.klass; + eklass = m_type_data_get_klass_unchecked (type); } else if (type->type == MONO_TYPE_ARRAY) { - eklass = type->data.array->eklass; + eklass = m_type_data_get_array_unchecked (type)->eklass; g_assert(m_class_is_blittable (eklass)); } else { g_assert_not_reached (); diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 99d914ba32b66e..03379d5c2fd9fe 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -1347,15 +1347,15 @@ mono_type_to_ldind (MonoType *type) case MONO_TYPE_R8: return CEE_LDIND_R8; case MONO_TYPE_VALUETYPE: - if (m_class_is_enumtype (type->data.klass)) { - type = mono_class_enum_basetype_internal (type->data.klass); + if (m_class_is_enumtype (m_type_data_get_klass_unchecked (type))) { + type = mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (type)); goto handle_enum; } return CEE_LDOBJ; case MONO_TYPE_TYPEDBYREF: return CEE_LDOBJ; case MONO_TYPE_GENERICINST: - type = m_class_get_byval_arg (type->data.generic_class->container_class); + type = m_class_get_byval_arg (m_type_data_get_generic_class_unchecked (type)->container_class); goto handle_enum; default: g_error ("unknown type 0x%02x in type_to_ldind", type->type); @@ -1401,15 +1401,15 @@ mono_type_to_stind (MonoType *type) case MONO_TYPE_R8: return CEE_STIND_R8; case MONO_TYPE_VALUETYPE: - if (m_class_is_enumtype (type->data.klass)) { - type = mono_class_enum_basetype_internal (type->data.klass); + if (m_class_is_enumtype (m_type_data_get_klass_unchecked (type))) { + type = mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (type)); goto handle_enum; } return CEE_STOBJ; case MONO_TYPE_TYPEDBYREF: return CEE_STOBJ; case MONO_TYPE_GENERICINST: - type = m_class_get_byval_arg (type->data.generic_class->container_class); + type = m_class_get_byval_arg (m_type_data_get_generic_class_unchecked (type)->container_class); goto handle_enum; default: g_error ("unknown type 0x%02x in type_to_stind", type->type); @@ -1602,7 +1602,7 @@ mono_marshal_need_free (MonoType *t, MonoMethodPInvoke *piinfo, MonoMarshalSpec return TRUE; case MONO_TYPE_OBJECT: case MONO_TYPE_CLASS: - if (t->data.klass == mono_class_try_get_stringbuilder_class ()) { + if (m_type_data_get_klass_unchecked (t) == mono_class_try_get_stringbuilder_class ()) { gboolean need_free; mono_marshal_get_ptr_to_stringbuilder_conv (piinfo, spec, &need_free); return need_free; @@ -2495,8 +2495,8 @@ get_runtime_invoke_type (MonoType *t, gboolean ret) case MONO_TYPE_U: return mono_get_int_type (); case MONO_TYPE_VALUETYPE: - if (m_class_is_enumtype (t->data.klass)) { - t = mono_class_enum_basetype_internal (t->data.klass); + if (m_class_is_enumtype (m_type_data_get_klass_unchecked (t))) { + t = mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (t)); goto handle_enum; } return t; @@ -5364,7 +5364,7 @@ mono_marshal_get_unsafe_accessor_wrapper (MonoMethod *accessor_method, MonoUnsaf return res; } // printf ("Cache miss\n"); - + mb = mono_mb_new (accessor_method->klass, accessor_method->name, MONO_WRAPPER_OTHER); if (generic_wrapper) { // If the accessor method was generic, make the wrapper generic, too. @@ -6325,7 +6325,7 @@ mono_marshal_asany_impl (MonoObjectHandle o, MonoMarshalNative string_encoding, case MONO_TYPE_CLASS: case MONO_TYPE_VALUETYPE: { - MonoClass *klass = t->data.klass; + MonoClass *klass = m_type_data_get_klass_unchecked (t); if (mono_class_is_auto_layout (klass)) break; @@ -6349,7 +6349,8 @@ mono_marshal_asany_impl (MonoObjectHandle o, MonoMarshalNative string_encoding, } case MONO_TYPE_SZARRAY: { //TODO: Implement structs and in-params for all value types - MonoClass *klass = t->data.klass; + // FIXME: This appears to be incorrect, t->data->klass is initialized to the eklass. -kg + MonoClass *klass = m_type_data_get_klass_unchecked (t); MonoClass *eklass = m_class_get_element_class (klass); MonoArray *arr = (MonoArray *) MONO_HANDLE_RAW (o); @@ -6357,6 +6358,7 @@ mono_marshal_asany_impl (MonoObjectHandle o, MonoMarshalNative string_encoding, if ((param_attrs & PARAM_ATTRIBUTE_IN) && eklass != mono_get_char_class ()) break; + // FIXME: SZARRAY rank is always 1; this is either never true or is trying to check for T[][,]. I suspect this is just a dead if. -kg if (m_class_get_rank (klass) > 1) break; @@ -6412,7 +6414,7 @@ mono_marshal_free_asany_impl (MonoObjectHandle o, gpointer ptr, MonoMarshalNativ break; case MONO_TYPE_CLASS: case MONO_TYPE_VALUETYPE: { - MonoClass *klass = t->data.klass; + MonoClass *klass = m_type_data_get_klass_unchecked (t); if (m_class_is_valuetype (klass) && (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass))) break; @@ -6437,7 +6439,8 @@ mono_marshal_free_asany_impl (MonoObjectHandle o, gpointer ptr, MonoMarshalNativ break; } case MONO_TYPE_SZARRAY: { - MonoClass *klass = t->data.klass; + // FIXME: t->data->klass should already be the eklass. -kg + MonoClass *klass = m_type_data_get_klass_unchecked (t); MonoClass *eklass = m_class_get_element_class (klass); MonoArray *arr = (MonoArray *) MONO_HANDLE_RAW (o); @@ -6446,6 +6449,8 @@ mono_marshal_free_asany_impl (MonoObjectHandle o, gpointer ptr, MonoMarshalNativ mono_unichar2 *utf16_array = g_utf8_to_utf16 ((const char *)ptr, arr->max_length, NULL, NULL, NULL); g_free (ptr); + // g_utf8_to_utf16 can fail and return NULL. In that case we can't do anything except either continue or crash. + g_assert (utf16_array); memcpy (arr->vector, utf16_array, arr->max_length * sizeof (mono_unichar2)); g_free (utf16_array); break; @@ -6751,7 +6756,7 @@ typedef enum { SWIFT_DOUBLE, } SwiftPhysicalLoweringKind; -static int get_swift_lowering_alignment (SwiftPhysicalLoweringKind kind) +static int get_swift_lowering_alignment (SwiftPhysicalLoweringKind kind) { switch (kind) { case SWIFT_INT64: @@ -6764,19 +6769,19 @@ static int get_swift_lowering_alignment (SwiftPhysicalLoweringKind kind) } } -static void set_lowering_range(guint8* lowered_bytes, guint32 offset, guint32 size, SwiftPhysicalLoweringKind kind) +static void set_lowering_range(guint8* lowered_bytes, guint32 offset, guint32 size, SwiftPhysicalLoweringKind kind) { bool force_opaque = false; - + if (offset != ALIGN_TO(offset, get_swift_lowering_alignment(kind))) { // If the start of the range is not aligned, we need to force the entire range to be opaque. force_opaque = true; } - + // Check if any of the range is non-empty. // If so, we need to force this range to be opaque // and extend the range to the existing tag's range and mark as opaque in addition to the requested range. - + for (guint32 i = 0; i < size; ++i) { SwiftPhysicalLoweringKind current = (SwiftPhysicalLoweringKind)lowered_bytes[offset + i]; if (current != SWIFT_EMPTY && current != kind) { @@ -6796,7 +6801,7 @@ static void set_lowering_range(guint8* lowered_bytes, guint32 offset, guint32 si static void record_struct_field_physical_lowering (guint8* lowered_bytes, MonoType* type, guint32 offset); -static void record_inlinearray_struct_physical_lowering (guint8* lowered_bytes, MonoClass* klass, guint32 offset) +static void record_inlinearray_struct_physical_lowering (guint8* lowered_bytes, MonoClass* klass, guint32 offset) { int align; int type_offset = MONO_ABI_SIZEOF (MonoObject); @@ -6841,7 +6846,7 @@ static void record_struct_physical_lowering (guint8* lowered_bytes, MonoClass* k } } -static void record_struct_field_physical_lowering (guint8* lowered_bytes, MonoType* type, guint32 offset) +static void record_struct_field_physical_lowering (guint8* lowered_bytes, MonoType* type, guint32 offset) { int align; @@ -6864,7 +6869,7 @@ static void record_struct_field_physical_lowering (guint8* lowered_bytes, MonoTy else if (type->type == MONO_TYPE_PTR || type->type == MONO_TYPE_FNPTR || type->type == MONO_TYPE_I || type->type == MONO_TYPE_U) { kind = SWIFT_INT64; - } + } #endif else if (type->type == MONO_TYPE_R4) { kind = SWIFT_FLOAT; @@ -6913,7 +6918,7 @@ mono_marshal_get_swift_physical_lowering (MonoType *type, gboolean native_layout } guint8 lowered_bytes[TARGET_SIZEOF_VOID_P * 4] = { 0 }; - + // Loop through all fields and get the physical lowering for each field record_struct_physical_lowering(lowered_bytes, klass, 0); @@ -6943,7 +6948,7 @@ mono_marshal_get_swift_physical_lowering (MonoType *type, gboolean native_layout || (i == ALIGN_TO(i, 8) && (current == SWIFT_DOUBLE || current == SWIFT_INT64)) // We've changed interval types || current != lowered_bytes[i - 1]; - + if (start_new_interval) { struct _SwiftInterval interval = { i, 1, current }; g_array_append_val(intervals, interval); @@ -6973,7 +6978,7 @@ mono_marshal_get_swift_physical_lowering (MonoType *type, gboolean native_layout MonoType *lowered_types[4]; guint32 offsets[4]; guint32 num_lowered_types = 0; - + for (int i = 0; i < intervals->len; ++i) { if (num_lowered_types == 4) { // We can't handle more than 4 fields @@ -6983,7 +6988,7 @@ mono_marshal_get_swift_physical_lowering (MonoType *type, gboolean native_layout } struct _SwiftInterval interval = g_array_index(intervals, struct _SwiftInterval, i); - + offsets[num_lowered_types] = interval.start; switch (interval.kind) { diff --git a/src/mono/mono/metadata/metadata-internals.h b/src/mono/mono/metadata/metadata-internals.h index 3f0345f881185c..1c40430e2488c5 100644 --- a/src/mono/mono/metadata/metadata-internals.h +++ b/src/mono/mono/metadata/metadata-internals.h @@ -23,6 +23,7 @@ #include "../native/containers/dn-simdhash-specializations.h" struct _MonoType { + /* don't access directly, use m_type_data_get_ and m_type_data_set_ */ union { MonoClass *klass; /* for VALUETYPE and CLASS */ MonoType *type; /* for PTR */ @@ -30,7 +31,7 @@ struct _MonoType { MonoMethodSignature *method; MonoGenericParam *generic_param; /* for VAR and MVAR */ MonoGenericClass *generic_class; /* for GENERICINST */ - } data; + } data__; unsigned int attrs : 16; /* param attributes or field flags */ MonoTypeEnum type : 8; unsigned int has_cmods : 1; @@ -1281,7 +1282,7 @@ static inline MonoMethodSignature* mono_type_get_signature_internal (MonoType *type) { g_assert (type->type == MONO_TYPE_FNPTR); - return type->data.method; + return type->data__.method; } /** @@ -1296,6 +1297,115 @@ m_type_is_byref (const MonoType *type) return type->byref__; } +static MONO_NEVER_INLINE void +m_type_invalid_access (const char *fn_name, MonoTypeEnum actual_type) +{ + g_error ("MonoType with type %d accessed by %s", actual_type, fn_name); +} + +static inline gboolean +m_type_data_is_klass_valid (const MonoType *type) { + switch (type->type) { + // list based on class.c mono_class_from_mono_type_internal cases + case MONO_TYPE_OBJECT: + case MONO_TYPE_VOID: + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_CHAR: + case MONO_TYPE_I1: + case MONO_TYPE_U1: + case MONO_TYPE_I2: + case MONO_TYPE_U2: + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_I: + case MONO_TYPE_U: + case MONO_TYPE_I8: + case MONO_TYPE_U8: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + case MONO_TYPE_STRING: + case MONO_TYPE_TYPEDBYREF: + case MONO_TYPE_CLASS: + case MONO_TYPE_VALUETYPE: + case MONO_TYPE_SZARRAY: + return TRUE; + default: + return FALSE; + } +} + +/** + * when using _unchecked accessors for performance, it is your responsibility to check + * MonoType->type first and make sure you are accessing the correct member! + * m_type_data_xxx_klass is legal for \c MONO_TYPE_CLASS, \c MONO_TYPE_VALUETYPE, and \c MONO_TYPE_SZARRAY. + * It may work for other types but you should really use \c mono_class_from_mono_type_internal instead. + * m_type_data_xxx_generic_param is legal for \c MONO_TYPE_VAR and \c MONO_TYPE_MVAR. + * m_type_data_xxx_array is legal for \c MONO_TYPE_ARRAY but *not* \c MONO_TYPE_SZARRAY. + * m_type_data_xxx_type is legal for \c MONO_TYPE_PTR. + * m_type_data_xxx_method is legal for \c MONO_TYPE_FNPTR. + * m_type_data_xxx_generic_class is legal for \c MONO_TYPE_GENERICINST. + */ +#define DEFINE_TYPE_DATA_MEMBER_CHECKED_ACCESSORS(field_type, field_name, predicate) \ + static inline field_type \ + m_type_data_get_ ## field_name (const MonoType *type) \ + { \ + if (G_LIKELY(predicate)) \ + return type->data__.field_name; \ + m_type_invalid_access (__func__, type->type); \ + return NULL; \ + } \ + \ + static inline void \ + m_type_data_set_ ## field_name (MonoType *type, field_type value) \ + { \ + if (!G_LIKELY(predicate)) \ + m_type_invalid_access (__func__, type->type); \ + else \ + type->data__.field_name = value; \ + } + +#if (defined(ENABLE_CHECKED_BUILD) || defined(_DEBUG) || defined(DEBUG)) + +#define DEFINE_TYPE_DATA_MEMBER(field_type, field_name, predicate) \ + DEFINE_TYPE_DATA_MEMBER_CHECKED_ACCESSORS(field_type, field_name, predicate) \ + static inline field_type \ + m_type_data_get_ ## field_name ## _unchecked (const MonoType *type) \ + { \ + return m_type_data_get_ ## field_name (type); \ + } \ + static inline void \ + m_type_data_set_ ## field_name ## _unchecked (MonoType *type, field_type value) \ + { \ + m_type_data_set_ ## field_name (type, value); \ + } + +#else // ENABLE_CHECKED_BUILD || _DEBUG || DEBUG + +#define DEFINE_TYPE_DATA_MEMBER(field_type, field_name, predicate) \ + DEFINE_TYPE_DATA_MEMBER_CHECKED_ACCESSORS(field_type, field_name, predicate) \ + static inline field_type \ + m_type_data_get_ ## field_name ## _unchecked (const MonoType *type) \ + { \ + return type->data__.field_name; \ + } \ + static inline void \ + m_type_data_set_ ## field_name ## _unchecked (MonoType *type, field_type value) \ + { \ + type->data__.field_name = value; \ + } + +#endif // ENABLE_CHECKED_BUILD || _DEBUG || DEBUG + +DEFINE_TYPE_DATA_MEMBER(MonoClass *, klass, (m_type_data_is_klass_valid (type))); +DEFINE_TYPE_DATA_MEMBER(MonoGenericParam *, generic_param, ((type->type == MONO_TYPE_VAR) || (type->type == MONO_TYPE_MVAR))); +DEFINE_TYPE_DATA_MEMBER(MonoArrayType *, array, (type->type == MONO_TYPE_ARRAY)); +DEFINE_TYPE_DATA_MEMBER(MonoType *, type, (type->type == MONO_TYPE_PTR)); +DEFINE_TYPE_DATA_MEMBER(MonoMethodSignature *, method, (type->type == MONO_TYPE_FNPTR)); +DEFINE_TYPE_DATA_MEMBER(MonoGenericClass *, generic_class, (type->type == MONO_TYPE_GENERICINST)); + +#undef DEFINE_TYPE_DATA_MEMBER_CHECKED_ACCESSORS +#undef DEFINE_TYPE_DATA_MEMBER + /** * mono_type_get_class_internal: * \param type the \c MonoType operated on @@ -1308,7 +1418,7 @@ static inline MonoClass* mono_type_get_class_internal (MonoType *type) { /* FIXME: review the runtime users before adding the assert here */ - return type->data.klass; + return m_type_data_get_klass (type); } /** @@ -1322,7 +1432,7 @@ mono_type_get_class_internal (MonoType *type) static inline MonoArrayType* mono_type_get_array_type_internal (MonoType *type) { - return type->data.array; + return m_type_data_get_array (type); } static inline int diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index 91da538ff585a6..d194af42eacdc9 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -1854,7 +1854,7 @@ mono_type_hash (gconstpointer data) { const MonoType *type = (const MonoType *) data; if (type->type == MONO_TYPE_GENERICINST) - return mono_generic_class_hash (type->data.generic_class); + return mono_generic_class_hash (m_type_data_get_generic_class_unchecked (type)); else return type->type | ((m_type_is_byref (type) ? 1 : 0) << 8) | (type->attrs << 9); } @@ -2091,7 +2091,7 @@ try_get_canonical_type (MonoType *type, MonoType **canonical_type) */ g_assert (!type->has_cmods); if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) { - MonoType *ret = m_type_is_byref (type) ? m_class_get_this_arg (type->data.klass) : m_class_get_byval_arg (type->data.klass); + MonoType *ret = m_type_is_byref (type) ? m_class_get_this_arg (m_type_data_get_klass_unchecked (type)) : m_class_get_byval_arg (m_type_data_get_klass_unchecked (type)); /* Consider the case: @@ -2103,15 +2103,17 @@ try_get_canonical_type (MonoType *type, MonoType **canonical_type) We ensure that the MonoClass is in a state that we can canonicalize to: - klass->_byval_arg.data.klass == klass - klass->this_arg.data.klass == klass + klass->_byval_arg.data__.klass == klass + klass->this_arg.data__.klass == klass If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it. LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field of a MonoClass which currently holds the loader lock. 'type' is local. + + FIXME: is 'ret' guaranteed to have a ->data.klass? Or could it be a different kind of type? -kg */ - if (ret->data.klass == type->data.klass) { + if (m_type_data_get_klass (ret) == m_type_data_get_klass_unchecked (type)) { *canonical_type = ret; return TRUE; } @@ -2997,24 +2999,24 @@ type_in_image (MonoType *type, MonoImage *image) switch (type->type) { case MONO_TYPE_GENERICINST: - return gclass_in_image (type->data.generic_class, image); + return gclass_in_image (m_type_data_get_generic_class_unchecked (type), image); case MONO_TYPE_PTR: - type = type->data.type; + type = m_type_data_get_type_unchecked (type); goto retry; case MONO_TYPE_SZARRAY: - type = m_class_get_byval_arg (type->data.klass); + type = m_class_get_byval_arg (m_type_data_get_klass_unchecked (type)); goto retry; case MONO_TYPE_ARRAY: - type = m_class_get_byval_arg (type->data.array->eklass); + type = m_class_get_byval_arg (m_type_data_get_array_unchecked (type)->eklass); goto retry; case MONO_TYPE_FNPTR: - return signature_in_image (type->data.method, image); + return signature_in_image (m_type_data_get_method_unchecked (type), image); case MONO_TYPE_VAR: case MONO_TYPE_MVAR: - if (image == mono_get_image_for_generic_param (type->data.generic_param)) + if (image == mono_get_image_for_generic_param (m_type_data_get_generic_param_unchecked (type))) return TRUE; - else if (type->data.generic_param->gshared_constraint) { - type = type->data.generic_param->gshared_constraint; + else if (m_type_data_get_generic_param_unchecked (type)->gshared_constraint) { + type = m_type_data_get_generic_param_unchecked (type)->gshared_constraint; goto retry; } return FALSE; @@ -3168,26 +3170,26 @@ collect_type_images (MonoType *type, CollectData *data) switch (type->type) { case MONO_TYPE_GENERICINST: - collect_gclass_images (type->data.generic_class, data); + collect_gclass_images (m_type_data_get_generic_class_unchecked (type), data); break; case MONO_TYPE_PTR: - type = type->data.type; + type = m_type_data_get_type_unchecked (type); goto retry; case MONO_TYPE_SZARRAY: - type = m_class_get_byval_arg (type->data.klass); + type = m_class_get_byval_arg (m_type_data_get_klass_unchecked (type)); goto retry; case MONO_TYPE_ARRAY: - type = m_class_get_byval_arg (type->data.array->eklass); + type = m_class_get_byval_arg (m_type_data_get_array_unchecked (type)->eklass); goto retry; case MONO_TYPE_FNPTR: - collect_signature_images (type->data.method, data); + collect_signature_images (m_type_data_get_method_unchecked (type), data); break; case MONO_TYPE_VAR: case MONO_TYPE_MVAR: { - MonoImage *image = mono_get_image_for_generic_param (type->data.generic_param); + MonoImage *image = mono_get_image_for_generic_param (m_type_data_get_generic_param_unchecked (type)); add_image (image, data); - type = type->data.generic_param->gshared_constraint; + type = m_type_data_get_generic_param_unchecked (type)->gshared_constraint; if (type) goto retry; break; @@ -3422,7 +3424,7 @@ type_is_gtd (MonoType *type) switch (type->type) { case MONO_TYPE_CLASS: case MONO_TYPE_VALUETYPE: - return mono_class_is_gtd (type->data.klass); + return mono_class_is_gtd (m_type_data_get_klass_unchecked (type)); default: return FALSE; } @@ -3458,7 +3460,7 @@ mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv) for (i = 0; i < type_argc; ++i) { MonoType *t = ginst->type_argv [i]; if (type_is_gtd (t)) { - ginst->type_argv [i] = mono_class_gtd_get_canonical_inst (t->data.klass); + ginst->type_argv [i] = mono_class_gtd_get_canonical_inst (m_type_data_get_klass_unchecked (t)); } } @@ -3732,7 +3734,7 @@ do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericC if (rptr) *rptr = ptr; - type->data.generic_class = mono_metadata_lookup_generic_class (gklass, inst, FALSE); + m_type_data_set_generic_class (type, mono_metadata_lookup_generic_class (gklass, inst, FALSE)); return TRUE; } @@ -3959,12 +3961,12 @@ mono_metadata_get_shared_type (MonoType *type) switch (type->type){ case MONO_TYPE_CLASS: case MONO_TYPE_VALUETYPE: - if (m_class_get_mem_manager (type->data.klass)->collectible) + if (m_class_get_mem_manager (m_type_data_get_klass_unchecked (type))->collectible) /* These can be unloaded, so references to them shouldn't be shared */ return NULL; - if (type == m_class_get_byval_arg (type->data.klass)) + if (type == m_class_get_byval_arg (m_type_data_get_klass_unchecked (type))) return type; - if (type == m_class_get_this_arg (type->data.klass)) + if (type == m_class_get_this_arg (m_type_data_get_klass_unchecked (type))) return type; break; default: @@ -4098,7 +4100,7 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer MonoClass *klass; token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr); klass = mono_class_get_checked (m, token, error); - type->data.klass = klass; + m_type_data_set_klass_unchecked (type, klass); if (!klass) return FALSE; @@ -4112,29 +4114,29 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer if (!etype) return FALSE; - type->data.klass = mono_class_from_mono_type_internal (etype); + m_type_data_set_klass_unchecked (type, mono_class_from_mono_type_internal (etype)); if (transient) mono_metadata_free_type (etype); - g_assert (type->data.klass); //This was previously a check for NULL, but mcfmt should never fail. It can return a borken MonoClass, but should return at least something. + g_assert (m_type_data_get_klass_unchecked (type)); //This was previously a check for NULL, but mcfmt should never fail. It can return a borken MonoClass, but should return at least something. break; } case MONO_TYPE_PTR: { - type->data.type = mono_metadata_parse_type_checked (m, container, 0, transient, ptr, &ptr, error); - if (!type->data.type) + m_type_data_set_type_unchecked (type, mono_metadata_parse_type_checked (m, container, 0, transient, ptr, &ptr, error)); + if (!m_type_data_get_type_unchecked (type)) return FALSE; break; } case MONO_TYPE_FNPTR: { - type->data.method = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr, error); - if (!type->data.method) + m_type_data_set_method_unchecked (type, mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr, error)); + if (!m_type_data_get_method_unchecked (type)) return FALSE; break; } case MONO_TYPE_ARRAY: { - type->data.array = mono_metadata_parse_array_internal (m, container, transient, ptr, &ptr, error); - if (!type->data.array) + m_type_data_set_array_unchecked (type, mono_metadata_parse_array_internal (m, container, transient, ptr, &ptr, error)); + if (!m_type_data_get_array_unchecked (type)) return FALSE; break; } @@ -4143,8 +4145,8 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer if (container && !verify_var_type_and_container (m, type->type, container, error)) return FALSE; - type->data.generic_param = mono_metadata_parse_generic_param (m, container, type->type, ptr, &ptr, error); - if (!type->data.generic_param) + m_type_data_set_generic_param_unchecked (type, mono_metadata_parse_generic_param (m, container, type->type, ptr, &ptr, error)); + if (!m_type_data_get_generic_param_unchecked (type)) return FALSE; break; @@ -4181,22 +4183,24 @@ mono_metadata_free_type (MonoType *type) switch (type->type){ case MONO_TYPE_OBJECT: case MONO_TYPE_STRING: - if (!type->data.klass) + /* We should normally not be using this accessor because klass could be null, but we're guarding against the potential null here. */ + /* fixme: is it legal and desirable to free System.Object or System.String? Under which circumstances do we need to do it? -kg */ + if (!m_type_data_get_klass_unchecked (type)) break; - /* fall through */ + /* fall through since we checked for null so the following logic is safe. */ case MONO_TYPE_CLASS: case MONO_TYPE_VALUETYPE: - if (type == m_class_get_byval_arg (type->data.klass) || type == m_class_get_this_arg (type->data.klass)) + if (type == m_class_get_byval_arg (m_type_data_get_klass_unchecked (type)) || type == m_class_get_this_arg (m_type_data_get_klass_unchecked (type))) return; break; case MONO_TYPE_PTR: - mono_metadata_free_type (type->data.type); + mono_metadata_free_type (m_type_data_get_type_unchecked (type)); break; case MONO_TYPE_FNPTR: - mono_metadata_free_method_signature (type->data.method); + mono_metadata_free_method_signature (m_type_data_get_method_unchecked (type)); break; case MONO_TYPE_ARRAY: - mono_metadata_free_array (type->data.array); + mono_metadata_free_array (m_type_data_get_array_unchecked (type)); break; default: break; @@ -5315,8 +5319,6 @@ mono_type_set_alignment (MonoTypeEnum type, int align) int mono_type_size (MonoType *t, int *align) { - MonoTypeEnum simple_type; - if (!t) { *align = 1; return 0; @@ -5326,9 +5328,7 @@ mono_type_size (MonoType *t, int *align) return MONO_ABI_SIZEOF (gpointer); } - simple_type = t->type; - again: - switch (simple_type) { + switch (t->type) { case MONO_TYPE_VOID: *align = 1; return 0; @@ -5363,10 +5363,10 @@ mono_type_size (MonoType *t, int *align) *align = MONO_ABI_ALIGNOF (gpointer); return MONO_ABI_SIZEOF (gpointer); case MONO_TYPE_VALUETYPE: { - if (m_class_is_enumtype (t->data.klass)) - return mono_type_size (mono_class_enum_basetype_internal (t->data.klass), align); + if (m_class_is_enumtype (m_type_data_get_klass_unchecked (t))) + return mono_type_size (mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (t)), align); else - return mono_class_value_size (t->data.klass, (guint32*)align); + return mono_class_value_size (m_type_data_get_klass_unchecked (t), (guint32*)align); } case MONO_TYPE_STRING: case MONO_TYPE_OBJECT: @@ -5380,7 +5380,7 @@ mono_type_size (MonoType *t, int *align) case MONO_TYPE_TYPEDBYREF: return mono_class_value_size (mono_defaults.typed_reference_class, (guint32*)align); case MONO_TYPE_GENERICINST: { - MonoGenericClass *gclass = t->data.generic_class; + MonoGenericClass *gclass = m_type_data_get_generic_class_unchecked (t); MonoClass *container_class = gclass->container_class; // g_assert (!gclass->inst->is_open); @@ -5397,13 +5397,12 @@ mono_type_size (MonoType *t, int *align) } case MONO_TYPE_VAR: case MONO_TYPE_MVAR: - if (!t->data.generic_param->gshared_constraint || t->data.generic_param->gshared_constraint->type == MONO_TYPE_VALUETYPE) { + if (!m_type_data_get_generic_param_unchecked (t)->gshared_constraint || m_type_data_get_generic_param_unchecked (t)->gshared_constraint->type == MONO_TYPE_VALUETYPE) { *align = MONO_ABI_ALIGNOF (gpointer); return MONO_ABI_SIZEOF (gpointer); } else { /* The gparam can only match types given by gshared_constraint */ - return mono_type_size (t->data.generic_param->gshared_constraint, align); - goto again; + return mono_type_size (m_type_data_get_generic_param_unchecked (t)->gshared_constraint, align); } default: g_error ("mono_type_size: type 0x%02x unknown", t->type); @@ -5465,12 +5464,12 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open) case MONO_TYPE_VAR: case MONO_TYPE_MVAR: g_assert (allow_open); - if (!t->data.generic_param->gshared_constraint || t->data.generic_param->gshared_constraint->type == MONO_TYPE_VALUETYPE) { + if (!m_type_data_get_generic_param_unchecked (t)->gshared_constraint || m_type_data_get_generic_param_unchecked (t)->gshared_constraint->type == MONO_TYPE_VALUETYPE) { *align = stack_slot_align; return stack_slot_size; } else { /* The gparam can only match types given by gshared_constraint */ - return mono_type_stack_size_internal (t->data.generic_param->gshared_constraint, align, allow_open); + return mono_type_stack_size_internal (m_type_data_get_generic_param_unchecked (t)->gshared_constraint, align, allow_open); } case MONO_TYPE_TYPEDBYREF: *align = stack_slot_align; @@ -5488,10 +5487,10 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open) case MONO_TYPE_VALUETYPE: { guint32 size; - if (m_class_is_enumtype (t->data.klass)) - return mono_type_stack_size_internal (mono_class_enum_basetype_internal (t->data.klass), align, allow_open); + if (m_class_is_enumtype (m_type_data_get_klass_unchecked (t))) + return mono_type_stack_size_internal (mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (t)), align, allow_open); else { - size = mono_class_value_size (t->data.klass, (guint32*)align); + size = mono_class_value_size (m_type_data_get_klass_unchecked (t), (guint32*)align); *align = *align + stack_slot_align - 1; *align &= ~(stack_slot_align - 1); @@ -5503,7 +5502,7 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open) } } case MONO_TYPE_GENERICINST: { - MonoGenericClass *gclass = t->data.generic_class; + MonoGenericClass *gclass = m_type_data_get_generic_class_unchecked (t); MonoClass *container_class = gclass->container_class; if (!allow_open) @@ -5538,7 +5537,7 @@ gboolean mono_type_generic_inst_is_valuetype (MonoType *type) { g_assert (type->type == MONO_TYPE_GENERICINST); - return m_class_is_valuetype (type->data.generic_class->container_class); + return m_class_is_valuetype (m_type_data_get_generic_class_unchecked (type)->container_class); } /** @@ -5635,7 +5634,7 @@ mono_metadata_type_hash (MonoType *t1) case MONO_TYPE_VALUETYPE: case MONO_TYPE_CLASS: case MONO_TYPE_SZARRAY: { - MonoClass *klass = t1->data.klass; + MonoClass *klass = m_type_data_get_klass_unchecked (t1); /* * Dynamic classes must not be hashed on their type since it can change * during runtime. For example, if we hash a reference type that is @@ -5649,14 +5648,14 @@ mono_metadata_type_hash (MonoType *t1) return ((hash << 5) - hash) ^ m_class_get_name_hash (klass); } case MONO_TYPE_PTR: - return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type); + return ((hash << 5) - hash) ^ mono_metadata_type_hash (m_type_data_get_type_unchecked (t1)); case MONO_TYPE_ARRAY: - return ((hash << 5) - hash) ^ mono_metadata_type_hash (m_class_get_byval_arg (t1->data.array->eklass)); + return ((hash << 5) - hash) ^ mono_metadata_type_hash (m_class_get_byval_arg (m_type_data_get_array_unchecked (t1)->eklass)); case MONO_TYPE_GENERICINST: - return ((hash << 5) - hash) ^ mono_generic_class_hash (t1->data.generic_class); + return ((hash << 5) - hash) ^ mono_generic_class_hash (m_type_data_get_generic_class_unchecked (t1)); case MONO_TYPE_VAR: case MONO_TYPE_MVAR: - return ((hash << 5) - hash) ^ mono_metadata_generic_param_hash (t1->data.generic_param); + return ((hash << 5) - hash) ^ mono_metadata_generic_param_hash (m_type_data_get_generic_param_unchecked (t1)); default: return hash; } @@ -5734,22 +5733,22 @@ mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only MonoType *c2_type = m_class_get_byval_arg (c2); if ((c1_type->type == MONO_TYPE_VAR) && (c2_type->type == MONO_TYPE_VAR)) return mono_metadata_generic_param_equal_internal ( - c1_type->data.generic_param, c2_type->data.generic_param, signature_only); + m_type_data_get_generic_param_unchecked (c1_type), m_type_data_get_generic_param_unchecked (c2_type), signature_only); if ((c1_type->type == MONO_TYPE_MVAR) && (c2_type->type == MONO_TYPE_MVAR)) return mono_metadata_generic_param_equal_internal ( - c1_type->data.generic_param, c2_type->data.generic_param, signature_only); + m_type_data_get_generic_param_unchecked (c1_type), m_type_data_get_generic_param_unchecked (c2_type), signature_only); if (signature_only && (c1_type->type == MONO_TYPE_SZARRAY) && (c2_type->type == MONO_TYPE_SZARRAY)) - return mono_metadata_class_equal (c1_type->data.klass, c2_type->data.klass, signature_only); + return mono_metadata_class_equal (m_type_data_get_klass_unchecked (c1_type), m_type_data_get_klass_unchecked (c2_type), signature_only); if (signature_only && (c1_type->type == MONO_TYPE_ARRAY) && (c2_type->type == MONO_TYPE_ARRAY)) return do_mono_metadata_type_equal (c1_type, c2_type, signature_only ? MONO_TYPE_EQ_FLAGS_SIG_ONLY : 0); if (signature_only && (c1_type->type == MONO_TYPE_PTR) && (c2_type->type == MONO_TYPE_PTR)) - return do_mono_metadata_type_equal (c1_type->data.type, c2_type->data.type, signature_only ? MONO_TYPE_EQ_FLAGS_SIG_ONLY : 0); + return do_mono_metadata_type_equal (m_type_data_get_type_unchecked (c1_type), m_type_data_get_type_unchecked (c2_type), signature_only ? MONO_TYPE_EQ_FLAGS_SIG_ONLY : 0); if (signature_only && (c1_type->type == MONO_TYPE_FNPTR) && (c2_type->type == MONO_TYPE_FNPTR)) - return mono_metadata_fnptr_equal (c1_type->data.method, c2_type->data.method, signature_only ? MONO_TYPE_EQ_FLAGS_SIG_ONLY : 0); + return mono_metadata_fnptr_equal (m_type_data_get_method_unchecked (c1_type), m_type_data_get_method_unchecked (c2_type), signature_only ? MONO_TYPE_EQ_FLAGS_SIG_ONLY : 0); return FALSE; } @@ -5891,31 +5890,31 @@ do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, int equiv_flags) case MONO_TYPE_VALUETYPE: case MONO_TYPE_CLASS: case MONO_TYPE_SZARRAY: - result = mono_metadata_class_equal (t1->data.klass, t2->data.klass, (equiv_flags & MONO_TYPE_EQ_FLAGS_SIG_ONLY) != 0); + result = mono_metadata_class_equal (m_type_data_get_klass_unchecked (t1), m_type_data_get_klass_unchecked (t2), (equiv_flags & MONO_TYPE_EQ_FLAGS_SIG_ONLY) != 0); break; case MONO_TYPE_PTR: - result = do_mono_metadata_type_equal (t1->data.type, t2->data.type, equiv_flags); + result = do_mono_metadata_type_equal (m_type_data_get_type_unchecked (t1), m_type_data_get_type_unchecked (t2), equiv_flags); break; case MONO_TYPE_ARRAY: - if (t1->data.array->rank != t2->data.array->rank) + if (m_type_data_get_array_unchecked (t1)->rank != m_type_data_get_array_unchecked (t2)->rank) result = FALSE; else - result = mono_metadata_class_equal (t1->data.array->eklass, t2->data.array->eklass, (equiv_flags & MONO_TYPE_EQ_FLAGS_SIG_ONLY) != 0); + result = mono_metadata_class_equal (m_type_data_get_array_unchecked (t1)->eklass, m_type_data_get_array_unchecked (t2)->eklass, (equiv_flags & MONO_TYPE_EQ_FLAGS_SIG_ONLY) != 0); break; case MONO_TYPE_GENERICINST: result = _mono_metadata_generic_class_equal ( - t1->data.generic_class, t2->data.generic_class, (equiv_flags & MONO_TYPE_EQ_FLAGS_SIG_ONLY) != 0); + m_type_data_get_generic_class_unchecked (t1), m_type_data_get_generic_class_unchecked (t2), (equiv_flags & MONO_TYPE_EQ_FLAGS_SIG_ONLY) != 0); break; case MONO_TYPE_VAR: result = mono_metadata_generic_param_equal_internal ( - t1->data.generic_param, t2->data.generic_param, (equiv_flags & MONO_TYPE_EQ_FLAGS_SIG_ONLY) != 0); + m_type_data_get_generic_param_unchecked (t1), m_type_data_get_generic_param_unchecked (t2), (equiv_flags & MONO_TYPE_EQ_FLAGS_SIG_ONLY) != 0); break; case MONO_TYPE_MVAR: result = mono_metadata_generic_param_equal_internal ( - t1->data.generic_param, t2->data.generic_param, (equiv_flags & MONO_TYPE_EQ_FLAGS_SIG_ONLY) != 0); + m_type_data_get_generic_param_unchecked (t1), m_type_data_get_generic_param_unchecked (t2), (equiv_flags & MONO_TYPE_EQ_FLAGS_SIG_ONLY) != 0); break; case MONO_TYPE_FNPTR: - result = mono_metadata_fnptr_equal (t1->data.method, t2->data.method, equiv_flags); + result = mono_metadata_fnptr_equal (m_type_data_get_method_unchecked (t1), m_type_data_get_method_unchecked (t2), equiv_flags); break; default: g_error ("implement type compare for %0x!", t1->type); @@ -6268,12 +6267,12 @@ static void deep_type_dup_fixup (MonoImage *image, MonoType *r, const MonoType *o) { if (o->type == MONO_TYPE_PTR) { - r->data.type = mono_metadata_type_dup (image, o->data.type); + m_type_data_set_type (r, mono_metadata_type_dup (image, m_type_data_get_type_unchecked (o))); } else if (o->type == MONO_TYPE_ARRAY) { - r->data.array = mono_dup_array_type (image, o->data.array); + m_type_data_set_array (r, mono_dup_array_type (image, m_type_data_get_array_unchecked (o))); } else if (o->type == MONO_TYPE_FNPTR) { /*FIXME the dup'ed signature is leaked mono_metadata_free_type*/ - r->data.method = mono_metadata_signature_deep_dup (image, o->data.method); + m_type_data_set_method (r, mono_metadata_signature_deep_dup (image, m_type_data_get_method_unchecked (o))); } } @@ -7008,24 +7007,27 @@ mono_type_to_unmanaged (MonoType *type, MonoMarshalSpec *mspec, gboolean as_fiel } case MONO_TYPE_PTR: return MONO_NATIVE_UINT; case MONO_TYPE_VALUETYPE: /*FIXME*/ + { if (mspec && mspec->native == MONO_NATIVE_CUSTOM) return MONO_NATIVE_CUSTOM; - if (m_class_is_enumtype (type->data.klass)) { - t = mono_class_enum_basetype_internal (type->data.klass)->type; + MonoClass *type_klass = m_type_data_get_klass (type); + if (m_class_is_enumtype (type_klass)) { + t = mono_class_enum_basetype_internal (type_klass)->type; goto handle_enum; } - if (type->data.klass == mono_class_try_get_handleref_class ()){ + if (type_klass == mono_class_try_get_handleref_class ()){ *conv = MONO_MARSHAL_CONV_HANDLEREF; return MONO_NATIVE_INT; } return MONO_NATIVE_STRUCT; + } case MONO_TYPE_SZARRAY: case MONO_TYPE_ARRAY: if (mspec) { switch (mspec->native) { case MONO_NATIVE_BYVALARRAY: - if ((m_class_get_element_class (type->data.klass) == mono_defaults.char_class) && !unicode) + if ((m_class_get_element_class (mono_class_from_mono_type_internal (type)) == mono_defaults.char_class) && !unicode) *conv = MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY; else *conv = MONO_MARSHAL_CONV_ARRAY_BYVALARRAY; @@ -7077,34 +7079,41 @@ mono_type_to_unmanaged (MonoType *type, MonoMarshalSpec *mspec, gboolean as_fiel *conv = MONO_MARSHAL_CONV_OBJECT_IUNKNOWN; return MONO_NATIVE_IUNKNOWN; case MONO_NATIVE_FUNC: - if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class || - type->data.klass == mono_defaults.delegate_class || - m_class_get_parent (type->data.klass) == mono_defaults.multicastdelegate_class)) { + { + MonoClass *type_klass = (t == MONO_TYPE_CLASS) ? m_type_data_get_klass (type) : NULL; + if (t == MONO_TYPE_CLASS && (type_klass == mono_defaults.multicastdelegate_class || + type_klass == mono_defaults.delegate_class || + m_class_get_parent (type_klass) == mono_defaults.multicastdelegate_class)) { *conv = MONO_MARSHAL_CONV_DEL_FTN; return MONO_NATIVE_FUNC; } /* Fall through */ + } default: g_error ("cant marshal object as native type %02x", mspec->native); } } - if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class || - type->data.klass == mono_defaults.delegate_class || - m_class_get_parent (type->data.klass) == mono_defaults.multicastdelegate_class)) { - *conv = MONO_MARSHAL_CONV_DEL_FTN; - return MONO_NATIVE_FUNC; - } - if (mono_class_try_get_safehandle_class () && type->data.klass != NULL && - mono_class_is_subclass_of_internal (type->data.klass, mono_class_try_get_safehandle_class (), FALSE)){ - *conv = MONO_MARSHAL_CONV_SAFEHANDLE; - return MONO_NATIVE_INT; + + { + MonoClass *type_klass = (t == MONO_TYPE_CLASS) ? m_type_data_get_klass (type) : NULL; + if (t == MONO_TYPE_CLASS && (type_klass == mono_defaults.multicastdelegate_class || + type_klass == mono_defaults.delegate_class || + m_class_get_parent (type_klass) == mono_defaults.multicastdelegate_class)) { + *conv = MONO_MARSHAL_CONV_DEL_FTN; + return MONO_NATIVE_FUNC; + } + if (mono_class_try_get_safehandle_class () && type_klass != NULL && + mono_class_is_subclass_of_internal (type_klass, mono_class_try_get_safehandle_class (), FALSE)){ + *conv = MONO_MARSHAL_CONV_SAFEHANDLE; + return MONO_NATIVE_INT; + } + *conv = MONO_MARSHAL_CONV_OBJECT_STRUCT; + return MONO_NATIVE_STRUCT; } - *conv = MONO_MARSHAL_CONV_OBJECT_STRUCT; - return MONO_NATIVE_STRUCT; } case MONO_TYPE_FNPTR: return MONO_NATIVE_FUNC; case MONO_TYPE_GENERICINST: - type = m_class_get_byval_arg (type->data.generic_class->container_class); + type = m_class_get_byval_arg (m_type_data_get_generic_class (type)->container_class); t = type->type; goto handle_enum; case MONO_TYPE_TYPEDBYREF: @@ -7525,7 +7534,7 @@ mono_get_shared_generic_inst (MonoGenericContainer *container) MonoType *t = &helper [i]; t->type = container->is_method ? MONO_TYPE_MVAR : MONO_TYPE_VAR; - t->data.generic_param = mono_generic_container_get_param (container, i); + m_type_data_set_generic_param_unchecked (t, mono_generic_container_get_param (container, i)); type_argv [i] = t; } @@ -7619,7 +7628,7 @@ MonoType* mono_type_get_ptr_type (MonoType *type) { g_assert (type->type == MONO_TYPE_PTR); - return type->data.type; + return m_type_data_get_type_unchecked (type); } /** @@ -7642,10 +7651,10 @@ mono_bool mono_type_is_struct (MonoType *type) { return (!m_type_is_byref (type) && ((type->type == MONO_TYPE_VALUETYPE && - !m_class_is_enumtype (type->data.klass)) || (type->type == MONO_TYPE_TYPEDBYREF) || + !m_class_is_enumtype (m_type_data_get_klass_unchecked (type))) || (type->type == MONO_TYPE_TYPEDBYREF) || ((type->type == MONO_TYPE_GENERICINST) && - mono_metadata_generic_class_is_valuetype (type->data.generic_class) && - !m_class_is_enumtype (type->data.generic_class->container_class)))); + mono_metadata_generic_class_is_valuetype (m_type_data_get_generic_class_unchecked (type)) && + !m_class_is_enumtype (m_type_data_get_generic_class_unchecked (type)->container_class)))); } /** @@ -7691,7 +7700,7 @@ mono_type_is_reference (MonoType *type) (type->type == MONO_TYPE_SZARRAY) || (type->type == MONO_TYPE_CLASS) || (type->type == MONO_TYPE_OBJECT) || (type->type == MONO_TYPE_ARRAY)) || ((type->type == MONO_TYPE_GENERICINST) && - !mono_metadata_generic_class_is_valuetype (type->data.generic_class)))); + !mono_metadata_generic_class_is_valuetype (m_type_data_get_generic_class_unchecked (type))))); } mono_bool diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index 167e8828a0878b..7b453e88d237a5 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -2624,7 +2624,7 @@ mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject ** MonoMethodSignature *sig = mono_method_signature_internal (method); for (int i = 0; i < sig->param_count; i++) { MonoType *t = sig->params [i]; - if (t->type == MONO_TYPE_GENERICINST && t->data.generic_class->container_class == mono_defaults.generic_nullable_class) { + if (t->type == MONO_TYPE_GENERICINST && m_type_data_get_generic_class_unchecked (t)->container_class == mono_defaults.generic_nullable_class) { MonoClass *klass = mono_class_from_mono_type_internal (t); MonoObject *boxed_vt = (MonoObject*)params [i]; gpointer nullable_vt = g_alloca (mono_class_value_size (klass, NULL)); @@ -2667,7 +2667,7 @@ mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject ** // to return it as boxed vt or NULL for (int i = 0; i < sig->param_count; i++) { MonoType *t = sig->params [i]; - if (t->type == MONO_TYPE_GENERICINST && m_type_is_byref (t) && t->data.generic_class->container_class == mono_defaults.generic_nullable_class) { + if (t->type == MONO_TYPE_GENERICINST && m_type_is_byref (t) && m_type_data_get_generic_class_unchecked (t)->container_class == mono_defaults.generic_nullable_class) { MonoClass *klass = mono_class_from_mono_type_internal (t); gpointer nullable_vt = params_arg [i]; params [i] = mono_nullable_box (nullable_vt, klass, error); @@ -2950,8 +2950,8 @@ mono_copy_value (MonoType *type, void *dest, void *value, int deref_pointer) } case MONO_TYPE_VALUETYPE: /* note that 't' and 'type->type' can be different */ - if (type->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (type->data.klass)) { - t = mono_class_enum_basetype_internal (type->data.klass)->type; + if (type->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_type_data_get_klass (type))) { + t = mono_class_enum_basetype_internal (m_type_data_get_klass (type))->type; goto handle_enum; } else { MonoClass *klass = mono_class_from_mono_type_internal (type); @@ -2963,7 +2963,7 @@ mono_copy_value (MonoType *type, void *dest, void *value, int deref_pointer) } return; case MONO_TYPE_GENERICINST: - t = m_class_get_byval_arg (type->data.generic_class->container_class)->type; + t = m_class_get_byval_arg (m_type_data_get_generic_class (type)->container_class)->type; goto handle_enum; default: g_error ("got type %x", type->type); @@ -4985,9 +4985,9 @@ invoke_array_extract_argument (MonoArray *array, int i, MonoType *t, gboolean* h break; case MONO_TYPE_GENERICINST: if (m_type_is_byref (t)) - t = m_class_get_this_arg (t->data.generic_class->container_class); + t = m_class_get_this_arg (m_type_data_get_generic_class_unchecked (t)->container_class); else - t = m_class_get_byval_arg (t->data.generic_class->container_class); + t = m_class_get_byval_arg (m_type_data_get_generic_class_unchecked (t)->container_class); goto again; case MONO_TYPE_PTR: { MonoObject *arg; @@ -5106,7 +5106,7 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params, // to return it as boxed vt or NULL for (int i = 0; i < param_count; i++) { MonoType *t = sig->params [i]; - if (t->type == MONO_TYPE_GENERICINST && m_type_is_byref (t) && t->data.generic_class->container_class == mono_defaults.generic_nullable_class) { + if (t->type == MONO_TYPE_GENERICINST && m_type_is_byref (t) && m_type_data_get_generic_class_unchecked (t)->container_class == mono_defaults.generic_nullable_class) { MonoClass *klass = mono_class_from_mono_type_internal (t); MonoObject *boxed_vt = mono_nullable_box (pa [i], klass, error); goto_if_nok (error, return_error); @@ -5160,9 +5160,9 @@ invoke_byrefs_extract_argument (gpointer *params_byref, int i, MonoType *t) break; case MONO_TYPE_GENERICINST: if (m_type_is_byref (t)) - t = m_class_get_this_arg (t->data.generic_class->container_class); + t = m_class_get_this_arg (m_type_data_get_generic_class_unchecked (t)->container_class); else - t = m_class_get_byval_arg (t->data.generic_class->container_class); + t = m_class_get_byval_arg (m_type_data_get_generic_class_unchecked (t)->container_class); goto again; case MONO_TYPE_PTR: case MONO_TYPE_FNPTR: diff --git a/src/mono/mono/metadata/reflection.c b/src/mono/mono/metadata/reflection.c index 70e114a191999f..ea3d4bb282787e 100644 --- a/src/mono/mono/metadata/reflection.c +++ b/src/mono/mono/metadata/reflection.c @@ -392,7 +392,7 @@ mono_type_normalize (MonoType *type) if (type->type != MONO_TYPE_GENERICINST) return type; - gclass = type->data.generic_class; + gclass = m_type_data_get_generic_class_unchecked (type); ginst = gclass->context.class_inst; if (!ginst->is_open) return type; @@ -403,7 +403,7 @@ mono_type_normalize (MonoType *type) for (guint i = 0; i < ginst->type_argc; ++i) { MonoType *t = ginst->type_argv [i], *norm; - if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer) + if (t->type != MONO_TYPE_VAR || m_type_data_get_generic_param_unchecked (t)->num != i || m_type_data_get_generic_param_unchecked (t)->owner != gcontainer) is_denorm_gtd = FALSE; norm = mono_type_normalize (t); argv [i] = norm; @@ -570,7 +570,7 @@ mono_type_get_object_checked (MonoType *type, MonoError *error) goto leave; } - if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !m_class_was_typebuilder (type->data.generic_class->container_class)) { + if ((type->type == MONO_TYPE_GENERICINST) && m_type_data_get_generic_class_unchecked (type)->is_dynamic && !m_class_was_typebuilder (m_type_data_get_generic_class_unchecked (type)->container_class)) { /* This can happen if a TypeBuilder for a generic class K * had reflection_create_generic_class) called on it, but not * ves_icall_TypeBuilder_create_runtime_class. This can happen @@ -1030,19 +1030,21 @@ add_parameter_object_to_array (MonoMethod *method, MonoObjectHandle member, int def_value = get_dbnull (dbnull, error); goto_if_nok (error, leave); } else { - MonoType blob_type; + MonoType blob_type = { 0 }; blob_type.type = (MonoTypeEnum)blob_type_enum; - blob_type.data.klass = NULL; if (blob_type_enum == MONO_TYPE_CLASS) - blob_type.data.klass = mono_defaults.object_class; - else if ((sig_param->type == MONO_TYPE_VALUETYPE) && m_class_is_enumtype (sig_param->data.klass)) { + m_type_data_set_klass_unchecked (&blob_type, mono_defaults.object_class); + else if ((sig_param->type == MONO_TYPE_VALUETYPE) && m_class_is_enumtype (m_type_data_get_klass_unchecked (sig_param))) { /* For enums, types [i] contains the base type */ blob_type.type = MONO_TYPE_VALUETYPE; - blob_type.data.klass = mono_class_from_mono_type_internal (sig_param); - } else - blob_type.data.klass = mono_class_from_mono_type_internal (&blob_type); + m_type_data_set_klass_unchecked (&blob_type, mono_class_from_mono_type_internal (sig_param)); + } else { + // FIXME: Should this be called on sig_param, not &blob_type? The other similar if/elseif/else chain in the codebase doesn't match this. + // See icall.c mono_type_from_blob_type + m_type_data_set_klass (&blob_type, mono_class_from_mono_type_internal (&blob_type)); + } def_value = mono_get_object_from_blob (&blob_type, blob, MONO_HANDLE_NEW (MonoString, NULL), error); goto_if_nok (error, leave); diff --git a/src/mono/mono/metadata/sre-encode.c b/src/mono/mono/metadata/sre-encode.c index 3ad08a46c45572..9593efd99a4e1b 100644 --- a/src/mono/mono/metadata/sre-encode.c +++ b/src/mono/mono/metadata/sre-encode.c @@ -187,11 +187,11 @@ encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf) break; case MONO_TYPE_PTR: sigbuffer_add_value (buf, type->type); - encode_type (assembly, type->data.type, buf); + encode_type (assembly, m_type_data_get_type_unchecked (type), buf); break; case MONO_TYPE_SZARRAY: sigbuffer_add_value (buf, type->type); - encode_type (assembly, m_class_get_byval_arg (type->data.klass), buf); + encode_type (assembly, m_class_get_byval_arg (m_type_data_get_klass_unchecked (type)), buf); break; case MONO_TYPE_VALUETYPE: case MONO_TYPE_CLASS: { @@ -216,13 +216,13 @@ encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf) } case MONO_TYPE_ARRAY: sigbuffer_add_value (buf, type->type); - encode_type (assembly, m_class_get_byval_arg (type->data.array->eklass), buf); - sigbuffer_add_value (buf, type->data.array->rank); + encode_type (assembly, m_class_get_byval_arg (m_type_data_get_array_unchecked (type)->eklass), buf); + sigbuffer_add_value (buf, m_type_data_get_array_unchecked (type)->rank); sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */ sigbuffer_add_value (buf, 0); break; case MONO_TYPE_GENERICINST: - encode_generic_class (assembly, type->data.generic_class, buf); + encode_generic_class (assembly, m_type_data_get_generic_class_unchecked (type), buf); break; case MONO_TYPE_VAR: case MONO_TYPE_MVAR: diff --git a/src/mono/mono/metadata/sre.c b/src/mono/mono/metadata/sre.c index 7def0d08abd665..47b303d86ba1b4 100644 --- a/src/mono/mono/metadata/sre.c +++ b/src/mono/mono/metadata/sre.c @@ -1714,11 +1714,11 @@ mono_reflection_type_handle_mono_type (MonoReflectionTypeHandle ref, MonoError * result = mono_image_new0 (eclass->image, MonoType, 1); if (rank == 0) { result->type = MONO_TYPE_SZARRAY; - result->data.klass = eclass; + m_type_data_set_klass_unchecked (result, eclass); } else { MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (eclass->image, sizeof (MonoArrayType)); result->type = MONO_TYPE_ARRAY; - result->data.array = at; + m_type_data_set_array_unchecked (result, at); at->eklass = eclass; at->rank = rank; } @@ -2011,6 +2011,7 @@ encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuf argval = (const char*)mono_object_get_data (arg); simple_type = type->type; handle_enum: + // Because simple_type != type->type after a goto targeting handle_enum, we have to use checked m_type_data accessors inside this switch switch (simple_type) { case MONO_TYPE_BOOLEAN: case MONO_TYPE_U1: @@ -2038,14 +2039,16 @@ encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuf swap_with_size (p, argval, 8, 1); p += 8; break; - case MONO_TYPE_VALUETYPE: - if (type->data.klass->enumtype) { - simple_type = mono_class_enum_basetype_internal (type->data.klass)->type; + case MONO_TYPE_VALUETYPE: { + MonoClass *klass_of_type = m_type_data_get_klass (type); + if (klass_of_type->enumtype) { + simple_type = mono_class_enum_basetype_internal (klass_of_type)->type; goto handle_enum; } else { - g_warning ("generic valuetype %s not handled in custom attr value decoding", type->data.klass->name); + g_warning ("generic valuetype %s not handled in custom attr value decoding", klass_of_type->name); } break; + } case MONO_TYPE_STRING: { char *str; size_t slen; @@ -2119,7 +2122,7 @@ MONO_RESTORE_WARNING *p++ = (len >> 24) & 0xff; *retp = p; *retbuffer = buffer; - eclass = type->data.klass; + eclass = m_type_data_get_klass (type); arg_eclass = mono_object_class (arg)->element_class; if (!eclass) { @@ -2229,7 +2232,7 @@ MONO_RESTORE_WARNING static void encode_field_or_prop_type (MonoType *type, char *p, char **retp) { - if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) { + if (type->type == MONO_TYPE_VALUETYPE && m_type_data_get_klass_unchecked (type)->enumtype) { char *str = type_get_qualified_name (type, NULL); size_t slen = strlen (str); @@ -2251,7 +2254,7 @@ encode_field_or_prop_type (MonoType *type, char *p, char **retp) mono_metadata_encode_value (type->type, p, &p); if (type->type == MONO_TYPE_SZARRAY) /* See the examples in Partition VI, Annex B */ - encode_field_or_prop_type (m_class_get_byval_arg (type->data.klass), p, &p); + encode_field_or_prop_type (m_class_get_byval_arg (m_type_data_get_klass_unchecked (type)), p, &p); } *retp = p; @@ -2266,12 +2269,12 @@ encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char error_init (error); /* Preallocate a large enough buffer */ - if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) { + if (type->type == MONO_TYPE_VALUETYPE && m_type_data_get_klass_unchecked (type)->enumtype) { char *str = type_get_qualified_name (type, NULL); len = strlen (str); g_free (str); - } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) { - char *str = type_get_qualified_name (m_class_get_byval_arg (type->data.klass), NULL); + } else if (type->type == MONO_TYPE_SZARRAY && m_type_data_get_klass_unchecked (type)->enumtype) { + char *str = type_get_qualified_name (m_class_get_byval_arg (m_type_data_get_klass_unchecked (type)), NULL); len = strlen (str); g_free (str); } else { @@ -2711,7 +2714,7 @@ reflection_init_generic_class (MonoReflectionTypeBuilderHandle ref_tb, MonoError MONO_HANDLE_ARRAY_GETREF (ref_gparam, generic_params, i); MonoType *param_type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionType, ref_gparam), error); goto_if_nok (error, leave); - MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param; + MonoGenericParamFull *param = (MonoGenericParamFull *) m_type_data_get_generic_param (param_type); generic_container->type_params [i] = *param; /*Make sure we are a different type instance */ generic_container->type_params [i].owner = generic_container; @@ -2727,7 +2730,7 @@ reflection_init_generic_class (MonoReflectionTypeBuilderHandle ref_tb, MonoError MonoType *canonical_inst; canonical_inst = &((MonoClassGtd*)klass)->canonical_inst; canonical_inst->type = MONO_TYPE_GENERICINST; - canonical_inst->data.generic_class = mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE); + m_type_data_set_generic_class_unchecked (canonical_inst, mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE)); leave: HANDLE_FUNCTION_RETURN_VAL (is_ok (error)); @@ -3001,11 +3004,11 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass, mono_array_get_internal (rmb->generic_params, MonoReflectionGenericParam*, i); MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error); mono_error_assert_ok (error); - MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param; + MonoGenericParamFull *param = (MonoGenericParamFull *) m_type_data_get_generic_param (gp_type); container->type_params [i] = *param; container->type_params [i].owner = container; - gp->type.type->data.generic_param = (MonoGenericParam*)&container->type_params [i]; + m_type_data_set_generic_param (gp->type.type, (MonoGenericParam*)&container->type_params [i]); MonoClass *gklass = mono_class_from_mono_type_internal (gp_type); gklass->wastypebuilder = TRUE; @@ -3019,10 +3022,10 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass, for (gint32 i = 0; i < m->signature->param_count; ++i) { MonoType *t = m->signature->params [i]; if (t->type == MONO_TYPE_MVAR) { - MonoGenericParam *gparam = t->data.generic_param; + MonoGenericParam *gparam = m_type_data_get_generic_param_unchecked (t); if (gparam->num < count) { m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]); - m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num); + m_type_data_set_generic_param_unchecked (m->signature->params [i], mono_generic_container_get_param (container, gparam->num)); } } @@ -3722,7 +3725,7 @@ remove_instantiations_of_and_ensure_contents (gpointer key, ERROR_DECL (lerror); MonoError *error = already_failed ? lerror : data->error; - if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) { + if ((type->type == MONO_TYPE_GENERICINST) && (m_type_data_get_generic_class_unchecked (type)->container_class == klass)) { MonoClass *inst_klass = mono_class_from_mono_type_internal (type); //Ensure it's safe to use it. if (!fix_partial_generic_class (inst_klass, error)) { @@ -4209,7 +4212,7 @@ mono_reflection_resolve_object (MonoImage *image, MonoObject *obj, MonoClass **h goto_if_nok (error, return_null); MonoClass *klass; - klass = type->data.klass; + klass = m_type_data_get_klass (type); if (klass->wastypebuilder) { /* Already created */ result = klass; diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 51889fa514b9b3..033ef0d96b94b3 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -3485,7 +3485,7 @@ encode_klass_ref_inner (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, gui } } else if ((m_class_get_byval_arg (klass)->type == MONO_TYPE_VAR) || (m_class_get_byval_arg (klass)->type == MONO_TYPE_MVAR)) { MonoGenericContainer *container = mono_type_get_generic_param_owner (m_class_get_byval_arg (klass)); - MonoGenericParam *par = m_class_get_byval_arg (klass)->data.generic_param; + MonoGenericParam *par = m_type_data_get_generic_param_unchecked (m_class_get_byval_arg (klass)); encode_value (MONO_AOT_TYPEREF_VAR, p, &p); @@ -3726,24 +3726,24 @@ encode_type (MonoAotCompile *acfg, MonoType *t, guint8 *buf, guint8 **endbuf) encode_klass_ref (acfg, mono_class_from_mono_type_internal (t), p, &p); break; case MONO_TYPE_SZARRAY: - encode_klass_ref (acfg, t->data.klass, p, &p); + encode_klass_ref (acfg, m_type_data_get_klass_unchecked (t), p, &p); break; case MONO_TYPE_PTR: - encode_type (acfg, t->data.type, p, &p); + encode_type (acfg, m_type_data_get_type_unchecked (t), p, &p); break; case MONO_TYPE_FNPTR: - encode_signature (acfg, t->data.method, p, &p); + encode_signature (acfg, m_type_data_get_method_unchecked (t), p, &p); break; case MONO_TYPE_GENERICINST: { - MonoClass *gclass = t->data.generic_class->container_class; - MonoGenericInst *inst = t->data.generic_class->context.class_inst; + MonoClass *gclass = m_type_data_get_generic_class_unchecked (t)->container_class; + MonoGenericInst *inst = m_type_data_get_generic_class_unchecked (t)->context.class_inst; encode_klass_ref (acfg, gclass, p, &p); encode_ginst (acfg, inst, p, &p); break; } case MONO_TYPE_ARRAY: { - MonoArrayType *array = t->data.array; + MonoArrayType *array = m_type_data_get_array_unchecked (t); int i; encode_klass_ref (acfg, array->eklass, p, &p); @@ -5666,7 +5666,7 @@ check_type_depth (MonoType *t, int depth) switch (t->type) { case MONO_TYPE_GENERICINST: { - MonoGenericClass *gklass = t->data.generic_class; + MonoGenericClass *gklass = m_type_data_get_generic_class_unchecked (t); MonoGenericInst *ginst = gklass->context.class_inst; if (ginst) { @@ -9390,7 +9390,7 @@ add_referenced_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, int depth) m = gen; } } - + add_extra_method_with_depth (acfg, m, depth + 1); add_types_from_method_header (acfg, m); } @@ -10486,8 +10486,8 @@ append_mangled_ginst (GString *str, MonoGenericInst *ginst) case MONO_TYPE_VAR: case MONO_TYPE_MVAR: { MonoType *constraint = NULL; - if (type->data.generic_param) - constraint = type->data.generic_param->gshared_constraint; + if (m_type_data_get_generic_param_unchecked (type)) + constraint = m_type_data_get_generic_param_unchecked (type)->gshared_constraint; if (constraint) { g_assert (constraint->type != MONO_TYPE_VAR && constraint->type != MONO_TYPE_MVAR); g_string_append (str, "gshared:"); @@ -11218,11 +11218,11 @@ mono_aot_type_hash (MonoType *t1) case MONO_TYPE_CLASS: case MONO_TYPE_SZARRAY: /* check if the distribution is good enough */ - return ((hash << 5) - hash) ^ m_class_get_name_hash (t1->data.klass); + return ((hash << 5) - hash) ^ m_class_get_name_hash (m_type_data_get_klass_unchecked (t1)); case MONO_TYPE_PTR: - return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type); + return ((hash << 5) - hash) ^ mono_metadata_type_hash (m_type_data_get_type_unchecked (t1)); case MONO_TYPE_ARRAY: - return ((hash << 5) - hash) ^ mono_metadata_type_hash (m_class_get_byval_arg (t1->data.array->eklass)); + return ((hash << 5) - hash) ^ mono_metadata_type_hash (m_class_get_byval_arg (m_type_data_get_array_unchecked (t1)->eklass)); case MONO_TYPE_GENERICINST: return ((hash << 5) - hash) ^ 0; default: diff --git a/src/mono/mono/mini/aot-runtime-wasm.c b/src/mono/mono/mini/aot-runtime-wasm.c index 30fde73c155bd5..1687088b16597e 100644 --- a/src/mono/mono/mini/aot-runtime-wasm.c +++ b/src/mono/mono/mini/aot-runtime-wasm.c @@ -53,8 +53,8 @@ type_to_c (MonoType *t, gboolean *is_byref_return) case MONO_TYPE_VOID: return 'V'; case MONO_TYPE_VALUETYPE: { - if (m_class_is_enumtype (t->data.klass)) { - t = mono_class_enum_basetype_internal (t->data.klass); + if (m_class_is_enumtype (m_type_data_get_klass_unchecked (t))) { + t = mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (t)); goto handle_enum; } @@ -72,7 +72,8 @@ type_to_c (MonoType *t, gboolean *is_byref_return) return 'I'; } case MONO_TYPE_GENERICINST: { - if (m_class_is_valuetype (t->data.klass)) { + // This previously erroneously used m_type_data_get_klass which isn't legal for genericinst, we have to use class_from_mono_type_internal + if (m_class_is_valuetype (mono_class_from_mono_type_internal (t))) { MonoType *scalar_vtype; if (mini_wasm_is_scalar_vtype (t, &scalar_vtype)) return type_to_c (scalar_vtype, NULL); diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c index 11c8888d17b038..1f2da3264b2601 100644 --- a/src/mono/mono/mini/aot-runtime.c +++ b/src/mono/mono/mini/aot-runtime.c @@ -614,11 +614,11 @@ decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf, MonoError t = g_new0 (MonoType, 1); t->type = (MonoTypeEnum)type; if (is_not_anonymous) { - t->data.generic_param = mono_generic_container_get_param (container, num); + m_type_data_set_generic_param (t, mono_generic_container_get_param (container, num)); } else { /* Anonymous */ MonoGenericParam *par = mono_metadata_create_anon_gparam (module->assembly->image, num, type == MONO_TYPE_MVAR); - t->data.generic_param = par; + m_type_data_set_generic_param (t, par); // FIXME: maybe do this for all anon gparams? ((MonoGenericParamFull*)par)->info.name = mono_make_generic_name_string (module->assembly->image, num); } @@ -759,24 +759,24 @@ decode_type (MonoAotModule *module, guint8 *buf, guint8 **endbuf, MonoError *err break; case MONO_TYPE_VALUETYPE: case MONO_TYPE_CLASS: - t->data.klass = decode_klass_ref (module, p, &p, error); - if (!t->data.klass) + m_type_data_set_klass_unchecked (t, decode_klass_ref (module, p, &p, error)); + if (!m_type_data_get_klass_unchecked (t)) goto fail; break; case MONO_TYPE_SZARRAY: - t->data.klass = decode_klass_ref (module, p, &p, error); + m_type_data_set_klass_unchecked (t, decode_klass_ref (module, p, &p, error)); - if (!t->data.klass) + if (!m_type_data_get_klass_unchecked (t)) goto fail; break; case MONO_TYPE_PTR: - t->data.type = decode_type (module, p, &p, error); - if (!t->data.type) + m_type_data_set_type_unchecked (t, decode_type (module, p, &p, error)); + if (!m_type_data_get_type_unchecked (t)) goto fail; break; case MONO_TYPE_FNPTR: - t->data.method = decode_signature (module, p, &p); - if (!t->data.method) + m_type_data_set_method_unchecked (t, decode_signature (module, p, &p)); + if (!m_type_data_get_method_unchecked (t)) goto fail; break; case MONO_TYPE_GENERICINST: { @@ -798,7 +798,7 @@ decode_type (MonoAotModule *module, guint8 *buf, guint8 **endbuf, MonoError *err if (!type) goto fail; klass = mono_class_from_mono_type_internal (type); - t->data.generic_class = mono_class_get_generic_class (klass); + m_type_data_set_generic_class_unchecked (t, mono_class_get_generic_class (klass)); break; } case MONO_TYPE_ARRAY: { @@ -823,7 +823,7 @@ decode_type (MonoAotModule *module, guint8 *buf, guint8 **endbuf, MonoError *err array->lobounds = (int *)g_malloc0 (sizeof (int) * array->numlobounds); for (i = 0; i < array->numlobounds; ++i) array->lobounds [i] = decode_value (p, &p); - t->data.array = array; + m_type_data_set_array_unchecked (t, array); break; } case MONO_TYPE_VAR: @@ -831,7 +831,7 @@ decode_type (MonoAotModule *module, guint8 *buf, guint8 **endbuf, MonoError *err MonoClass *klass = decode_klass_ref (module, p, &p, error); if (!klass) goto fail; - t->data.generic_param = m_class_get_byval_arg (klass)->data.generic_param; + m_type_data_set_generic_param_unchecked (t, m_type_data_get_generic_param (m_class_get_byval_arg (klass))); break; } default: @@ -2119,10 +2119,10 @@ load_aot_module (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer void *handle; g_assert (info); - + // Copy aotid to MonoImage memcpy(&assembly->image->aotid, info->aotid, 16); - + if (info->flags & MONO_AOT_FILE_FLAG_SEPARATE_DATA) { aot_data = open_aot_data (assembly, info, &handle); @@ -4598,7 +4598,7 @@ inst_is_private (MonoGenericInst *inst) for (guint i = 0; i < inst->type_argc; ++i) { MonoType *t = inst->type_argv [i]; if ((t->type == MONO_TYPE_CLASS || t->type == MONO_TYPE_VALUETYPE)) { - int access_level = mono_class_get_flags (t->data.klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK; + int access_level = mono_class_get_flags (m_type_data_get_klass_unchecked (t)) & TYPE_ATTRIBUTE_VISIBILITY_MASK; if (access_level == TYPE_ATTRIBUTE_NESTED_PRIVATE || access_level == TYPE_ATTRIBUTE_NOT_PUBLIC) return TRUE; } diff --git a/src/mono/mono/mini/calls.c b/src/mono/mono/mini/calls.c index f150bc4d308174..dd07b3579f375b 100644 --- a/src/mono/mono/mini/calls.c +++ b/src/mono/mono/mini/calls.c @@ -118,8 +118,8 @@ ret_type_to_call_opcode (MonoCompile *cfg, MonoType *type, int calli, int virt) case MONO_TYPE_R8: return calli? OP_FCALL_REG: virt? OP_FCALL_MEMBASE: OP_FCALL; case MONO_TYPE_VALUETYPE: - if (m_class_is_enumtype (type->data.klass)) { - type = mono_class_enum_basetype_internal (type->data.klass); + if (m_class_is_enumtype (m_type_data_get_klass_unchecked (type))) { + type = mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (type)); goto handle_enum; } else { if (mini_class_is_simd (cfg, mono_class_from_mono_type_internal (type))) @@ -132,7 +132,7 @@ ret_type_to_call_opcode (MonoCompile *cfg, MonoType *type, int calli, int virt) case MONO_TYPE_GENERICINST: { if (mini_class_is_simd (cfg, mono_class_from_mono_type_internal (type))) return calli? OP_XCALL_REG: virt? OP_XCALL_MEMBASE: OP_XCALL; - type = m_class_get_byval_arg (type->data.generic_class->container_class); + type = m_class_get_byval_arg (m_type_data_get_generic_class_unchecked (type)->container_class); goto handle_enum; } case MONO_TYPE_VAR: diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index a83fd3ac4e3380..2bc048ca8d5fe7 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -843,15 +843,15 @@ stackval_from_data (MonoType *type, stackval *result, const void *data, gboolean result->data.p = *(gpointer*)data; break; case MONO_TYPE_VALUETYPE: - if (m_class_is_enumtype (type->data.klass)) { - stackval_from_data (mono_class_enum_basetype_internal (type->data.klass), result, data, pinvoke); + if (m_class_is_enumtype (m_type_data_get_klass_unchecked (type))) { + stackval_from_data (mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (type)), result, data, pinvoke); break; } else { int size; if (pinvoke) - size = mono_class_native_size (type->data.klass, NULL); + size = mono_class_native_size (m_type_data_get_klass_unchecked (type), NULL); else - size = mono_class_value_size (type->data.klass, NULL); + size = mono_class_value_size (m_type_data_get_klass_unchecked (type), NULL); memcpy (result, data, size); break; } @@ -866,7 +866,7 @@ stackval_from_data (MonoType *type, stackval *result, const void *data, gboolean memcpy (result, data, size); break; } - stackval_from_data (m_class_get_byval_arg (type->data.generic_class->container_class), result, data, pinvoke); + stackval_from_data (m_class_get_byval_arg (m_type_data_get_generic_class_unchecked (type)->container_class), result, data, pinvoke); break; } default: @@ -949,21 +949,21 @@ stackval_to_data (MonoType *type, stackval *val, void *data, gboolean pinvoke) return MINT_STACK_SLOT_SIZE; } case MONO_TYPE_VALUETYPE: - if (m_class_is_enumtype (type->data.klass)) { - return stackval_to_data (mono_class_enum_basetype_internal (type->data.klass), val, data, pinvoke); + if (m_class_is_enumtype (m_type_data_get_klass_unchecked (type))) { + return stackval_to_data (mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (type)), val, data, pinvoke); } else { int size; if (pinvoke) { - size = mono_class_native_size (type->data.klass, NULL); + size = mono_class_native_size (m_type_data_get_klass_unchecked (type), NULL); memcpy (data, val, size); } else { - size = mono_class_value_size (type->data.klass, NULL); - mono_value_copy_internal (data, val, type->data.klass); + size = mono_class_value_size (m_type_data_get_klass_unchecked (type), NULL); + mono_value_copy_internal (data, val, m_type_data_get_klass_unchecked (type)); } return ALIGN_TO (size, MINT_STACK_SLOT_SIZE); } case MONO_TYPE_GENERICINST: { - MonoClass *container_class = type->data.generic_class->container_class; + MonoClass *container_class = m_type_data_get_generic_class_unchecked (type)->container_class; if (m_class_is_valuetype (container_class) && !m_class_is_enumtype (container_class)) { MonoClass *klass = mono_class_from_mono_type_internal (type); @@ -977,7 +977,7 @@ stackval_to_data (MonoType *type, stackval *val, void *data, gboolean pinvoke) } return ALIGN_TO (size, MINT_STACK_SLOT_SIZE); } - return stackval_to_data (m_class_get_byval_arg (type->data.generic_class->container_class), val, data, pinvoke); + return stackval_to_data (m_class_get_byval_arg (m_type_data_get_generic_class_unchecked (type)->container_class), val, data, pinvoke); } default: g_error ("got type %x", type->type); @@ -1426,8 +1426,8 @@ get_build_args_from_sig_info (MonoMemoryManager *mem_manager, MonoMethodSignatur flen++; break; case MONO_TYPE_VALUETYPE: - if (m_class_is_enumtype (type->data.klass)) { - type = mono_class_enum_basetype_internal (type->data.klass); + if (m_class_is_enumtype (m_type_data_get_klass_unchecked (type))) { + type = mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (type)); goto retry; } info->arg_types [i] = PINVOKE_ARG_VTYPE; @@ -1446,7 +1446,7 @@ get_build_args_from_sig_info (MonoMemoryManager *mem_manager, MonoMethodSignatur break; case MONO_TYPE_GENERICINST: { // FIXME: Should mini_wasm_is_scalar_vtype stuff go in here? - MonoClass *container_class = type->data.generic_class->container_class; + MonoClass *container_class = m_type_data_get_generic_class_unchecked (type)->container_class; type = m_class_get_byval_arg (container_class); goto retry; } @@ -2046,7 +2046,7 @@ dump_stackval (GString *str, stackval *s, MonoType *type) g_string_append_printf (str, "[%p] ", s->data.p); break; case MONO_TYPE_VALUETYPE: - if (m_class_is_enumtype (type->data.klass)) + if (m_class_is_enumtype (m_type_data_get_klass_unchecked (type))) g_string_append_printf (str, "[%d] ", s->data.i); else g_string_append_printf (str, "[vt:%p] ", s->data.p); @@ -3209,9 +3209,9 @@ interp_entry_from_trampoline (gpointer ccontext_untyped, gpointer rmethod_untype size = mono_class_value_size (mono_class_from_mono_type_internal (type), NULL); } else if (type->type == MONO_TYPE_VALUETYPE) { if (sig->pinvoke && !sig->marshalling_disabled) - size = mono_class_native_size (type->data.klass, NULL); + size = mono_class_native_size (m_type_data_get_klass_unchecked (type), NULL); else - size = mono_class_value_size (type->data.klass, NULL); + size = mono_class_value_size (m_type_data_get_klass_unchecked (type), NULL); } else { size = MINT_STACK_SLOT_SIZE; } diff --git a/src/mono/mono/mini/interp/transform-simd.c b/src/mono/mono/mini/interp/transform-simd.c index a9c0a697e4ee9d..f98cc584b8dea5 100644 --- a/src/mono/mono/mini/interp/transform-simd.c +++ b/src/mono/mono/mini/interp/transform-simd.c @@ -640,7 +640,7 @@ emit_sri_vector128_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignatur explicitly_implemented = true; } } - + int id = lookup_intrins (sri_vector128_t_methods, sizeof (sri_vector128_t_methods), cmethod->name); if (id == -1) { if (explicitly_implemented) { @@ -689,7 +689,7 @@ emit_sn_vector_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *c cmethod_name += 77; } } - + int id = lookup_intrins (sn_vector_t_methods, sizeof (sn_vector_t_methods), cmethod_name); if (id == -1) return FALSE; @@ -906,7 +906,7 @@ lookup_packedsimd_intrinsic (const char *name, MonoType *arg1) if (m_class_is_simd_type (vector_klass)) { arg_type = mono_class_get_context (vector_klass)->class_inst->type_argv [0]; } else if (arg1->type == MONO_TYPE_PTR) { - arg_type = arg1->data.type; + arg_type = m_type_data_get_type_unchecked (arg1); } else { // g_printf ("%s arg1 type was not pointer or simd type: %s\n", name, m_class_get_name (vector_klass)); return FALSE; diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 04bf096566f838..a948639a4bd3b8 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -330,15 +330,15 @@ mono_mint_type (MonoType *type) case MONO_TYPE_ARRAY: return MINT_TYPE_O; case MONO_TYPE_VALUETYPE: - if (m_class_is_enumtype (type->data.klass)) { - type = mono_class_enum_basetype_internal (type->data.klass); + if (m_class_is_enumtype (m_type_data_get_klass_unchecked (type))) { + type = mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (type)); goto enum_type; } else return MINT_TYPE_VT; case MONO_TYPE_TYPEDBYREF: return MINT_TYPE_VT; case MONO_TYPE_GENERICINST: - type = m_class_get_byval_arg (type->data.generic_class->container_class); + type = m_class_get_byval_arg (m_type_data_get_generic_class_unchecked (type)->container_class); goto enum_type; case MONO_TYPE_VOID: return MINT_TYPE_VOID; @@ -2795,7 +2795,7 @@ interp_type_as_ptr (MonoType *tp) return TRUE; if ((tp)->type == MONO_TYPE_CHAR) return TRUE; - if ((tp)->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (tp->data.klass)) + if ((tp)->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_type_data_get_klass_unchecked (tp))) return TRUE; if (is_scalar_vtype (tp)) return TRUE; @@ -4627,8 +4627,8 @@ interp_method_compute_offsets (TransformData *td, InterpMethod *imethod, MonoMet int mt = mono_mint_type (header->locals [i]); size = mono_interp_type_size (header->locals [i], mt, &align); if (header->locals [i]->type == MONO_TYPE_VALUETYPE) { - if (mono_class_has_failure (header->locals [i]->data.klass)) { - mono_error_set_for_class_failure (error, header->locals [i]->data.klass); + if (mono_class_has_failure (m_type_data_get_klass_unchecked (header->locals [i]))) { + mono_error_set_for_class_failure (error, m_type_data_get_klass_unchecked (header->locals [i])); return; } } diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c index 1b2c85c64bf744..046dfa79e5b0a7 100644 --- a/src/mono/mono/mini/intrinsics.c +++ b/src/mono/mono/mini/intrinsics.c @@ -951,7 +951,7 @@ get_rttype_ins_relation (MonoCompile *cfg, MonoInst *ins1, MonoInst *ins2, gbool /* Common case in gshared BCL code: t1 is a gshared type like T_INT, and t2 is a concrete type */ if (mono_class_is_gparam (k1)) { - MonoGenericParam *gparam = t1->data.generic_param; + MonoGenericParam *gparam = m_type_data_get_generic_param (t1); constraint1 = gparam->gshared_constraint; } if (constraint1) { @@ -1742,7 +1742,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign i2u_cmp->sreg1 = args[2]->dreg; MONO_ADD_INS (cfg->cbb, i2u_cmp); } - + if (is_ref && !mini_debug_options.weak_memory_model) mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL); @@ -2206,7 +2206,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign /* Common case in gshared BCL code: t1 is a gshared type like T_INT */ if (mono_class_is_gparam (k1)) { - MonoGenericParam *gparam = t1->data.generic_param; + MonoGenericParam *gparam = m_type_data_get_generic_param (t1); constraint1 = gparam->gshared_constraint; if (constraint1) { if (constraint1->type == MONO_TYPE_OBJECT) { @@ -2411,7 +2411,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign cmethod_name += 80; } } - + if (!strcmp (cmethod_name, "get_IsHardwareAccelerated")) { EMIT_NEW_ICONST (cfg, ins, 0); ins->type = STACK_I4; diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index d966d0ec0de6bf..8468b5741d45a3 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -334,8 +334,8 @@ mono_type_to_regmove (MonoCompile *cfg, MonoType *type) case MONO_TYPE_R8: return OP_FMOVE; case MONO_TYPE_VALUETYPE: - if (m_class_is_enumtype (type->data.klass)) { - type = mono_class_enum_basetype_internal (type->data.klass); + if (m_class_is_enumtype (m_type_data_get_klass_unchecked (type))) { + type = mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (type)); goto handle_enum; } if (mini_class_is_simd (cfg, mono_class_from_mono_type_internal (type))) @@ -346,7 +346,7 @@ mono_type_to_regmove (MonoCompile *cfg, MonoType *type) case MONO_TYPE_GENERICINST: if (mini_class_is_simd (cfg, mono_class_from_mono_type_internal (type))) return OP_XMOVE; - type = m_class_get_byval_arg (type->data.generic_class->container_class); + type = m_class_get_byval_arg (m_type_data_get_generic_class_unchecked (type)->container_class); goto handle_enum; case MONO_TYPE_VAR: case MONO_TYPE_MVAR: @@ -826,8 +826,8 @@ mini_type_to_eval_stack_type (MonoCompile *cfg, MonoType *type, MonoInst *inst) inst->type = STACK_R8; return; case MONO_TYPE_VALUETYPE: - if (m_class_is_enumtype (type->data.klass)) { - type = mono_class_enum_basetype_internal (type->data.klass); + if (m_class_is_enumtype (m_type_data_get_klass_unchecked (type))) { + type = mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (type)); goto handle_enum; } else { inst->klass = klass; @@ -839,7 +839,7 @@ mini_type_to_eval_stack_type (MonoCompile *cfg, MonoType *type, MonoInst *inst) inst->type = STACK_VTYPE; return; case MONO_TYPE_GENERICINST: - type = m_class_get_byval_arg (type->data.generic_class->container_class); + type = m_class_get_byval_arg (m_type_data_get_generic_class_unchecked (type)->container_class); goto handle_enum; case MONO_TYPE_VAR: case MONO_TYPE_MVAR: @@ -2084,8 +2084,8 @@ check_call_signature (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **arg return TRUE; continue; case MONO_TYPE_VALUETYPE: - if (m_class_is_enumtype (simple_type->data.klass)) { - simple_type = mono_class_enum_basetype_internal (simple_type->data.klass); + if (m_class_is_enumtype (m_type_data_get_klass_unchecked (simple_type))) { + simple_type = mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (simple_type)); goto handle_enum; } if (args [i]->type != STACK_VTYPE) @@ -2096,7 +2096,7 @@ check_call_signature (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **arg return TRUE; continue; case MONO_TYPE_GENERICINST: - simple_type = m_class_get_byval_arg (simple_type->data.generic_class->container_class); + simple_type = m_class_get_byval_arg (m_type_data_get_generic_class_unchecked (simple_type)->container_class); goto handle_enum; case MONO_TYPE_VAR: case MONO_TYPE_MVAR: @@ -5395,8 +5395,8 @@ mono_type_to_stloc_coerce (MonoType *type) case MONO_TYPE_GENERICINST: return 0; case MONO_TYPE_VALUETYPE: - if (m_class_is_enumtype (type->data.klass)) { - type = mono_class_enum_basetype_internal (type->data.klass); + if (m_class_is_enumtype (m_type_data_get_klass_unchecked (type))) { + type = mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (type)); goto handle_enum; } return 0; @@ -5931,7 +5931,7 @@ handle_constrained_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignat constrained_partial_call = TRUE; MonoType *t = m_class_get_byval_arg (constrained_class); - MonoGenericParam *gparam = t->data.generic_param; + MonoGenericParam *gparam = m_type_data_get_generic_param (t); gshared_constraint = gparam->gshared_constraint; } } @@ -10544,8 +10544,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b int ro_type = ftype->type; if (!addr) addr = mono_static_field_get_addr (vtable, field); - if (ro_type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (ftype->data.klass)) { - ro_type = mono_class_enum_basetype_internal (ftype->data.klass)->type; + if (ro_type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_type_data_get_klass_unchecked (ftype))) { + ro_type = mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (ftype))->type; } GSHAREDVT_FAILURE (il_op); diff --git a/src/mono/mono/mini/mini-amd64.c b/src/mono/mono/mini/mini-amd64.c index 329c83a1138e47..cb6002dd87630c 100644 --- a/src/mono/mono/mini/mini-amd64.c +++ b/src/mono/mono/mini/mini-amd64.c @@ -311,7 +311,8 @@ merge_argument_class_from_type (MonoType *type, ArgumentClass class1) } /* fall through */ case MONO_TYPE_VALUETYPE: { - MonoMarshalType *info = mono_marshal_load_type_info (ptype->data.klass); + // We have to use mono_class_from_mono_type_internal here due to the fallthrough from GENERICINST + MonoMarshalType *info = mono_marshal_load_type_info (mono_class_from_mono_type_internal (ptype)); for (guint32 i = 0; i < info->num_fields; ++i) { class2 = class1; class2 = merge_argument_class_from_type (info->fields [i].field->type, class2); @@ -625,13 +626,13 @@ add_return_valuetype_swiftcall (ArgInfo *ainfo, MonoType *type, guint32 *gr, gui // The structs that cannot be lowered, we pass them by reference if (lowered_swift_struct.by_reference) { ainfo->storage = ArgValuetypeAddrInIReg; - /* + /* * On x64, Swift calls expect the return buffer to be passed in RAX. * However, since RAX mono reg allocator could assign RAX to a different value, * the R10 register is used instead and before the native call, * the value is moved from R10 to RAX (`amd64_handle_swift_return_buffer_reg`). */ - ainfo->reg = AMD64_R10; + ainfo->reg = AMD64_R10; return; } @@ -987,9 +988,9 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) if (cinfo->ret.storage == ArgValuetypeAddrInIReg) { /* * We need to set this even when sig->pinvoke is FALSE, because the `cinfo` gets copied to the - * `cfg->arch` on the first pass. However, later in `amd64_handle_swift_return_buffer_reg` we + * `cfg->arch` on the first pass. However, later in `amd64_handle_swift_return_buffer_reg` we * condition the Swift return buffer handling only to P/Invoke calls. This however can trigger - * a false positive in some scenarios where the Swift return buffer is not needed. + * a false positive in some scenarios where the Swift return buffer is not needed. */ cinfo->need_swift_return_buffer = TRUE; } @@ -998,7 +999,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) { add_valuetype (sig, &cinfo->ret, ret_type, TRUE, &tmp_gr, &tmp_fr, &tmp_stacksize); } - g_assert (cinfo->ret.storage != ArgInIReg); + g_assert (cinfo->ret.storage != ArgInIReg); break; } case MONO_TYPE_VAR: @@ -1038,8 +1039,8 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) if (ret_storage == ArgValuetypeAddrInIReg || ret_storage == ArgGsharedvtVariableInReg) { #ifdef MONO_ARCH_HAVE_SWIFTCALL - // When Swift struct is returned by reference, we use the R10 register to hold the return buffer. - if (!(cinfo->need_swift_return_buffer && cinfo->ret.reg == AMD64_R10 && + // When Swift struct is returned by reference, we use the R10 register to hold the return buffer. + if (!(cinfo->need_swift_return_buffer && cinfo->ret.reg == AMD64_R10 && sig->pinvoke && mono_method_signature_has_ext_callconv (sig, MONO_EXT_CALLCONV_SWIFTCALL))) #endif { @@ -1306,7 +1307,7 @@ arg_get_val (CallContext *ccontext, ArgInfo *ainfo, gpointer dest) g_assert_not_reached (); } - + } static void @@ -1361,7 +1362,7 @@ arg_set_val (CallContext *ccontext, ArgInfo *ainfo, gpointer src) default: g_assert_not_reached (); } - + } gpointer @@ -2041,7 +2042,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) } else { offset += cinfo->ret.arg_size; cfg->ret->inst_offset = - offset; - } + } break; #endif /* MONO_ARCH_HAVE_SWIFTCALL */ default: @@ -5476,11 +5477,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) amd64_div_reg_size (code, ins->sreg3, FALSE, 4); break; case OP_X86_IDIVREM2: - if (ins->dreg != AMD64_RDX) + if (ins->dreg != AMD64_RDX) amd64_mov_reg_reg (code, ins->dreg, AMD64_RDX, 4); break; case OP_X86_LDIVREM2: - if (ins->dreg != AMD64_RDX) + if (ins->dreg != AMD64_RDX) amd64_mov_reg_reg (code, ins->dreg, AMD64_RDX, 8); break; @@ -8465,7 +8466,7 @@ MONO_RESTORE_WARNING if (cfg->vret_addr && (cfg->vret_addr->opcode != OP_REGVAR)) { #ifdef MONO_ARCH_HAVE_SWIFTCALL if (mono_method_signature_has_ext_callconv (sig, MONO_EXT_CALLCONV_SWIFTCALL) && sig->pinvoke && - cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED && + cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED && cfg->arch.cinfo->need_swift_return_buffer && cinfo->ret.reg == AMD64_R10) { // Save the return buffer passed by the Swift caller amd64_mov_membase_reg (code, cfg->vret_addr->inst_basereg, cfg->vret_addr->inst_offset, SWIFT_RETURN_BUFFER_REG, 8); @@ -8478,8 +8479,8 @@ MONO_RESTORE_WARNING } #ifdef MONO_ARCH_HAVE_SWIFTCALL - if (mono_method_signature_has_ext_callconv (sig, MONO_EXT_CALLCONV_SWIFTCALL) && - cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED && + if (mono_method_signature_has_ext_callconv (sig, MONO_EXT_CALLCONV_SWIFTCALL) && + cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED && cfg->arch.cinfo->need_swift_return_buffer) { amd64_mov_reg_reg (code, AMD64_R10, SWIFT_RETURN_BUFFER_REG, 8); } diff --git a/src/mono/mono/mini/mini-generic-sharing.c b/src/mono/mono/mini/mini-generic-sharing.c index 90e724bf417bf4..11df39a80f664c 100644 --- a/src/mono/mono/mini/mini-generic-sharing.c +++ b/src/mono/mono/mini/mini-generic-sharing.c @@ -82,6 +82,7 @@ type_check_context_used (MonoType *type, gboolean recursive) return MONO_GENERIC_CONTEXT_USED_CLASS; case MONO_TYPE_MVAR: return MONO_GENERIC_CONTEXT_USED_METHOD; + // FIXME: This is inconsistent - for SZARRAY it is checking T[] while for ARRAY it is checking T -kg case MONO_TYPE_SZARRAY: return mono_class_check_context_used (mono_type_get_class_internal (type)); case MONO_TYPE_ARRAY: @@ -93,7 +94,7 @@ type_check_context_used (MonoType *type, gboolean recursive) return 0; case MONO_TYPE_GENERICINST: if (recursive) { - MonoGenericClass *gclass = type->data.generic_class; + MonoGenericClass *gclass = m_type_data_get_generic_class_unchecked (type); g_assert (mono_class_is_gtd (gclass->container_class)); return mono_generic_context_check_used (&gclass->context); @@ -1894,7 +1895,7 @@ mini_get_interp_in_wrapper (MonoMethodSignature *sig) int retval_var = 0; if (return_native_struct) { retval_var = mono_mb_add_local (mb, int_type); - mono_mb_emit_icon (mb, mono_class_native_size (sig->ret->data.klass, NULL)); + mono_mb_emit_icon (mb, mono_class_native_size (m_type_data_get_klass (sig->ret), NULL)); mono_mb_emit_byte (mb, CEE_PREFIX1); mono_mb_emit_byte (mb, CEE_LOCALLOC); mono_mb_emit_stloc (mb, retval_var); @@ -1963,7 +1964,7 @@ mini_get_interp_in_wrapper (MonoMethodSignature *sig) if (return_native_struct) { mono_mb_emit_ldloc (mb, retval_var); mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - mono_mb_emit_op (mb, CEE_MONO_LDNATIVEOBJ, sig->ret->data.klass); + mono_mb_emit_op (mb, CEE_MONO_LDNATIVEOBJ, m_type_data_get_klass (sig->ret)); } else if (sig->ret->type != MONO_TYPE_VOID) { mono_mb_emit_ldloc (mb, retval_var); } @@ -3404,7 +3405,7 @@ static gboolean type_is_sharable (MonoType *type, gboolean allow_type_vars, gboolean allow_partial) { if (allow_type_vars && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) { - MonoType *constraint = type->data.generic_param->gshared_constraint; + MonoType *constraint = m_type_data_get_generic_param_unchecked (type)->gshared_constraint; if (!constraint) return TRUE; type = constraint; @@ -3414,11 +3415,11 @@ type_is_sharable (MonoType *type, gboolean allow_type_vars, gboolean allow_parti return TRUE; /* Allow non ref arguments if they are primitive types or enums (partial sharing). */ - if (allow_partial && !m_type_is_byref (type) && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U) || (type->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (type->data.klass)))) + if (allow_partial && !m_type_is_byref (type) && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U) || (type->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_type_data_get_klass_unchecked (type))))) return TRUE; if (allow_partial && !m_type_is_byref (type) && type->type == MONO_TYPE_GENERICINST && MONO_TYPE_ISSTRUCT (type)) { - MonoGenericClass *gclass = type->data.generic_class; + MonoGenericClass *gclass = m_type_data_get_generic_class_unchecked (type); if (gclass->context.class_inst && !mini_generic_inst_is_sharable (gclass->context.class_inst, allow_type_vars, allow_partial)) return FALSE; @@ -3618,8 +3619,8 @@ is_async_method (MonoMethod *method) /* Do less expensive checks first */ sig = mono_method_signature_internal (method); if (attr_class && sig && ((sig->ret->type == MONO_TYPE_VOID) || - (sig->ret->type == MONO_TYPE_CLASS && !strcmp (m_class_get_name (sig->ret->data.generic_class->container_class), "Task")) || - (sig->ret->type == MONO_TYPE_GENERICINST && !strcmp (m_class_get_name (sig->ret->data.generic_class->container_class), "Task`1")))) { + (sig->ret->type == MONO_TYPE_CLASS && !strcmp (m_class_get_name (m_type_data_get_klass_unchecked (sig->ret)), "Task")) || + (sig->ret->type == MONO_TYPE_GENERICINST && !strcmp (m_class_get_name (m_type_data_get_generic_class_unchecked (sig->ret)->container_class), "Task`1")))) { //printf ("X: %s\n", mono_method_full_name (method, TRUE)); cattr = mono_custom_attrs_from_method_checked (method, error); if (!is_ok (error)) { @@ -4006,7 +4007,7 @@ mini_get_basic_type_from_generic (MonoType *type) if (!m_type_is_byref (type) && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) && mini_is_gsharedvt_type (type)) return type; else if (!m_type_is_byref (type) && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) { - MonoType *constraint = type->data.generic_param->gshared_constraint; + MonoType *constraint = m_type_data_get_generic_param_unchecked (type)->gshared_constraint; /* The gparam constraint encodes the type this gparam can represent */ if (!constraint) { return mono_get_object_type (); @@ -4128,7 +4129,7 @@ gboolean mini_type_var_is_vt (MonoType *type) { if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) { - return type->data.generic_param->gshared_constraint && (type->data.generic_param->gshared_constraint->type == MONO_TYPE_VALUETYPE || type->data.generic_param->gshared_constraint->type == MONO_TYPE_GENERICINST); + return m_type_data_get_generic_param_unchecked (type)->gshared_constraint && (m_type_data_get_generic_param_unchecked (type)->gshared_constraint->type == MONO_TYPE_VALUETYPE || m_type_data_get_generic_param_unchecked (type)->gshared_constraint->type == MONO_TYPE_GENERICINST); } else { g_assert_not_reached (); return FALSE; @@ -4212,7 +4213,7 @@ gboolean mini_is_gsharedvt_gparam (MonoType *t) { /* Matches get_gsharedvt_type () */ - return (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) && t->data.generic_param->gshared_constraint && t->data.generic_param->gshared_constraint->type == MONO_TYPE_VALUETYPE; + return (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) && m_type_data_get_generic_param_unchecked (t)->gshared_constraint && m_type_data_get_generic_param_unchecked (t)->gshared_constraint->type == MONO_TYPE_VALUETYPE; } static char* @@ -4276,7 +4277,7 @@ MonoType* mini_get_shared_gparam (MonoType *t, MonoType *constraint) { MonoMemoryManager *mm; - MonoGenericParam *par = t->data.generic_param; + MonoGenericParam *par = m_type_data_get_generic_param (t); MonoGSharedGenericParam *copy, key; MonoType *res; char *name; @@ -4319,7 +4320,7 @@ mini_get_shared_gparam (MonoType *t, MonoType *constraint) copy->param.gshared_constraint = constraint; copy->parent = par; res = mono_metadata_type_dup (NULL, t); - res->data.generic_param = (MonoGenericParam*)copy; + m_type_data_set_generic_param (res, (MonoGenericParam*)copy); mono_mem_manager_lock (mm); /* Duplicates are ok */ @@ -4339,7 +4340,7 @@ get_shared_type (MonoType *t, MonoType *type) if (!m_type_is_byref (type) && type->type == MONO_TYPE_GENERICINST && MONO_TYPE_ISSTRUCT (type)) { ERROR_DECL (error); - MonoGenericClass *gclass = type->data.generic_class; + MonoGenericClass *gclass = m_type_data_get_generic_class_unchecked (type); MonoGenericContext context; MonoClass *k; @@ -4361,14 +4362,14 @@ get_shared_type (MonoType *t, MonoType *type) /* Create a type variable with a constraint which encodes which types can match it */ ttype = type->type; if (type->type == MONO_TYPE_VALUETYPE) { - ttype = mono_class_enum_basetype_internal (type->data.klass)->type; - } else if (type->type == MONO_TYPE_GENERICINST && m_class_is_enumtype(type->data.generic_class->container_class)) { + ttype = mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (type))->type; + } else if (type->type == MONO_TYPE_GENERICINST && m_class_is_enumtype(m_type_data_get_generic_class_unchecked (type)->container_class)) { ttype = mono_class_enum_basetype_internal (mono_class_from_mono_type_internal (type))->type; } else if (MONO_TYPE_IS_REFERENCE (type)) { ttype = MONO_TYPE_OBJECT; } else if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) { - if (type->data.generic_param->gshared_constraint) - return mini_get_shared_gparam (t, type->data.generic_param->gshared_constraint); + if (m_type_data_get_generic_param_unchecked (type)->gshared_constraint) + return mini_get_shared_gparam (t, m_type_data_get_generic_param_unchecked (type)->gshared_constraint); ttype = MONO_TYPE_OBJECT; } @@ -4643,10 +4644,10 @@ mini_is_gsharedvt_type (MonoType *t) { if (m_type_is_byref (t)) return FALSE; - if ((t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) && t->data.generic_param->gshared_constraint && t->data.generic_param->gshared_constraint->type == MONO_TYPE_VALUETYPE) + if ((t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) && m_type_data_get_generic_param_unchecked (t)->gshared_constraint && m_type_data_get_generic_param_unchecked (t)->gshared_constraint->type == MONO_TYPE_VALUETYPE) return TRUE; else if (t->type == MONO_TYPE_GENERICINST) { - MonoGenericClass *gclass = t->data.generic_class; + MonoGenericClass *gclass = m_type_data_get_generic_class_unchecked (t); MonoGenericContext *context = &gclass->context; MonoGenericInst *inst; @@ -4700,11 +4701,11 @@ mini_is_gsharedvt_variable_type (MonoType *t) if (!mini_is_gsharedvt_type (t)) return FALSE; if (t->type == MONO_TYPE_GENERICINST) { - MonoGenericClass *gclass = t->data.generic_class; + MonoGenericClass *gclass = m_type_data_get_generic_class_unchecked (t); MonoGenericContext *context = &gclass->context; MonoGenericInst *inst; - if (m_class_get_byval_arg (t->data.generic_class->container_class)->type != MONO_TYPE_VALUETYPE || m_class_is_enumtype (t->data.generic_class->container_class)) + if (m_class_get_byval_arg (m_type_data_get_generic_class_unchecked (t)->container_class)->type != MONO_TYPE_VALUETYPE || m_class_is_enumtype (m_type_data_get_generic_class_unchecked (t)->container_class)) return FALSE; inst = context->class_inst; @@ -4732,7 +4733,7 @@ is_variable_size (MonoType *t) return FALSE; if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) { - MonoGenericParam *param = t->data.generic_param; + MonoGenericParam *param = m_type_data_get_generic_param_unchecked (t); if (param->gshared_constraint && param->gshared_constraint->type != MONO_TYPE_VALUETYPE && param->gshared_constraint->type != MONO_TYPE_GENERICINST) return FALSE; @@ -4740,8 +4741,8 @@ is_variable_size (MonoType *t) return is_variable_size (param->gshared_constraint); return TRUE; } - if (t->type == MONO_TYPE_GENERICINST && m_class_get_byval_arg (t->data.generic_class->container_class)->type == MONO_TYPE_VALUETYPE) { - MonoGenericClass *gclass = t->data.generic_class; + if (t->type == MONO_TYPE_GENERICINST && m_class_get_byval_arg (m_type_data_get_generic_class_unchecked (t)->container_class)->type == MONO_TYPE_VALUETYPE) { + MonoGenericClass *gclass = m_type_data_get_generic_class_unchecked (t); MonoGenericContext *context = &gclass->context; MonoGenericInst *inst; diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 8cc8c986381b52..8aa11b4868dfc9 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -698,7 +698,7 @@ simd_valuetuple_to_llvm_type (EmitContext *ctx, MonoClass *klass) MonoGenericInst *class_inst = mono_class_get_generic_class (klass)->context.class_inst; MonoType *etype = class_inst->type_argv [0]; g_assert (etype->type == MONO_TYPE_GENERICINST); - MonoClass *eklass = etype->data.generic_class->cached_class; + MonoClass *eklass = m_type_data_get_generic_class_unchecked (etype)->cached_class; LLVMTypeRef ltype = simd_class_to_llvm_type (ctx, eklass); return LLVMArrayType (ltype, class_inst->type_argc); } @@ -11736,7 +11736,7 @@ MONO_RESTORE_WARNING default: g_assert_not_reached (); break; - + } lhs = LLVMBuildLoad2 (builder, ret_t, addresses [ins->sreg1]->value, ""); @@ -11944,7 +11944,7 @@ MONO_RESTORE_WARNING default: g_assert_not_reached (); break; - + } } diff --git a/src/mono/mono/mini/mini.c b/src/mono/mono/mini/mini.c index 63d89b3f28a561..1982b84a4cdcf7 100644 --- a/src/mono/mono/mini/mini.c +++ b/src/mono/mono/mini/mini.c @@ -353,8 +353,8 @@ mono_type_to_store_membase (MonoCompile *cfg, MonoType *type) case MONO_TYPE_R8: return OP_STORER8_MEMBASE_REG; case MONO_TYPE_VALUETYPE: - if (m_class_is_enumtype (type->data.klass)) { - type = mono_class_enum_basetype_internal (type->data.klass); + if (m_class_is_enumtype (m_type_data_get_klass_unchecked (type))) { + type = mono_class_enum_basetype_internal (m_type_data_get_klass_unchecked (type)); goto handle_enum; } if (mini_class_is_simd (cfg, mono_class_from_mono_type_internal (type))) @@ -365,7 +365,7 @@ mono_type_to_store_membase (MonoCompile *cfg, MonoType *type) case MONO_TYPE_GENERICINST: if (mini_class_is_simd (cfg, mono_class_from_mono_type_internal (type))) return OP_STOREX_MEMBASE; - type = m_class_get_byval_arg (type->data.generic_class->container_class); + type = m_class_get_byval_arg (m_type_data_get_generic_class_unchecked (type)->container_class); goto handle_enum; case MONO_TYPE_VAR: case MONO_TYPE_MVAR: @@ -1058,6 +1058,8 @@ mono_allocate_stack_slots2 (MonoCompile *cfg, gboolean backward, guint32 *stack_ if (cfg->disable_reuse_stack_slots) reuse_slot = FALSE; + MonoClass *class_of_t = NULL; + t = mini_get_underlying_type (t); switch (t->type) { case MONO_TYPE_GENERICINST: @@ -1070,8 +1072,9 @@ mono_allocate_stack_slots2 (MonoCompile *cfg, gboolean backward, guint32 *stack_ if (!vtype_stack_slots) vtype_stack_slots = (StackSlotInfo *)mono_mempool_alloc0 (cfg->mempool, sizeof (StackSlotInfo) * vtype_stack_slots_size); int i; + class_of_t = mono_class_from_mono_type_internal (t); for (i = 0; i < nvtypes; ++i) - if (t->data.klass == vtype_stack_slots [i].vtype) + if (class_of_t == vtype_stack_slots [i].vtype) break; if (i < nvtypes) slot_info = &vtype_stack_slots [i]; @@ -1085,7 +1088,7 @@ mono_allocate_stack_slots2 (MonoCompile *cfg, gboolean backward, guint32 *stack_ vtype_stack_slots = new_slots; vtype_stack_slots_size = new_slots_size; } - vtype_stack_slots [nvtypes].vtype = t->data.klass; + vtype_stack_slots [nvtypes].vtype = class_of_t; slot_info = &vtype_stack_slots [nvtypes]; nvtypes ++; } @@ -1369,6 +1372,8 @@ mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_s if (cfg->disable_reuse_stack_slots) reuse_slot = FALSE; + MonoClass *class_of_t = NULL; + t = mini_get_underlying_type (t); switch (t->type) { case MONO_TYPE_GENERICINST: @@ -1381,8 +1386,9 @@ mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_s if (!vtype_stack_slots) vtype_stack_slots = (StackSlotInfo *)mono_mempool_alloc0 (cfg->mempool, sizeof (StackSlotInfo) * vtype_stack_slots_size); int i; + class_of_t = mono_class_from_mono_type_internal (t); for (i = 0; i < nvtypes; ++i) - if (t->data.klass == vtype_stack_slots [i].vtype) + if (class_of_t == vtype_stack_slots [i].vtype) break; if (i < nvtypes) slot_info = &vtype_stack_slots [i]; @@ -1396,7 +1402,7 @@ mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_s vtype_stack_slots = new_slots; vtype_stack_slots_size = new_slots_size; } - vtype_stack_slots [nvtypes].vtype = t->data.klass; + vtype_stack_slots [nvtypes].vtype = class_of_t; slot_info = &vtype_stack_slots [nvtypes]; nvtypes ++; } diff --git a/src/mono/mono/profiler/aot.c b/src/mono/mono/profiler/aot.c index f9298e725584b1..3fd9128eb6b7d4 100644 --- a/src/mono/mono/profiler/aot.c +++ b/src/mono/mono/profiler/aot.c @@ -488,7 +488,7 @@ add_type (MonoProfiler *prof, MonoType *type) switch (type->type) { #if 0 case MONO_TYPE_SZARRAY: { - int eid = add_type (prof, m_class_get_byval_arg (type->data.klass)); + int eid = add_type (prof, m_class_get_byval_arg (m_type_data_get_klass_unchecked (type))); if (eid == -1) return -1; int id = prof->id ++; From ec118c7e798862fd69dc7fa6544c0d9849d32488 Mon Sep 17 00:00:00 2001 From: Steve Date: Wed, 12 Feb 2025 00:09:01 +0900 Subject: [PATCH 05/20] Enable AltJits build for LoongArch64 and RiscV64 (#110282) * Build LoongArch64 and RiscV64 AltJit * Add a new target for alljitscommunity --- Directory.Build.props | 2 +- eng/Subsets.props | 5 ++++ eng/native/functions.cmake | 6 ++-- src/coreclr/build-runtime.cmd | 41 +++++++++++++++++++------- src/coreclr/build-runtime.sh | 2 +- src/coreclr/gcinfo/CMakeLists.txt | 4 +++ src/coreclr/inc/corinfo.h | 11 +++++++ src/coreclr/inc/gcinfotypes.h | 8 ++--- src/coreclr/inc/palclr.h | 4 +++ src/coreclr/jit/CMakeLists.txt | 4 +++ src/coreclr/jit/codegenloongarch64.cpp | 9 +++--- src/coreclr/jit/codegenriscv64.cpp | 4 +-- src/coreclr/jit/emitloongarch64.cpp | 4 +-- src/coreclr/jit/emitriscv64.cpp | 4 +-- src/coreclr/jit/lclvars.cpp | 4 +-- src/coreclr/jit/targetloongarch64.cpp | 2 +- src/coreclr/jit/targetriscv64.cpp | 2 +- src/coreclr/pal/inc/rt/ntimage.h | 11 ------- src/coreclr/runtime.proj | 1 + 19 files changed, 81 insertions(+), 47 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index ce5c6e9173bc81..bed931fe34d414 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -328,7 +328,7 @@ true - ClrFullNativeBuild;ClrRuntimeSubset;ClrJitSubset;ClrPalTestsSubset;ClrAllJitsSubset;ClrILToolsSubset;ClrNativeAotSubset;ClrSpmiSubset;ClrCrossComponentsSubset;ClrDebugSubset;HostArchitecture;PgoInstrument;NativeOptimizationDataSupported;CMakeArgs;CxxStandardLibrary;CxxStandardLibraryStatic;CxxAbiLibrary + ClrFullNativeBuild;ClrRuntimeSubset;ClrJitSubset;ClrPalTestsSubset;ClrAllJitsSubset;ClrAllJitsCommunitySubset;ClrILToolsSubset;ClrNativeAotSubset;ClrSpmiSubset;ClrCrossComponentsSubset;ClrDebugSubset;HostArchitecture;PgoInstrument;NativeOptimizationDataSupported;CMakeArgs;CxxStandardLibrary;CxxStandardLibraryStatic;CxxAbiLibrary true diff --git a/eng/Subsets.props b/eng/Subsets.props index 1a32d113896dd7..1ef526826cce1a 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -191,6 +191,7 @@ + @@ -291,6 +292,10 @@ $(ClrRuntimeBuildSubsets);ClrAllJitsSubset=true + + $(ClrRuntimeBuildSubsets);ClrAllJitsCommunitySubset=true + + $(ClrRuntimeBuildSubsets);ClrILToolsSubset=true diff --git a/eng/native/functions.cmake b/eng/native/functions.cmake index 2b8db967373341..2dee8bf0c50986 100644 --- a/eng/native/functions.cmake +++ b/eng/native/functions.cmake @@ -1,8 +1,8 @@ function(clr_unknown_arch) if (WIN32) - message(FATAL_ERROR "Only AMD64, ARM64, ARM and I386 hosts are supported. Found: ${CMAKE_SYSTEM_PROCESSOR}") + message(FATAL_ERROR "Only AMD64, ARM64, ARM, I386, LOONGARCH64 and RISCV64 hosts are supported. Found: ${CMAKE_SYSTEM_PROCESSOR}") elseif(CLR_CROSS_COMPONENTS_BUILD) - message(FATAL_ERROR "Only AMD64, ARM64 and I386 hosts are supported for linux cross-architecture component. Found: ${CMAKE_SYSTEM_PROCESSOR}") + message(FATAL_ERROR "Only AMD64, ARM64, I386, LOONGARCH64 and RISCV64 hosts are supported for linux cross-architecture component. Found: ${CMAKE_SYSTEM_PROCESSOR}") else() message(FATAL_ERROR "'${CMAKE_SYSTEM_PROCESSOR}' is an unsupported architecture.") endif() @@ -319,7 +319,7 @@ function(add_component componentName) else() set(componentTargetName "${componentName}") endif() - if (${ARGC} EQUAL 3 AND "${ARG2}" STREQUAL "EXCLUDE_FROM_ALL") + if (${ARGC} EQUAL 3 AND "${ARGV2}" STREQUAL "EXCLUDE_FROM_ALL") set(exclude_from_all_flag "EXCLUDE_FROM_ALL") endif() get_property(definedComponents GLOBAL PROPERTY CLR_CMAKE_COMPONENTS) diff --git a/src/coreclr/build-runtime.cmd b/src/coreclr/build-runtime.cmd index 907565de64f22c..aa8c92500e04cd 100644 --- a/src/coreclr/build-runtime.cmd +++ b/src/coreclr/build-runtime.cmd @@ -44,6 +44,8 @@ set __TargetArchX64=0 set __TargetArchX86=0 set __TargetArchArm=0 set __TargetArchArm64=0 +set __TargetArchLoongArch64=0 +set __TargetArchRiscV64=0 set __BuildTypeDebug=0 set __BuildTypeChecked=0 @@ -89,6 +91,8 @@ if /i "%1" == "-x64" (set __TargetArchX64=1&shift&goto Arg_Loop) if /i "%1" == "-x86" (set __TargetArchX86=1&shift&goto Arg_Loop) if /i "%1" == "-arm" (set __TargetArchArm=1&shift&goto Arg_Loop) if /i "%1" == "-arm64" (set __TargetArchArm64=1&shift&goto Arg_Loop) +if /i "%1" == "-loongarch64" (set __TargetArchLoongArch64=1&shift&goto Arg_Loop) +if /i "%1" == "-riscv64" (set __TargetArchRiscV64=1&shift&goto Arg_Loop) if /i "%1" == "-debug" (set __BuildTypeDebug=1&shift&goto Arg_Loop) if /i "%1" == "-checked" (set __BuildTypeChecked=1&shift&goto Arg_Loop) @@ -103,6 +107,8 @@ if /i "%1" == "x64" (set __TargetArchX64=1&shift&goto Arg_Loop) if /i "%1" == "x86" (set __TargetArchX86=1&shift&goto Arg_Loop) if /i "%1" == "arm" (set __TargetArchArm=1&shift&goto Arg_Loop) if /i "%1" == "arm64" (set __TargetArchArm64=1&shift&goto Arg_Loop) +if /i "%1" == "loongarch64" (set __TargetArchLoongArch64=1&shift&goto Arg_Loop) +if /i "%1" == "riscv64" (set __TargetArchRiscV64=1&shift&goto Arg_Loop) if /i "%1" == "debug" (set __BuildTypeDebug=1&shift&goto Arg_Loop) if /i "%1" == "checked" (set __BuildTypeChecked=1&shift&goto Arg_Loop) @@ -167,16 +173,18 @@ if defined VCINSTALLDIR ( if defined __BuildAll goto BuildAll -set /A __TotalSpecifiedTargetArch=__TargetArchX64 + __TargetArchX86 + __TargetArchArm + __TargetArchArm64 +set /A __TotalSpecifiedTargetArch=__TargetArchX64 + __TargetArchX86 + __TargetArchArm + __TargetArchArm64 + __TargetArchLoongArch64 + __TargetArchRiscV64 if %__TotalSpecifiedTargetArch% GTR 1 ( echo Error: more than one build architecture specified, but "all" not specified. goto Usage ) -if %__TargetArchX64%==1 set __TargetArch=x64 -if %__TargetArchX86%==1 set __TargetArch=x86 -if %__TargetArchArm%==1 set __TargetArch=arm -if %__TargetArchArm64%==1 set __TargetArch=arm64 +if %__TargetArchX64%==1 set __TargetArch=x64 +if %__TargetArchX86%==1 set __TargetArch=x86 +if %__TargetArchArm%==1 set __TargetArch=arm +if %__TargetArchArm64%==1 set __TargetArch=arm64 +if %__TargetArchLoongArch64%==1 set __TargetArch=loongarch64 +if %__TargetArchRiscV64%==1 set __TargetArch=riscv64 if "%__HostArch%" == "" set __HostArch=%__TargetArch% set /A __TotalSpecifiedBuildType=__BuildTypeDebug + __BuildTypeChecked + __BuildTypeRelease @@ -294,6 +302,7 @@ if NOT DEFINED PYTHON ( ) set __CMakeTarget= +set __BuildAllJitsCommunity=0 for /f "delims=" %%a in ("-%__RequestedBuildComponents%-") do ( set "string=%%a" if not "!string:-hosts-=!"=="!string!" ( @@ -305,6 +314,10 @@ for /f "delims=" %%a in ("-%__RequestedBuildComponents%-") do ( if not "!string:-alljits-=!"=="!string!" ( set __CMakeTarget=!__CMakeTarget! alljits ) + if not "!string:-alljitscommunity-=!"=="!string!" ( + set __CMakeTarget=!__CMakeTarget! alljitscommunity + set __BuildAllJitsCommunity=1 + ) if not "!string:-runtime-=!"=="!string!" ( set __CMakeTarget=!__CMakeTarget! runtime ) @@ -459,18 +472,24 @@ REM ============================================================================ set __TargetArchList= -set /A __TotalSpecifiedTargetArch=__TargetArchX64 + __TargetArchX86 + __TargetArchArm + __TargetArchArm64 +set /A __TotalSpecifiedTargetArch=__TargetArchX64 + __TargetArchX86 + __TargetArchArm + __TargetArchArm64 + __TargetArchLoongArch64 + __TargetArchRiscV64 if %__TotalSpecifiedTargetArch% EQU 0 ( REM Nothing specified means we want to build all architectures. set __TargetArchList=x64 x86 arm arm64 + + if %__BuildAllJitsCommunity%==1 ( + set __TargetArchList=%__TargetArchList% loongarch64 riscv64 + ) ) REM Otherwise, add all the specified architectures to the list. -if %__TargetArchX64%==1 set __TargetArchList=%__TargetArchList% x64 -if %__TargetArchX86%==1 set __TargetArchList=%__TargetArchList% x86 -if %__TargetArchArm%==1 set __TargetArchList=%__TargetArchList% arm -if %__TargetArchArm64%==1 set __TargetArchList=%__TargetArchList% arm64 +if %__TargetArchX64%==1 set __TargetArchList=%__TargetArchList% x64 +if %__TargetArchX86%==1 set __TargetArchList=%__TargetArchList% x86 +if %__TargetArchArm%==1 set __TargetArchList=%__TargetArchList% arm +if %__TargetArchArm64%==1 set __TargetArchList=%__TargetArchList% arm64 +if %__TargetArchLoongArch64%==1 set __TargetArchList=%__TargetArchList% loongarch64 +if %__TargetArchRiscV64%==1 set __TargetArchList=%__TargetArchList% riscv64 set __BuildTypeList= @@ -553,7 +572,7 @@ echo All arguments are optional. The options are: echo. echo.-? -h -help --help: view this message. echo -all: Builds all configurations and platforms. -echo Build architecture: one of -x64, -x86, -arm, -arm64 ^(default: -x64^). +echo Build architecture: one of -x64, -x86, -arm, -arm64, -loongarch64, -riscv64 ^(default: -x64^). echo Build type: one of -Debug, -Checked, -Release ^(default: -Debug^). echo -component ^ : specify this option one or more times to limit components built to those specified. echo Allowed ^: hosts jit alljits runtime paltests iltools nativeaot spmi diff --git a/src/coreclr/build-runtime.sh b/src/coreclr/build-runtime.sh index 2e00e9ba399ace..52fcb9ef3714cf 100755 --- a/src/coreclr/build-runtime.sh +++ b/src/coreclr/build-runtime.sh @@ -21,7 +21,7 @@ export PYTHON usage_list+=("-pgodatapath: path to profile guided optimization data.") usage_list+=("-pgoinstrument: generate instrumented code for profile guided optimization enabled binaries.") usage_list+=("-staticanalyzer: use scan_build static analyzer.") -usage_list+=("-component: Build individual components instead of the full project. Available options are 'hosts', 'jit', 'runtime', 'paltests', 'alljits', 'iltools', 'nativeaot', and 'spmi'. Can be specified multiple times.") +usage_list+=("-component: Build individual components instead of the full project. Available options are 'hosts', 'jit', 'runtime', 'paltests', 'alljits', 'alljitscommunity', 'iltools', 'nativeaot', and 'spmi'. Can be specified multiple times.") usage_list+=("-subdir: Append a directory with the provided name to the obj and bin paths.") setup_dirs_local() diff --git a/src/coreclr/gcinfo/CMakeLists.txt b/src/coreclr/gcinfo/CMakeLists.txt index cdc4ae794c8e85..9ec2ae84eb0784 100644 --- a/src/coreclr/gcinfo/CMakeLists.txt +++ b/src/coreclr/gcinfo/CMakeLists.txt @@ -66,6 +66,10 @@ endif() if (CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_AMD64) create_gcinfo_lib(TARGET gcinfo_universal_arm64 OS universal ARCH arm64) create_gcinfo_lib(TARGET gcinfo_unix_x64 OS unix ARCH x64) + if (CLR_CMAKE_BUILD_COMMUNITY_ALTJITS EQUAL 1) + create_gcinfo_lib(TARGET gcinfo_unix_loongarch64 OS unix ARCH loongarch64) + create_gcinfo_lib(TARGET gcinfo_unix_riscv64 OS unix ARCH riscv64) + endif(CLR_CMAKE_BUILD_COMMUNITY_ALTJITS EQUAL 1) create_gcinfo_lib(TARGET gcinfo_win_x64 OS win ARCH x64) endif (CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_AMD64) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 2128b8cabe7c32..3939ac8d6074d2 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -3351,6 +3351,17 @@ class ICorDynamicInfo : public ICorStaticInfo // #define IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL 0x14 +// +// LOONGARCH64 relocation types +// +#define IMAGE_REL_LOONGARCH64_PC 0x0003 +#define IMAGE_REL_LOONGARCH64_JIR 0x0004 + +// +// RISCV64 relocation types +// +#define IMAGE_REL_RISCV64_PC 0x0003 + /**********************************************************************************/ #ifdef TARGET_64BIT #define USE_PER_FRAME_PINVOKE_INIT diff --git a/src/coreclr/inc/gcinfotypes.h b/src/coreclr/inc/gcinfotypes.h index f3cf31ffdc320e..e1f7b517897a3f 100644 --- a/src/coreclr/inc/gcinfotypes.h +++ b/src/coreclr/inc/gcinfotypes.h @@ -781,8 +781,8 @@ void FASTCALL decodeCallPattern(int pattern, #define DENORMALIZE_STACK_SLOT(x) ((x)<<3) #define NORMALIZE_CODE_LENGTH(x) ((x)>>2) // All Instructions are 4 bytes long #define DENORMALIZE_CODE_LENGTH(x) ((x)<<2) -#define NORMALIZE_STACK_BASE_REGISTER(x) ((x) == 22 ? 0 : 1) // Encode Frame pointer fp=$22 as zero -#define DENORMALIZE_STACK_BASE_REGISTER(x) ((x) == 0 ? 22 : 3) +#define NORMALIZE_STACK_BASE_REGISTER(x) ((x) == 22 ? 0u : 1u) // Encode Frame pointer fp=$22 as zero +#define DENORMALIZE_STACK_BASE_REGISTER(x) ((x) == 0 ? 22u : 3u) #define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>3) #define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<3) #define CODE_OFFSETS_NEED_NORMALIZATION 1 @@ -834,8 +834,8 @@ void FASTCALL decodeCallPattern(int pattern, #define DENORMALIZE_STACK_SLOT(x) ((x)<<3) #define NORMALIZE_CODE_LENGTH(x) ((x)>>2) // All Instructions are 4 bytes long #define DENORMALIZE_CODE_LENGTH(x) ((x)<<2) -#define NORMALIZE_STACK_BASE_REGISTER(x) ((x) == 8 ? 0 : 1) // Encode Frame pointer X8 as zero, sp/x2 as 1 -#define DENORMALIZE_STACK_BASE_REGISTER(x) ((x) == 0 ? 8 : 2) +#define NORMALIZE_STACK_BASE_REGISTER(x) ((x) == 8 ? 0u : 1u) // Encode Frame pointer X8 as zero, sp/x2 as 1 +#define DENORMALIZE_STACK_BASE_REGISTER(x) ((x) == 0 ? 8u : 2u) #define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>3) #define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<3) #define CODE_OFFSETS_NEED_NORMALIZATION 1 diff --git a/src/coreclr/inc/palclr.h b/src/coreclr/inc/palclr.h index 98321ba87f8383..c5628a1b9eee6e 100644 --- a/src/coreclr/inc/palclr.h +++ b/src/coreclr/inc/palclr.h @@ -612,4 +612,8 @@ #define IMAGE_FILE_MACHINE_LOONGARCH64 0x6264 // LOONGARCH64. #endif +#ifndef IMAGE_FILE_MACHINE_RISCV64 +#define IMAGE_FILE_MACHINE_RISCV64 0x5064 // RISCV64. +#endif + #endif // defined(HOST_WINDOWS) diff --git a/src/coreclr/jit/CMakeLists.txt b/src/coreclr/jit/CMakeLists.txt index 20ed5f5eec6609..9ec67d98e47f3f 100644 --- a/src/coreclr/jit/CMakeLists.txt +++ b/src/coreclr/jit/CMakeLists.txt @@ -642,6 +642,10 @@ if (CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_AMD64) create_standalone_jit(TARGET clrjit_universal_arm64_${ARCH_HOST_NAME} OS universal ARCH arm64) create_standalone_jit(TARGET clrjit_unix_x64_${ARCH_HOST_NAME} OS unix_anyos ARCH x64) create_standalone_jit(TARGET clrjit_win_x64_${ARCH_HOST_NAME} OS win ARCH x64) + if (CLR_CMAKE_BUILD_COMMUNITY_ALTJITS EQUAL 1) + create_standalone_jit(TARGET clrjit_unix_loongarch64_${ARCH_HOST_NAME} OS unix ARCH loongarch64) + create_standalone_jit(TARGET clrjit_unix_riscv64_${ARCH_HOST_NAME} OS unix ARCH riscv64) + endif(CLR_CMAKE_BUILD_COMMUNITY_ALTJITS EQUAL 1) endif (CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_AMD64) if (CLR_CMAKE_TARGET_ARCH_LOONGARCH64) diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp index f8e26e956209aa..94390a88580012 100644 --- a/src/coreclr/jit/codegenloongarch64.cpp +++ b/src/coreclr/jit/codegenloongarch64.cpp @@ -174,7 +174,7 @@ void CodeGen::genStackPointerAdjustment(ssize_t spDelta, regNumber tmpReg, bool* { // spDelta is negative in the prolog, positive in the epilog, // but we always tell the unwind codes the positive value. - ssize_t spDeltaAbs = abs(spDelta); + ssize_t spDeltaAbs = std::abs(spDelta); unsigned unwindSpDelta = (unsigned)spDeltaAbs; assert((ssize_t)unwindSpDelta == spDeltaAbs); // make sure that it fits in a unsigned @@ -2460,10 +2460,9 @@ static inline bool isImmed(GenTree* treeNode) instruction CodeGen::genGetInsForOper(GenTree* treeNode) { - var_types type = treeNode->TypeGet(); - genTreeOps oper = treeNode->OperGet(); - GenTree* op1 = treeNode->gtGetOp1(); - GenTree* op2; + var_types type = treeNode->TypeGet(); + genTreeOps oper = treeNode->OperGet(); + GenTree* op1 = treeNode->gtGetOp1(); emitAttr attr = emitActualTypeSize(treeNode); bool isImm = false; diff --git a/src/coreclr/jit/codegenriscv64.cpp b/src/coreclr/jit/codegenriscv64.cpp index 75f5c73dcfb592..54cd716b1ccebd 100644 --- a/src/coreclr/jit/codegenriscv64.cpp +++ b/src/coreclr/jit/codegenriscv64.cpp @@ -163,7 +163,7 @@ void CodeGen::genStackPointerAdjustment(ssize_t spDelta, regNumber tmpReg, bool* { // spDelta is negative in the prolog, positive in the epilog, // but we always tell the unwind codes the positive value. - ssize_t spDeltaAbs = abs(spDelta); + ssize_t spDeltaAbs = std::abs(spDelta); unsigned unwindSpDelta = (unsigned)spDeltaAbs; assert((ssize_t)unwindSpDelta == spDeltaAbs); // make sure that it fits in a unsigned @@ -6362,8 +6362,6 @@ void CodeGen::genIntToIntCast(GenTreeCast* cast) if ((desc.ExtendKind() != GenIntCastDesc::COPY) || (srcReg != dstReg)) { - instruction ins; - switch (desc.ExtendKind()) { case GenIntCastDesc::ZERO_EXTEND_SMALL_INT: diff --git a/src/coreclr/jit/emitloongarch64.cpp b/src/coreclr/jit/emitloongarch64.cpp index f732b353bea039..cb3292e5878249 100644 --- a/src/coreclr/jit/emitloongarch64.cpp +++ b/src/coreclr/jit/emitloongarch64.cpp @@ -2404,7 +2404,7 @@ void emitter::emitIns_Call(EmitCallType callType, // Our stack level should be always greater than the bytes of arguments we push. Just // a sanity test. - assert((unsigned)abs(argSize) <= codeGen->genStackLevel); + assert((unsigned)std::abs(argSize) <= codeGen->genStackLevel); // Trim out any callee-trashed registers from the live set. regMaskTP savedSet = emitGetGCRegsSavedOrModified(methHnd); @@ -4002,7 +4002,7 @@ void emitter::emitDisInsName(code_t code, const BYTE* addr, instrDesc* id) int tmp; instruction ins = INS_invalid; - for (int i = 1; i < INS_count; i++) + for (uint32_t i = 1; i < INS_count; i++) { if ((code & emitGetInsMask(i)) == emitInsCode((instruction)i)) { diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index f5f0cd64e4be1e..740e9b5fe040cc 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -1385,7 +1385,7 @@ void emitter::emitIns_Call(EmitCallType callType, // Our stack level should be always greater than the bytes of arguments we push. Just // a sanity test. - assert((unsigned)abs(argSize) <= codeGen->genStackLevel); + assert((unsigned)std::abs(argSize) <= codeGen->genStackLevel); // Trim out any callee-trashed registers from the live set. regMaskTP savedSet = emitGetGCRegsSavedOrModified(methHnd); @@ -4573,7 +4573,7 @@ void emitter::emitDispIns( emitDispInsInstrNum(id); const BYTE* instr = pCode + writeableOffset; - size_t instrSize; + unsigned instrSize; for (size_t i = 0; i < sz; instr += instrSize, i += instrSize, offset += instrSize) { // TODO-RISCV64: support different size instructions diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 5b2308634fad83..4cfd2c3d560204 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -863,7 +863,7 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo, unsigned skipArgs, un if (lowering->numLoweredElements == 1) assert(varDsc->lvExactSize() <= argSize); - cSlotsToEnregister = lowering->numLoweredElements; + cSlotsToEnregister = static_cast(lowering->numLoweredElements); argRegTypeInStruct1 = JITtype2varType(lowering->loweredElements[0]); if (lowering->numLoweredElements == 2) argRegTypeInStruct2 = JITtype2varType(lowering->loweredElements[1]); @@ -872,7 +872,7 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo, unsigned skipArgs, un assert(floatNum > 0); canPassArgInRegisters = varDscInfo->canEnreg(TYP_DOUBLE, floatNum); - if (canPassArgInRegisters && (floatNum < lowering->numLoweredElements)) + if (canPassArgInRegisters && ((unsigned)floatNum < lowering->numLoweredElements)) { assert(floatNum == 1); assert(lowering->numLoweredElements == 2); diff --git a/src/coreclr/jit/targetloongarch64.cpp b/src/coreclr/jit/targetloongarch64.cpp index fe98ab56d5d462..1e876d7eb5f65e 100644 --- a/src/coreclr/jit/targetloongarch64.cpp +++ b/src/coreclr/jit/targetloongarch64.cpp @@ -85,7 +85,7 @@ ABIPassingInformation LoongArch64Classifier::Classify(Compiler* comp, if (!lowering->byIntegerCallConv) { - slots = lowering->numLoweredElements; + slots = static_cast(lowering->numLoweredElements); if (lowering->numLoweredElements == 1) { canPassArgInRegisters = m_floatRegs.Count() > 0; diff --git a/src/coreclr/jit/targetriscv64.cpp b/src/coreclr/jit/targetriscv64.cpp index 3f39c9516812f2..b91420136fb754 100644 --- a/src/coreclr/jit/targetriscv64.cpp +++ b/src/coreclr/jit/targetriscv64.cpp @@ -83,7 +83,7 @@ ABIPassingInformation RiscV64Classifier::Classify(Compiler* comp, floatFields += (unsigned)varTypeIsFloating(type); INDEBUG(debugIntFields += (unsigned)varTypeIsIntegralOrI(type);) } - intFields = lowering->numLoweredElements - floatFields; + intFields = static_cast(lowering->numLoweredElements) - floatFields; assert(debugIntFields == intFields); } } diff --git a/src/coreclr/pal/inc/rt/ntimage.h b/src/coreclr/pal/inc/rt/ntimage.h index 3c7de052340495..8f88791ef51cf6 100644 --- a/src/coreclr/pal/inc/rt/ntimage.h +++ b/src/coreclr/pal/inc/rt/ntimage.h @@ -1015,17 +1015,6 @@ typedef IMAGE_RELOCATION UNALIGNED *PIMAGE_RELOCATION; #define IMAGE_REL_IA64_GPREL32 0x001C #define IMAGE_REL_IA64_ADDEND 0x001F -// -// LOONGARCH64 relocation types -// -#define IMAGE_REL_LOONGARCH64_PC 0x0003 -#define IMAGE_REL_LOONGARCH64_JIR 0x0004 - -// -// RISCV64 relocation types -// -#define IMAGE_REL_RISCV64_PC 0x0003 - // // CEF relocation types. // diff --git a/src/coreclr/runtime.proj b/src/coreclr/runtime.proj index e3b3001caa43c4..3af9a3f5a653b4 100644 --- a/src/coreclr/runtime.proj +++ b/src/coreclr/runtime.proj @@ -68,6 +68,7 @@ <_CoreClrBuildArg Condition="'$(ClrJitSubset)' == 'true'" Include="-component jit" /> <_CoreClrBuildArg Condition="'$(ClrPalTestsSubset)' == 'true'" Include="-component paltests" /> <_CoreClrBuildArg Condition="'$(ClrAllJitsSubset)' == 'true'" Include="-component alljits" /> + <_CoreClrBuildArg Condition="'$(ClrAllJitsCommunitySubset)' == 'true'" Include="-component alljits;-cmakeargs "-DCLR_CMAKE_BUILD_COMMUNITY_ALTJITS=1"" /> <_CoreClrBuildArg Condition="'$(ClrILToolsSubset)' == 'true'" Include="-component iltools" /> <_CoreClrBuildArg Condition="'$(ClrNativeAotSubset)' == 'true'" Include="-component nativeaot" /> <_CoreClrBuildArg Condition="'$(ClrSpmiSubset)' == 'true'" Include="-component spmi" /> From 44b7251f94772c69c2efb9daa7b69979d7ddd001 Mon Sep 17 00:00:00 2001 From: David Wrighton Date: Tue, 11 Feb 2025 10:05:08 -0800 Subject: [PATCH 06/20] Use enum for frametype not v table (#112166) This change refactors the frame identification mechanism in the runtime by replacing the use of the VTable with an enum FrameIdentifier. The VTable-based approach more suited to C++ code, but presented challenges for assembly code and out-of-process inspections. By using FrameIdentifier, polymorphic dispatch is now handled via if-statements. This change also eliminates the need for GS cookies on Frame objects, as it is no longer necessary to protect the VTable. Key changes include: Renaming FrameType to FrameIdentifier Introducing a GetFrameIdentifier method This update streamlines frame management while improving performance and flexibility for various platforms. --- .../debug/daccess/dacdbiimplstackwalk.cpp | 10 +- src/coreclr/debug/ee/debugger.cpp | 257 +++- src/coreclr/debug/ee/debugger.inl | 252 ---- src/coreclr/debug/ee/frameinfo.cpp | 20 +- src/coreclr/debug/ee/funceval.cpp | 4 +- src/coreclr/inc/corinfo.h | 2 - src/coreclr/inc/daccess.h | 3 - src/coreclr/inc/jiteeversionguid.h | 12 +- src/coreclr/inc/vptr_list.h | 46 - src/coreclr/jit/importercalls.cpp | 7 +- src/coreclr/jit/lower.cpp | 23 +- .../tools/Common/JitInterface/CorInfoTypes.cs | 2 - .../tools/superpmi/superpmi-shared/agnostic.h | 2 - .../superpmi-shared/methodcontext.cpp | 9 +- src/coreclr/vm/FrameTypes.h | 54 + src/coreclr/vm/amd64/ComCallPreStub.asm | 20 +- src/coreclr/vm/amd64/GenericComCallStubs.asm | 16 - src/coreclr/vm/amd64/PInvokeStubs.asm | 17 +- .../vm/amd64/RedirectedHandledJITCase.asm | 4 +- src/coreclr/vm/amd64/asmconstants.h | 6 +- src/coreclr/vm/amd64/cgenamd64.cpp | 18 +- src/coreclr/vm/amd64/pinvokestubs.S | 18 +- .../vm/amd64/redirectedhandledjitcase.S | 4 +- src/coreclr/vm/arm/asmconstants.h | 6 +- src/coreclr/vm/arm/ehhelpers.S | 4 +- src/coreclr/vm/arm/pinvokestubs.S | 22 +- src/coreclr/vm/arm/stubs.cpp | 39 +- src/coreclr/vm/arm64/PInvokeStubs.asm | 34 +- src/coreclr/vm/arm64/asmconstants.h | 6 +- src/coreclr/vm/arm64/asmhelpers.S | 4 +- src/coreclr/vm/arm64/asmhelpers.asm | 8 +- src/coreclr/vm/arm64/pinvokestubs.S | 17 +- src/coreclr/vm/arm64/stubs.cpp | 24 +- src/coreclr/vm/assembly.cpp | 2 +- src/coreclr/vm/callcounting.cpp | 4 +- src/coreclr/vm/ceemain.cpp | 5 - src/coreclr/vm/clrtocomcall.cpp | 6 +- src/coreclr/vm/common.h | 2 +- src/coreclr/vm/comtoclrcall.cpp | 5 +- src/coreclr/vm/dispatchinfo.cpp | 2 +- src/coreclr/vm/dllimport.cpp | 6 +- src/coreclr/vm/eepolicy.cpp | 5 +- src/coreclr/vm/encee.cpp | 2 +- src/coreclr/vm/excep.cpp | 22 +- src/coreclr/vm/exceptionhandling.cpp | 26 +- src/coreclr/vm/fcall.h | 2 +- src/coreclr/vm/frames.cpp | 457 ++++--- src/coreclr/vm/frames.h | 1076 ++++++----------- src/coreclr/vm/gccover.cpp | 4 +- src/coreclr/vm/gcenv.ee.common.cpp | 4 +- src/coreclr/vm/gcenv.ee.cpp | 2 +- src/coreclr/vm/i386/PInvokeStubs.asm | 13 +- src/coreclr/vm/i386/asmconstants.h | 10 +- src/coreclr/vm/i386/asmhelpers.asm | 18 +- src/coreclr/vm/i386/cgenx86.cpp | 67 +- src/coreclr/vm/i386/excepx86.cpp | 10 +- src/coreclr/vm/i386/jithelp.asm | 44 +- src/coreclr/vm/i386/jitinterfacex86.cpp | 10 - src/coreclr/vm/jithelpers.cpp | 10 +- src/coreclr/vm/jitinterface.cpp | 22 +- src/coreclr/vm/loongarch64/asmconstants.h | 6 +- src/coreclr/vm/loongarch64/asmhelpers.S | 4 +- src/coreclr/vm/loongarch64/pinvokestubs.S | 14 +- src/coreclr/vm/loongarch64/stubs.cpp | 24 +- src/coreclr/vm/prestub.cpp | 6 +- src/coreclr/vm/proftoeeinterfaceimpl.cpp | 4 +- src/coreclr/vm/reflectioninvocation.cpp | 6 +- src/coreclr/vm/riscv64/asmconstants.h | 6 +- src/coreclr/vm/riscv64/asmhelpers.S | 4 +- src/coreclr/vm/riscv64/pinvokestubs.S | 17 +- src/coreclr/vm/riscv64/stubs.cpp | 24 +- src/coreclr/vm/runtimecallablewrapper.cpp | 6 +- src/coreclr/vm/stackwalk.cpp | 33 +- src/coreclr/vm/threads.cpp | 4 +- src/coreclr/vm/threadsuspend.cpp | 18 +- src/coreclr/vm/virtualcallstub.cpp | 2 +- 76 files changed, 1286 insertions(+), 1698 deletions(-) create mode 100644 src/coreclr/vm/FrameTypes.h diff --git a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp index 3f60dec6a9b1ad..90158d237ba5a9 100644 --- a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp +++ b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp @@ -465,7 +465,7 @@ ULONG32 DacDbiInterfaceImpl::GetCountOfInternalFrames(VMPTR_Thread vmThread) if (g_isNewExceptionHandlingEnabled && InlinedCallFrame::FrameHasActiveCall(pFrame)) { // Skip new exception handling helpers - InlinedCallFrame *pInlinedCallFrame = (InlinedCallFrame *)pFrame; + InlinedCallFrame *pInlinedCallFrame = dac_cast(pFrame); PTR_NDirectMethodDesc pMD = pInlinedCallFrame->m_Datum; TADDR datum = dac_cast(pMD); if ((datum & (TADDR)InlinedCallFrameMarker::Mask) == (TADDR)InlinedCallFrameMarker::ExceptionHandlingHelper) @@ -518,7 +518,7 @@ void DacDbiInterfaceImpl::EnumerateInternalFrames(VMPTR_Thread if (g_isNewExceptionHandlingEnabled && InlinedCallFrame::FrameHasActiveCall(pFrame)) { // Skip new exception handling helpers - InlinedCallFrame *pInlinedCallFrame = (InlinedCallFrame *)pFrame; + InlinedCallFrame *pInlinedCallFrame = dac_cast(pFrame); PTR_NDirectMethodDesc pMD = pInlinedCallFrame->m_Datum; TADDR datum = dac_cast(pMD); if ((datum & (TADDR)InlinedCallFrameMarker::Mask) == (TADDR)InlinedCallFrameMarker::ExceptionHandlingHelper) @@ -558,7 +558,7 @@ void DacDbiInterfaceImpl::EnumerateInternalFrames(VMPTR_Thread // it. In this case, pMD will remain NULL. EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY { - if (pFrame->GetVTablePtr() == ComMethodFrame::GetMethodFrameVPtr()) + if (pFrame->GetFrameIdentifier() == FrameIdentifier::ComMethodFrame) { ComMethodFrame * pCOMFrame = dac_cast(pFrame); PTR_VOID pUnkStackSlot = pCOMFrame->GetPointerToArguments(); @@ -1142,7 +1142,7 @@ CorDebugInternalFrameType DacDbiInterfaceImpl::GetInternalFrameType(Frame * pFra } else if (ft == Frame::TYPE_EXIT) { - if ((pFrame->GetVTablePtr() != InlinedCallFrame::GetMethodFrameVPtr()) || + if ((pFrame->GetFrameIdentifier() != FrameIdentifier::InlinedCallFrame) || InlinedCallFrame::FrameHasActiveCall(pFrame)) { resultType = STUBFRAME_M2U; @@ -1153,7 +1153,7 @@ CorDebugInternalFrameType DacDbiInterfaceImpl::GetInternalFrameType(Frame * pFra case Frame::TT_M2U: // Refer to the comment in DebuggerWalkStackProc() for StubDispatchFrame. - if (pFrame->GetVTablePtr() != StubDispatchFrame::GetMethodFrameVPtr()) + if (pFrame->GetFrameIdentifier() != FrameIdentifier::StubDispatchFrame) { if (it == Frame::INTERCEPTION_SECURITY) { diff --git a/src/coreclr/debug/ee/debugger.cpp b/src/coreclr/debug/ee/debugger.cpp index 6c494e29922628..0345218e861b45 100644 --- a/src/coreclr/debug/ee/debugger.cpp +++ b/src/coreclr/debug/ee/debugger.cpp @@ -13475,10 +13475,7 @@ void Debugger::UnhandledHijackWorker(CONTEXT * pContext, EXCEPTION_RECORD * pRec fSOException)) { - FrameWithCookie fef; -#if defined(FEATURE_EH_FUNCLETS) - *((&fef)->GetGSCookiePtr()) = GetProcessGSCookie(); -#endif // FEATURE_EH_FUNCLETS + FaultingExceptionFrame fef; if ((pContext != NULL) && fSOException) { GCX_COOP(); // Must be cooperative to modify frame chain. @@ -16799,4 +16796,256 @@ void Debugger::ExternalMethodFixupNextStep(PCODE address) } #endif //DACCESS_COMPILE +unsigned FuncEvalFrame::GetFrameAttribs_Impl(void) +{ + LIMITED_METHOD_DAC_CONTRACT; + + if (GetDebuggerEval()->m_evalDuringException) + { + return FRAME_ATTR_NONE; + } + else + { + return FRAME_ATTR_RESUMABLE; // Treat the next frame as the top frame. + } +} + +TADDR FuncEvalFrame::GetReturnAddressPtr_Impl() +{ + LIMITED_METHOD_DAC_CONTRACT; + + if (GetDebuggerEval()->m_evalDuringException) + { + return (TADDR)NULL; + } + else + { + return PTR_HOST_MEMBER_TADDR(FuncEvalFrame, this, m_ReturnAddress); + } +} + +// +// This updates the register display for a FuncEvalFrame. +// +void FuncEvalFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) +{ + SUPPORTS_DAC; + DebuggerEval * pDE = GetDebuggerEval(); + + // No context to update if we're doing a func eval from within exception processing. + if (pDE->m_evalDuringException) + { + return; + } + +#ifndef FEATURE_EH_FUNCLETS + // Reset pContext; it's only valid for active (top-most) frame. + pRD->pContext = NULL; +#endif // !FEATURE_EH_FUNCLETS + + +#ifdef TARGET_X86 + // Update all registers in the reg display from the CONTEXT we stored when the thread was hijacked for this func + // eval. We have to update all registers, not just the callee saved registers, because we can hijack a thread at any + // point for a func eval, not just at a call site. + pRD->SetEdiLocation(&(pDE->m_context.Edi)); + pRD->SetEsiLocation(&(pDE->m_context.Esi)); + pRD->SetEbxLocation(&(pDE->m_context.Ebx)); + pRD->SetEdxLocation(&(pDE->m_context.Edx)); + pRD->SetEcxLocation(&(pDE->m_context.Ecx)); + pRD->SetEaxLocation(&(pDE->m_context.Eax)); + pRD->SetEbpLocation(&(pDE->m_context.Ebp)); + pRD->PCTAddr = GetReturnAddressPtr(); + +#ifdef FEATURE_EH_FUNCLETS + + pRD->IsCallerContextValid = FALSE; + pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. + + pRD->pCurrentContext->Eip = *PTR_PCODE(pRD->PCTAddr); + pRD->pCurrentContext->Esp = (DWORD)GetSP(&pDE->m_context); + + SyncRegDisplayToCurrentContext(pRD); + +#else // FEATURE_EH_FUNCLETS + + pRD->ControlPC = *PTR_PCODE(pRD->PCTAddr); + pRD->SP = (DWORD)GetSP(&pDE->m_context); + +#endif // FEATURE_EH_FUNCLETS + +#elif defined(TARGET_AMD64) + pRD->IsCallerContextValid = FALSE; + pRD->IsCallerSPValid = FALSE; // Don't add usage of this flag. This is only temporary. + + memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(CONTEXT)); + + pRD->pCurrentContextPointers->Rax = &(pDE->m_context.Rax); + pRD->pCurrentContextPointers->Rcx = &(pDE->m_context.Rcx); + pRD->pCurrentContextPointers->Rdx = &(pDE->m_context.Rdx); + pRD->pCurrentContextPointers->R8 = &(pDE->m_context.R8); + pRD->pCurrentContextPointers->R9 = &(pDE->m_context.R9); + pRD->pCurrentContextPointers->R10 = &(pDE->m_context.R10); + pRD->pCurrentContextPointers->R11 = &(pDE->m_context.R11); + + pRD->pCurrentContextPointers->Rbx = &(pDE->m_context.Rbx); + pRD->pCurrentContextPointers->Rsi = &(pDE->m_context.Rsi); + pRD->pCurrentContextPointers->Rdi = &(pDE->m_context.Rdi); + pRD->pCurrentContextPointers->Rbp = &(pDE->m_context.Rbp); + pRD->pCurrentContextPointers->R12 = &(pDE->m_context.R12); + pRD->pCurrentContextPointers->R13 = &(pDE->m_context.R13); + pRD->pCurrentContextPointers->R14 = &(pDE->m_context.R14); + pRD->pCurrentContextPointers->R15 = &(pDE->m_context.R15); + + // SyncRegDisplayToCurrentContext() sets the pRD->SP and pRD->ControlPC on AMD64. + SyncRegDisplayToCurrentContext(pRD); + +#elif defined(TARGET_ARM) + pRD->IsCallerContextValid = FALSE; + pRD->IsCallerSPValid = FALSE; // Don't add usage of this flag. This is only temporary. + + memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(T_CONTEXT)); + + pRD->pCurrentContextPointers->R4 = &(pDE->m_context.R4); + pRD->pCurrentContextPointers->R5 = &(pDE->m_context.R5); + pRD->pCurrentContextPointers->R6 = &(pDE->m_context.R6); + pRD->pCurrentContextPointers->R7 = &(pDE->m_context.R7); + pRD->pCurrentContextPointers->R8 = &(pDE->m_context.R8); + pRD->pCurrentContextPointers->R9 = &(pDE->m_context.R9); + pRD->pCurrentContextPointers->R10 = &(pDE->m_context.R10); + pRD->pCurrentContextPointers->R11 = &(pDE->m_context.R11); + pRD->pCurrentContextPointers->Lr = &(pDE->m_context.Lr); + + pRD->volatileCurrContextPointers.R0 = &(pDE->m_context.R0); + pRD->volatileCurrContextPointers.R1 = &(pDE->m_context.R1); + pRD->volatileCurrContextPointers.R2 = &(pDE->m_context.R2); + pRD->volatileCurrContextPointers.R3 = &(pDE->m_context.R3); + pRD->volatileCurrContextPointers.R12 = &(pDE->m_context.R12); + + SyncRegDisplayToCurrentContext(pRD); + +#elif defined(TARGET_ARM64) + pRD->IsCallerContextValid = FALSE; + pRD->IsCallerSPValid = FALSE; // Don't add usage of this flag. This is only temporary. + + memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(T_CONTEXT)); + + pRD->pCurrentContextPointers->X19 = &(pDE->m_context.X19); + pRD->pCurrentContextPointers->X20 = &(pDE->m_context.X20); + pRD->pCurrentContextPointers->X21 = &(pDE->m_context.X21); + pRD->pCurrentContextPointers->X22 = &(pDE->m_context.X22); + pRD->pCurrentContextPointers->X23 = &(pDE->m_context.X23); + pRD->pCurrentContextPointers->X24 = &(pDE->m_context.X24); + pRD->pCurrentContextPointers->X25 = &(pDE->m_context.X25); + pRD->pCurrentContextPointers->X26 = &(pDE->m_context.X26); + pRD->pCurrentContextPointers->X27 = &(pDE->m_context.X27); + pRD->pCurrentContextPointers->X28 = &(pDE->m_context.X28); + pRD->pCurrentContextPointers->Lr = &(pDE->m_context.Lr); + pRD->pCurrentContextPointers->Fp = &(pDE->m_context.Fp); + + pRD->volatileCurrContextPointers.X0 = &(pDE->m_context.X0); + pRD->volatileCurrContextPointers.X1 = &(pDE->m_context.X1); + pRD->volatileCurrContextPointers.X2 = &(pDE->m_context.X2); + pRD->volatileCurrContextPointers.X3 = &(pDE->m_context.X3); + pRD->volatileCurrContextPointers.X4 = &(pDE->m_context.X4); + pRD->volatileCurrContextPointers.X5 = &(pDE->m_context.X5); + pRD->volatileCurrContextPointers.X6 = &(pDE->m_context.X6); + pRD->volatileCurrContextPointers.X7 = &(pDE->m_context.X7); + pRD->volatileCurrContextPointers.X8 = &(pDE->m_context.X8); + pRD->volatileCurrContextPointers.X9 = &(pDE->m_context.X9); + pRD->volatileCurrContextPointers.X10 = &(pDE->m_context.X10); + pRD->volatileCurrContextPointers.X11 = &(pDE->m_context.X11); + pRD->volatileCurrContextPointers.X12 = &(pDE->m_context.X12); + pRD->volatileCurrContextPointers.X13 = &(pDE->m_context.X13); + pRD->volatileCurrContextPointers.X14 = &(pDE->m_context.X14); + pRD->volatileCurrContextPointers.X15 = &(pDE->m_context.X15); + pRD->volatileCurrContextPointers.X16 = &(pDE->m_context.X16); + pRD->volatileCurrContextPointers.X17 = &(pDE->m_context.X17); + + SyncRegDisplayToCurrentContext(pRD); +#elif defined(TARGET_RISCV64) + pRD->IsCallerContextValid = FALSE; + pRD->IsCallerSPValid = FALSE; // Don't add usage of this flag. This is only temporary. + + memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(T_CONTEXT)); + + pRD->pCurrentContextPointers->S1 = &(pDE->m_context.S1); + pRD->pCurrentContextPointers->S2 = &(pDE->m_context.S2); + pRD->pCurrentContextPointers->S3 = &(pDE->m_context.S3); + pRD->pCurrentContextPointers->S4 = &(pDE->m_context.S4); + pRD->pCurrentContextPointers->S5 = &(pDE->m_context.S5); + pRD->pCurrentContextPointers->S6 = &(pDE->m_context.S6); + pRD->pCurrentContextPointers->S7 = &(pDE->m_context.S7); + pRD->pCurrentContextPointers->S8 = &(pDE->m_context.S8); + pRD->pCurrentContextPointers->S9 = &(pDE->m_context.S9); + pRD->pCurrentContextPointers->S10 = &(pDE->m_context.S10); + pRD->pCurrentContextPointers->S11 = &(pDE->m_context.S11); + pRD->pCurrentContextPointers->Fp = &(pDE->m_context.Fp); + pRD->pCurrentContextPointers->Gp = &(pDE->m_context.Gp); + pRD->pCurrentContextPointers->Tp = &(pDE->m_context.Tp); + pRD->pCurrentContextPointers->Ra = &(pDE->m_context.Ra); + + pRD->volatileCurrContextPointers.R0 = &(pDE->m_context.R0); + pRD->volatileCurrContextPointers.A0 = &(pDE->m_context.A0); + pRD->volatileCurrContextPointers.A1 = &(pDE->m_context.A1); + pRD->volatileCurrContextPointers.A2 = &(pDE->m_context.A2); + pRD->volatileCurrContextPointers.A3 = &(pDE->m_context.A3); + pRD->volatileCurrContextPointers.A4 = &(pDE->m_context.A4); + pRD->volatileCurrContextPointers.A5 = &(pDE->m_context.A5); + pRD->volatileCurrContextPointers.A6 = &(pDE->m_context.A6); + pRD->volatileCurrContextPointers.A7 = &(pDE->m_context.A7); + pRD->volatileCurrContextPointers.T0 = &(pDE->m_context.T0); + pRD->volatileCurrContextPointers.T1 = &(pDE->m_context.T1); + pRD->volatileCurrContextPointers.T2 = &(pDE->m_context.T2); + pRD->volatileCurrContextPointers.T3 = &(pDE->m_context.T3); + pRD->volatileCurrContextPointers.T4 = &(pDE->m_context.T4); + pRD->volatileCurrContextPointers.T5 = &(pDE->m_context.T5); + pRD->volatileCurrContextPointers.T6 = &(pDE->m_context.T6); + + SyncRegDisplayToCurrentContext(pRD); +#elif defined(TARGET_LOONGARCH64) + pRD->IsCallerContextValid = FALSE; + pRD->IsCallerSPValid = FALSE; // Don't add usage of this flag. This is only temporary. + + memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(T_CONTEXT)); + + pRD->pCurrentContextPointers->S0 = &(pDE->m_context.S0); + pRD->pCurrentContextPointers->S1 = &(pDE->m_context.S1); + pRD->pCurrentContextPointers->S2 = &(pDE->m_context.S2); + pRD->pCurrentContextPointers->S3 = &(pDE->m_context.S3); + pRD->pCurrentContextPointers->S4 = &(pDE->m_context.S4); + pRD->pCurrentContextPointers->S5 = &(pDE->m_context.S5); + pRD->pCurrentContextPointers->S6 = &(pDE->m_context.S6); + pRD->pCurrentContextPointers->S7 = &(pDE->m_context.S7); + pRD->pCurrentContextPointers->S8 = &(pDE->m_context.S8); + pRD->pCurrentContextPointers->Fp = &(pDE->m_context.Fp); + pRD->pCurrentContextPointers->Ra = &(pDE->m_context.Ra); + + pRD->volatileCurrContextPointers.R0 = &(pDE->m_context.R0); + pRD->volatileCurrContextPointers.A0 = &(pDE->m_context.A0); + pRD->volatileCurrContextPointers.A1 = &(pDE->m_context.A1); + pRD->volatileCurrContextPointers.A2 = &(pDE->m_context.A2); + pRD->volatileCurrContextPointers.A3 = &(pDE->m_context.A3); + pRD->volatileCurrContextPointers.A4 = &(pDE->m_context.A4); + pRD->volatileCurrContextPointers.A5 = &(pDE->m_context.A5); + pRD->volatileCurrContextPointers.A6 = &(pDE->m_context.A6); + pRD->volatileCurrContextPointers.A7 = &(pDE->m_context.A7); + pRD->volatileCurrContextPointers.T0 = &(pDE->m_context.T0); + pRD->volatileCurrContextPointers.T1 = &(pDE->m_context.T1); + pRD->volatileCurrContextPointers.T2 = &(pDE->m_context.T2); + pRD->volatileCurrContextPointers.T3 = &(pDE->m_context.T3); + pRD->volatileCurrContextPointers.T4 = &(pDE->m_context.T4); + pRD->volatileCurrContextPointers.T5 = &(pDE->m_context.T5); + pRD->volatileCurrContextPointers.T6 = &(pDE->m_context.T6); + pRD->volatileCurrContextPointers.T7 = &(pDE->m_context.T7); + pRD->volatileCurrContextPointers.T8 = &(pDE->m_context.T8); + pRD->volatileCurrContextPointers.X0 = &(pDE->m_context.X0); + + SyncRegDisplayToCurrentContext(pRD); + +#else + PORTABILITY_ASSERT("FuncEvalFrame::UpdateRegDisplay is not implemented on this platform."); +#endif +} + #endif //DEBUGGING_SUPPORTED diff --git a/src/coreclr/debug/ee/debugger.inl b/src/coreclr/debug/ee/debugger.inl index f16227820451ac..4f69164a292f9f 100644 --- a/src/coreclr/debug/ee/debugger.inl +++ b/src/coreclr/debug/ee/debugger.inl @@ -132,256 +132,4 @@ inline DebuggerEval * FuncEvalFrame::GetDebuggerEval() return m_pDebuggerEval; } -inline unsigned FuncEvalFrame::GetFrameAttribs(void) -{ - LIMITED_METHOD_DAC_CONTRACT; - - if (GetDebuggerEval()->m_evalDuringException) - { - return FRAME_ATTR_NONE; - } - else - { - return FRAME_ATTR_RESUMABLE; // Treat the next frame as the top frame. - } -} - -inline TADDR FuncEvalFrame::GetReturnAddressPtr() -{ - LIMITED_METHOD_DAC_CONTRACT; - - if (GetDebuggerEval()->m_evalDuringException) - { - return (TADDR)NULL; - } - else - { - return PTR_HOST_MEMBER_TADDR(FuncEvalFrame, this, m_ReturnAddress); - } -} - -// -// This updates the register display for a FuncEvalFrame. -// -inline void FuncEvalFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) -{ - SUPPORTS_DAC; - DebuggerEval * pDE = GetDebuggerEval(); - - // No context to update if we're doing a func eval from within exception processing. - if (pDE->m_evalDuringException) - { - return; - } - -#ifndef FEATURE_EH_FUNCLETS - // Reset pContext; it's only valid for active (top-most) frame. - pRD->pContext = NULL; -#endif // !FEATURE_EH_FUNCLETS - - -#ifdef TARGET_X86 - // Update all registers in the reg display from the CONTEXT we stored when the thread was hijacked for this func - // eval. We have to update all registers, not just the callee saved registers, because we can hijack a thread at any - // point for a func eval, not just at a call site. - pRD->SetEdiLocation(&(pDE->m_context.Edi)); - pRD->SetEsiLocation(&(pDE->m_context.Esi)); - pRD->SetEbxLocation(&(pDE->m_context.Ebx)); - pRD->SetEdxLocation(&(pDE->m_context.Edx)); - pRD->SetEcxLocation(&(pDE->m_context.Ecx)); - pRD->SetEaxLocation(&(pDE->m_context.Eax)); - pRD->SetEbpLocation(&(pDE->m_context.Ebp)); - pRD->PCTAddr = GetReturnAddressPtr(); - -#ifdef FEATURE_EH_FUNCLETS - - pRD->IsCallerContextValid = FALSE; - pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. - - pRD->pCurrentContext->Eip = *PTR_PCODE(pRD->PCTAddr); - pRD->pCurrentContext->Esp = (DWORD)GetSP(&pDE->m_context); - - SyncRegDisplayToCurrentContext(pRD); - -#else // FEATURE_EH_FUNCLETS - - pRD->ControlPC = *PTR_PCODE(pRD->PCTAddr); - pRD->SP = (DWORD)GetSP(&pDE->m_context); - -#endif // FEATURE_EH_FUNCLETS - -#elif defined(TARGET_AMD64) - pRD->IsCallerContextValid = FALSE; - pRD->IsCallerSPValid = FALSE; // Don't add usage of this flag. This is only temporary. - - memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(CONTEXT)); - - pRD->pCurrentContextPointers->Rax = &(pDE->m_context.Rax); - pRD->pCurrentContextPointers->Rcx = &(pDE->m_context.Rcx); - pRD->pCurrentContextPointers->Rdx = &(pDE->m_context.Rdx); - pRD->pCurrentContextPointers->R8 = &(pDE->m_context.R8); - pRD->pCurrentContextPointers->R9 = &(pDE->m_context.R9); - pRD->pCurrentContextPointers->R10 = &(pDE->m_context.R10); - pRD->pCurrentContextPointers->R11 = &(pDE->m_context.R11); - - pRD->pCurrentContextPointers->Rbx = &(pDE->m_context.Rbx); - pRD->pCurrentContextPointers->Rsi = &(pDE->m_context.Rsi); - pRD->pCurrentContextPointers->Rdi = &(pDE->m_context.Rdi); - pRD->pCurrentContextPointers->Rbp = &(pDE->m_context.Rbp); - pRD->pCurrentContextPointers->R12 = &(pDE->m_context.R12); - pRD->pCurrentContextPointers->R13 = &(pDE->m_context.R13); - pRD->pCurrentContextPointers->R14 = &(pDE->m_context.R14); - pRD->pCurrentContextPointers->R15 = &(pDE->m_context.R15); - - // SyncRegDisplayToCurrentContext() sets the pRD->SP and pRD->ControlPC on AMD64. - SyncRegDisplayToCurrentContext(pRD); - -#elif defined(TARGET_ARM) - pRD->IsCallerContextValid = FALSE; - pRD->IsCallerSPValid = FALSE; // Don't add usage of this flag. This is only temporary. - - memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(T_CONTEXT)); - - pRD->pCurrentContextPointers->R4 = &(pDE->m_context.R4); - pRD->pCurrentContextPointers->R5 = &(pDE->m_context.R5); - pRD->pCurrentContextPointers->R6 = &(pDE->m_context.R6); - pRD->pCurrentContextPointers->R7 = &(pDE->m_context.R7); - pRD->pCurrentContextPointers->R8 = &(pDE->m_context.R8); - pRD->pCurrentContextPointers->R9 = &(pDE->m_context.R9); - pRD->pCurrentContextPointers->R10 = &(pDE->m_context.R10); - pRD->pCurrentContextPointers->R11 = &(pDE->m_context.R11); - pRD->pCurrentContextPointers->Lr = &(pDE->m_context.Lr); - - pRD->volatileCurrContextPointers.R0 = &(pDE->m_context.R0); - pRD->volatileCurrContextPointers.R1 = &(pDE->m_context.R1); - pRD->volatileCurrContextPointers.R2 = &(pDE->m_context.R2); - pRD->volatileCurrContextPointers.R3 = &(pDE->m_context.R3); - pRD->volatileCurrContextPointers.R12 = &(pDE->m_context.R12); - - SyncRegDisplayToCurrentContext(pRD); - -#elif defined(TARGET_ARM64) - pRD->IsCallerContextValid = FALSE; - pRD->IsCallerSPValid = FALSE; // Don't add usage of this flag. This is only temporary. - - memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(T_CONTEXT)); - - pRD->pCurrentContextPointers->X19 = &(pDE->m_context.X19); - pRD->pCurrentContextPointers->X20 = &(pDE->m_context.X20); - pRD->pCurrentContextPointers->X21 = &(pDE->m_context.X21); - pRD->pCurrentContextPointers->X22 = &(pDE->m_context.X22); - pRD->pCurrentContextPointers->X23 = &(pDE->m_context.X23); - pRD->pCurrentContextPointers->X24 = &(pDE->m_context.X24); - pRD->pCurrentContextPointers->X25 = &(pDE->m_context.X25); - pRD->pCurrentContextPointers->X26 = &(pDE->m_context.X26); - pRD->pCurrentContextPointers->X27 = &(pDE->m_context.X27); - pRD->pCurrentContextPointers->X28 = &(pDE->m_context.X28); - pRD->pCurrentContextPointers->Lr = &(pDE->m_context.Lr); - pRD->pCurrentContextPointers->Fp = &(pDE->m_context.Fp); - - pRD->volatileCurrContextPointers.X0 = &(pDE->m_context.X0); - pRD->volatileCurrContextPointers.X1 = &(pDE->m_context.X1); - pRD->volatileCurrContextPointers.X2 = &(pDE->m_context.X2); - pRD->volatileCurrContextPointers.X3 = &(pDE->m_context.X3); - pRD->volatileCurrContextPointers.X4 = &(pDE->m_context.X4); - pRD->volatileCurrContextPointers.X5 = &(pDE->m_context.X5); - pRD->volatileCurrContextPointers.X6 = &(pDE->m_context.X6); - pRD->volatileCurrContextPointers.X7 = &(pDE->m_context.X7); - pRD->volatileCurrContextPointers.X8 = &(pDE->m_context.X8); - pRD->volatileCurrContextPointers.X9 = &(pDE->m_context.X9); - pRD->volatileCurrContextPointers.X10 = &(pDE->m_context.X10); - pRD->volatileCurrContextPointers.X11 = &(pDE->m_context.X11); - pRD->volatileCurrContextPointers.X12 = &(pDE->m_context.X12); - pRD->volatileCurrContextPointers.X13 = &(pDE->m_context.X13); - pRD->volatileCurrContextPointers.X14 = &(pDE->m_context.X14); - pRD->volatileCurrContextPointers.X15 = &(pDE->m_context.X15); - pRD->volatileCurrContextPointers.X16 = &(pDE->m_context.X16); - pRD->volatileCurrContextPointers.X17 = &(pDE->m_context.X17); - - SyncRegDisplayToCurrentContext(pRD); -#elif defined(TARGET_RISCV64) - pRD->IsCallerContextValid = FALSE; - pRD->IsCallerSPValid = FALSE; // Don't add usage of this flag. This is only temporary. - - memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(T_CONTEXT)); - - pRD->pCurrentContextPointers->S1 = &(pDE->m_context.S1); - pRD->pCurrentContextPointers->S2 = &(pDE->m_context.S2); - pRD->pCurrentContextPointers->S3 = &(pDE->m_context.S3); - pRD->pCurrentContextPointers->S4 = &(pDE->m_context.S4); - pRD->pCurrentContextPointers->S5 = &(pDE->m_context.S5); - pRD->pCurrentContextPointers->S6 = &(pDE->m_context.S6); - pRD->pCurrentContextPointers->S7 = &(pDE->m_context.S7); - pRD->pCurrentContextPointers->S8 = &(pDE->m_context.S8); - pRD->pCurrentContextPointers->S9 = &(pDE->m_context.S9); - pRD->pCurrentContextPointers->S10 = &(pDE->m_context.S10); - pRD->pCurrentContextPointers->S11 = &(pDE->m_context.S11); - pRD->pCurrentContextPointers->Fp = &(pDE->m_context.Fp); - pRD->pCurrentContextPointers->Gp = &(pDE->m_context.Gp); - pRD->pCurrentContextPointers->Tp = &(pDE->m_context.Tp); - pRD->pCurrentContextPointers->Ra = &(pDE->m_context.Ra); - - pRD->volatileCurrContextPointers.R0 = &(pDE->m_context.R0); - pRD->volatileCurrContextPointers.A0 = &(pDE->m_context.A0); - pRD->volatileCurrContextPointers.A1 = &(pDE->m_context.A1); - pRD->volatileCurrContextPointers.A2 = &(pDE->m_context.A2); - pRD->volatileCurrContextPointers.A3 = &(pDE->m_context.A3); - pRD->volatileCurrContextPointers.A4 = &(pDE->m_context.A4); - pRD->volatileCurrContextPointers.A5 = &(pDE->m_context.A5); - pRD->volatileCurrContextPointers.A6 = &(pDE->m_context.A6); - pRD->volatileCurrContextPointers.A7 = &(pDE->m_context.A7); - pRD->volatileCurrContextPointers.T0 = &(pDE->m_context.T0); - pRD->volatileCurrContextPointers.T1 = &(pDE->m_context.T1); - pRD->volatileCurrContextPointers.T2 = &(pDE->m_context.T2); - pRD->volatileCurrContextPointers.T3 = &(pDE->m_context.T3); - pRD->volatileCurrContextPointers.T4 = &(pDE->m_context.T4); - pRD->volatileCurrContextPointers.T5 = &(pDE->m_context.T5); - pRD->volatileCurrContextPointers.T6 = &(pDE->m_context.T6); - - SyncRegDisplayToCurrentContext(pRD); -#elif defined(TARGET_LOONGARCH64) - pRD->IsCallerContextValid = FALSE; - pRD->IsCallerSPValid = FALSE; // Don't add usage of this flag. This is only temporary. - - memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(T_CONTEXT)); - - pRD->pCurrentContextPointers->S0 = &(pDE->m_context.S0); - pRD->pCurrentContextPointers->S1 = &(pDE->m_context.S1); - pRD->pCurrentContextPointers->S2 = &(pDE->m_context.S2); - pRD->pCurrentContextPointers->S3 = &(pDE->m_context.S3); - pRD->pCurrentContextPointers->S4 = &(pDE->m_context.S4); - pRD->pCurrentContextPointers->S5 = &(pDE->m_context.S5); - pRD->pCurrentContextPointers->S6 = &(pDE->m_context.S6); - pRD->pCurrentContextPointers->S7 = &(pDE->m_context.S7); - pRD->pCurrentContextPointers->S8 = &(pDE->m_context.S8); - pRD->pCurrentContextPointers->Fp = &(pDE->m_context.Fp); - pRD->pCurrentContextPointers->Ra = &(pDE->m_context.Ra); - - pRD->volatileCurrContextPointers.R0 = &(pDE->m_context.R0); - pRD->volatileCurrContextPointers.A0 = &(pDE->m_context.A0); - pRD->volatileCurrContextPointers.A1 = &(pDE->m_context.A1); - pRD->volatileCurrContextPointers.A2 = &(pDE->m_context.A2); - pRD->volatileCurrContextPointers.A3 = &(pDE->m_context.A3); - pRD->volatileCurrContextPointers.A4 = &(pDE->m_context.A4); - pRD->volatileCurrContextPointers.A5 = &(pDE->m_context.A5); - pRD->volatileCurrContextPointers.A6 = &(pDE->m_context.A6); - pRD->volatileCurrContextPointers.A7 = &(pDE->m_context.A7); - pRD->volatileCurrContextPointers.T0 = &(pDE->m_context.T0); - pRD->volatileCurrContextPointers.T1 = &(pDE->m_context.T1); - pRD->volatileCurrContextPointers.T2 = &(pDE->m_context.T2); - pRD->volatileCurrContextPointers.T3 = &(pDE->m_context.T3); - pRD->volatileCurrContextPointers.T4 = &(pDE->m_context.T4); - pRD->volatileCurrContextPointers.T5 = &(pDE->m_context.T5); - pRD->volatileCurrContextPointers.T6 = &(pDE->m_context.T6); - pRD->volatileCurrContextPointers.T7 = &(pDE->m_context.T7); - pRD->volatileCurrContextPointers.T8 = &(pDE->m_context.T8); - pRD->volatileCurrContextPointers.X0 = &(pDE->m_context.X0); - - SyncRegDisplayToCurrentContext(pRD); - -#else - PORTABILITY_ASSERT("FuncEvalFrame::UpdateRegDisplay is not implemented on this platform."); -#endif -} - #endif // DEBUGGER_INL_ diff --git a/src/coreclr/debug/ee/frameinfo.cpp b/src/coreclr/debug/ee/frameinfo.cpp index 48e0d2d56c146f..d2a73fbd9b8e1b 100644 --- a/src/coreclr/debug/ee/frameinfo.cpp +++ b/src/coreclr/debug/ee/frameinfo.cpp @@ -454,7 +454,7 @@ bool HasExitRuntime(Frame *pFrame, DebuggerFrameData *pData, FramePointer *pPote #else // TARGET_X86 // DebuggerExitFrame always return a NULL returnSP on x86. - if (pFrame->GetVTablePtr() == DebuggerExitFrame::GetMethodFrameVPtr()) + if (pFrame->GetFrameIdentifier() == FrameIdentifier::DebuggerExitFrame) { if (pPotentialFP != NULL) { @@ -462,9 +462,9 @@ bool HasExitRuntime(Frame *pFrame, DebuggerFrameData *pData, FramePointer *pPote } return true; } - else if (pFrame->GetVTablePtr() == InlinedCallFrame::GetMethodFrameVPtr()) + else if (pFrame->GetFrameIdentifier() == FrameIdentifier::InlinedCallFrame) { - InlinedCallFrame *pInlinedFrame = static_cast(pFrame); + InlinedCallFrame *pInlinedFrame = dac_cast(pFrame); LPVOID sp = (LPVOID)pInlinedFrame->GetCallSiteSP(); // The sp returned below is the sp of the caller, which is either an IL stub in the normal case @@ -485,7 +485,7 @@ bool HasExitRuntime(Frame *pFrame, DebuggerFrameData *pData, FramePointer *pPote { // It'll be nice if there's a way to assert that the current frame is indeed of a // derived class of TransitionFrame. - TransitionFrame *pTransFrame = static_cast(pFrame); + TransitionFrame *pTransFrame = dac_cast(pFrame); LPVOID sp = (LPVOID)pTransFrame->GetSP(); // The sp returned below is the sp of the caller, which is either an IL stub in the normal case @@ -788,7 +788,7 @@ void FrameInfo::InitForM2UInternalFrame(CrawlFrame * pCF) // For a M2U call, there's a managed method wrapping the unmanaged call. Use that. Frame * pFrame = pCF->GetFrame(); _ASSERTE(pFrame->GetTransitionType() == Frame::TT_M2U); - FramedMethodFrame * pM2U = static_cast (pFrame); + FramedMethodFrame * pM2U = dac_cast (pFrame); MethodDesc * pMDWrapper = pM2U->GetFunction(); // Soem M2U transitions may not have a function associated w/ them, @@ -814,9 +814,9 @@ void FrameInfo::InitForU2MInternalFrame(CrawlFrame * pCF) // For regular U2M PInvoke cases, we don't care about MD b/c it's just going to // be the next frame. // If we're a COM2CLR call, perhaps we can get the MD for the interface. - if (pFrame->GetVTablePtr() == ComMethodFrame::GetMethodFrameVPtr()) + if (pFrame->GetFrameIdentifier() == FrameIdentifier::ComMethodFrame) { - ComMethodFrame* pCOMFrame = static_cast (pFrame); + ComMethodFrame* pCOMFrame = dac_cast (pFrame); ComCallMethodDesc* pCMD = reinterpret_cast (pCOMFrame->ComMethodFrame::GetDatum()); pMDHint = pCMD->GetInterfaceMethodDesc(); @@ -1190,7 +1190,7 @@ StackWalkAction TrackUMChain(CrawlFrame *pCF, DebuggerFrameData *d) #ifdef FEATURE_COMINTEROP if ((frame != NULL) && - (frame->GetVTablePtr() == CLRToCOMMethodFrame::GetMethodFrameVPtr())) + (frame->GetFrameIdentifier() == FrameIdentifier::CLRToCOMMethodFrame)) { // This condition is part of the fix for 650903. (See // code:ControllerStackInfo::WalkStack and code:DebuggerStepper::TrapStepOut @@ -1717,7 +1717,7 @@ StackWalkAction DebuggerWalkStackProc(CrawlFrame *pCF, void *data) // The jitted code on X64 behaves differently. // // Note that there is a corresponding change in DacDbiInterfaceImpl::GetInternalFrameType(). - if (frame->GetVTablePtr() == StubDispatchFrame::GetMethodFrameVPtr()) + if (frame->GetFrameIdentifier() == FrameIdentifier::StubDispatchFrame) { use = false; } @@ -1739,7 +1739,7 @@ StackWalkAction DebuggerWalkStackProc(CrawlFrame *pCF, void *data) { // We only show a FuncEvalFrame if the funceval is not trying to abort the thread. - FuncEvalFrame *pFuncEvalFrame = static_cast(frame); + FuncEvalFrame *pFuncEvalFrame = dac_cast(frame); use = pFuncEvalFrame->ShowFrame() ? true : false; } diff --git a/src/coreclr/debug/ee/funceval.cpp b/src/coreclr/debug/ee/funceval.cpp index 287f6f11e51778..66a85ab0d239da 100644 --- a/src/coreclr/debug/ee/funceval.cpp +++ b/src/coreclr/debug/ee/funceval.cpp @@ -3525,7 +3525,7 @@ static void GCProtectArgsAndDoNormalFuncEval(DebuggerEval *pDE, INT64 *pBufferForArgsArray = (INT64*)_alloca(cbAllocSize); memset(pBufferForArgsArray, 0, cbAllocSize); - FrameWithCookie protectValueClassFrame; + ProtectValueClassFrame protectValueClassFrame; // // Initialize our tracking array @@ -3858,7 +3858,7 @@ void * STDCALL FuncEvalHijackWorker(DebuggerEval *pDE) // Push our FuncEvalFrame. The return address is equal to the IP in the saved context in the DebuggerEval. The // m_Datum becomes the ptr to the DebuggerEval. The frame address also serves as the address of the catch-handler-found. // - FrameWithCookie FEFrame(pDE, GetIP(&pDE->m_context), true); + FuncEvalFrame FEFrame(pDE, GetIP(&pDE->m_context), true); FEFrame.Push(); // On ARM/ARM64 the single step flag is per-thread and not per context. We need to make sure that the SS flag is cleared diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 3939ac8d6074d2..08970ec4102e9b 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -1650,8 +1650,6 @@ struct CORINFO_EE_INFO // Size of the Frame structure when it also contains the secret stub arg unsigned sizeWithSecretStubArg; - unsigned offsetOfGSCookie; - unsigned offsetOfFrameVptr; unsigned offsetOfFrameLink; unsigned offsetOfCallSiteSP; unsigned offsetOfCalleeSavedFP; diff --git a/src/coreclr/inc/daccess.h b/src/coreclr/inc/daccess.h index 7bc2baed536e39..ca3cb5c004c327 100644 --- a/src/coreclr/inc/daccess.h +++ b/src/coreclr/inc/daccess.h @@ -2205,9 +2205,6 @@ public: name(int dummy) : base(dummy) {} // helper macro to make the vtables unique for DAC #define VPTR_UNIQUE(unique) virtual int MakeVTableUniqueForDAC() { return unique; } -#define VPTR_UNIQUE_ComMethodFrame (100000) -#define VPTR_UNIQUE_RedirectedThreadFrame (VPTR_UNIQUE_ComMethodFrame + 1) -#define VPTR_UNIQUE_HijackFrame (VPTR_UNIQUE_RedirectedThreadFrame + 1) #define PTR_TO_TADDR(ptr) ((TADDR)(ptr)) #define GFN_TADDR(name) ((TADDR)(name)) diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 2db16d00df135b..9383fceebc29b2 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,12 +43,12 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* cc0e7adf-e397-40b6-9d14-a7149815c991 */ - 0xcc0e7adf, - 0xe397, - 0x40b6, - {0x9d, 0x14, 0xa7, 0x14, 0x98, 0x15, 0xc9, 0x91} - }; +constexpr GUID JITEEVersionIdentifier = { /* a116647a-3f80-4fd6-9c80-95156c7e9923 */ + 0xa116647a, + 0x3f80, + 0x4fd6, + {0x9c, 0x80, 0x95, 0x15, 0x6c, 0x7e, 0x99, 0x23} +}; ////////////////////////////////////////////////////////////////////////////////////////////////////////// // diff --git a/src/coreclr/inc/vptr_list.h b/src/coreclr/inc/vptr_list.h index 17e1867aa79b95..dcc1e197acd770 100644 --- a/src/coreclr/inc/vptr_list.h +++ b/src/coreclr/inc/vptr_list.h @@ -41,52 +41,6 @@ VPTR_CLASS(ConvertedImageLayout) VPTR_CLASS(LoadedImageLayout) VPTR_CLASS(FlatImageLayout) -#ifdef FEATURE_COMINTEROP -VPTR_CLASS(ComMethodFrame) -VPTR_CLASS(CLRToCOMMethodFrame) -VPTR_CLASS(ComPrestubMethodFrame) -#endif // FEATURE_COMINTEROP - -VPTR_CLASS(DebuggerClassInitMarkFrame) -VPTR_CLASS(DebuggerExitFrame) -VPTR_CLASS(DebuggerU2MCatchHandlerFrame) -VPTR_CLASS(FaultingExceptionFrame) -#ifdef FEATURE_EH_FUNCLETS -VPTR_CLASS(SoftwareExceptionFrame) -#endif // FEATURE_EH_FUNCLETS -VPTR_CLASS(FuncEvalFrame) -VPTR_CLASS(HelperMethodFrame) -VPTR_CLASS(HelperMethodFrame_1OBJ) -VPTR_CLASS(HelperMethodFrame_2OBJ) -VPTR_CLASS(HelperMethodFrame_3OBJ) -VPTR_CLASS(HelperMethodFrame_PROTECTOBJ) -#ifdef FEATURE_HIJACK -VPTR_CLASS(HijackFrame) -#endif -VPTR_CLASS(InlinedCallFrame) -VPTR_CLASS(PInvokeCalliFrame) -VPTR_CLASS(PrestubMethodFrame) -VPTR_CLASS(ProtectByRefsFrame) -VPTR_CLASS(ProtectValueClassFrame) -#ifdef FEATURE_HIJACK -VPTR_CLASS(ResumableFrame) -VPTR_CLASS(RedirectedThreadFrame) -#endif -VPTR_CLASS(StubDispatchFrame) -VPTR_CLASS(CallCountingHelperFrame) -VPTR_CLASS(ExternalMethodFrame) -#ifdef FEATURE_READYTORUN -VPTR_CLASS(DynamicHelperFrame) -#endif -#if defined(TARGET_X86) && !defined(UNIX_X86_ABI) -VPTR_CLASS(TailCallFrame) -#endif -VPTR_CLASS(ExceptionFilterFrame) - -#ifdef _DEBUG -VPTR_CLASS(AssumeByrefFromJITStack) -#endif - #ifdef DEBUGGING_SUPPORTED VPTR_CLASS(Debugger) VPTR_CLASS(EEDbgInterfaceImpl) diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 319466fd94071d..408b3653f948e0 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -6387,7 +6387,12 @@ bool Compiler::impCanPInvokeInline() // unmanaged code, we cannot reuse the inlined stub (we still need // the original state until we are in the catch handler) // -// * We disable pinvoke inlining inside handlers since the GSCookie +// TODO-CQ: The inlining frame no longer has a GSCookie, so the common on this +// restriction is out of date. However, given that there is a comment +// about protecting the framelet, I'm not confident about what this +// is actually protecteing, so I don't want to remove this +// restriction without further analysis analysis. +// * We disable pinvoke inlini1ng inside handlers since the GSCookie // is in the inlined Frame (see // CORINFO_EE_INFO::InlinedCallFrameInfo::offsetOfGSCookie), but // this would not protect framelets/return-address of handlers. diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index dfd489eac21b88..34c8bd16b310c0 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -5861,7 +5861,7 @@ GenTree* Lowering::CreateFrameLinkUpdate(FrameLinkAction action) if (action == PushFrame) { // Thread->m_pFrame = &inlinedCallFrame; - data = comp->gtNewLclAddrNode(comp->lvaInlinedPInvokeFrameVar, callFrameInfo.offsetOfFrameVptr); + data = comp->gtNewLclVarAddrNode(comp->lvaInlinedPInvokeFrameVar); } else { @@ -5889,20 +5889,19 @@ GenTree* Lowering::CreateFrameLinkUpdate(FrameLinkAction action) // 64-bit 32-bit CORINFO_EE_INFO // offset offset field name offset when set // ----------------------------------------------------------------------------------------- -// +00h +00h GS cookie offsetOfGSCookie -// +08h +04h vptr for class InlinedCallFrame offsetOfFrameVptr method prolog -// +10h +08h m_Next offsetOfFrameLink method prolog -// +18h +0Ch m_Datum offsetOfCallTarget call site -// +20h +10h m_pCallSiteSP offsetOfCallSiteSP x86: call site, and zeroed in method +// +00h +00h _frameIdentifier 0 method prolog +// +08h +04h m_Next offsetOfFrameLink method prolog +// +10h +08h m_Datum offsetOfCallTarget call site +// +18h +0Ch m_pCallSiteSP offsetOfCallSiteSP x86: call site, and zeroed in method // prolog; // non-x86: method prolog (SP remains // constant in function, after prolog: no // localloc and PInvoke in same function) -// +28h +14h m_pCallerReturnAddress offsetOfReturnAddress call site -// +30h +18h m_pCalleeSavedFP offsetOfCalleeSavedFP not set by JIT -// +38h +1Ch m_pThread -// +20h m_pSPAfterProlog offsetOfSPAfterProlog arm only -// +40h +20/24h m_StubSecretArg offsetOfSecretStubArg method prolog of IL stubs with secret arg +// +20h +10h m_pCallerReturnAddress offsetOfReturnAddress call site +// +28h +14h m_pCalleeSavedFP offsetOfCalleeSavedFP not set by JIT +// +30h +18h m_pThread +// +1Ch m_pSPAfterProlog offsetOfSPAfterProlog arm only +// +38h +1C/20h m_StubSecretArg offsetOfSecretStubArg method prolog of IL stubs with secret arg // // Note that in the VM, InlinedCallFrame is a C++ class whose objects have a 'this' pointer that points // to the InlinedCallFrame vptr (the 2nd field listed above), and the GS cookie is stored *before* @@ -5946,7 +5945,7 @@ void Lowering::InsertPInvokeMethodProlog() // Call runtime helper to fill in our InlinedCallFrame and push it on the Frame list: // TCB = CORINFO_HELP_INIT_PINVOKE_FRAME(&symFrameStart); - GenTree* frameAddr = comp->gtNewLclAddrNode(comp->lvaInlinedPInvokeFrameVar, callFrameInfo.offsetOfFrameVptr); + GenTree* frameAddr = comp->gtNewLclVarAddrNode(comp->lvaInlinedPInvokeFrameVar); NewCallArg frameAddrArg = NewCallArg::Primitive(frameAddr).WellKnown(WellKnownArg::PInvokeFrame); GenTreeCall* call = comp->gtNewHelperCallNode(CORINFO_HELP_INIT_PINVOKE_FRAME, TYP_I_IMPL); diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs index 03dff074620ac2..08d7df78c946d8 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs @@ -836,8 +836,6 @@ public struct InlinedCallFrameInfo // Size of the Frame structure inside IL stubs that include secret stub arg in the frame public uint sizeWithSecretStubArg; - public uint offsetOfGSCookie; - public uint offsetOfFrameVptr; public uint offsetOfFrameLink; public uint offsetOfCallSiteSP; public uint offsetOfCalleeSavedFP; diff --git a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h index 771951a68baea8..18fd918a7a5cea 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h @@ -173,8 +173,6 @@ struct Agnostic_CORINFO_EE_INFO { DWORD size; DWORD sizeWithSecretStubArg; - DWORD offsetOfGSCookie; - DWORD offsetOfFrameVptr; DWORD offsetOfFrameLink; DWORD offsetOfCallSiteSP; DWORD offsetOfCalleeSavedFP; diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index cb831838f21756..351622b6a61cab 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -4365,8 +4365,6 @@ void MethodContext::recGetEEInfo(CORINFO_EE_INFO* pEEInfoOut) value.inlinedCallFrameInfo.size = (DWORD)pEEInfoOut->inlinedCallFrameInfo.size; value.inlinedCallFrameInfo.sizeWithSecretStubArg = (DWORD)pEEInfoOut->inlinedCallFrameInfo.sizeWithSecretStubArg; - value.inlinedCallFrameInfo.offsetOfGSCookie = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfGSCookie; - value.inlinedCallFrameInfo.offsetOfFrameVptr = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameVptr; value.inlinedCallFrameInfo.offsetOfFrameLink = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameLink; value.inlinedCallFrameInfo.offsetOfCallSiteSP = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfCallSiteSP; value.inlinedCallFrameInfo.offsetOfCalleeSavedFP = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfCalleeSavedFP; @@ -4390,11 +4388,10 @@ void MethodContext::recGetEEInfo(CORINFO_EE_INFO* pEEInfoOut) } void MethodContext::dmpGetEEInfo(DWORD key, const Agnostic_CORINFO_EE_INFO& value) { - printf("GetEEInfo key %u, value icfi{sz-%u sz-witharg-%u ogs-%u ofv-%u ofl-%u ocsp-%u ocsfp-%u oct-%u ora-%u ossa-%u osap-%u} " + printf("GetEEInfo key %u, value icfi{sz-%u sz-witharg-%u ofl-%u ocsp-%u ocsfp-%u oct-%u ora-%u ossa-%u osap-%u} " "otf-%u ogcs-%u odi-%u odft-%u osdic-%u srpf-%u osps-%u muono-%u tabi-%u osType-%u", key, value.inlinedCallFrameInfo.size, value.inlinedCallFrameInfo.sizeWithSecretStubArg, - value.inlinedCallFrameInfo.offsetOfGSCookie, - value.inlinedCallFrameInfo.offsetOfFrameVptr, value.inlinedCallFrameInfo.offsetOfFrameLink, + value.inlinedCallFrameInfo.offsetOfFrameLink, value.inlinedCallFrameInfo.offsetOfCallSiteSP, value.inlinedCallFrameInfo.offsetOfCalleeSavedFP, value.inlinedCallFrameInfo.offsetOfCallTarget, value.inlinedCallFrameInfo.offsetOfReturnAddress, value.inlinedCallFrameInfo.offsetOfSecretStubArg, value.inlinedCallFrameInfo.offsetOfSPAfterProlog, @@ -4411,8 +4408,6 @@ void MethodContext::repGetEEInfo(CORINFO_EE_INFO* pEEInfoOut) pEEInfoOut->inlinedCallFrameInfo.size = (unsigned)value.inlinedCallFrameInfo.size; pEEInfoOut->inlinedCallFrameInfo.sizeWithSecretStubArg = (unsigned)value.inlinedCallFrameInfo.sizeWithSecretStubArg; - pEEInfoOut->inlinedCallFrameInfo.offsetOfGSCookie = (unsigned)value.inlinedCallFrameInfo.offsetOfGSCookie; - pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameVptr = (unsigned)value.inlinedCallFrameInfo.offsetOfFrameVptr; pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameLink = (unsigned)value.inlinedCallFrameInfo.offsetOfFrameLink; pEEInfoOut->inlinedCallFrameInfo.offsetOfCallSiteSP = (unsigned)value.inlinedCallFrameInfo.offsetOfCallSiteSP; pEEInfoOut->inlinedCallFrameInfo.offsetOfCalleeSavedFP = diff --git a/src/coreclr/vm/FrameTypes.h b/src/coreclr/vm/FrameTypes.h new file mode 100644 index 00000000000000..59e1c56356e80e --- /dev/null +++ b/src/coreclr/vm/FrameTypes.h @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef FRAME_TYPE_NAME +#define FRAME_TYPE_NAME(frameType) +#endif + +FRAME_TYPE_NAME(InlinedCallFrame) +#if defined(TARGET_X86) && !defined(UNIX_X86_ABI) +FRAME_TYPE_NAME(TailCallFrame) +#endif +#ifdef FEATURE_HIJACK +FRAME_TYPE_NAME(ResumableFrame) +FRAME_TYPE_NAME(RedirectedThreadFrame) +#endif // FEATURE_HIJACK +FRAME_TYPE_NAME(FaultingExceptionFrame) +#ifdef FEATURE_EH_FUNCLETS +FRAME_TYPE_NAME(SoftwareExceptionFrame) +#endif // FEATURE_EH_FUNCLETS +#ifdef DEBUGGING_SUPPORTED +FRAME_TYPE_NAME(FuncEvalFrame) +#endif // DEBUGGING_SUPPORTED +FRAME_TYPE_NAME(HelperMethodFrame) +FRAME_TYPE_NAME(HelperMethodFrame_1OBJ) +FRAME_TYPE_NAME(HelperMethodFrame_2OBJ) +FRAME_TYPE_NAME(HelperMethodFrame_3OBJ) +FRAME_TYPE_NAME(HelperMethodFrame_PROTECTOBJ) +#ifdef FEATURE_COMINTEROP +FRAME_TYPE_NAME(ComMethodFrame) +FRAME_TYPE_NAME(CLRToCOMMethodFrame) +FRAME_TYPE_NAME(ComPrestubMethodFrame) +#endif // FEATURE_COMINTEROP +FRAME_TYPE_NAME(PInvokeCalliFrame) +#ifdef FEATURE_HIJACK +FRAME_TYPE_NAME(HijackFrame) +#endif // FEATURE_HIJACK +FRAME_TYPE_NAME(PrestubMethodFrame) +FRAME_TYPE_NAME(CallCountingHelperFrame) +FRAME_TYPE_NAME(StubDispatchFrame) +FRAME_TYPE_NAME(ExternalMethodFrame) +#ifdef FEATURE_READYTORUN +FRAME_TYPE_NAME(DynamicHelperFrame) +#endif +FRAME_TYPE_NAME(ProtectByRefsFrame) +FRAME_TYPE_NAME(ProtectValueClassFrame) +FRAME_TYPE_NAME(DebuggerClassInitMarkFrame) +FRAME_TYPE_NAME(DebuggerExitFrame) +FRAME_TYPE_NAME(DebuggerU2MCatchHandlerFrame) +FRAME_TYPE_NAME(ExceptionFilterFrame) +#if defined(_DEBUG) +FRAME_TYPE_NAME(AssumeByrefFromJITStackFrame) +#endif // _DEBUG + +#undef FRAME_TYPE_NAME diff --git a/src/coreclr/vm/amd64/ComCallPreStub.asm b/src/coreclr/vm/amd64/ComCallPreStub.asm index 8057d86a078071..237fcd954f10f0 100644 --- a/src/coreclr/vm/amd64/ComCallPreStub.asm +++ b/src/coreclr/vm/amd64/ComCallPreStub.asm @@ -9,7 +9,6 @@ include asmconstants.inc ; extern "C" const BYTE* ComPreStubWorker(ComPrestubMethodFrame *pPFrame, UINT64 *pErrorResult) extern ComPreStubWorker:proc extern JIT_FailFast:proc -extern s_gsCookie:qword ; extern "C" VOID ComCallPreStub() @@ -27,9 +26,8 @@ NESTED_ENTRY ComCallPreStub, _TEXT ; ComPrestubMethodFrame::m_ReturnAddress ; ComPrestubMethodFrame::m_pFuncDesc ; Frame::m_Next -; __VFN_table <-- rsp + ComCallPreStub_ComPrestubMethodFrame_OFFSET -; gsCookie -; HRESULT <-- rsp + ComCallPreStub_HRESULT_OFFSET +; FrameIdentifier::ComPrestubMethodFrame <-- rsp + ComCallPreStub_ComPrestubMethodFrame_OFFSET +; HRESULT <-- rsp + ComCallPreStub_ERRORRETVAL_OFFSET ; (optional padding to qword align xmm save area) ; xmm3 ; xmm2 @@ -52,9 +50,6 @@ ComCallPreStub_ComPrestubMethodFrame_NEGOFFSET = ComCallPreStub_STACK_FRAME_SIZE ComCallPreStub_STACK_FRAME_SIZE = ComCallPreStub_STACK_FRAME_SIZE + 8*8 ComCallPreStub_CalleeSavedRegisters_NEGOFFSET = ComCallPreStub_STACK_FRAME_SIZE -; GSCookie MUST be immediately below CalleeSavedRegisters -ComCallPreStub_STACK_FRAME_SIZE = ComCallPreStub_STACK_FRAME_SIZE + SIZEOF_GSCookie - ; UINT64 (out param to ComPreStubWorker) ComCallPreStub_STACK_FRAME_SIZE = ComCallPreStub_STACK_FRAME_SIZE + 8 ComCallPreStub_ERRORRETVAL_NEGOFFSET = ComCallPreStub_STACK_FRAME_SIZE @@ -74,7 +69,6 @@ ComCallPreStub_STACK_FRAME_SIZE = ComCallPreStub_STACK_FRAME_SIZE + 20h ; Now we have the full size of the stack frame. The offsets have been computed relative to the ; top, so negate them to make them relative to the post-prologue rsp. ComCallPreStub_ComPrestubMethodFrame_OFFSET = ComCallPreStub_STACK_FRAME_SIZE - ComCallPreStub_ComPrestubMethodFrame_NEGOFFSET -OFFSETOF_GSCookie = ComCallPreStub_ComPrestubMethodFrame_OFFSET - SIZEOF_GSCookie ComCallPreStub_ERRORRETVAL_OFFSET = ComCallPreStub_STACK_FRAME_SIZE - ComCallPreStub_ERRORRETVAL_NEGOFFSET ComCallPreStub_XMM_SAVE_OFFSET = ComCallPreStub_STACK_FRAME_SIZE - ComCallPreStub_XMM_SAVE_NEGOFFSET @@ -104,8 +98,6 @@ ComCallPreStub_XMM_SAVE_OFFSET = ComCallPreStub_STACK_FRAME_SIZE - END_PROLOGUE - mov rcx, s_gsCookie - mov [rsp + OFFSETOF_GSCookie], rcx ; ; Resolve target. ; @@ -115,14 +107,6 @@ ComCallPreStub_XMM_SAVE_OFFSET = ComCallPreStub_STACK_FRAME_SIZE - test rax, rax jz ExitError -ifdef _DEBUG - mov rcx, s_gsCookie - cmp [rsp + OFFSETOF_GSCookie], rcx - je GoodGSCookie - call JIT_FailFast -GoodGSCookie: -endif ; _DEBUG - ; ; Restore FP parameters ; diff --git a/src/coreclr/vm/amd64/GenericComCallStubs.asm b/src/coreclr/vm/amd64/GenericComCallStubs.asm index f4e6eccc666ffa..355c6baae2dd4c 100644 --- a/src/coreclr/vm/amd64/GenericComCallStubs.asm +++ b/src/coreclr/vm/amd64/GenericComCallStubs.asm @@ -10,7 +10,6 @@ extern CallDescrWorkerUnwindFrameChainHandler:proc extern ReverseComUnwindFrameChainHandler:proc extern COMToCLRWorker:proc extern JIT_FailFast:proc -extern s_gsCookie:qword NESTED_ENTRY GenericComCallStub, _TEXT, ReverseComUnwindFrameChainHandler @@ -30,7 +29,6 @@ NESTED_ENTRY GenericComCallStub, _TEXT, ReverseComUnwindFrameChainHandler ; UnmanagedToManagedFrame::m_Datum ; Frame::m_Next ; __VFN_table <-- rsp + GenericComCallStub_ComMethodFrame_OFFSET -; GSCookie ; (optional padding to qword align xmm save area) ; xmm3 ; xmm2 @@ -54,8 +52,6 @@ GenericComCallStub_STACK_FRAME_SIZE = 0 GenericComCallStub_STACK_FRAME_SIZE = GenericComCallStub_STACK_FRAME_SIZE + (SIZEOF__ComMethodFrame - 8) GenericComCallStub_ComMethodFrame_NEGOFFSET = GenericComCallStub_STACK_FRAME_SIZE -GenericComCallStub_STACK_FRAME_SIZE = GenericComCallStub_STACK_FRAME_SIZE + SIZEOF_GSCookie - ; Ensure that the offset of the XMM save area will be 16-byte aligned. if ((GenericComCallStub_STACK_FRAME_SIZE + 8) MOD 16) ne 0 GenericComCallStub_STACK_FRAME_SIZE = GenericComCallStub_STACK_FRAME_SIZE + 8 @@ -74,7 +70,6 @@ GenericComCallStub_STACK_FRAME_SIZE = GenericComCallStub_STACK_FRAME_SIZE + Gene ; top, so negate them to make them relative to the post-prologue rsp. GenericComCallStub_ComMethodFrame_OFFSET = GenericComCallStub_STACK_FRAME_SIZE - GenericComCallStub_ComMethodFrame_NEGOFFSET GenericComCallStub_XMM_SAVE_OFFSET = GenericComCallStub_STACK_FRAME_SIZE - GenericComCallStub_XMM_SAVE_NEGOFFSET -OFFSETOF_GSCookie = GenericComCallStub_ComMethodFrame_OFFSET - SIZEOF_GSCookie .allocstack 8 ; UnmanagedToManagedFrame::m_Datum, pushed by prepad @@ -103,9 +98,6 @@ OFFSETOF_GSCookie = GenericComCallStub_ComMethodFrame_OFFSET - SIZEOF_GSCookie END_PROLOGUE - mov rcx, s_gsCookie - mov [rsp + OFFSETOF_GSCookie], rcx - ; ; Call COMToCLRWorker. ; @@ -113,14 +105,6 @@ OFFSETOF_GSCookie = GenericComCallStub_ComMethodFrame_OFFSET - SIZEOF_GSCookie mov rcx, r10 call COMToCLRWorker -ifdef _DEBUG - mov rcx, s_gsCookie - cmp [rsp + OFFSETOF_GSCookie], rcx - je GoodGSCookie - call JIT_FailFast -GoodGSCookie: -endif ; _DEBUG - ; ; epilogue ; diff --git a/src/coreclr/vm/amd64/PInvokeStubs.asm b/src/coreclr/vm/amd64/PInvokeStubs.asm index 4f19cb7d032a21..a18ed56b752d3c 100644 --- a/src/coreclr/vm/amd64/PInvokeStubs.asm +++ b/src/coreclr/vm/amd64/PInvokeStubs.asm @@ -8,8 +8,6 @@ extern GenericPInvokeCalliStubWorker:proc extern VarargPInvokeStubWorker:proc extern JIT_PInvokeEndRarePath:proc -extern s_gsCookie:QWORD -extern ??_7InlinedCallFrame@@6B@:QWORD extern g_TrapReturningThreads:DWORD ; @@ -135,19 +133,13 @@ NESTED_END VarargPInvokeGenILStub, _TEXT ; ; in: -; InlinedCallFrame (rcx) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right -; before actual InlinedCallFrame data) +; InlinedCallFrame (rcx) = pointer to the InlinedCallFrame data ; ; LEAF_ENTRY JIT_PInvokeBegin, _TEXT - mov rax, qword ptr [s_gsCookie] - mov qword ptr [rcx], rax - add rcx, SIZEOF_GSCookie - ;; set first slot to the value of InlinedCallFrame::`vftable' (checked by runtime code) - lea rax,[??_7InlinedCallFrame@@6B@] - mov qword ptr [rcx], rax + mov qword ptr [rcx], FRAMETYPE_InlinedCallFrame mov qword ptr [rcx + OFFSETOF__InlinedCallFrame__m_Datum], 0 @@ -176,14 +168,11 @@ LEAF_END JIT_PInvokeBegin, _TEXT ; ; in: -; InlinedCallFrame (rcx) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right -; before actual InlinedCallFrame data) +; InlinedCallFrame (rcx) = pointer to the InlinedCallFrame data ; ; LEAF_ENTRY JIT_PInvokeEnd, _TEXT - add rcx, SIZEOF_GSCookie - INLINE_GETTHREAD rdx ;; rcx = pFrame diff --git a/src/coreclr/vm/amd64/RedirectedHandledJITCase.asm b/src/coreclr/vm/amd64/RedirectedHandledJITCase.asm index 47b1ecfd50fb33..15a33bdce0bc18 100644 --- a/src/coreclr/vm/amd64/RedirectedHandledJITCase.asm +++ b/src/coreclr/vm/amd64/RedirectedHandledJITCase.asm @@ -97,8 +97,8 @@ endif endif -; scratch area; padding; GSCookie -OFFSET_OF_FRAME = SIZEOF_MAX_OUTGOING_ARGUMENT_HOMES + 8 + SIZEOF_GSCookie +; scratch area +OFFSET_OF_FRAME = SIZEOF_MAX_OUTGOING_ARGUMENT_HOMES ; force evaluation to avoid "expression is too complex errors" SIZEOF__FaultingExceptionFrame = SIZEOF__FaultingExceptionFrame diff --git a/src/coreclr/vm/amd64/asmconstants.h b/src/coreclr/vm/amd64/asmconstants.h index 4b38aeeaca52d7..bd86950467f495 100644 --- a/src/coreclr/vm/amd64/asmconstants.h +++ b/src/coreclr/vm/amd64/asmconstants.h @@ -78,8 +78,8 @@ ASMCONSTANTS_C_ASSERT(SIZEOF_CalleeSavedRegisters == sizeof(CalleeSavedRegisters ASMCONSTANTS_C_ASSERT(SIZEOF_CalleeSavedRegisters == sizeof(CalleeSavedRegisters)); #endif -#define SIZEOF_GSCookie 0x8 -ASMCONSTANTS_C_ASSERT(SIZEOF_GSCookie == sizeof(GSCookie)); +#define FRAMETYPE_InlinedCallFrame 0x1 +ASMCONSTANTS_C_ASSERT(FRAMETYPE_InlinedCallFrame == (int)FrameIdentifier::InlinedCallFrame) #define OFFSETOF__Frame____VFN_table 0 @@ -433,7 +433,7 @@ ASMCONSTANTS_C_ASSERT(OFFSET__TEB__ThreadLocalStoragePointer == offsetof(TEB, Th #define REDIRECTSTUB_ESTABLISHER_OFFSET_RBP 0 #define REDIRECTSTUB_RBP_OFFSET_CONTEXT 0x20 -#define THROWSTUB_ESTABLISHER_OFFSET_FaultingExceptionFrame 0x30 +#define THROWSTUB_ESTABLISHER_OFFSET_FaultingExceptionFrame 0x20 #ifdef FEATURE_SPECIAL_USER_MODE_APC #define OFFSETOF__APC_CALLBACK_DATA__ContextRecord 0x8 diff --git a/src/coreclr/vm/amd64/cgenamd64.cpp b/src/coreclr/vm/amd64/cgenamd64.cpp index 7548cd8a1742b5..ec952dd0f6f873 100644 --- a/src/coreclr/vm/amd64/cgenamd64.cpp +++ b/src/coreclr/vm/amd64/cgenamd64.cpp @@ -58,7 +58,7 @@ void ClearRegDisplayArgumentAndScratchRegisters(REGDISPLAY * pRD) pContextPointers->R11 = NULL; } -void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void TransitionFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { LIMITED_METHOD_CONTRACT; @@ -81,10 +81,10 @@ void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) SyncRegDisplayToCurrentContext(pRD); - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK TransitionFrame::UpdateRegDisplay(rip:%p, rsp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK TransitionFrame::UpdateRegDisplay_Impl(rip:%p, rsp:%p)\n", pRD->ControlPC, pRD->SP)); } -void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void InlinedCallFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACTL { @@ -135,10 +135,10 @@ void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats SyncRegDisplayToCurrentContext(pRD); - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK InlinedCallFrame::UpdateRegDisplay(rip:%p, rsp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK InlinedCallFrame::UpdateRegDisplay_Impl(rip:%p, rsp:%p)\n", pRD->ControlPC, pRD->SP)); } -void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void HelperMethodFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACTL { @@ -225,7 +225,7 @@ void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloat ClearRegDisplayArgumentAndScratchRegisters(pRD); } -void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void FaultingExceptionFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { LIMITED_METHOD_DAC_CONTRACT; @@ -264,13 +264,13 @@ void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool update } #ifdef FEATURE_HIJACK -TADDR ResumableFrame::GetReturnAddressPtr() +TADDR ResumableFrame::GetReturnAddressPtr_Impl() { LIMITED_METHOD_DAC_CONTRACT; return dac_cast(m_Regs) + offsetof(CONTEXT, Rip); } -void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void ResumableFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACT_VOID { @@ -310,7 +310,7 @@ void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) } // The HijackFrame has to know the registers that are pushed by OnHijackTripThread -void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void HijackFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACTL { NOTHROW; diff --git a/src/coreclr/vm/amd64/pinvokestubs.S b/src/coreclr/vm/amd64/pinvokestubs.S index 6c57f8713831b6..3d33a63d8a0862 100644 --- a/src/coreclr/vm/amd64/pinvokestubs.S +++ b/src/coreclr/vm/amd64/pinvokestubs.S @@ -129,8 +129,7 @@ NESTED_END VarargPInvokeGenILStub, _TEXT // // IN: -// InlinedCallFrame (rdi) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right -// before actual InlinedCallFrame data) +// InlinedCallFrame (rdi) = pointer to the InlinedCallFrame data // // NESTED_ENTRY JIT_PInvokeBegin, _TEXT, NoHandler @@ -138,15 +137,8 @@ NESTED_ENTRY JIT_PInvokeBegin, _TEXT, NoHandler push_nonvol_reg r14 END_PROLOGUE - PREPARE_EXTERNAL_VAR s_gsCookie, rax - mov rax, qword ptr [rax] - mov qword ptr [rdi], rax - add rdi, SIZEOF_GSCookie - - // set first slot to the value of InlinedCallFrame vftable (checked by runtime code) - PREPARE_EXTERNAL_VAR _ZTV16InlinedCallFrame, rax - add rax, 0x10 - mov qword ptr [rdi], rax + // set first slot to the value of InlinedCallFrame identifier (checked by runtime code) + mov qword ptr [rdi], FRAMETYPE_InlinedCallFrame mov qword ptr [rdi + OFFSETOF__InlinedCallFrame__m_Datum], 0 @@ -181,13 +173,11 @@ NESTED_END JIT_PInvokeBegin, _TEXT // // IN: -// InlinedCallFrame (rdi) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right -// before actual InlinedCallFrame data) +// InlinedCallFrame (rdi) = pointer to the InlinedCallFrame data // // LEAF_ENTRY JIT_PInvokeEnd, _TEXT - add rdi, SIZEOF_GSCookie mov rsi, qword ptr [rdi + OFFSETOF__InlinedCallFrame__m_pThread] // rdi = pFrame diff --git a/src/coreclr/vm/amd64/redirectedhandledjitcase.S b/src/coreclr/vm/amd64/redirectedhandledjitcase.S index 23de3d6fee93ca..c326de58571240 100644 --- a/src/coreclr/vm/amd64/redirectedhandledjitcase.S +++ b/src/coreclr/vm/amd64/redirectedhandledjitcase.S @@ -5,9 +5,7 @@ #include "unixasmmacros.inc" #include "asmconstants.h" -#define FaultingExceptionFrame_StackAlloc (SIZEOF__GSCookie + SIZEOF__FaultingExceptionFrame) -#define FaultingExceptionFrame_FrameOffset SIZEOF__GSCookie -#define OFFSET_OF_FRAME (8 + SIZEOF_GSCookie) +#define OFFSET_OF_FRAME 0 .macro GenerateRedirectedStubWithFrame stub, target diff --git a/src/coreclr/vm/arm/asmconstants.h b/src/coreclr/vm/arm/asmconstants.h index dbd83bd6a947a2..4495b42dca78ca 100644 --- a/src/coreclr/vm/arm/asmconstants.h +++ b/src/coreclr/vm/arm/asmconstants.h @@ -29,6 +29,9 @@ #define DBG_FRE(dbg,fre) fre #endif +#define FRAMETYPE_InlinedCallFrame 1 +ASMCONSTANTS_C_ASSERT(FRAMETYPE_InlinedCallFrame == (int)FrameIdentifier::InlinedCallFrame) + #define DynamicHelperFrameFlags_Default 0 #define DynamicHelperFrameFlags_ObjectArg 1 #define DynamicHelperFrameFlags_ObjectArg2 2 @@ -79,9 +82,6 @@ ASMCONSTANTS_C_ASSERT(PtrArray__m_Array == offsetof(PtrArray, m_Array)); #define TypeHandle_CanCast 0x1 // TypeHandle::CanCast -#define SIZEOF__GSCookie 0x4 -ASMCONSTANTS_C_ASSERT(SIZEOF__GSCookie == sizeof(GSCookie)); - #define SIZEOF__Frame 0x8 ASMCONSTANTS_C_ASSERT(SIZEOF__Frame == sizeof(Frame)); diff --git a/src/coreclr/vm/arm/ehhelpers.S b/src/coreclr/vm/arm/ehhelpers.S index 6f44931ebe2be8..eeb6e3894a575e 100644 --- a/src/coreclr/vm/arm/ehhelpers.S +++ b/src/coreclr/vm/arm/ehhelpers.S @@ -17,8 +17,8 @@ // WARNING!! to occur when the stack is unwalkable // - // GSCookie + alignment padding -OFFSET_OF_FRAME=(4 + SIZEOF__GSCookie) + // alignment padding +OFFSET_OF_FRAME=0 .macro GenerateRedirectedStubWithFrame STUB, TARGET diff --git a/src/coreclr/vm/arm/pinvokestubs.S b/src/coreclr/vm/arm/pinvokestubs.S index 5875a58749492a..cc84c541a183bb 100644 --- a/src/coreclr/vm/arm/pinvokestubs.S +++ b/src/coreclr/vm/arm/pinvokestubs.S @@ -79,27 +79,12 @@ PROLOG_PUSH "{r4, lr}" -#if defined(__clang__) - ldr r1, =s_gsCookie-(1f+4) -1: - add r1, pc -#else - ldr r1, =s_gsCookie -#endif - ldr r1, [r1] - str r1, [r0] - add r4, r0, SIZEOF__GSCookie + mov r4, r0 // r4 = pFrame - // set first slot to the value of InlinedCallFrame::`vftable' (checked by runtime code) -#if defined(__clang__) - ldr r1, =_ZTV16InlinedCallFrame+8-(2f+4) -2: - add r1, pc -#else - ldr r1, =_ZTV16InlinedCallFrame+8 -#endif + // set first slot to the value of InlinedCallFrame identifier (checked by runtime code) + mov r1, #FRAMETYPE_InlinedCallFrame str r1, [r4] mov r1, 0 @@ -138,7 +123,6 @@ // LEAF_ENTRY JIT_PInvokeEnd, _TEXT - add r0, r0, SIZEOF__GSCookie ldr r1, [r0, #InlinedCallFrame__m_pThread] // r0 = pFrame diff --git a/src/coreclr/vm/arm/stubs.cpp b/src/coreclr/vm/arm/stubs.cpp index 57594beb859d82..08448a0ab0d555 100644 --- a/src/coreclr/vm/arm/stubs.cpp +++ b/src/coreclr/vm/arm/stubs.cpp @@ -615,7 +615,7 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, unwoundstate->_isValid = true; } -void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void HelperMethodFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACTL { @@ -1119,9 +1119,6 @@ Stub *GenerateInitPInvokeFrameHelper() CORINFO_EE_INFO::InlinedCallFrameInfo FrameInfo; InlinedCallFrame::GetEEInfo(&FrameInfo); - // R4 contains address of the frame on stack (the frame ptr, not its neg space) - unsigned negSpace = FrameInfo.offsetOfFrameVptr; - ThumbReg regFrame = ThumbReg(4); ThumbReg regThread = ThumbReg(5); ThumbReg regScratch = ThumbReg(6); @@ -1139,32 +1136,28 @@ Stub *GenerateInitPInvokeFrameHelper() for (int reg = 0; reg < 4; reg++) psl->ThumbEmitLoadRegIndirect(ThumbReg(reg), thumbRegSp, offsetof(ArgumentRegisters, r) + sizeof(*ArgumentRegisters::r) * reg); - // mov [regFrame + FrameInfo.offsetOfGSCookie], GetProcessGSCookie() - psl->ThumbEmitMovConstant(regScratch, GetProcessGSCookie()); - psl->ThumbEmitStoreRegIndirect(regScratch, regFrame, FrameInfo.offsetOfGSCookie - negSpace); - - // mov [regFrame + FrameInfo.offsetOfFrameVptr], InlinedCallFrame::GetMethodFrameVPtr() - psl->ThumbEmitMovConstant(regScratch, InlinedCallFrame::GetMethodFrameVPtr()); - psl->ThumbEmitStoreRegIndirect(regScratch, regFrame, FrameInfo.offsetOfFrameVptr - negSpace); + // mov [regFrame], FrameIdentifier::InlinedCallFrame + psl->ThumbEmitMovConstant(regScratch, (DWORD)FrameIdentifier::InlinedCallFrame); + psl->ThumbEmitStoreRegIndirect(regScratch, regFrame, 0); // ldr regScratch, [regThread + offsetof(Thread, m_pFrame)] // str regScratch, [regFrame + FrameInfo.offsetOfFrameLink] psl->ThumbEmitLoadRegIndirect(regScratch, regThread, offsetof(Thread, m_pFrame)); - psl->ThumbEmitStoreRegIndirect(regScratch, regFrame, FrameInfo.offsetOfFrameLink - negSpace); + psl->ThumbEmitStoreRegIndirect(regScratch, regFrame, FrameInfo.offsetOfFrameLink); // str FP, [regFrame + FrameInfo.offsetOfCalleeSavedFP] - psl->ThumbEmitStoreRegIndirect(thumbRegFp, regFrame, FrameInfo.offsetOfCalleeSavedFP - negSpace); + psl->ThumbEmitStoreRegIndirect(thumbRegFp, regFrame, FrameInfo.offsetOfCalleeSavedFP); // str R9, [regFrame + FrameInfo.offsetOfSPAfterProlog] - psl->ThumbEmitStoreRegIndirect(regR9, regFrame, FrameInfo.offsetOfSPAfterProlog - negSpace); + psl->ThumbEmitStoreRegIndirect(regR9, regFrame, FrameInfo.offsetOfSPAfterProlog); // mov [regFrame + FrameInfo.offsetOfReturnAddress], 0 psl->ThumbEmitMovConstant(regScratch, 0); - psl->ThumbEmitStoreRegIndirect(regScratch, regFrame, FrameInfo.offsetOfReturnAddress - negSpace); + psl->ThumbEmitStoreRegIndirect(regScratch, regFrame, FrameInfo.offsetOfReturnAddress); DWORD cbSavedRegs = sizeof(ArgumentRegisters) + 2 * 4; // r0-r3, r4, lr psl->ThumbEmitAdd(regScratch, thumbRegSp, cbSavedRegs); - psl->ThumbEmitStoreRegIndirect(regScratch, regFrame, FrameInfo.offsetOfCallSiteSP - negSpace); + psl->ThumbEmitStoreRegIndirect(regScratch, regFrame, FrameInfo.offsetOfCallSiteSP); // mov [regThread + offsetof(Thread, m_pFrame)], regFrame psl->ThumbEmitStoreRegIndirect(regFrame, regThread, offsetof(Thread, m_pFrame)); @@ -1497,7 +1490,7 @@ void UpdateRegDisplayFromCalleeSavedRegisters(REGDISPLAY * pRD, CalleeSavedRegis pRD->pCurrentContextPointers->Lr = NULL; } -void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void TransitionFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { #ifndef DACCESS_COMPILE if (updateFloats) @@ -1531,10 +1524,10 @@ void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) // Finally, syncup the regdisplay with the context SyncRegDisplayToCurrentContext(pRD); - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK TransitionFrame::UpdateRegDisplay(rip:%p, rsp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK TransitionFrame::UpdateRegDisplay_Impl(rip:%p, rsp:%p)\n", pRD->ControlPC, pRD->SP)); } -void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void FaultingExceptionFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { LIMITED_METHOD_DAC_CONTRACT; @@ -1560,7 +1553,7 @@ void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool update pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. } -void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void InlinedCallFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACT_VOID { @@ -1618,13 +1611,13 @@ void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats } #ifdef FEATURE_HIJACK -TADDR ResumableFrame::GetReturnAddressPtr(void) +TADDR ResumableFrame::GetReturnAddressPtr_Impl(void) { LIMITED_METHOD_DAC_CONTRACT; return dac_cast(m_Regs) + offsetof(T_CONTEXT, Pc); } -void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void ResumableFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACT_VOID { @@ -1660,7 +1653,7 @@ void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. } -void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void HijackFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACTL { NOTHROW; diff --git a/src/coreclr/vm/arm64/PInvokeStubs.asm b/src/coreclr/vm/arm64/PInvokeStubs.asm index 37699e790b241e..05e21ae22d16e4 100644 --- a/src/coreclr/vm/arm64/PInvokeStubs.asm +++ b/src/coreclr/vm/arm64/PInvokeStubs.asm @@ -12,13 +12,8 @@ IMPORT GenericPInvokeCalliStubWorker IMPORT JIT_PInvokeEndRarePath - IMPORT s_gsCookie IMPORT g_TrapReturningThreads - SETALIAS InlinedCallFrame_vftable, ??_7InlinedCallFrame@@6B@ - IMPORT $InlinedCallFrame_vftable - - ; ------------------------------------------------------------------ ; Macro to generate PInvoke Stubs. ; $__PInvokeStubFuncName : function which calls the actual stub obtained from VASigCookie @@ -119,34 +114,29 @@ __PInvokeStubWorkerName SETS "$FuncPrefix":CC:"StubWorker" ; LEAF_ENTRY JIT_PInvokeBegin - ldr x9, =s_gsCookie - ldr x9, [x9] + ;; set first slot to the value of InlinedCallFrame identifier (checked by runtime code) + mov x9, #FRAMETYPE_InlinedCallFrame str x9, [x0] - add x10, x0, SIZEOF__GSCookie - ;; set first slot to the value of InlinedCallFrame::`vftable' (checked by runtime code) - ldr x9, =$InlinedCallFrame_vftable - str x9, [x10] - - str xzr, [x10, #InlinedCallFrame__m_Datum] + str xzr, [x0, #InlinedCallFrame__m_Datum] mov x9, sp - str x9, [x10, #InlinedCallFrame__m_pCallSiteSP] - str fp, [x10, #InlinedCallFrame__m_pCalleeSavedFP] - str lr, [x10, #InlinedCallFrame__m_pCallerReturnAddress] + str x9, [x0, #InlinedCallFrame__m_pCallSiteSP] + str fp, [x0, #InlinedCallFrame__m_pCalleeSavedFP] + str lr, [x0, #InlinedCallFrame__m_pCallerReturnAddress] ;; x0 = GetThread(), TRASHES x9 - INLINE_GETTHREAD x0, x9 + INLINE_GETTHREAD x10, x9 ;; pFrame->m_Next = pThread->m_pFrame; - ldr x9, [x0, #Thread_m_pFrame] - str x9, [x10, #Frame__m_Next] + ldr x9, [x10, #Thread_m_pFrame] + str x9, [x0, #Frame__m_Next] ;; pThread->m_pFrame = pFrame; - str x10, [x0, #Thread_m_pFrame] + str x0, [x10, #Thread_m_pFrame] ;; pThread->m_fPreemptiveGCDisabled = 0 - str wzr, [x0, #Thread_m_fPreemptiveGCDisabled] + str wzr, [x10, #Thread_m_fPreemptiveGCDisabled] ret @@ -160,8 +150,6 @@ __PInvokeStubWorkerName SETS "$FuncPrefix":CC:"StubWorker" ; LEAF_ENTRY JIT_PInvokeEnd - add x0, x0, SIZEOF__GSCookie - ;; x1 = GetThread(), TRASHES x2 INLINE_GETTHREAD x1, x2 diff --git a/src/coreclr/vm/arm64/asmconstants.h b/src/coreclr/vm/arm64/asmconstants.h index 9c263b945a84f9..87003693b87164 100644 --- a/src/coreclr/vm/arm64/asmconstants.h +++ b/src/coreclr/vm/arm64/asmconstants.h @@ -29,6 +29,9 @@ #define DBG_FRE(dbg,fre) fre #endif +#define FRAMETYPE_InlinedCallFrame 1 +ASMCONSTANTS_C_ASSERT(FRAMETYPE_InlinedCallFrame == (int)FrameIdentifier::InlinedCallFrame) + #define DynamicHelperFrameFlags_Default 0 #define DynamicHelperFrameFlags_ObjectArg 1 #define DynamicHelperFrameFlags_ObjectArg2 2 @@ -100,9 +103,6 @@ ASMCONSTANTS_C_ASSERT(LazyMachState_captureIp == offsetof(LazyMachState, capture #define VASigCookie__pNDirectILStub 0x8 ASMCONSTANTS_C_ASSERT(VASigCookie__pNDirectILStub == offsetof(VASigCookie, pNDirectILStub)) -#define SIZEOF__GSCookie 0x8 -ASMCONSTANTS_C_ASSERT(SIZEOF__GSCookie == sizeof(GSCookie)); - #define SIZEOF__Frame 0x10 ASMCONSTANTS_C_ASSERT(SIZEOF__Frame == sizeof(Frame)); diff --git a/src/coreclr/vm/arm64/asmhelpers.S b/src/coreclr/vm/arm64/asmhelpers.S index 25bf36d00ce64d..682f5efdca0144 100644 --- a/src/coreclr/vm/arm64/asmhelpers.S +++ b/src/coreclr/vm/arm64/asmhelpers.S @@ -426,8 +426,8 @@ NESTED_ENTRY CallEHFilterFunclet, _TEXT, NoHandler NESTED_END CallEHFilterFunclet, _TEXT -#define FaultingExceptionFrame_StackAlloc (SIZEOF__GSCookie + SIZEOF__FaultingExceptionFrame) -#define FaultingExceptionFrame_FrameOffset SIZEOF__GSCookie +#define FaultingExceptionFrame_StackAlloc (SIZEOF__FaultingExceptionFrame) +#define FaultingExceptionFrame_FrameOffset 0 .macro GenerateRedirectedStubWithFrame stub, target diff --git a/src/coreclr/vm/arm64/asmhelpers.asm b/src/coreclr/vm/arm64/asmhelpers.asm index 04d69679ec4506..081ee30a97c431 100644 --- a/src/coreclr/vm/arm64/asmhelpers.asm +++ b/src/coreclr/vm/arm64/asmhelpers.asm @@ -435,7 +435,7 @@ NoFloatingPointRetVal GBLA ComCallPreStub_ErrorReturnOffset GBLA ComCallPreStub_FirstStackAdjust -ComCallPreStub_FrameSize SETA (SIZEOF__GSCookie + SIZEOF__ComMethodFrame) +ComCallPreStub_FrameSize SETA (SIZEOF__ComMethodFrame) ComCallPreStub_FirstStackAdjust SETA (8 + SIZEOF__ArgumentRegisters + 2 * 8) ; x8, reg args , fp & lr already pushed ComCallPreStub_StackAlloc SETA ComCallPreStub_FrameSize - ComCallPreStub_FirstStackAdjust ComCallPreStub_StackAlloc SETA ComCallPreStub_StackAlloc + SIZEOF__FloatArgumentRegisters + 8; 8 for ErrorReturn @@ -505,7 +505,7 @@ ComCallPreStub_ErrorExit GBLA GenericComCallStub_FrameOffset GBLA GenericComCallStub_FirstStackAdjust -GenericComCallStub_FrameSize SETA (SIZEOF__GSCookie + SIZEOF__ComMethodFrame) +GenericComCallStub_FrameSize SETA (SIZEOF__ComMethodFrame) GenericComCallStub_FirstStackAdjust SETA (8 + SIZEOF__ArgumentRegisters + 2 * 8) GenericComCallStub_StackAlloc SETA GenericComCallStub_FrameSize - GenericComCallStub_FirstStackAdjust GenericComCallStub_StackAlloc SETA GenericComCallStub_StackAlloc + SIZEOF__FloatArgumentRegisters @@ -765,8 +765,8 @@ COMToCLRDispatchHelper_RegSetup GBLA FaultingExceptionFrame_StackAlloc GBLA FaultingExceptionFrame_FrameOffset -FaultingExceptionFrame_StackAlloc SETA (SIZEOF__GSCookie + SIZEOF__FaultingExceptionFrame) -FaultingExceptionFrame_FrameOffset SETA SIZEOF__GSCookie +FaultingExceptionFrame_StackAlloc SETA (SIZEOF__FaultingExceptionFrame) +FaultingExceptionFrame_FrameOffset SETA 0 MACRO GenerateRedirectedStubWithFrame $STUB, $TARGET diff --git a/src/coreclr/vm/arm64/pinvokestubs.S b/src/coreclr/vm/arm64/pinvokestubs.S index e2eacde16a4ff8..84bb08bac1463a 100644 --- a/src/coreclr/vm/arm64/pinvokestubs.S +++ b/src/coreclr/vm/arm64/pinvokestubs.S @@ -82,8 +82,7 @@ LOCAL_LABEL(\__PInvokeStubFuncName\()_0): // ------------------------------------------------------------------ // IN: -// InlinedCallFrame (x0) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right -// before actual InlinedCallFrame data) +// InlinedCallFrame (x0) = pointer to the InlinedCallFrame data // // NESTED_ENTRY JIT_PInvokeBegin, _TEXT, NoHandler @@ -91,16 +90,12 @@ LOCAL_LABEL(\__PInvokeStubFuncName\()_0): PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -32 PROLOG_SAVE_REG x19, 16 //the stack slot at sp+24 is empty for 16 byte alignment - PREPARE_EXTERNAL_VAR s_gsCookie, x9 - ldr x9, [x9] - str x9, [x0] - add x19, x0, SIZEOF__GSCookie + mov x19, x0 // x19 = pFrame - // set first slot to the value of InlinedCallFrame::`vftable' (checked by runtime code) - PREPARE_EXTERNAL_VAR _ZTV16InlinedCallFrame, x9 - add x9, x9, 16 + // set first slot to the value of InlinedCallFrame identifier (checked by runtime code) + mov x9, #FRAMETYPE_InlinedCallFrame str x9, [x19] str xzr, [x19, #InlinedCallFrame__m_Datum] @@ -134,13 +129,11 @@ LOCAL_LABEL(\__PInvokeStubFuncName\()_0): // ------------------------------------------------------------------ // IN: -// InlinedCallFrame (x0) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right -// before actual InlinedCallFrame data) +// InlinedCallFrame (x0) = pointer to the InlinedCallFrame data // // LEAF_ENTRY JIT_PInvokeEnd, _TEXT - add x0, x0, SIZEOF__GSCookie ldr x1, [x0, #InlinedCallFrame__m_pThread] // x0 = pFrame diff --git a/src/coreclr/vm/arm64/stubs.cpp b/src/coreclr/vm/arm64/stubs.cpp index fdc54c5815918a..427bf342003389 100644 --- a/src/coreclr/vm/arm64/stubs.cpp +++ b/src/coreclr/vm/arm64/stubs.cpp @@ -412,7 +412,7 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, unwoundstate->_isValid = TRUE; } -void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void HelperMethodFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACTL { @@ -595,7 +595,7 @@ void UpdateRegDisplayFromCalleeSavedRegisters(REGDISPLAY * pRD, CalleeSavedRegis } -void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void TransitionFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { #ifndef DACCESS_COMPILE if (updateFloats) @@ -623,12 +623,12 @@ void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) // Finally, syncup the regdisplay with the context SyncRegDisplayToCurrentContext(pRD); - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK TransitionFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK TransitionFrame::UpdateRegDisplay_Impl(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); } -void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void FaultingExceptionFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { LIMITED_METHOD_DAC_CONTRACT; @@ -662,10 +662,10 @@ void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool update pRD->IsCallerContextValid = FALSE; pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK FaultingExceptionFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK FaultingExceptionFrame::UpdateRegDisplay_Impl(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); } -void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void InlinedCallFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACT_VOID { @@ -722,19 +722,19 @@ void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats // Update the frame pointer in the current context. pRD->pCurrentContextPointers->Fp = (DWORD64 *)&m_pCalleeSavedFP; - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK InlinedCallFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK InlinedCallFrame::UpdateRegDisplay_Impl(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); RETURN; } #ifdef FEATURE_HIJACK -TADDR ResumableFrame::GetReturnAddressPtr(void) +TADDR ResumableFrame::GetReturnAddressPtr_Impl(void) { LIMITED_METHOD_DAC_CONTRACT; return dac_cast(m_Regs) + offsetof(T_CONTEXT, Pc); } -void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void ResumableFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACT_VOID { @@ -769,12 +769,12 @@ void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) pRD->IsCallerContextValid = FALSE; pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK ResumableFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK ResumableFrame::UpdateRegDisplay_Impl(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); RETURN; } -void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void HijackFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { LIMITED_METHOD_CONTRACT; @@ -822,7 +822,7 @@ void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) SyncRegDisplayToCurrentContext(pRD); - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK HijackFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK HijackFrame::UpdateRegDisplay_Impl(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); } #endif // FEATURE_HIJACK diff --git a/src/coreclr/vm/assembly.cpp b/src/coreclr/vm/assembly.cpp index e124702167889b..0b4c0f2598aa36 100644 --- a/src/coreclr/vm/assembly.cpp +++ b/src/coreclr/vm/assembly.cpp @@ -1513,7 +1513,7 @@ MethodDesc* Assembly::GetEntryPoint() // This code needs a class init frame, because without it, the // debugger will assume any code that results from searching for a // type handle (ie, loading an assembly) is the first line of a program. - FrameWithCookie __dcimf; + DebuggerClassInitMarkFrame __dcimf; MethodTable * pInitialMT = ClassLoader::LoadTypeDefOrRefThrowing(pModule, mdParent, ClassLoader::ThrowIfNotFound, diff --git a/src/coreclr/vm/callcounting.cpp b/src/coreclr/vm/callcounting.cpp index 33b0839b5213c2..3b2df30ed4cfcc 100644 --- a/src/coreclr/vm/callcounting.cpp +++ b/src/coreclr/vm/callcounting.cpp @@ -774,8 +774,8 @@ PCODE CallCountingManager::OnCallCountThresholdReached(TransitionBlock *transiti CallCountingInfo::From(CallCountingStub::From(stubIdentifyingToken)->GetRemainingCallCountCell())->GetCodeVersion(); MethodDesc *methodDesc = codeVersion.GetMethodDesc(); - FrameWithCookie frameWithCookie(transitionBlock, methodDesc); - CallCountingHelperFrame *frame = &frameWithCookie; + CallCountingHelperFrame callCountingFrame(transitionBlock, methodDesc); + CallCountingHelperFrame *frame = &callCountingFrame; frame->Push(CURRENT_THREAD); INSTALL_MANAGED_EXCEPTION_DISPATCHER; diff --git a/src/coreclr/vm/ceemain.cpp b/src/coreclr/vm/ceemain.cpp index 9251ef02c916c8..58f1544146f9e4 100644 --- a/src/coreclr/vm/ceemain.cpp +++ b/src/coreclr/vm/ceemain.cpp @@ -729,11 +729,6 @@ void EEStartupHelper() InitGSCookie(); - Frame::Init(); - - - - #ifdef LOGGING InitializeLogging(); #endif diff --git a/src/coreclr/vm/clrtocomcall.cpp b/src/coreclr/vm/clrtocomcall.cpp index b7e3fc8ca06b56..a9505696385123 100644 --- a/src/coreclr/vm/clrtocomcall.cpp +++ b/src/coreclr/vm/clrtocomcall.cpp @@ -713,7 +713,7 @@ UINT32 STDCALL CLRToCOMWorker(TransitionBlock * pTransitionBlock, CLRToCOMCallMe MAKE_CURRENT_THREAD_AVAILABLE(); - FrameWithCookie frame(pTransitionBlock, pMD); + CLRToCOMMethodFrame frame(pTransitionBlock, pMD); CLRToCOMMethodFrame * pFrame = &frame; //we need to zero out the return value buffer because we will report it during GC @@ -843,7 +843,7 @@ TADDR CLRToCOMCall::GetFrameCallIP(FramedMethodFrame *frame) RETURN ip; } -void CLRToCOMMethodFrame::GetUnmanagedCallSite(TADDR* ip, +void CLRToCOMMethodFrame::GetUnmanagedCallSite_Impl(TADDR* ip, TADDR* returnIP, TADDR* returnSP) { @@ -884,7 +884,7 @@ void CLRToCOMMethodFrame::GetUnmanagedCallSite(TADDR* ip, -BOOL CLRToCOMMethodFrame::TraceFrame(Thread *thread, BOOL fromPatch, +BOOL CLRToCOMMethodFrame::TraceFrame_Impl(Thread *thread, BOOL fromPatch, TraceDestination *trace, REGDISPLAY *regs) { CONTRACTL diff --git a/src/coreclr/vm/common.h b/src/coreclr/vm/common.h index 7e38b98e3f452f..b2e9dd295d02ee 100644 --- a/src/coreclr/vm/common.h +++ b/src/coreclr/vm/common.h @@ -128,7 +128,7 @@ typedef DPTR(class EEConfig) PTR_EEConfig; typedef VPTR(class EEDbgInterfaceImpl) PTR_EEDbgInterfaceImpl; typedef VPTR(class DebugInfoManager) PTR_DebugInfoManager; typedef DPTR(class FieldDesc) PTR_FieldDesc; -typedef VPTR(class Frame) PTR_Frame; +typedef DPTR(class Frame) PTR_Frame; typedef DPTR(class GCFrame) PTR_GCFrame; typedef VPTR(class ICodeManager) PTR_ICodeManager; typedef VPTR(class IJitManager) PTR_IJitManager; diff --git a/src/coreclr/vm/comtoclrcall.cpp b/src/coreclr/vm/comtoclrcall.cpp index 7d5b9e3140511f..0f51af428e8b04 100644 --- a/src/coreclr/vm/comtoclrcall.cpp +++ b/src/coreclr/vm/comtoclrcall.cpp @@ -470,9 +470,8 @@ extern "C" UINT64 __stdcall COMToCLRWorker(ComMethodFrame* pFrame) goto ErrorExit; } - // Initialize the frame's VPTR and GS cookie. - *((TADDR*)pFrame) = ComMethodFrame::GetMethodFrameVPtr(); - *pFrame->GetGSCookiePtr() = GetProcessGSCookie(); + // Initialize the frame's identifier. + *((TADDR*)pFrame) = (TADDR)FrameIdentifier::ComMethodFrame; // Link frame into the chain. pFrame->Push(pThread); diff --git a/src/coreclr/vm/dispatchinfo.cpp b/src/coreclr/vm/dispatchinfo.cpp index a0c684b3f97915..652d0927097299 100644 --- a/src/coreclr/vm/dispatchinfo.cpp +++ b/src/coreclr/vm/dispatchinfo.cpp @@ -2164,7 +2164,7 @@ HRESULT DispatchInfo::InvokeMember(SimpleComCallWrapper *pSimpleWrap, DISPID id, // The sole purpose of having this frame is to tell the debugger that we have a catch handler here // which may swallow managed exceptions. The debugger needs this in order to send a // CatchHandlerFound (CHF) notification. - FrameWithCookie catchFrame; + DebuggerU2MCatchHandlerFrame catchFrame; EX_TRY { InvokeMemberDebuggerWrapper(pDispMemberInfo, diff --git a/src/coreclr/vm/dllimport.cpp b/src/coreclr/vm/dllimport.cpp index 55ba8dc4151bdd..24d7461e3d02b9 100644 --- a/src/coreclr/vm/dllimport.cpp +++ b/src/coreclr/vm/dllimport.cpp @@ -5859,7 +5859,7 @@ EXTERN_C LPVOID STDCALL NDirectImportWorker(NDirectMethodDesc* pMD) // INDEBUG(Thread *pThread = GetThread()); { - _ASSERTE((pThread->GetFrame() != FRAME_TOP && pThread->GetFrame()->GetVTablePtr() == InlinedCallFrame::GetMethodFrameVPtr()) + _ASSERTE((pThread->GetFrame() != FRAME_TOP && pThread->GetFrame()->GetFrameIdentifier() == FrameIdentifier::InlinedCallFrame) || pMD->ShouldSuppressGCTransition()); CONSISTENCY_CHECK(pMD->IsNDirect()); @@ -5904,7 +5904,7 @@ EXTERN_C void STDCALL VarargPInvokeStubWorker(TransitionBlock * pTransitionBlock Thread::ObjectRefFlush(CURRENT_THREAD); #endif - FrameWithCookie frame(pTransitionBlock, pMD); + PrestubMethodFrame frame(pTransitionBlock, pMD); PrestubMethodFrame * pFrame = &frame; pFrame->Push(CURRENT_THREAD); @@ -5934,7 +5934,7 @@ EXTERN_C void STDCALL GenericPInvokeCalliStubWorker(TransitionBlock * pTransitio Thread::ObjectRefFlush(CURRENT_THREAD); #endif - FrameWithCookie frame(pTransitionBlock, pVASigCookie, pUnmanagedTarget); + PInvokeCalliFrame frame(pTransitionBlock, pVASigCookie, pUnmanagedTarget); PInvokeCalliFrame * pFrame = &frame; pFrame->Push(CURRENT_THREAD); diff --git a/src/coreclr/vm/eepolicy.cpp b/src/coreclr/vm/eepolicy.cpp index 14157b1f77e697..62909498efe387 100644 --- a/src/coreclr/vm/eepolicy.cpp +++ b/src/coreclr/vm/eepolicy.cpp @@ -615,10 +615,7 @@ void DECLSPEC_NORETURN EEPolicy::HandleFatalStackOverflow(EXCEPTION_POINTERS *pE STRESS_LOG0(LF_EH, LL_INFO100, "In EEPolicy::HandleFatalStackOverflow\n"); - FrameWithCookie fef; -#if defined(FEATURE_EH_FUNCLETS) - *((&fef)->GetGSCookiePtr()) = GetProcessGSCookie(); -#endif // FEATURE_EH_FUNCLETS + FaultingExceptionFrame fef; if (pExceptionInfo->ContextRecord) { GCX_COOP(); diff --git a/src/coreclr/vm/encee.cpp b/src/coreclr/vm/encee.cpp index 250a90eb51eae8..b61b8acdc8bfe2 100644 --- a/src/coreclr/vm/encee.cpp +++ b/src/coreclr/vm/encee.cpp @@ -551,7 +551,7 @@ PCODE EditAndContinueModule::JitUpdatedFunction( MethodDesc *pMD, // so that gc can crawl the stack and do the right thing. _ASSERTE(pOrigContext); Thread *pCurThread = GetThread(); - FrameWithCookie resFrame(pOrigContext); + ResumableFrame resFrame(pOrigContext); resFrame.Push(pCurThread); CONTEXT *pCtxTemp = NULL; diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index ca58365087b933..5734d184610eee 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -6261,11 +6261,8 @@ void HandleManagedFaultNew(EXCEPTION_RECORD* pExceptionRecord, CONTEXT* pContext { WRAPPER_NO_CONTRACT; - FrameWithCookie frameWithCookie; - FaultingExceptionFrame *frame = &frameWithCookie; -#if defined(FEATURE_EH_FUNCLETS) - *frame->GetGSCookiePtr() = GetProcessGSCookie(); -#endif // FEATURE_EH_FUNCLETS + FaultingExceptionFrame fef; + FaultingExceptionFrame *frame = &fef; frame->InitAndLink(pContext); Thread *pThread = GetThread(); @@ -6300,11 +6297,8 @@ void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord, CONTEXT* pContext) WRAPPER_NO_CONTRACT; // Ok. Now we have a brand new fault in jitted code. - FrameWithCookie frameWithCookie; - FaultingExceptionFrame *frame = &frameWithCookie; -#if defined(FEATURE_EH_FUNCLETS) - *frame->GetGSCookiePtr() = GetProcessGSCookie(); -#endif // FEATURE_EH_FUNCLETS + FaultingExceptionFrame fef; + FaultingExceptionFrame *frame = &fef; frame->InitAndLink(pContext); HandleManagedFaultFilterParam param; @@ -6530,7 +6524,7 @@ VEH_ACTION WINAPI CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo // That IP is an interruptible safe point, so we can suspend right there. interruptedContext->Rip = (uintptr_t)pThread->GetHijackedReturnAddress(); - FrameWithCookie frame(pExceptionInfo->ContextRecord); + ResumableFrame frame(pExceptionInfo->ContextRecord); frame.Push(pThread); CommonTripThread(); frame.Pop(pThread); @@ -11514,7 +11508,7 @@ MethodDesc * GetUserMethodForILStub(Thread * pThread, UINT_PTR uStubSP, MethodDe // should be present further up the stack. Normally, the ComMethodFrame in question is // simply the next stack frame; however, there are situations where there may be other // stack frames present (such as an inlined stack frame from a QCall in the IL stub). - while (pCurFrame->GetVTablePtr() != ComMethodFrame::GetMethodFrameVPtr()) + while (pCurFrame->GetFrameIdentifier() != FrameIdentifier::ComMethodFrame) { pCurFrame = pCurFrame->PtrNextFrame(); } @@ -11522,7 +11516,7 @@ MethodDesc * GetUserMethodForILStub(Thread * pThread, UINT_PTR uStubSP, MethodDe ComMethodFrame * pComFrame = (ComMethodFrame *)pCurFrame; _ASSERTE((UINT_PTR)pComFrame > uStubSP); - CONSISTENCY_CHECK_MSG(pComFrame->GetVTablePtr() == ComMethodFrame::GetMethodFrameVPtr(), + CONSISTENCY_CHECK_MSG(pComFrame->GetFrameIdentifier() == FrameIdentifier::ComMethodFrame, "Expected to find a ComMethodFrame."); ComCallMethodDesc * pCMD = pComFrame->GetComCallMethodDesc(); @@ -11540,7 +11534,7 @@ MethodDesc * GetUserMethodForILStub(Thread * pThread, UINT_PTR uStubSP, MethodDe #ifdef FEATURE_EH_FUNCLETS -void SoftwareExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void SoftwareExceptionFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { LIMITED_METHOD_DAC_CONTRACT; diff --git a/src/coreclr/vm/exceptionhandling.cpp b/src/coreclr/vm/exceptionhandling.cpp index 02a14707092fd7..1476bbd19ec9d1 100644 --- a/src/coreclr/vm/exceptionhandling.cpp +++ b/src/coreclr/vm/exceptionhandling.cpp @@ -343,7 +343,7 @@ StackWalkAction UpdateObjectRefInResumeContextCallback(CrawlFrame* pCF, LPVOID p pState->pHighestFrameWithRegisters = pFrame; // Is this an InlinedCallFrame? - if (pFrame->GetVTablePtr() == InlinedCallFrame::GetMethodFrameVPtr()) + if (pFrame->GetFrameIdentifier() == FrameIdentifier::InlinedCallFrame) { // If we are here, then ICF is expected to be active. _ASSERTE(InlinedCallFrame::FrameHasActiveCall(pFrame)); @@ -1467,7 +1467,7 @@ void ExceptionTracker::InitializeCrawlFrameForExplicitFrame(CrawlFrame* pcfThisF pcfThisFrame->pFrame = pFrame; pcfThisFrame->pFunc = pFrame->GetFunction(); - if (pFrame->GetVTablePtr() == InlinedCallFrame::GetMethodFrameVPtr() && + if (pFrame->GetFrameIdentifier() == FrameIdentifier::InlinedCallFrame && !InlinedCallFrame::FrameHasActiveCall(pFrame)) { // Inactive ICFs in IL stubs contain the true interop MethodDesc which must be @@ -1905,11 +1905,6 @@ CLRUnwindStatus ExceptionTracker::ProcessOSExceptionNotification( MethodDesc *pMD = cfThisFrame.GetFunction(); Frame* pFrame = GetLimitFrame(); // next frame to process - if (pFrame != FRAME_TOP) - { - // The following function call sets the GS cookie pointers and checks the cookie. - cfThisFrame.SetCurGSCookie(Frame::SafeGetGSCookiePtr(pFrame)); - } while (((UINT_PTR)pFrame) < uCallerSP) { @@ -1968,7 +1963,7 @@ CLRUnwindStatus ExceptionTracker::ProcessOSExceptionNotification( // the ICF immediately before and after a PInvoke in non-IL-stubs, like ReadyToRun. // See the usages for USE_PER_FRAME_PINVOKE_INIT for more information. - if (fTargetUnwind && (pFrame->GetVTablePtr() == InlinedCallFrame::GetMethodFrameVPtr())) + if (fTargetUnwind && (pFrame->GetFrameIdentifier() == FrameIdentifier::InlinedCallFrame)) { PTR_InlinedCallFrame pICF = (PTR_InlinedCallFrame)pFrame; // Does it live inside the current managed method? It will iff: @@ -5521,8 +5516,7 @@ BOOL HandleHardwareException(PAL_SEHException* ex) #endif // TARGET_AMD64 || TARGET_X86 // Create frame necessary for the exception handling - FrameWithCookie fef; - *((&fef)->GetGSCookiePtr()) = GetProcessGSCookie(); + FaultingExceptionFrame fef; { GCX_COOP(); // Must be cooperative to modify frame chain. @@ -7600,7 +7594,7 @@ void ExceptionTracker::ResetThreadAbortStatus(PTR_Thread pThread, CrawlFrame *pC // Mark the pinvoke frame as invoking CallCatchFunclet (and similar) for collided unwind detection void MarkInlinedCallFrameAsFuncletCall(Frame* pFrame) { - _ASSERTE(pFrame->GetVTablePtr() == InlinedCallFrame::GetMethodFrameVPtr()); + _ASSERTE(pFrame->GetFrameIdentifier() == FrameIdentifier::InlinedCallFrame); InlinedCallFrame* pInlinedCallFrame = (InlinedCallFrame*)pFrame; pInlinedCallFrame->m_Datum = (PTR_NDirectMethodDesc)((TADDR)pInlinedCallFrame->m_Datum | (TADDR)InlinedCallFrameMarker::ExceptionHandlingHelper | (TADDR)InlinedCallFrameMarker::SecondPassFuncletCaller); } @@ -7608,7 +7602,7 @@ void MarkInlinedCallFrameAsFuncletCall(Frame* pFrame) // Mark the pinvoke frame as invoking any exception handling helper void MarkInlinedCallFrameAsEHHelperCall(Frame* pFrame) { - _ASSERTE(pFrame->GetVTablePtr() == InlinedCallFrame::GetMethodFrameVPtr()); + _ASSERTE(pFrame->GetFrameIdentifier() == FrameIdentifier::InlinedCallFrame); InlinedCallFrame* pInlinedCallFrame = (InlinedCallFrame*)pFrame; pInlinedCallFrame->m_Datum = (PTR_NDirectMethodDesc)((TADDR)pInlinedCallFrame->m_Datum | (TADDR)InlinedCallFrameMarker::ExceptionHandlingHelper); } @@ -8263,7 +8257,7 @@ void FailFastIfCorruptingStateException(ExInfo *pExInfo) static bool IsTopmostDebuggerU2MCatchHandlerFrame(Frame *pFrame) { - return (pFrame->GetVTablePtr() == DebuggerU2MCatchHandlerFrame::GetMethodFrameVPtr()) && (pFrame->PtrNextFrame() == FRAME_TOP); + return (pFrame->GetFrameIdentifier() == FrameIdentifier::DebuggerU2MCatchHandlerFrame) && (pFrame->PtrNextFrame() == FRAME_TOP); } static void NotifyExceptionPassStarted(StackFrameIterator *pThis, Thread *pThread, ExInfo *pExInfo) @@ -8337,12 +8331,12 @@ static void NotifyExceptionPassStarted(StackFrameIterator *pThis, Thread *pThrea { Frame* pFrame = pThis->m_crawl.GetFrame(); // If the frame is ProtectValueClassFrame, move to the next one as we want to report the FuncEvalFrame - if (pFrame->GetVTablePtr() == ProtectValueClassFrame::GetMethodFrameVPtr()) + if (pFrame->GetFrameIdentifier() == FrameIdentifier::ProtectValueClassFrame) { pFrame = pFrame->PtrNextFrame(); _ASSERTE(pFrame != FRAME_TOP); } - if ((pFrame->GetVTablePtr() == FuncEvalFrame::GetMethodFrameVPtr()) || IsTopmostDebuggerU2MCatchHandlerFrame(pFrame)) + if ((pFrame->GetFrameIdentifier() == FrameIdentifier::FuncEvalFrame) || IsTopmostDebuggerU2MCatchHandlerFrame(pFrame)) { EEToDebuggerExceptionInterfaceWrapper::NotifyOfCHFFilter((EXCEPTION_POINTERS *)&pExInfo->m_ptrs, pFrame); } @@ -8447,7 +8441,7 @@ extern "C" bool QCALLTYPE SfiInit(StackFrameIterator* pThis, CONTEXT* pStackwalk // a slightly different location in the managed code calling the pinvoke and the inlined // call frame doesn't update the context pointers anyways. Frame *pSkippedFrame = pThis->m_crawl.GetFrame(); - if (pSkippedFrame->NeedsUpdateRegDisplay() && (pSkippedFrame->GetVTablePtr() != InlinedCallFrame::GetMethodFrameVPtr())) + if (pSkippedFrame->NeedsUpdateRegDisplay() && (pSkippedFrame->GetFrameIdentifier() != FrameIdentifier::InlinedCallFrame)) { pSkippedFrame->UpdateRegDisplay(pThis->m_crawl.GetRegisterSet()); } diff --git a/src/coreclr/vm/fcall.h b/src/coreclr/vm/fcall.h index fb641548741777..0b362c0cc71696 100644 --- a/src/coreclr/vm/fcall.h +++ b/src/coreclr/vm/fcall.h @@ -525,7 +525,7 @@ LPVOID __FCThrow(LPVOID me, enum RuntimeExceptionKind reKind, UINT resID, LPCWST #endif // !SWIZZLE_STKARG_ORDER -#define HELPER_FRAME_DECL(x) FrameWithCookie __helperframe +#define HELPER_FRAME_DECL(x) HelperMethodFrame_##x##OBJ __helperframe // use the capture state machinery if the architecture has one // diff --git a/src/coreclr/vm/frames.cpp b/src/coreclr/vm/frames.cpp index 4479e678241908..f5628896728d2d 100644 --- a/src/coreclr/vm/frames.cpp +++ b/src/coreclr/vm/frames.cpp @@ -37,6 +37,259 @@ #define CHECK_APP_DOMAIN 0 +#ifdef DACCESS_COMPILE +#define FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE() _ASSERTE("!Unexpected value in Frame") +#else +#define FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE() DoJITFailFast() +#endif + +void Frame::GcScanRoots(promote_func *fn, ScanContext* sc) +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->GcScanRoots_Impl(fn, sc); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return; + } +} + +unsigned Frame::GetFrameAttribs() +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->GetFrameAttribs_Impl(); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return 0; + } +} + +#ifndef DACCESS_COMPILE +void Frame::ExceptionUnwind() +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->ExceptionUnwind_Impl(); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return; + } +} +#endif + +BOOL Frame::NeedsUpdateRegDisplay() +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->NeedsUpdateRegDisplay_Impl(); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return FALSE; + } +} + +BOOL Frame::IsTransitionToNativeFrame() +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->IsTransitionToNativeFrame_Impl(); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return FALSE; + } +} + +MethodDesc *Frame::GetFunction() +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->GetFunction_Impl(); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return NULL; + } +} + +Assembly *Frame::GetAssembly() +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->GetAssembly_Impl(); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return NULL; + } +} + +PTR_BYTE Frame::GetIP() +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->GetIP_Impl(); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return NULL; + } +} + +TADDR Frame::GetReturnAddressPtr() +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->GetReturnAddressPtr_Impl(); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return (TADDR)0; + } +} + +PCODE Frame::GetReturnAddress() +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->GetReturnAddress_Impl(); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return (PCODE)NULL; + } +} + +void Frame::UpdateRegDisplay(const PREGDISPLAY pRegDisplay, bool updateFloats) +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->UpdateRegDisplay_Impl(pRegDisplay, updateFloats); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return; + } +} + +int Frame::GetFrameType() +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->GetFrameType_Impl(); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return 0; + } +} + +Frame::ETransitionType Frame::GetTransitionType() +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->GetTransitionType_Impl(); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return (ETransitionType)0; + } +} + +Frame::Interception Frame::GetInterception() +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->GetInterception_Impl(); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return (Interception)0; + } +} + +void Frame::GetUnmanagedCallSite(TADDR* ip, TADDR* returnIP, TADDR* returnSP) +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->GetUnmanagedCallSite_Impl(ip, returnIP, returnSP); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return; + } +} + +BOOL Frame::TraceFrame(Thread *thread, BOOL fromPatch, TraceDestination *trace, REGDISPLAY *regs) +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->TraceFrame_Impl(thread, fromPatch, trace, regs); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return FALSE; + } +} + +#ifdef DACCESS_COMPILE +void Frame::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->EnumMemoryRegions_Impl(flags); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return; + } +} +#endif // DACCESS_COMPILE + +#if defined(_DEBUG) && !defined(DACCESS_COMPILE) +BOOL Frame::Protects(OBJECTREF *ppObjectRef) +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->Protects_Impl(ppObjectRef); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return FALSE; + } +} +#endif // defined(_DEBUG) && !defined(DACCESS_COMPILE) + +// TransitionFrame only apis +TADDR TransitionFrame::GetTransitionBlock() +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->GetTransitionBlock_Impl(); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return (TADDR)0; + } +} + +BOOL TransitionFrame::SuppressParamTypeArg() +{ + switch (GetFrameIdentifier()) + { +#define FRAME_TYPE_NAME(frameType) case FrameIdentifier::frameType: { return dac_cast(this)->SuppressParamTypeArg_Impl(); } +#include "FrameTypes.h" + default: + FRAME_POLYMORPHIC_DISPATCH_UNREACHABLE(); + return FALSE; + } +} + //----------------------------------------------------------------------- #if _DEBUG //----------------------------------------------------------------------- @@ -63,17 +316,17 @@ void Frame::Log() { char buff[64]; const char* frameType; - if (GetVTablePtr() == PrestubMethodFrame::GetMethodFrameVPtr()) + if (GetFrameIdentifier() == FrameIdentifier::PrestubMethodFrame) frameType = "PreStub"; - else if (GetVTablePtr() == PInvokeCalliFrame::GetMethodFrameVPtr()) + else if (GetFrameIdentifier() == FrameIdentifier::PInvokeCalliFrame) { sprintf_s(buff, ARRAY_SIZE(buff), "PInvoke CALLI target" FMT_ADDR, DBG_ADDR(((PInvokeCalliFrame*)this)->GetPInvokeCalliTarget())); frameType = buff; } - else if (GetVTablePtr() == StubDispatchFrame::GetMethodFrameVPtr()) + else if (GetFrameIdentifier() == FrameIdentifier::StubDispatchFrame) frameType = "StubDispatch"; - else if (GetVTablePtr() == ExternalMethodFrame::GetMethodFrameVPtr()) + else if (GetFrameIdentifier() == FrameIdentifier::ExternalMethodFrame) frameType = "ExternalMethod"; else frameType = "Unknown"; @@ -111,14 +364,6 @@ void __stdcall Frame::LogTransition(Frame* frame) GC_NOTRIGGER; } CONTRACTL_END; -#ifdef TARGET_X86 - // On x86, StubLinkerCPU::EmitMethodStubProlog calls Frame::LogTransition - // but the caller of EmitMethodStubProlog sets the GSCookie later on. - // So the cookie is not initialized by the point we get here. -#else - _ASSERTE(*frame->GetGSCookiePtr() == GetProcessGSCookie()); -#endif - if (Frame::ShouldLogTransitions()) frame->Log(); } // void Frame::Log() @@ -186,37 +431,26 @@ bool isLegalManagedCodeCaller(PCODE retAddr) { #endif //0 -//----------------------------------------------------------------------- -// Count of the number of frame types -const size_t FRAME_TYPES_COUNT = -#define FRAME_TYPE_NAME(frameType) +1 -#include "frames.h" -; - #if defined (_DEBUG_IMPL) // _DEBUG and !DAC //----------------------------------------------------------------------- // Implementation of the global table of names. On the DAC side, just the global pointer. // On the runtime side, the array of names. - #define FRAME_TYPE_NAME(x) {x::GetMethodFrameVPtr(), #x} , - static FrameTypeName FrameTypeNameTable[] = { + #define FRAME_TYPE_NAME(x) #x, + static PTR_CSTR FrameTypeNameTable[] = { #include "frames.h" }; /* static */ -PTR_CSTR Frame::GetFrameTypeName(TADDR vtbl) +PTR_CSTR Frame::GetFrameTypeName(FrameIdentifier frameIdentifier) { LIMITED_METHOD_CONTRACT; - for (size_t i=0; i= FrameIdentifier::CountPlusOne) { - if (vtbl == FrameTypeNameTable[(int)i].vtbl) - { - return FrameTypeNameTable[(int)i].name; - } + return NULL; } - - return NULL; + return FrameTypeNameTable[(int)frameIdentifier - 1]; } // char* Frame::FrameTypeName() @@ -229,18 +463,14 @@ void Frame::LogFrame( { char buf[32]; const char *pFrameType; - pFrameType = GetFrameTypeName(); - if (pFrameType == NULL) - { - pFrameType = GetFrameTypeName(GetVTablePtr()); - } + pFrameType = GetFrameTypeName(GetFrameIdentifier()); if (pFrameType == NULL) { _ASSERTE(!"New Frame type needs to be added to FrameTypeName()"); // Pointer is up to 17chars + vtbl@ = 22 chars - sprintf_s(buf, ARRAY_SIZE(buf), "vtbl@%p", (VOID *)GetVTablePtr()); + sprintf_s(buf, ARRAY_SIZE(buf), "frameIdentifier@%p", (VOID *)GetFrameIdentifier()); pFrameType = buf; } @@ -269,77 +499,29 @@ void Frame::LogFrameChain( #ifndef DACCESS_COMPILE -// This hashtable contains the vtable value of every Frame type. -static PtrHashMap* s_pFrameVTables = NULL; - -// static -void Frame::Init() +void Frame::Init(FrameIdentifier frameIdentifier) { - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END; - // create a table big enough for all the frame types, not in asynchronous mode, and with no lock owner - s_pFrameVTables = ::new PtrHashMap; - s_pFrameVTables->Init(2 * FRAME_TYPES_COUNT, FALSE, &g_lockTrustMeIAmThreadSafe); -#define FRAME_TYPE_NAME(frameType) \ - s_pFrameVTables->InsertValue(frameType::GetMethodFrameVPtr(), \ - (LPVOID) frameType::GetMethodFrameVPtr()); -#include "frames.h" - + LIMITED_METHOD_CONTRACT; + _frameIdentifier = frameIdentifier; } // void Frame::Init() #endif // DACCESS_COMPILE -// Returns true if the Frame's VTablePtr is valid +// Returns true if the Frame has a valid FrameIdentifier // static -bool Frame::HasValidVTablePtr(Frame * pFrame) +bool Frame::HasValidFrameIdentifier(Frame * pFrame) { WRAPPER_NO_CONTRACT; if (pFrame == NULL || pFrame == FRAME_TOP) return false; -#ifndef DACCESS_COMPILE - TADDR vptr = pFrame->GetVTablePtr(); - // - // Explicitly check for the most common frames. + FrameIdentifier vptr = pFrame->GetFrameIdentifier(); // - if (vptr == HelperMethodFrame::GetMethodFrameVPtr()) - return true; - + // Use a simple compare which is dependent on the tightly packed arrangement of FrameIdentifier // - // otherwise consult the hashtable - // - if (s_pFrameVTables->LookupValue(vptr, (LPVOID) vptr) == (LPVOID) INVALIDENTRY) - return false; -#endif - - return true; -} - -// Returns the location of the expected GSCookie, -// Return NULL if the frame's vtable pointer is corrupt -// -// Note that Frame::GetGSCookiePtr is a virtual method, -// and so it cannot be used without first checking if -// the vtable is valid. - -// static -PTR_GSCookie Frame::SafeGetGSCookiePtr(Frame * pFrame) -{ - WRAPPER_NO_CONTRACT; - - _ASSERTE(pFrame != FRAME_TOP); - - if (Frame::HasValidVTablePtr(pFrame)) - return pFrame->GetGSCookiePtr(); - else - return NULL; + return (((TADDR)vptr > (TADDR)FrameIdentifier::None) && ((TADDR)vptr < (TADDR)FrameIdentifier::CountPlusOne)); } //----------------------------------------------------------------------- @@ -371,8 +553,6 @@ VOID Frame::Push(Thread *pThread) } CONTRACTL_END; - _ASSERTE(*GetGSCookiePtr() == GetProcessGSCookie()); - m_Next = pThread->GetFrame(); // GetOsPageSize() is used to relax the assert for cases where two Frames are @@ -392,7 +572,7 @@ VOID Frame::Push(Thread *pThread) // during stack-walking. !g_pConfig->fAssertOnFailFast() || (m_Next == FRAME_TOP) || - (*m_Next->GetGSCookiePtr() == GetProcessGSCookie())); + (Frame::HasValidFrameIdentifier(m_Next))); pThread->SetFrame(this); } @@ -421,7 +601,6 @@ VOID Frame::Pop(Thread *pThread) CONTRACTL_END; _ASSERTE(pThread->GetFrame() == this && "Popping a frame out of order ?"); - _ASSERTE(*GetGSCookiePtr() == GetProcessGSCookie()); _ASSERTE(// If AssertOnFailFast is set, the test expects to do stack overrun // corruptions. In that case, the Frame chain may be corrupted, // and the rest of the assert is not valid. @@ -429,7 +608,7 @@ VOID Frame::Pop(Thread *pThread) // during stack-walking. !g_pConfig->fAssertOnFailFast() || (m_Next == FRAME_TOP) || - (*m_Next->GetGSCookiePtr() == GetProcessGSCookie())); + (Frame::HasValidFrameIdentifier(m_Next))); pThread->SetFrame(m_Next); m_Next = NULL; @@ -533,13 +712,13 @@ VASigCookie * TransitionFrame::GetVASigCookie() #ifndef DACCESS_COMPILE PrestubMethodFrame::PrestubMethodFrame(TransitionBlock * pTransitionBlock, MethodDesc * pMD) - : FramedMethodFrame(pTransitionBlock, pMD) + : FramedMethodFrame(FrameIdentifier::PrestubMethodFrame, pTransitionBlock, pMD) { LIMITED_METHOD_CONTRACT; } #endif // #ifndef DACCESS_COMPILE -BOOL PrestubMethodFrame::TraceFrame(Thread *thread, BOOL fromPatch, +BOOL PrestubMethodFrame::TraceFrame_Impl(Thread *thread, BOOL fromPatch, TraceDestination *trace, REGDISPLAY *regs) { WRAPPER_NO_CONTRACT; @@ -576,7 +755,7 @@ BOOL PrestubMethodFrame::TraceFrame(Thread *thread, BOOL fromPatch, // A rather specialized routine for the exclusive use of StubDispatch. //----------------------------------------------------------------------- StubDispatchFrame::StubDispatchFrame(TransitionBlock * pTransitionBlock) - : FramedMethodFrame(pTransitionBlock, NULL) + : FramedMethodFrame(FrameIdentifier::StubDispatchFrame, pTransitionBlock, NULL) { LIMITED_METHOD_CONTRACT; @@ -591,7 +770,7 @@ StubDispatchFrame::StubDispatchFrame(TransitionBlock * pTransitionBlock) #endif // #ifndef DACCESS_COMPILE -MethodDesc* StubDispatchFrame::GetFunction() +MethodDesc* StubDispatchFrame::GetFunction_Impl() { CONTRACTL { NOTHROW; @@ -689,7 +868,7 @@ PTR_BYTE StubDispatchFrame::GetGCRefMap() return pGCRefMap; } -void StubDispatchFrame::GcScanRoots(promote_func *fn, ScanContext* sc) +void StubDispatchFrame::GcScanRoots_Impl(promote_func *fn, ScanContext* sc) { CONTRACTL { @@ -698,7 +877,7 @@ void StubDispatchFrame::GcScanRoots(promote_func *fn, ScanContext* sc) } CONTRACTL_END - FramedMethodFrame::GcScanRoots(fn, sc); + FramedMethodFrame::GcScanRoots_Impl(fn, sc); PTR_BYTE pGCRefMap = GetGCRefMap(); if (pGCRefMap != NULL) @@ -711,7 +890,7 @@ void StubDispatchFrame::GcScanRoots(promote_func *fn, ScanContext* sc) } } -BOOL StubDispatchFrame::TraceFrame(Thread *thread, BOOL fromPatch, +BOOL StubDispatchFrame::TraceFrame_Impl(Thread *thread, BOOL fromPatch, TraceDestination *trace, REGDISPLAY *regs) { WRAPPER_NO_CONTRACT; @@ -723,7 +902,7 @@ BOOL StubDispatchFrame::TraceFrame(Thread *thread, BOOL fromPatch, return FALSE; } -Frame::Interception StubDispatchFrame::GetInterception() +Frame::Interception StubDispatchFrame::GetInterception_Impl() { LIMITED_METHOD_CONTRACT; @@ -732,21 +911,21 @@ Frame::Interception StubDispatchFrame::GetInterception() #ifndef DACCESS_COMPILE CallCountingHelperFrame::CallCountingHelperFrame(TransitionBlock *pTransitionBlock, MethodDesc *pMD) - : FramedMethodFrame(pTransitionBlock, pMD) + : FramedMethodFrame(FrameIdentifier::CallCountingHelperFrame, pTransitionBlock, pMD) { WRAPPER_NO_CONTRACT; } #endif -void CallCountingHelperFrame::GcScanRoots(promote_func *fn, ScanContext *sc) +void CallCountingHelperFrame::GcScanRoots_Impl(promote_func *fn, ScanContext *sc) { WRAPPER_NO_CONTRACT; - FramedMethodFrame::GcScanRoots(fn, sc); + FramedMethodFrame::GcScanRoots_Impl(fn, sc); PromoteCallerStack(fn, sc); } -BOOL CallCountingHelperFrame::TraceFrame(Thread *thread, BOOL fromPatch, TraceDestination *trace, REGDISPLAY *regs) +BOOL CallCountingHelperFrame::TraceFrame_Impl(Thread *thread, BOOL fromPatch, TraceDestination *trace, REGDISPLAY *regs) { WRAPPER_NO_CONTRACT; @@ -758,7 +937,7 @@ BOOL CallCountingHelperFrame::TraceFrame(Thread *thread, BOOL fromPatch, TraceDe #ifndef DACCESS_COMPILE ExternalMethodFrame::ExternalMethodFrame(TransitionBlock * pTransitionBlock) - : FramedMethodFrame(pTransitionBlock, NULL) + : FramedMethodFrame(FrameIdentifier::ExternalMethodFrame, pTransitionBlock, NULL) { LIMITED_METHOD_CONTRACT; @@ -769,7 +948,7 @@ ExternalMethodFrame::ExternalMethodFrame(TransitionBlock * pTransitionBlock) } #endif // !DACCESS_COMPILE -void ExternalMethodFrame::GcScanRoots(promote_func *fn, ScanContext* sc) +void ExternalMethodFrame::GcScanRoots_Impl(promote_func *fn, ScanContext* sc) { CONTRACTL { @@ -778,7 +957,7 @@ void ExternalMethodFrame::GcScanRoots(promote_func *fn, ScanContext* sc) } CONTRACTL_END - FramedMethodFrame::GcScanRoots(fn, sc); + FramedMethodFrame::GcScanRoots_Impl(fn, sc); PromoteCallerStackUsingGCRefMap(fn, sc, GetGCRefMap()); } @@ -803,14 +982,14 @@ PTR_BYTE ExternalMethodFrame::GetGCRefMap() return pGCRefMap; } -Frame::Interception ExternalMethodFrame::GetInterception() +Frame::Interception ExternalMethodFrame::GetInterception_Impl() { LIMITED_METHOD_CONTRACT; return INTERCEPTION_NONE; } -Frame::Interception PrestubMethodFrame::GetInterception() +Frame::Interception PrestubMethodFrame::GetInterception_Impl() { LIMITED_METHOD_DAC_CONTRACT; @@ -826,7 +1005,7 @@ Frame::Interception PrestubMethodFrame::GetInterception() #ifndef DACCESS_COMPILE DynamicHelperFrame::DynamicHelperFrame(TransitionBlock * pTransitionBlock, int dynamicHelperFrameFlags) - : FramedMethodFrame(pTransitionBlock, NULL) + : FramedMethodFrame(FrameIdentifier::DynamicHelperFrame, pTransitionBlock, NULL) { LIMITED_METHOD_CONTRACT; @@ -834,7 +1013,7 @@ DynamicHelperFrame::DynamicHelperFrame(TransitionBlock * pTransitionBlock, int d } #endif // !DACCESS_COMPILE -void DynamicHelperFrame::GcScanRoots(promote_func *fn, ScanContext* sc) +void DynamicHelperFrame::GcScanRoots_Impl(promote_func *fn, ScanContext* sc) { CONTRACTL { @@ -843,7 +1022,7 @@ void DynamicHelperFrame::GcScanRoots(promote_func *fn, ScanContext* sc) } CONTRACTL_END - FramedMethodFrame::GcScanRoots(fn, sc); + FramedMethodFrame::GcScanRoots_Impl(fn, sc); PTR_PTR_Object pArgumentRegisters = dac_cast(GetTransitionBlock() + TransitionBlock::GetOffsetOfArgumentRegisters()); @@ -884,11 +1063,8 @@ ComPrestubMethodFrame::Init() { WRAPPER_NO_CONTRACT; - // Initializes the frame's VPTR. This assumes C++ puts the vptr - // at offset 0 for a class not using MI, but this is no different - // than the assumption that COM Classic makes. - *((TADDR*)this) = GetMethodFrameVPtr(); - *GetGSCookiePtr() = GetProcessGSCookie(); + // Initializes the frame's identifier. + Frame::Init(FrameIdentifier::ComPrestubMethodFrame); } #endif // FEATURE_COMINTEROP @@ -1174,7 +1350,7 @@ BOOL IsProtectedByGCFrame(OBJECTREF *ppObjectRef) #ifdef FEATURE_HIJACK #ifdef TARGET_X86 -void HijackFrame::GcScanRoots(promote_func *fn, ScanContext* sc) +void HijackFrame::GcScanRoots_Impl(promote_func *fn, ScanContext* sc) { LIMITED_METHOD_CONTRACT; @@ -1220,7 +1396,7 @@ void HijackFrame::GcScanRoots(promote_func *fn, ScanContext* sc) #endif // TARGET_X86 #endif // FEATURE_HIJACK -void ProtectByRefsFrame::GcScanRoots(promote_func *fn, ScanContext *sc) +void ProtectByRefsFrame::GcScanRoots_Impl(promote_func *fn, ScanContext *sc) { CONTRACTL { @@ -1255,7 +1431,7 @@ void ProtectByRefsFrame::GcScanRoots(promote_func *fn, ScanContext *sc) } } -void ProtectValueClassFrame::GcScanRoots(promote_func *fn, ScanContext *sc) +void ProtectValueClassFrame::GcScanRoots_Impl(promote_func *fn, ScanContext *sc) { CONTRACTL { @@ -1503,7 +1679,7 @@ void PInvokeCalliFrame::PromoteCallerStack(promote_func* fn, ScanContext* sc) #ifndef DACCESS_COMPILE PInvokeCalliFrame::PInvokeCalliFrame(TransitionBlock * pTransitionBlock, VASigCookie * pVASigCookie, PCODE pUnmanagedTarget) - : FramedMethodFrame(pTransitionBlock, NULL) + : FramedMethodFrame(FrameIdentifier::PInvokeCalliFrame, pTransitionBlock, NULL) { LIMITED_METHOD_CONTRACT; @@ -1516,21 +1692,21 @@ PInvokeCalliFrame::PInvokeCalliFrame(TransitionBlock * pTransitionBlock, VASigCo #ifndef DACCESS_COMPILE CLRToCOMMethodFrame::CLRToCOMMethodFrame(TransitionBlock * pTransitionBlock, MethodDesc * pMD) - : FramedMethodFrame(pTransitionBlock, pMD) + : FramedMethodFrame(FrameIdentifier::CLRToCOMMethodFrame, pTransitionBlock, pMD) { LIMITED_METHOD_CONTRACT; } #endif // #ifndef DACCESS_COMPILE //virtual -void CLRToCOMMethodFrame::GcScanRoots(promote_func* fn, ScanContext* sc) +void CLRToCOMMethodFrame::GcScanRoots_Impl(promote_func* fn, ScanContext* sc) { WRAPPER_NO_CONTRACT; // CLRToCOMMethodFrame is only used in the event call / late bound call code path where we do not have IL stub // so we need to promote the arguments and return value manually. - FramedMethodFrame::GcScanRoots(fn, sc); + FramedMethodFrame::GcScanRoots_Impl(fn, sc); PromoteCallerStack(fn, sc); @@ -1580,7 +1756,7 @@ void IsObjRefProtected (Object** ppObj, ScanContext* sc, uint32_t) orefProtectedSc->oref_protected = TRUE; } -BOOL TransitionFrame::Protects(OBJECTREF * ppORef) +BOOL TransitionFrame::Protects_Impl(OBJECTREF * ppORef) { WRAPPER_NO_CONTRACT; IsObjRefProtectedScanContext sc (ppORef); @@ -1626,7 +1802,7 @@ void ComMethodFrame::DoSecondPassHandlerCleanup(Frame * pCurFrame) // Find ComMethodFrame while ((pCurFrame != FRAME_TOP) && - (pCurFrame->GetVTablePtr() != ComMethodFrame::GetMethodFrameVPtr())) + (pCurFrame->GetFrameIdentifier() != FrameIdentifier::ComMethodFrame)) { pCurFrame = pCurFrame->PtrNextFrame(); } @@ -1675,11 +1851,6 @@ void HelperMethodFrame::Push() // Finish initialization // - // Compiler would not inline GetGSCookiePtr() because of it is virtual method. - // Inline it manually and verify that it gives same result. - _ASSERTE(GetGSCookiePtr() == (((GSCookie *)(this)) - 1)); - *(((GSCookie *)(this)) - 1) = GetProcessGSCookie(); - _ASSERTE(!m_MachState.isValid()); Thread * pThread = ::GetThread(); @@ -1751,7 +1922,7 @@ NOINLINE void HelperMethodFrame::PopSlowHelper() #endif // #ifndef DACCESS_COMPILE -MethodDesc* HelperMethodFrame::GetFunction() +MethodDesc* HelperMethodFrame::GetFunction_Impl() { WRAPPER_NO_CONTRACT; @@ -1876,13 +2047,7 @@ VOID InlinedCallFrame::Init() { WRAPPER_NO_CONTRACT; - *((TADDR *)this) = GetMethodFrameVPtr(); - - // GetGSCookiePtr contains a virtual call and this is a perf critical method so we don't want to call it in ret builds - GSCookie *ptrGS = (GSCookie *)((BYTE *)this - sizeof(GSCookie)); - _ASSERTE(ptrGS == GetGSCookiePtr()); - - *ptrGS = GetProcessGSCookie(); + Frame::Init(FrameIdentifier::InlinedCallFrame); m_Datum = NULL; m_pCallSiteSP = NULL; @@ -1891,7 +2056,7 @@ VOID InlinedCallFrame::Init() #ifdef FEATURE_COMINTEROP -void UnmanagedToManagedFrame::ExceptionUnwind() +void UnmanagedToManagedFrame::ExceptionUnwind_Impl() { WRAPPER_NO_CONTRACT; @@ -1902,11 +2067,11 @@ void UnmanagedToManagedFrame::ExceptionUnwind() #endif // !DACCESS_COMPILE #ifdef FEATURE_COMINTEROP -PCODE UnmanagedToManagedFrame::GetReturnAddress() +PCODE UnmanagedToManagedFrame::GetReturnAddress_Impl() { WRAPPER_NO_CONTRACT; - PCODE pRetAddr = Frame::GetReturnAddress(); + PCODE pRetAddr = Frame::GetReturnAddress_Impl(); if (InlinedCallFrame::FrameHasActiveCall(m_Next) && pRetAddr == m_Next->GetReturnAddress()) diff --git a/src/coreclr/vm/frames.h b/src/coreclr/vm/frames.h index 8ca02f5061d528..faf0e660e03541 100644 --- a/src/coreclr/vm/frames.h +++ b/src/coreclr/vm/frames.h @@ -173,66 +173,7 @@ obtained from function pointers): #endif // 0 //------------------------------------------------------------------------ -#ifndef FRAME_ABSTRACT_TYPE_NAME -#define FRAME_ABSTRACT_TYPE_NAME(frameType) -#endif -#ifndef FRAME_TYPE_NAME -#define FRAME_TYPE_NAME(frameType) -#endif - -FRAME_ABSTRACT_TYPE_NAME(FrameBase) -FRAME_ABSTRACT_TYPE_NAME(Frame) -FRAME_ABSTRACT_TYPE_NAME(TransitionFrame) -#ifdef FEATURE_HIJACK -FRAME_TYPE_NAME(ResumableFrame) -FRAME_TYPE_NAME(RedirectedThreadFrame) -#endif // FEATURE_HIJACK -FRAME_TYPE_NAME(FaultingExceptionFrame) -#ifdef FEATURE_EH_FUNCLETS -FRAME_TYPE_NAME(SoftwareExceptionFrame) -#endif // FEATURE_EH_FUNCLETS -#ifdef DEBUGGING_SUPPORTED -FRAME_TYPE_NAME(FuncEvalFrame) -#endif // DEBUGGING_SUPPORTED -FRAME_TYPE_NAME(HelperMethodFrame) -FRAME_TYPE_NAME(HelperMethodFrame_1OBJ) -FRAME_TYPE_NAME(HelperMethodFrame_2OBJ) -FRAME_TYPE_NAME(HelperMethodFrame_3OBJ) -FRAME_TYPE_NAME(HelperMethodFrame_PROTECTOBJ) -FRAME_ABSTRACT_TYPE_NAME(FramedMethodFrame) -#ifdef FEATURE_COMINTEROP -FRAME_ABSTRACT_TYPE_NAME(UnmanagedToManagedFrame) -FRAME_TYPE_NAME(ComMethodFrame) -FRAME_TYPE_NAME(CLRToCOMMethodFrame) -FRAME_TYPE_NAME(ComPrestubMethodFrame) -#endif // FEATURE_COMINTEROP -FRAME_TYPE_NAME(PInvokeCalliFrame) -#ifdef FEATURE_HIJACK -FRAME_TYPE_NAME(HijackFrame) -#endif // FEATURE_HIJACK -FRAME_TYPE_NAME(PrestubMethodFrame) -FRAME_TYPE_NAME(CallCountingHelperFrame) -FRAME_TYPE_NAME(StubDispatchFrame) -FRAME_TYPE_NAME(ExternalMethodFrame) -#ifdef FEATURE_READYTORUN -FRAME_TYPE_NAME(DynamicHelperFrame) -#endif -FRAME_TYPE_NAME(ProtectByRefsFrame) -FRAME_TYPE_NAME(ProtectValueClassFrame) -FRAME_TYPE_NAME(DebuggerClassInitMarkFrame) -FRAME_TYPE_NAME(DebuggerExitFrame) -FRAME_TYPE_NAME(DebuggerU2MCatchHandlerFrame) -FRAME_TYPE_NAME(InlinedCallFrame) -#if defined(TARGET_X86) && !defined(UNIX_X86_ABI) -FRAME_TYPE_NAME(TailCallFrame) -#endif -FRAME_TYPE_NAME(ExceptionFilterFrame) -#if defined(_DEBUG) -FRAME_TYPE_NAME(AssumeByrefFromJITStack) -#endif // _DEBUG - -#undef FRAME_ABSTRACT_TYPE_NAME -#undef FRAME_TYPE_NAME +#include "FrameTypes.h" //------------------------------------------------------------------------ @@ -260,7 +201,7 @@ FRAME_TYPE_NAME(AssumeByrefFromJITStack) // Forward references class Frame; class FramedMethodFrame; -typedef VPTR(class FramedMethodFrame) PTR_FramedMethodFrame; +typedef DPTR(class FramedMethodFrame) PTR_FramedMethodFrame; struct HijackArgs; struct ResolveCacheElem; #if defined(DACCESS_COMPILE) @@ -280,111 +221,100 @@ class ComCallMethodDesc; #define FRAME_TOP_VALUE ~0 // we want to say -1 here, but gcc has trouble with the signed value #define FRAME_TOP (PTR_Frame(FRAME_TOP_VALUE)) -#ifndef DACCESS_COMPILE - -#if defined(TARGET_UNIX) -#define DEFINE_DTOR(klass) \ - public: \ - virtual ~klass() { PopIfChained(); } - -#else - -#define DEFINE_DTOR(klass) - -#endif // TARGET_UNIX - -#define DEFINE_VTABLE_GETTER(klass) \ - public: \ - static TADDR GetMethodFrameVPtr() { \ - LIMITED_METHOD_CONTRACT; \ - klass boilerplate(false); \ - return *((TADDR*)&boilerplate); \ - } \ - klass(bool dummy) { LIMITED_METHOD_CONTRACT; } - -#define DEFINE_VTABLE_GETTER_AND_DTOR(klass) \ - DEFINE_VTABLE_GETTER(klass) \ - DEFINE_DTOR(klass) - -#define DEFINE_VTABLE_GETTER_AND_CTOR(klass) \ - DEFINE_VTABLE_GETTER(klass) \ - protected: \ - klass() { LIMITED_METHOD_CONTRACT; } - -#define DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(klass) \ - DEFINE_VTABLE_GETTER_AND_DTOR(klass) \ - protected: \ - klass() { LIMITED_METHOD_CONTRACT; } - -#else - -#define DEFINE_VTABLE_GETTER(klass) \ - public: \ - static TADDR GetMethodFrameVPtr() { \ - LIMITED_METHOD_CONTRACT; \ - return klass::VPtrTargetVTable(); \ - } \ - -#define DEFINE_VTABLE_GETTER_AND_DTOR(klass) \ - DEFINE_VTABLE_GETTER(klass) \ - -#define DEFINE_VTABLE_GETTER_AND_CTOR(klass) \ - DEFINE_VTABLE_GETTER(klass) \ - -#define DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(klass) \ - DEFINE_VTABLE_GETTER_AND_CTOR(klass) \ - -#endif // #ifndef DACCESS_COMPILE - -//----------------------------------------------------------------------------- -// For reporting on types of frames at runtime. -class FrameTypeName +enum class FrameIdentifier : TADDR { -public: - TADDR vtbl; - PTR_CSTR name; + None = 0, +#define FRAME_TYPE_NAME(frameType) frameType, +#include "FrameTypes.h" + CountPlusOne }; -typedef DPTR(FrameTypeName) PTR_FrameTypeName; -//----------------------------------------------------------------------------- -// Frame depends on the location of its vtable within the object. This -// superclass ensures that the vtable for Frame objects is in the same -// location under both MSVC and GCC. -//----------------------------------------------------------------------------- - -class FrameBase -{ - VPTR_BASE_VTABLE_CLASS(FrameBase) - -public: - FrameBase() {LIMITED_METHOD_CONTRACT; } - - virtual void GcScanRoots(promote_func *fn, ScanContext* sc) { - LIMITED_METHOD_CONTRACT; - // Nothing to protect - } - -#ifdef DACCESS_COMPILE - virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) = 0; -#endif -}; +// TransitionFrame only apis +class TransitionFrame; +TADDR Frame_GetTransitionBlock(TransitionFrame* frame); +BOOL Frame_SuppressParamTypeArg(TransitionFrame* frame); //------------------------------------------------------------------------ // Frame defines methods common to all frame types. There are no actual // instances of root frames. //------------------------------------------------------------------------ -class Frame : public FrameBase +class Frame { friend class CheckAsmOffsets; #ifdef DACCESS_COMPILE friend void Thread::EnumMemoryRegions(CLRDataEnumMemoryFlags flags); #endif - VPTR_ABSTRACT_VTABLE_CLASS(Frame, FrameBase) - public: + FrameIdentifier GetFrameIdentifier() { LIMITED_METHOD_DAC_CONTRACT; return _frameIdentifier; } + + enum ETransitionType + { + TT_NONE, + TT_M2U, // we can safely cast to a FramedMethodFrame + TT_U2M, // we can safely cast to a UnmanagedToManagedFrame + TT_AppDomain, // transitioniting between AppDomains. + TT_InternalCall, // calling into the CLR (ecall/fcall). + }; + + enum Interception + { + INTERCEPTION_NONE, + INTERCEPTION_CLASS_INIT, + INTERCEPTION_EXCEPTION, + INTERCEPTION_CONTEXT, + INTERCEPTION_SECURITY, + INTERCEPTION_PRESTUB, + INTERCEPTION_OTHER, + + INTERCEPTION_COUNT + }; + + void GcScanRoots(promote_func *fn, ScanContext* sc); + unsigned GetFrameAttribs(); +#ifndef DACCESS_COMPILE + void ExceptionUnwind(); +#endif + BOOL NeedsUpdateRegDisplay(); + BOOL IsTransitionToNativeFrame(); + MethodDesc *GetFunction(); + Assembly *GetAssembly(); + PTR_BYTE GetIP(); + TADDR GetReturnAddressPtr(); + PCODE GetReturnAddress(); + void UpdateRegDisplay(const PREGDISPLAY, bool updateFloats = false); + int GetFrameType(); + ETransitionType GetTransitionType(); + Interception GetInterception(); + void GetUnmanagedCallSite(TADDR* ip, TADDR* returnIP, TADDR* returnSP); + BOOL TraceFrame(Thread *thread, BOOL fromPatch, TraceDestination *trace, REGDISPLAY *regs); +#ifdef DACCESS_COMPILE + void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); +#endif // DACCESS_COMPILE +#if defined(_DEBUG) && !defined(DACCESS_COMPILE) + BOOL Protects(OBJECTREF *ppObjectRef); +#endif // defined(_DEBUG) && !defined(DACCESS_COMPILE) + + void GcScanRoots_Impl(promote_func *fn, ScanContext* sc) { + LIMITED_METHOD_CONTRACT; + // Nothing to protect + } + + // Should only be called on Frames that derive from TransitionFrame + TADDR GetTransitionBlock_Impl() + { + _ASSERTE(!"Unexpected"); + return (TADDR)0; + } + + // Should only be called on Frames that derive from TransitionFrame + BOOL SuppressParamTypeArg_Impl() + { + _ASSERTE(!"Unexpected"); + return FALSE; + } //------------------------------------------------------------------------ // Special characteristics of a frame @@ -398,7 +328,7 @@ class Frame : public FrameBase FRAME_ATTR_EXACT_DEPTH = 0x20, // This is a helperMethodFrame and a jit helper, but only crawl to the given depth FRAME_ATTR_NO_THREAD_ABORT = 0x40, // This is a helperMethodFrame that should not trigger thread aborts on entry }; - virtual unsigned GetFrameAttribs() + unsigned GetFrameAttribs_Impl() { LIMITED_METHOD_DAC_CONTRACT; return FRAME_ATTR_NONE; @@ -408,7 +338,7 @@ class Frame : public FrameBase // Performs cleanup on an exception unwind //------------------------------------------------------------------------ #ifndef DACCESS_COMPILE - virtual void ExceptionUnwind() + void ExceptionUnwind_Impl() { // Nothing to do here. LIMITED_METHOD_CONTRACT; @@ -417,7 +347,7 @@ class Frame : public FrameBase // Should be overridden to return TRUE if the frame contains register // state of the caller. - virtual BOOL NeedsUpdateRegDisplay() + BOOL NeedsUpdateRegDisplay_Impl() { return FALSE; } @@ -425,19 +355,19 @@ class Frame : public FrameBase //------------------------------------------------------------------------ // Is this a frame used on transition to native code from jitted code? //------------------------------------------------------------------------ - virtual BOOL IsTransitionToNativeFrame() + BOOL IsTransitionToNativeFrame_Impl() { LIMITED_METHOD_CONTRACT; return FALSE; } - virtual MethodDesc *GetFunction() + MethodDesc *GetFunction_Impl() { LIMITED_METHOD_DAC_CONTRACT; return NULL; } - virtual Assembly *GetAssembly() + Assembly *GetAssembly_Impl() { WRAPPER_NO_CONTRACT; MethodDesc *pMethod = GetFunction(); @@ -449,7 +379,7 @@ class Frame : public FrameBase // indicate the current X86 IP address within the current method // return 0 if the information is not available - virtual PTR_BYTE GetIP() + PTR_BYTE GetIP_Impl() { LIMITED_METHOD_CONTRACT; return NULL; @@ -457,14 +387,14 @@ class Frame : public FrameBase // DACCESS: GetReturnAddressPtr should return the // target address of the return address in the frame. - virtual TADDR GetReturnAddressPtr() + TADDR GetReturnAddressPtr_Impl() { LIMITED_METHOD_DAC_CONTRACT; return 0; } // ASAN doesn't like us messing with the return address. - virtual DISABLE_ASAN PCODE GetReturnAddress() + DISABLE_ASAN PCODE GetReturnAddress_Impl() { WRAPPER_NO_CONTRACT; TADDR ptr = GetReturnAddressPtr(); @@ -472,12 +402,6 @@ class Frame : public FrameBase } #ifndef DACCESS_COMPILE - virtual Object **GetReturnExecutionContextAddr() - { - LIMITED_METHOD_CONTRACT; - return NULL; - } - // ASAN doesn't like us messing with the return address. void DISABLE_ASAN SetReturnAddress(TADDR val) { @@ -488,27 +412,14 @@ class Frame : public FrameBase } #endif // #ifndef DACCESS_COMPILE - PTR_GSCookie GetGSCookiePtr() - { - WRAPPER_NO_CONTRACT; - return dac_cast(dac_cast(this) + GetOffsetOfGSCookie()); - } - - static int GetOffsetOfGSCookie() - { - LIMITED_METHOD_DAC_CONTRACT; - return -(int)sizeof(GSCookie); - } - - static bool HasValidVTablePtr(Frame * pFrame); - static PTR_GSCookie SafeGetGSCookiePtr(Frame * pFrame); - static void Init(); + static bool HasValidFrameIdentifier(Frame * pFrame); + void Init(FrameIdentifier frameIdentifier); // Callers, note that the REGDISPLAY parameter is actually in/out. While // UpdateRegDisplay is generally used to fill out the REGDISPLAY parameter, some // overrides (e.g., code:ResumableFrame::UpdateRegDisplay) will actually READ what // you pass in. So be sure to pass in a valid or zeroed out REGDISPLAY. - virtual void UpdateRegDisplay(const PREGDISPLAY, bool updateFloats = false) + void UpdateRegDisplay_Impl(const PREGDISPLAY, bool updateFloats) { LIMITED_METHOD_DAC_CONTRACT; return; @@ -520,18 +431,9 @@ class Frame : public FrameBase public: - enum ETransitionType - { - TT_NONE, - TT_M2U, // we can safely cast to a FramedMethodFrame - TT_U2M, // we can safely cast to a UnmanagedToManagedFrame - TT_AppDomain, // transitioniting between AppDomains. - TT_InternalCall, // calling into the CLR (ecall/fcall). - }; - // Get the type of transition. // M-->U, U-->M - virtual ETransitionType GetTransitionType() + ETransitionType GetTransitionType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TT_NONE; @@ -555,7 +457,7 @@ class Frame : public FrameBase TYPE_COUNT }; - virtual int GetFrameType() + int GetFrameType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TYPE_INTERNAL; @@ -566,20 +468,7 @@ class Frame : public FrameBase // with frames of various types. GetInterception() indicates whether // the frame was set up for execution of such interceptors - enum Interception - { - INTERCEPTION_NONE, - INTERCEPTION_CLASS_INIT, - INTERCEPTION_EXCEPTION, - INTERCEPTION_CONTEXT, - INTERCEPTION_SECURITY, - INTERCEPTION_PRESTUB, - INTERCEPTION_OTHER, - - INTERCEPTION_COUNT - }; - - virtual Interception GetInterception() + Interception GetInterception_Impl() { LIMITED_METHOD_DAC_CONTRACT; return INTERCEPTION_NONE; @@ -593,9 +482,9 @@ class Frame : public FrameBase // returnSP - the location returnIP is pushed onto the stack // during the call. // - virtual void GetUnmanagedCallSite(TADDR* ip, - TADDR* returnIP, - TADDR* returnSP) + void GetUnmanagedCallSite_Impl(TADDR* ip, + TADDR* returnIP, + TADDR* returnSP) { LIMITED_METHOD_CONTRACT; if (ip) @@ -611,7 +500,7 @@ class Frame : public FrameBase // Return where the frame will execute next - the result is filled // into the given "trace" structure. The frame is responsible for // detecting where it is in its execution lifetime. - virtual BOOL TraceFrame(Thread *thread, BOOL fromPatch, + BOOL TraceFrame_Impl(Thread *thread, BOOL fromPatch, TraceDestination *trace, REGDISPLAY *regs) { LIMITED_METHOD_CONTRACT; @@ -621,10 +510,9 @@ class Frame : public FrameBase } #ifdef DACCESS_COMPILE - virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) + void EnumMemoryRegions_Impl(CLRDataEnumMemoryFlags flags) { WRAPPER_NO_CONTRACT; - DAC_ENUM_VTHIS(); // Many frames store a MethodDesc pointer in m_Datum // so pick that up automatically. @@ -633,12 +521,6 @@ class Frame : public FrameBase { func->EnumMemoryRegions(flags); } - - // Include the NegSpace - GSCookie * pGSCookie = GetGSCookiePtr(); - _ASSERTE(FitsIn(PBYTE(pGSCookie) - PBYTE(this))); - ULONG32 negSpaceSize = static_cast(PBYTE(pGSCookie) - PBYTE(this)); - DacEnumMemoryRegion(dac_cast(this) - negSpaceSize, negSpaceSize); } #endif @@ -653,15 +535,8 @@ class Frame : public FrameBase return (BYTE)ofs; } - // get your VTablePointer (can be used to check what type the frame is) - TADDR GetVTablePtr() - { - LIMITED_METHOD_DAC_CONTRACT; - return VPTR_HOST_VTABLE_TO_TADDR(*(LPVOID*)this); - } - #if defined(_DEBUG) && !defined(DACCESS_COMPILE) - virtual BOOL Protects(OBJECTREF *ppObjectRef) + BOOL Protects_Impl(OBJECTREF *ppObjectRef) { LIMITED_METHOD_CONTRACT; return FALSE; @@ -682,24 +557,14 @@ class Frame : public FrameBase static void __stdcall LogTransition(Frame* frame); void LogFrame(int LF, int LL); // General purpose logging. void LogFrameChain(int LF, int LL); // Log the whole chain. - virtual const char* GetFrameTypeName() {return NULL;} - static PTR_CSTR GetFrameTypeName(TADDR vtbl); + static PTR_CSTR GetFrameTypeName(FrameIdentifier frameIdentifier); #endif - //------------------------------------------------------------------------ - // Returns the address of a security object or - // null if there is no space for an object on this frame. - //------------------------------------------------------------------------ - virtual OBJECTREF *GetAddrOfSecurityDesc() - { - LIMITED_METHOD_CONTRACT; - return NULL; - } - private: - // Pointer to the next frame up the stack. + FrameIdentifier _frameIdentifier; protected: + // Pointer to the next frame up the stack. PTR_Frame m_Next; // offset +4 public: @@ -740,14 +605,17 @@ class Frame : public FrameBase } protected: +#ifndef DACCESS_COMPILE // Frame is considered an abstract class: this protected constructor // causes any attempt to instantiate one to fail at compile-time. - Frame() - : m_Next(dac_cast(nullptr)) + Frame(FrameIdentifier frameIdentifier) + : _frameIdentifier(frameIdentifier), m_Next(dac_cast(nullptr)) { LIMITED_METHOD_CONTRACT; } +#endif // DACCESS_COMPILE + #ifndef DACCESS_COMPILE #if !defined(TARGET_X86) || defined(TARGET_UNIX) static void UpdateFloatingPointRegisters(const PREGDISPLAY pRD); @@ -755,7 +623,7 @@ class Frame : public FrameBase #endif // DACCESS_COMPILE #if defined(TARGET_UNIX) && !defined(DACCESS_COMPILE) - virtual ~Frame() { LIMITED_METHOD_CONTRACT; } + ~Frame() { PopIfChained(); } void PopIfChained(); #endif // TARGET_UNIX && !DACCESS_COMPILE @@ -777,28 +645,33 @@ class Frame : public FrameBase #ifdef FEATURE_HIJACK //----------------------------------------------------------------------------- +typedef DPTR(class ResumableFrame) PTR_ResumableFrame; + class ResumableFrame : public Frame { - VPTR_VTABLE_CLASS(ResumableFrame, Frame) - public: #ifndef DACCESS_COMPILE - ResumableFrame(T_CONTEXT* regs) { + ResumableFrame(T_CONTEXT* regs) : Frame(FrameIdentifier::ResumableFrame) { + LIMITED_METHOD_CONTRACT; + m_Regs = regs; + } + + ResumableFrame(FrameIdentifier frameIdentifier, T_CONTEXT* regs) : Frame(frameIdentifier) { LIMITED_METHOD_CONTRACT; m_Regs = regs; } #endif - virtual TADDR GetReturnAddressPtr(); + TADDR GetReturnAddressPtr_Impl(); - virtual BOOL NeedsUpdateRegDisplay() + BOOL NeedsUpdateRegDisplay_Impl() { return TRUE; } - virtual void UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats = false); + void UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats); - virtual unsigned GetFrameAttribs() { + unsigned GetFrameAttribs_Impl() { LIMITED_METHOD_DAC_CONTRACT; return FRAME_ATTR_RESUMABLE; // Treat the next frame as the top frame. } @@ -809,15 +682,15 @@ class ResumableFrame : public Frame } #ifdef DACCESS_COMPILE - virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) + void EnumMemoryRegions_Impl(CLRDataEnumMemoryFlags flags) { WRAPPER_NO_CONTRACT; - Frame::EnumMemoryRegions(flags); + Frame::EnumMemoryRegions_Impl(flags); m_Regs.EnumMem(); } #endif - virtual void GcScanRoots(promote_func* fn, ScanContext* sc) + void GcScanRoots_Impl(promote_func* fn, ScanContext* sc) { WRAPPER_NO_CONTRACT; @@ -861,9 +734,6 @@ class ResumableFrame : public Frame protected: PTR_CONTEXT m_Regs; - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(ResumableFrame) }; @@ -873,20 +743,14 @@ class ResumableFrame : public Frame class RedirectedThreadFrame : public ResumableFrame { - VPTR_VTABLE_CLASS(RedirectedThreadFrame, ResumableFrame) - VPTR_UNIQUE(VPTR_UNIQUE_RedirectedThreadFrame) - public: #ifndef DACCESS_COMPILE - RedirectedThreadFrame(T_CONTEXT *regs) : ResumableFrame(regs) { + RedirectedThreadFrame(T_CONTEXT *regs) : ResumableFrame(FrameIdentifier::RedirectedThreadFrame, regs) { LIMITED_METHOD_CONTRACT; } - virtual void ExceptionUnwind(); + void ExceptionUnwind_Impl(); #endif - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(RedirectedThreadFrame) }; typedef DPTR(RedirectedThreadFrame) PTR_RedirectedThreadFrame; @@ -895,8 +759,8 @@ inline BOOL ISREDIRECTEDTHREAD(Thread * thread) { WRAPPER_NO_CONTRACT; return (thread->GetFrame() != FRAME_TOP && - thread->GetFrame()->GetVTablePtr() == - RedirectedThreadFrame::GetMethodFrameVPtr()); + thread->GetFrame()->GetFrameIdentifier() == + FrameIdentifier::RedirectedThreadFrame); } inline T_CONTEXT * GETREDIRECTEDCONTEXT(Thread * thread) @@ -924,16 +788,25 @@ inline CONTEXT * GETREDIRECTEDCONTEXT(Thread * thread) { LIMITED_METHOD_CONTRACT // getting lost. //------------------------------------------------------------------------ +typedef DPTR(class TransitionFrame) PTR_TransitionFrame; + class TransitionFrame : public Frame { - VPTR_ABSTRACT_VTABLE_CLASS(TransitionFrame, Frame) +#ifndef DACCESS_COMPILE +protected: + TransitionFrame(FrameIdentifier frameIdentifier) : Frame(frameIdentifier) { + LIMITED_METHOD_CONTRACT; + } +#endif public: - virtual TADDR GetTransitionBlock() = 0; + + TADDR GetTransitionBlock(); + BOOL SuppressParamTypeArg(); // DACCESS: GetReturnAddressPtr should return the // target address of the return address in the frame. - virtual TADDR GetReturnAddressPtr() + TADDR GetReturnAddressPtr_Impl() { LIMITED_METHOD_DAC_CONTRACT; return GetTransitionBlock() + TransitionBlock::GetOffsetOfReturnAddress(); @@ -964,7 +837,7 @@ class TransitionFrame : public Frame // Gets value indicating whether the generic parameter type // argument should be suppressed. //--------------------------------------------------------------- - virtual BOOL SuppressParamTypeArg() + BOOL SuppressParamTypeArg_Impl() { return FALSE; } @@ -1002,18 +875,18 @@ class TransitionFrame : public Frame return GetTransitionBlock() + sizeof(TransitionBlock); } - virtual BOOL NeedsUpdateRegDisplay() + BOOL NeedsUpdateRegDisplay_Impl() { return TRUE; } - virtual void UpdateRegDisplay(const PREGDISPLAY, bool updateFloats = false); + void UpdateRegDisplay_Impl(const PREGDISPLAY, bool updateFloats = false); #ifdef TARGET_X86 void UpdateRegDisplayHelper(const PREGDISPLAY, UINT cbStackPop); #endif #if defined (_DEBUG) && !defined (DACCESS_COMPILE) - virtual BOOL Protects(OBJECTREF *ppORef); + BOOL Protects_Impl(OBJECTREF *ppORef); #endif //defined (_DEBUG) && defined (DACCESS_COMPILE) // For use by classes deriving from FramedMethodFrame. @@ -1027,12 +900,6 @@ class TransitionFrame : public Frame #ifdef TARGET_X86 UINT CbStackPopUsingGCRefMap(PTR_BYTE pGCRefMap); #endif - -protected: - TransitionFrame() - { - LIMITED_METHOD_CONTRACT; - } }; //----------------------------------------------------------------------- @@ -1041,6 +908,7 @@ class TransitionFrame : public Frame // The define USE_FEF controls how this class is used. Look for occurrences // of USE_FEF. +typedef DPTR(class FaultingExceptionFrame) PTR_FaultingExceptionFrame; class FaultingExceptionFrame : public Frame { @@ -1064,16 +932,14 @@ class FaultingExceptionFrame : public Frame TADDR m_SSP; #endif - VPTR_VTABLE_CLASS(FaultingExceptionFrame, Frame) - public: #ifndef DACCESS_COMPILE - FaultingExceptionFrame() { + FaultingExceptionFrame() : Frame(FrameIdentifier::FaultingExceptionFrame) { LIMITED_METHOD_CONTRACT; } #endif - virtual TADDR GetReturnAddressPtr() + TADDR GetReturnAddressPtr_Impl() { LIMITED_METHOD_DAC_CONTRACT; return PTR_HOST_MEMBER_TADDR(FaultingExceptionFrame, this, m_ReturnAddress); @@ -1082,13 +948,13 @@ class FaultingExceptionFrame : public Frame void Init(T_CONTEXT *pContext); void InitAndLink(T_CONTEXT *pContext); - Interception GetInterception() + Interception GetInterception_Impl() { LIMITED_METHOD_DAC_CONTRACT; return INTERCEPTION_EXCEPTION; } - unsigned GetFrameAttribs() + unsigned GetFrameAttribs_Impl() { LIMITED_METHOD_DAC_CONTRACT; #ifdef FEATURE_EH_FUNCLETS @@ -1131,35 +997,32 @@ class FaultingExceptionFrame : public Frame } #endif - virtual BOOL NeedsUpdateRegDisplay() + BOOL NeedsUpdateRegDisplay_Impl() { return TRUE; } - virtual void UpdateRegDisplay(const PREGDISPLAY, bool updateFloats = false); - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_DTOR(FaultingExceptionFrame) + void UpdateRegDisplay_Impl(const PREGDISPLAY, bool updateFloats = false); }; #ifdef FEATURE_EH_FUNCLETS +typedef DPTR(class SoftwareExceptionFrame) PTR_SoftwareExceptionFrame; + class SoftwareExceptionFrame : public Frame { TADDR m_ReturnAddress; T_CONTEXT m_Context; T_KNONVOLATILE_CONTEXT_POINTERS m_ContextPointers; - VPTR_VTABLE_CLASS(SoftwareExceptionFrame, Frame) - public: #ifndef DACCESS_COMPILE - SoftwareExceptionFrame() { + SoftwareExceptionFrame() : Frame(FrameIdentifier::SoftwareExceptionFrame) { LIMITED_METHOD_CONTRACT; } #endif - virtual TADDR GetReturnAddressPtr() + TADDR GetReturnAddressPtr_Impl() { LIMITED_METHOD_DAC_CONTRACT; return PTR_HOST_MEMBER_TADDR(SoftwareExceptionFrame, this, m_ReturnAddress); @@ -1168,19 +1031,19 @@ class SoftwareExceptionFrame : public Frame void Init(); void InitAndLink(Thread *pThread); - Interception GetInterception() + Interception GetInterception_Impl() { LIMITED_METHOD_DAC_CONTRACT; return INTERCEPTION_EXCEPTION; } - virtual ETransitionType GetTransitionType() + ETransitionType GetTransitionType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TT_InternalCall; } - unsigned GetFrameAttribs() + unsigned GetFrameAttribs_Impl() { LIMITED_METHOD_DAC_CONTRACT; return FRAME_ATTR_EXCEPTION; @@ -1192,15 +1055,12 @@ class SoftwareExceptionFrame : public Frame return &m_Context; } - virtual BOOL NeedsUpdateRegDisplay() + BOOL NeedsUpdateRegDisplay_Impl() { return TRUE; } - virtual void UpdateRegDisplay(const PREGDISPLAY, bool updateFloats = false); - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_DTOR(SoftwareExceptionFrame) + void UpdateRegDisplay_Impl(const PREGDISPLAY, bool updateFloats = false); }; #endif // FEATURE_EH_FUNCLETS @@ -1224,8 +1084,6 @@ typedef DPTR(class DebuggerEval) PTR_DebuggerEval; class FuncEvalFrame : public Frame { - VPTR_VTABLE_CLASS(FuncEvalFrame, Frame) - TADDR m_ReturnAddress; PTR_DebuggerEval m_pDebuggerEval; @@ -1233,7 +1091,7 @@ class FuncEvalFrame : public Frame public: #ifndef DACCESS_COMPILE - FuncEvalFrame(DebuggerEval *pDebuggerEval, TADDR returnAddress, BOOL showFrame) + FuncEvalFrame(DebuggerEval *pDebuggerEval, TADDR returnAddress, BOOL showFrame) : Frame(FrameIdentifier::FuncEvalFrame) { LIMITED_METHOD_CONTRACT; m_pDebuggerEval = pDebuggerEval; @@ -1242,30 +1100,30 @@ class FuncEvalFrame : public Frame } #endif - virtual BOOL IsTransitionToNativeFrame() + BOOL IsTransitionToNativeFrame_Impl() { LIMITED_METHOD_CONTRACT; return FALSE; } - virtual int GetFrameType() + int GetFrameType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TYPE_FUNC_EVAL; } - virtual unsigned GetFrameAttribs(); + unsigned GetFrameAttribs_Impl(); - virtual BOOL NeedsUpdateRegDisplay() + BOOL NeedsUpdateRegDisplay_Impl() { return TRUE; } - virtual void UpdateRegDisplay(const PREGDISPLAY, bool updateFloats = false); + void UpdateRegDisplay_Impl(const PREGDISPLAY, bool updateFloats = false); - virtual DebuggerEval * GetDebuggerEval(); + DebuggerEval * GetDebuggerEval(); - virtual TADDR GetReturnAddressPtr(); + TADDR GetReturnAddressPtr_Impl(); /* * ShowFrame @@ -1279,12 +1137,9 @@ class FuncEvalFrame : public Frame return m_showFrame; } - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(FuncEvalFrame) }; -typedef VPTR(FuncEvalFrame) PTR_FuncEvalFrame; +typedef DPTR(FuncEvalFrame) PTR_FuncEvalFrame; #endif // DEBUGGING_SUPPORTED //---------------------------------------------------------------------------------------------- @@ -1294,10 +1149,10 @@ typedef VPTR(FuncEvalFrame) PTR_FuncEvalFrame; // subclases. (see JitInterface for sample use, YOU CAN'T RETURN WHILE IN THE PROTECTED STATE!) //---------------------------------------------------------------------------------------------- +typedef DPTR(class HelperMethodFrame) PTR_HelperMethodFrame; + class HelperMethodFrame : public Frame { - VPTR_VTABLE_CLASS(HelperMethodFrame, Frame); - public: #ifndef DACCESS_COMPILE // Lazy initialization of HelperMethodFrame. Need to @@ -1305,7 +1160,7 @@ class HelperMethodFrame : public Frame // If this is an FCall, the first param is the entry point for the FCALL. // The MethodDesc will be looked up form this (lazily), and this method // will be used in stack reporting, if this is not an FCall pass a 0 - FORCEINLINE HelperMethodFrame(void* fCallFtnEntry, unsigned attribs = 0) + FORCEINLINE HelperMethodFrame(void* fCallFtnEntry, unsigned attribs = 0, FrameIdentifier frameIdentifier = FrameIdentifier::HelperMethodFrame) : Frame(frameIdentifier) { WRAPPER_NO_CONTRACT; // Most of the initialization is actually done in HelperMethodFrame::Push() @@ -1315,13 +1170,13 @@ class HelperMethodFrame : public Frame } #endif // DACCESS_COMPILE - virtual int GetFrameType() + int GetFrameType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TYPE_HELPER_METHOD_FRAME; }; - virtual PCODE GetReturnAddress() + PCODE GetReturnAddress_Impl() { LIMITED_METHOD_DAC_CONTRACT; @@ -1341,16 +1196,16 @@ class HelperMethodFrame : public Frame return m_MachState.GetRetAddr(); } - virtual MethodDesc* GetFunction(); + MethodDesc* GetFunction_Impl(); - virtual BOOL NeedsUpdateRegDisplay() + BOOL NeedsUpdateRegDisplay_Impl() { return TRUE; } - virtual void UpdateRegDisplay(const PREGDISPLAY, bool updateFloats = false); + void UpdateRegDisplay_Impl(const PREGDISPLAY, bool updateFloats = false); - virtual Interception GetInterception() + Interception GetInterception_Impl() { WRAPPER_NO_CONTRACT; LIMITED_METHOD_DAC_CONTRACT; @@ -1359,7 +1214,7 @@ class HelperMethodFrame : public Frame return(INTERCEPTION_NONE); } - virtual ETransitionType GetTransitionType() + ETransitionType GetTransitionType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TT_InternalCall; @@ -1386,17 +1241,17 @@ class HelperMethodFrame : public Frame } #endif - virtual unsigned GetFrameAttribs() + unsigned GetFrameAttribs_Impl() { LIMITED_METHOD_DAC_CONTRACT; return(m_Attribs); } #ifdef DACCESS_COMPILE - virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) + void EnumMemoryRegions_Impl(CLRDataEnumMemoryFlags flags) { WRAPPER_NO_CONTRACT; - Frame::EnumMemoryRegions(flags); + Frame::EnumMemoryRegions_Impl(flags); } #endif @@ -1437,9 +1292,6 @@ class HelperMethodFrame : public Frame TADDR m_FCallEntry; // used to determine our identity for stack traces LazyMachState m_MachState; // pRetAddr points to the return address and the stack arguments - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(HelperMethodFrame) }; // Restores registers saved in m_MachState @@ -1472,14 +1324,14 @@ inline void DoPromote(promote_func *fn, ScanContext* sc, OBJECTREF *address, BOO // a HelplerMethodFrames that also report additional object references //----------------------------------------------------------------------------- +typedef DPTR(class HelperMethodFrame_1OBJ) PTR_HelperMethodFrame_1OBJ; + class HelperMethodFrame_1OBJ : public HelperMethodFrame { - VPTR_VTABLE_CLASS(HelperMethodFrame_1OBJ, HelperMethodFrame) - public: #if !defined(DACCESS_COMPILE) HelperMethodFrame_1OBJ(void* fCallFtnEntry, unsigned attribs, OBJECTREF* aGCPtr1) - : HelperMethodFrame(fCallFtnEntry, attribs) + : HelperMethodFrame(fCallFtnEntry, attribs, FrameIdentifier::HelperMethodFrame_1OBJ) { LIMITED_METHOD_CONTRACT; gcPtrs[0] = aGCPtr1; @@ -1495,11 +1347,11 @@ class HelperMethodFrame_1OBJ : public HelperMethodFrame INDEBUG(Thread::ObjectRefProtected(objPtr);) } - virtual void GcScanRoots(promote_func *fn, ScanContext* sc) + void GcScanRoots_Impl(promote_func *fn, ScanContext* sc) { WRAPPER_NO_CONTRACT; DoPromote(fn, sc, gcPtrs[0], FALSE); - HelperMethodFrame::GcScanRoots(fn, sc); + HelperMethodFrame::GcScanRoots_Impl(fn, sc); } #ifdef _DEBUG @@ -1512,7 +1364,7 @@ class HelperMethodFrame_1OBJ : public HelperMethodFrame } #endif // DACCESS_COMPILE - BOOL Protects(OBJECTREF *ppORef) + BOOL Protects_Impl(OBJECTREF *ppORef) { LIMITED_METHOD_CONTRACT; return (ppORef == gcPtrs[0]) ? TRUE : FALSE; @@ -1522,9 +1374,6 @@ class HelperMethodFrame_1OBJ : public HelperMethodFrame private: PTR_OBJECTREF gcPtrs[1]; - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(HelperMethodFrame_1OBJ) }; @@ -1532,10 +1381,10 @@ class HelperMethodFrame_1OBJ : public HelperMethodFrame // HelperMethodFrame_2OBJ //----------------------------------------------------------------------------- +typedef DPTR(class HelperMethodFrame_2OBJ) PTR_HelperMethodFrame_2OBJ; + class HelperMethodFrame_2OBJ : public HelperMethodFrame { - VPTR_VTABLE_CLASS(HelperMethodFrame_2OBJ, HelperMethodFrame) - public: #if !defined(DACCESS_COMPILE) HelperMethodFrame_2OBJ( @@ -1543,7 +1392,7 @@ class HelperMethodFrame_2OBJ : public HelperMethodFrame unsigned attribs, OBJECTREF* aGCPtr1, OBJECTREF* aGCPtr2) - : HelperMethodFrame(fCallFtnEntry, attribs) + : HelperMethodFrame(fCallFtnEntry, attribs, FrameIdentifier::HelperMethodFrame_2OBJ) { LIMITED_METHOD_CONTRACT; gcPtrs[0] = aGCPtr1; @@ -1555,12 +1404,12 @@ class HelperMethodFrame_2OBJ : public HelperMethodFrame } #endif - virtual void GcScanRoots(promote_func *fn, ScanContext* sc) + void GcScanRoots_Impl(promote_func *fn, ScanContext* sc) { WRAPPER_NO_CONTRACT; DoPromote(fn, sc, gcPtrs[0], FALSE); DoPromote(fn, sc, gcPtrs[1], FALSE); - HelperMethodFrame::GcScanRoots(fn, sc); + HelperMethodFrame::GcScanRoots_Impl(fn, sc); } #ifdef _DEBUG @@ -1574,7 +1423,7 @@ class HelperMethodFrame_2OBJ : public HelperMethodFrame } #endif // DACCESS_COMPILE - BOOL Protects(OBJECTREF *ppORef) + BOOL Protects_Impl(OBJECTREF *ppORef) { LIMITED_METHOD_CONTRACT; return (ppORef == gcPtrs[0] || ppORef == gcPtrs[1]) ? TRUE : FALSE; @@ -1583,19 +1432,16 @@ class HelperMethodFrame_2OBJ : public HelperMethodFrame private: PTR_OBJECTREF gcPtrs[2]; - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(HelperMethodFrame_2OBJ) }; //----------------------------------------------------------------------------- // HelperMethodFrame_3OBJ //----------------------------------------------------------------------------- +typedef DPTR(class HelperMethodFrame_3OBJ) PTR_HelperMethodFrame_3OBJ; + class HelperMethodFrame_3OBJ : public HelperMethodFrame { - VPTR_VTABLE_CLASS(HelperMethodFrame_3OBJ, HelperMethodFrame) - public: #if !defined(DACCESS_COMPILE) HelperMethodFrame_3OBJ( @@ -1604,7 +1450,7 @@ class HelperMethodFrame_3OBJ : public HelperMethodFrame OBJECTREF* aGCPtr1, OBJECTREF* aGCPtr2, OBJECTREF* aGCPtr3) - : HelperMethodFrame(fCallFtnEntry, attribs) + : HelperMethodFrame(fCallFtnEntry, attribs, FrameIdentifier::HelperMethodFrame_3OBJ) { LIMITED_METHOD_CONTRACT; gcPtrs[0] = aGCPtr1; @@ -1619,13 +1465,13 @@ class HelperMethodFrame_3OBJ : public HelperMethodFrame } #endif - virtual void GcScanRoots(promote_func *fn, ScanContext* sc) + void GcScanRoots_Impl(promote_func *fn, ScanContext* sc) { WRAPPER_NO_CONTRACT; DoPromote(fn, sc, gcPtrs[0], FALSE); DoPromote(fn, sc, gcPtrs[1], FALSE); DoPromote(fn, sc, gcPtrs[2], FALSE); - HelperMethodFrame::GcScanRoots(fn, sc); + HelperMethodFrame::GcScanRoots_Impl(fn, sc); } #ifdef _DEBUG @@ -1640,7 +1486,7 @@ class HelperMethodFrame_3OBJ : public HelperMethodFrame } #endif // DACCESS_COMPILE - BOOL Protects(OBJECTREF *ppORef) + BOOL Protects_Impl(OBJECTREF *ppORef) { LIMITED_METHOD_CONTRACT; return (ppORef == gcPtrs[0] || ppORef == gcPtrs[1] || ppORef == gcPtrs[2]) ? TRUE : FALSE; @@ -1649,9 +1495,6 @@ class HelperMethodFrame_3OBJ : public HelperMethodFrame private: PTR_OBJECTREF gcPtrs[3]; - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(HelperMethodFrame_3OBJ) }; @@ -1659,14 +1502,14 @@ class HelperMethodFrame_3OBJ : public HelperMethodFrame // HelperMethodFrame_PROTECTOBJ //----------------------------------------------------------------------------- +typedef DPTR(class HelperMethodFrame_PROTECTOBJ) PTR_HelperMethodFrame_PROTECTOBJ; + class HelperMethodFrame_PROTECTOBJ : public HelperMethodFrame { - VPTR_VTABLE_CLASS(HelperMethodFrame_PROTECTOBJ, HelperMethodFrame) - public: #if !defined(DACCESS_COMPILE) HelperMethodFrame_PROTECTOBJ(void* fCallFtnEntry, unsigned attribs, OBJECTREF* pObjRefs, int numObjRefs) - : HelperMethodFrame(fCallFtnEntry, attribs) + : HelperMethodFrame(fCallFtnEntry, attribs, FrameIdentifier::HelperMethodFrame_PROTECTOBJ) { LIMITED_METHOD_CONTRACT; m_pObjRefs = pObjRefs; @@ -1680,13 +1523,13 @@ class HelperMethodFrame_PROTECTOBJ : public HelperMethodFrame } #endif - virtual void GcScanRoots(promote_func *fn, ScanContext* sc) + void GcScanRoots_Impl(promote_func *fn, ScanContext* sc) { WRAPPER_NO_CONTRACT; for (UINT i = 0; i < m_numObjRefs; i++) { DoPromote(fn, sc, &m_pObjRefs[i], FALSE); } - HelperMethodFrame::GcScanRoots(fn, sc); + HelperMethodFrame::GcScanRoots_Impl(fn, sc); } #ifdef _DEBUG @@ -1701,7 +1544,7 @@ class HelperMethodFrame_PROTECTOBJ : public HelperMethodFrame } #endif // DACCESS_COMPILE - BOOL Protects(OBJECTREF *ppORef) + BOOL Protects_Impl(OBJECTREF *ppORef) { LIMITED_METHOD_CONTRACT; for (UINT i = 0; i < m_numObjRefs; i++) { @@ -1715,15 +1558,10 @@ class HelperMethodFrame_PROTECTOBJ : public HelperMethodFrame private: PTR_OBJECTREF m_pObjRefs; UINT m_numObjRefs; - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(HelperMethodFrame_PROTECTOBJ) }; class FramedMethodFrame : public TransitionFrame { - VPTR_ABSTRACT_VTABLE_CLASS(FramedMethodFrame, TransitionFrame) - TADDR m_pTransitionBlock; protected: @@ -1731,20 +1569,20 @@ class FramedMethodFrame : public TransitionFrame public: #ifndef DACCESS_COMPILE - FramedMethodFrame(TransitionBlock * pTransitionBlock, MethodDesc * pMD) - : m_pTransitionBlock(dac_cast(pTransitionBlock)), m_pMD(pMD) + FramedMethodFrame(FrameIdentifier frameIdentifier, TransitionBlock * pTransitionBlock, MethodDesc * pMD) + : TransitionFrame(frameIdentifier), m_pTransitionBlock(dac_cast(pTransitionBlock)), m_pMD(pMD) { LIMITED_METHOD_CONTRACT; } #endif // DACCESS_COMPILE - virtual TADDR GetTransitionBlock() + TADDR GetTransitionBlock_Impl() { LIMITED_METHOD_DAC_CONTRACT; return m_pTransitionBlock; } - virtual MethodDesc *GetFunction() + MethodDesc *GetFunction_Impl() { LIMITED_METHOD_DAC_CONTRACT; return m_pMD; @@ -1765,13 +1603,13 @@ class FramedMethodFrame : public TransitionFrame } #endif - virtual ETransitionType GetTransitionType() + ETransitionType GetTransitionType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TT_M2U; // we can safely cast to a FramedMethodFrame } - int GetFrameType() + int GetFrameType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TYPE_CALL; @@ -1816,12 +1654,6 @@ class FramedMethodFrame : public TransitionFrame #endif return dac_cast(p); } - -protected: - FramedMethodFrame() - { - LIMITED_METHOD_CONTRACT; - } }; @@ -1835,20 +1667,26 @@ class UnmanagedToManagedFrame : public Frame { friend class CheckAsmOffsets; - VPTR_ABSTRACT_VTABLE_CLASS_AND_CTOR(UnmanagedToManagedFrame, Frame) +protected: +#ifndef DACCESS_COMPILE + UnmanagedToManagedFrame(FrameIdentifier frameIdentifier) : Frame(frameIdentifier) + { + LIMITED_METHOD_CONTRACT; + } +#endif // DACCESS_COMPILE public: // DACCESS: GetReturnAddressPtr should return the // target address of the return address in the frame. - virtual TADDR GetReturnAddressPtr() + TADDR GetReturnAddressPtr_Impl() { LIMITED_METHOD_DAC_CONTRACT; return PTR_HOST_MEMBER_TADDR(UnmanagedToManagedFrame, this, m_ReturnAddress); } - virtual PCODE GetReturnAddress(); + PCODE GetReturnAddress_Impl(); // Retrieves pointer to the lowest-addressed argument on // the stack. Depending on the calling convention, this @@ -1879,7 +1717,7 @@ class UnmanagedToManagedFrame : public Frame return m_pvDatum; } - int GetFrameType() + int GetFrameType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TYPE_ENTRY; @@ -1888,7 +1726,7 @@ class UnmanagedToManagedFrame : public Frame //------------------------------------------------------------------------ // For the debugger. //------------------------------------------------------------------------ - virtual ETransitionType GetTransitionType() + ETransitionType GetTransitionType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TT_U2M; @@ -1898,7 +1736,7 @@ class UnmanagedToManagedFrame : public Frame // Performs cleanup on an exception unwind //------------------------------------------------------------------------ #ifndef DACCESS_COMPILE - virtual void ExceptionUnwind(); + void ExceptionUnwind_Impl(); #endif protected: @@ -1931,10 +1769,13 @@ class UnmanagedToManagedFrame : public Frame class ComMethodFrame : public UnmanagedToManagedFrame { - VPTR_VTABLE_CLASS(ComMethodFrame, UnmanagedToManagedFrame) - VPTR_UNIQUE(VPTR_UNIQUE_ComMethodFrame) - public: +#ifndef DACCESS_COMPILE + ComMethodFrame(FrameIdentifier frameIdentifier = FrameIdentifier::ComMethodFrame) : UnmanagedToManagedFrame(FrameIdentifier::ComMethodFrame) + { + LIMITED_METHOD_CONTRACT; + } +#endif // DACCESS_COMPILE #ifdef TARGET_X86 // Return the # of stack bytes pushed by the unmanaged caller. @@ -1950,10 +1791,6 @@ class ComMethodFrame : public UnmanagedToManagedFrame #ifndef DACCESS_COMPILE static void DoSecondPassHandlerCleanup(Frame * pCurFrame); #endif // !DACCESS_COMPILE - -protected: - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(ComMethodFrame) }; typedef DPTR(class ComMethodFrame) PTR_ComMethodFrame; @@ -1962,36 +1799,33 @@ typedef DPTR(class ComMethodFrame) PTR_ComMethodFrame; // This represents a generic call from CLR to COM //------------------------------------------------------------------------ +typedef DPTR(class CLRToCOMMethodFrame) PTR_CLRToCOMMethodFrame; + class CLRToCOMMethodFrame : public FramedMethodFrame { - VPTR_VTABLE_CLASS(CLRToCOMMethodFrame, FramedMethodFrame) - public: CLRToCOMMethodFrame(TransitionBlock * pTransitionBlock, MethodDesc * pMethodDesc); - virtual void GcScanRoots(promote_func *fn, ScanContext* sc); + void GcScanRoots_Impl(promote_func *fn, ScanContext* sc); - virtual BOOL IsTransitionToNativeFrame() + BOOL IsTransitionToNativeFrame_Impl() { LIMITED_METHOD_CONTRACT; return TRUE; } - int GetFrameType() + int GetFrameType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TYPE_EXIT; } - void GetUnmanagedCallSite(TADDR* ip, + void GetUnmanagedCallSite_Impl(TADDR* ip, TADDR* returnIP, TADDR* returnSP); - BOOL TraceFrame(Thread *thread, BOOL fromPatch, + BOOL TraceFrame_Impl(Thread *thread, BOOL fromPatch, TraceDestination *trace, REGDISPLAY *regs); - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(CLRToCOMMethodFrame) }; #endif // FEATURE_COMINTEROP @@ -2000,33 +1834,33 @@ class CLRToCOMMethodFrame : public FramedMethodFrame // This represents a call from a helper to GetILStubForCalli //------------------------------------------------------------------------ +typedef DPTR(class PInvokeCalliFrame) PTR_PInvokeCalliFrame; + class PInvokeCalliFrame : public FramedMethodFrame { - VPTR_VTABLE_CLASS(PInvokeCalliFrame, FramedMethodFrame) - PTR_VASigCookie m_pVASigCookie; PCODE m_pUnmanagedTarget; public: PInvokeCalliFrame(TransitionBlock * pTransitionBlock, VASigCookie * pVASigCookie, PCODE pUnmanagedTarget); - virtual void GcScanRoots(promote_func *fn, ScanContext* sc) + void GcScanRoots_Impl(promote_func *fn, ScanContext* sc) { WRAPPER_NO_CONTRACT; - FramedMethodFrame::GcScanRoots(fn, sc); + FramedMethodFrame::GcScanRoots_Impl(fn, sc); PromoteCallerStack(fn, sc); } void PromoteCallerStack(promote_func* fn, ScanContext* sc); // not a method - virtual MethodDesc *GetFunction() + MethodDesc *GetFunction_Impl() { LIMITED_METHOD_DAC_CONTRACT; return NULL; } - int GetFrameType() + int GetFrameType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TYPE_INTERCEPTION; @@ -2045,10 +1879,10 @@ class PInvokeCalliFrame : public FramedMethodFrame } #ifdef TARGET_X86 - virtual void UpdateRegDisplay(const PREGDISPLAY, bool updateFloats = false); + void UpdateRegDisplay_Impl(const PREGDISPLAY, bool updateFloats = false); #endif // TARGET_X86 - BOOL TraceFrame(Thread *thread, BOOL fromPatch, + BOOL TraceFrame_Impl(Thread *thread, BOOL fromPatch, TraceDestination *trace, REGDISPLAY *regs) { WRAPPER_NO_CONTRACT; @@ -2056,9 +1890,6 @@ class PInvokeCalliFrame : public FramedMethodFrame trace->InitForUnmanaged(GetPInvokeCalliTarget()); return TRUE; } - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(PInvokeCalliFrame) }; // Some context-related forwards. @@ -2068,32 +1899,32 @@ class PInvokeCalliFrame : public FramedMethodFrame // it gets us back to where the return should have gone (and eventually will // go). //------------------------------------------------------------------------ + +typedef DPTR(class HijackFrame) PTR_HijackFrame; + class HijackFrame : public Frame { - VPTR_VTABLE_CLASS(HijackFrame, Frame) - VPTR_UNIQUE(VPTR_UNIQUE_HijackFrame); - public: // DACCESS: GetReturnAddressPtr should return the // target address of the return address in the frame. - virtual TADDR GetReturnAddressPtr() + TADDR GetReturnAddressPtr_Impl() { LIMITED_METHOD_DAC_CONTRACT; return PTR_HOST_MEMBER_TADDR(HijackFrame, this, m_ReturnAddress); } - virtual BOOL NeedsUpdateRegDisplay() + BOOL NeedsUpdateRegDisplay_Impl() { LIMITED_METHOD_CONTRACT; return TRUE; } - virtual void UpdateRegDisplay(const PREGDISPLAY, bool updateFloats = false); + void UpdateRegDisplay_Impl(const PREGDISPLAY, bool updateFloats = false); #ifdef TARGET_X86 // On x86 we need to specialcase return values - virtual void GcScanRoots(promote_func *fn, ScanContext* sc); + void GcScanRoots_Impl(promote_func *fn, ScanContext* sc); #else // On non-x86 platforms HijackFrame is just a more compact form of a resumable // frame with main difference that OnHijackTripThread captures just the registers @@ -2101,7 +1932,7 @@ class HijackFrame : public Frame // The regular reporting of a top frame will report everything that is live // after the call as specified in GC info, thus we do not need to worry about // return values. - virtual unsigned GetFrameAttribs() { + unsigned GetFrameAttribs_Impl() { LIMITED_METHOD_DAC_CONTRACT; return FRAME_ATTR_RESUMABLE; // Treat the next frame as the top frame. } @@ -2117,9 +1948,6 @@ class HijackFrame : public Frame TADDR m_ReturnAddress; PTR_Thread m_Thread; DPTR(HijackArgs) m_Args; - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(HijackFrame) }; #endif // FEATURE_HIJACK @@ -2130,40 +1958,37 @@ class HijackFrame : public Frame // stub, we need this frame to keep things straight. //------------------------------------------------------------------------ +typedef DPTR(class PrestubMethodFrame) PTR_PrestubMethodFrame; + class PrestubMethodFrame : public FramedMethodFrame { - VPTR_VTABLE_CLASS(PrestubMethodFrame, FramedMethodFrame) - public: PrestubMethodFrame(TransitionBlock * pTransitionBlock, MethodDesc * pMD); - virtual void GcScanRoots(promote_func *fn, ScanContext* sc) + void GcScanRoots_Impl(promote_func *fn, ScanContext* sc) { WRAPPER_NO_CONTRACT; - FramedMethodFrame::GcScanRoots(fn, sc); + FramedMethodFrame::GcScanRoots_Impl(fn, sc); PromoteCallerStack(fn, sc); } - BOOL TraceFrame(Thread *thread, BOOL fromPatch, + BOOL TraceFrame_Impl(Thread *thread, BOOL fromPatch, TraceDestination *trace, REGDISPLAY *regs); - int GetFrameType() + int GetFrameType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TYPE_INTERCEPTION; } // Our base class is an M2U TransitionType; but we're not. So override and set us back to None. - ETransitionType GetTransitionType() + ETransitionType GetTransitionType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TT_NONE; } - Interception GetInterception(); - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(PrestubMethodFrame) + Interception GetInterception_Impl(); }; //------------------------------------------------------------------------ @@ -2176,8 +2001,6 @@ class PrestubMethodFrame : public FramedMethodFrame class StubDispatchFrame : public FramedMethodFrame { - VPTR_VTABLE_CLASS(StubDispatchFrame, FramedMethodFrame) - // Representative MethodTable * and slot. They are used to // compute the MethodDesc* lazily PTR_MethodTable m_pRepresentativeMT; @@ -2193,23 +2016,23 @@ class StubDispatchFrame : public FramedMethodFrame public: StubDispatchFrame(TransitionBlock * pTransitionBlock); - MethodDesc* GetFunction(); + MethodDesc* GetFunction_Impl(); // Returns this frame GC ref map if it has one PTR_BYTE GetGCRefMap(); #ifdef TARGET_X86 - virtual void UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats = false); - virtual PCODE GetReturnAddress(); + void UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats = false); + PCODE GetReturnAddress_Impl(); #endif // TARGET_X86 PCODE GetUnadjustedReturnAddress() { LIMITED_METHOD_DAC_CONTRACT; - return FramedMethodFrame::GetReturnAddress(); + return FramedMethodFrame::GetReturnAddress_Impl(); } - virtual void GcScanRoots(promote_func *fn, ScanContext* sc); + void GcScanRoots_Impl(promote_func *fn, ScanContext* sc); #ifndef DACCESS_COMPILE void SetRepresentativeSlot(MethodTable * pMT, UINT32 representativeSlot) @@ -2236,18 +2059,18 @@ class StubDispatchFrame : public FramedMethodFrame } #endif - BOOL TraceFrame(Thread *thread, BOOL fromPatch, + BOOL TraceFrame_Impl(Thread *thread, BOOL fromPatch, TraceDestination *trace, REGDISPLAY *regs); - int GetFrameType() + int GetFrameType_Impl() { LIMITED_METHOD_CONTRACT; return TYPE_CALL; } - Interception GetInterception(); + Interception GetInterception_Impl(); - virtual BOOL SuppressParamTypeArg() + BOOL SuppressParamTypeArg_Impl() { // // Shared default interface methods (i.e. virtual interface methods with an implementation) require @@ -2265,37 +2088,31 @@ class StubDispatchFrame : public FramedMethodFrame private: friend class VirtualCallStubManager; - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(StubDispatchFrame) }; -typedef VPTR(class StubDispatchFrame) PTR_StubDispatchFrame; +typedef DPTR(class StubDispatchFrame) PTR_StubDispatchFrame; + +typedef DPTR(class CallCountingHelperFrame) PTR_CallCountingHelperFrame; class CallCountingHelperFrame : public FramedMethodFrame { - VPTR_VTABLE_CLASS(CallCountingHelperFrame, FramedMethodFrame); - public: CallCountingHelperFrame(TransitionBlock *pTransitionBlock, MethodDesc *pMD); - virtual void GcScanRoots(promote_func *fn, ScanContext *sc); // override - virtual BOOL TraceFrame(Thread *thread, BOOL fromPatch, TraceDestination *trace, REGDISPLAY *regs); // override + void GcScanRoots_Impl(promote_func *fn, ScanContext *sc); // override + BOOL TraceFrame_Impl(Thread *thread, BOOL fromPatch, TraceDestination *trace, REGDISPLAY *regs); // override - virtual int GetFrameType() // override + int GetFrameType_Impl() // override { LIMITED_METHOD_DAC_CONTRACT; return TYPE_CALL; } - virtual Interception GetInterception() // override + Interception GetInterception_Impl() // override { LIMITED_METHOD_DAC_CONTRACT; return INTERCEPTION_NONE; } - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(CallCountingHelperFrame) }; //------------------------------------------------------------------------ @@ -2306,8 +2123,6 @@ class CallCountingHelperFrame : public FramedMethodFrame class ExternalMethodFrame : public FramedMethodFrame { - VPTR_VTABLE_CLASS(ExternalMethodFrame, FramedMethodFrame) - // Indirection and containing module. Used to compute pGCRefMap lazily. PTR_Module m_pZapModule; TADDR m_pIndirection; @@ -2318,7 +2133,7 @@ class ExternalMethodFrame : public FramedMethodFrame public: ExternalMethodFrame(TransitionBlock * pTransitionBlock); - virtual void GcScanRoots(promote_func *fn, ScanContext* sc); + void GcScanRoots_Impl(promote_func *fn, ScanContext* sc); // Returns this frame GC ref map if it has one PTR_BYTE GetGCRefMap(); @@ -2333,51 +2148,43 @@ class ExternalMethodFrame : public FramedMethodFrame } #endif - int GetFrameType() + int GetFrameType_Impl() { LIMITED_METHOD_CONTRACT; return TYPE_CALL; } - Interception GetInterception(); + Interception GetInterception_Impl(); #ifdef TARGET_X86 - virtual void UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats = false); + void UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats = false); #endif - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(ExternalMethodFrame) }; -typedef VPTR(class ExternalMethodFrame) PTR_ExternalMethodFrame; +typedef DPTR(class ExternalMethodFrame) PTR_ExternalMethodFrame; #ifdef FEATURE_READYTORUN class DynamicHelperFrame : public FramedMethodFrame { - VPTR_VTABLE_CLASS(DynamicHelperFrame, FramedMethodFrame) - int m_dynamicHelperFrameFlags; public: DynamicHelperFrame(TransitionBlock * pTransitionBlock, int dynamicHelperFrameFlags); - virtual void GcScanRoots(promote_func *fn, ScanContext* sc); + void GcScanRoots_Impl(promote_func *fn, ScanContext* sc); #ifdef TARGET_X86 - virtual void UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats = false); + void UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats = false); #endif - virtual ETransitionType GetTransitionType() + ETransitionType GetTransitionType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TT_InternalCall; } - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(DynamicHelperFrame) }; -typedef VPTR(class DynamicHelperFrame) PTR_DynamicHelperFrame; +typedef DPTR(class DynamicHelperFrame) PTR_DynamicHelperFrame; #endif // FEATURE_READYTORUN #ifdef FEATURE_COMINTEROP @@ -2390,17 +2197,18 @@ typedef VPTR(class DynamicHelperFrame) PTR_DynamicHelperFrame; // which pinvoke-inlined a call to a COM interface, which happenned to be // implemented by a managed function via COM-interop. //------------------------------------------------------------------------ + +typedef DPTR(class ComPrestubMethodFrame) PTR_ComPrestubMethodFrame; + class ComPrestubMethodFrame : public ComMethodFrame { friend class CheckAsmOffsets; - VPTR_VTABLE_CLASS(ComPrestubMethodFrame, ComMethodFrame) - public: // Set the vptr and GSCookie VOID Init(); - int GetFrameType() + int GetFrameType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TYPE_INTERCEPTION; @@ -2408,26 +2216,22 @@ class ComPrestubMethodFrame : public ComMethodFrame // ComPrestubMethodFrame should return the same interception type as // code:PrestubMethodFrame.GetInterception. - virtual Interception GetInterception() + Interception GetInterception_Impl() { LIMITED_METHOD_DAC_CONTRACT; return INTERCEPTION_PRESTUB; } // Our base class is an M2U TransitionType; but we're not. So override and set us back to None. - virtual ETransitionType GetTransitionType() + ETransitionType GetTransitionType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TT_NONE; } - virtual void ExceptionUnwind() + void ExceptionUnwind_Impl() { } - -private: - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(ComPrestubMethodFrame) }; #endif // FEATURE_COMINTEROP @@ -2510,27 +2314,24 @@ struct ByRefInfo // ProtectByRefsFrame //----------------------------------------------------------------------------- +typedef DPTR(class ProtectByRefsFrame) PTR_ProtectByRefsFrame; + class ProtectByRefsFrame : public Frame { - VPTR_VTABLE_CLASS(ProtectByRefsFrame, Frame) - public: #ifndef DACCESS_COMPILE ProtectByRefsFrame(Thread *pThread, ByRefInfo *brInfo) - : m_brInfo(brInfo) + : Frame(FrameIdentifier::ProtectByRefsFrame), m_brInfo(brInfo) { WRAPPER_NO_CONTRACT; Frame::Push(pThread); } #endif - virtual void GcScanRoots(promote_func *fn, ScanContext *sc); + void GcScanRoots_Impl(promote_func *fn, ScanContext *sc); private: PTR_ByRefInfo m_brInfo; - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(ProtectByRefsFrame) }; @@ -2555,29 +2356,28 @@ struct ValueClassInfo // ProtectValueClassFrame //----------------------------------------------------------------------------- +typedef DPTR(class ProtectValueClassFrame) PTR_ProtectValueClassFrame; class ProtectValueClassFrame : public Frame { - VPTR_VTABLE_CLASS(ProtectValueClassFrame, Frame) - public: #ifndef DACCESS_COMPILE ProtectValueClassFrame() - : m_pVCInfo(NULL) + : Frame(FrameIdentifier::ProtectValueClassFrame), m_pVCInfo(NULL) { WRAPPER_NO_CONTRACT; Frame::Push(); } ProtectValueClassFrame(Thread *pThread, ValueClassInfo *vcInfo) - : m_pVCInfo(vcInfo) + : Frame(FrameIdentifier::ProtectValueClassFrame), m_pVCInfo(vcInfo) { WRAPPER_NO_CONTRACT; Frame::Push(pThread); } #endif - virtual void GcScanRoots(promote_func *fn, ScanContext *sc); + void GcScanRoots_Impl(promote_func *fn, ScanContext *sc); ValueClassInfo ** GetValueClassInfoList() { @@ -2588,9 +2388,6 @@ class ProtectValueClassFrame : public Frame private: ValueClassInfo *m_pVCInfo; - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_DTOR(ProtectValueClassFrame) }; @@ -2606,34 +2403,31 @@ BOOL IsProtectedByGCFrame(OBJECTREF *ppObjectRef); // GetFrameType and GetInterception. //------------------------------------------------------------------------ +typedef DPTR(class DebuggerClassInitMarkFrame) PTR_DebuggerClassInitMarkFrame; + class DebuggerClassInitMarkFrame : public Frame { - VPTR_VTABLE_CLASS(DebuggerClassInitMarkFrame, Frame) - public: #ifndef DACCESS_COMPILE - DebuggerClassInitMarkFrame() + DebuggerClassInitMarkFrame() : Frame(FrameIdentifier::DebuggerClassInitMarkFrame) { WRAPPER_NO_CONTRACT; Push(); }; #endif - virtual int GetFrameType() + int GetFrameType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TYPE_INTERCEPTION; } - virtual Interception GetInterception() + Interception GetInterception_Impl() { LIMITED_METHOD_DAC_CONTRACT; return INTERCEPTION_CLASS_INIT; } - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_DTOR(DebuggerClassInitMarkFrame) }; //------------------------------------------------------------------------ @@ -2642,20 +2436,20 @@ class DebuggerClassInitMarkFrame : public Frame // the stack. //------------------------------------------------------------------------ +typedef DPTR(class DebuggerExitFrame) PTR_DebuggerExitFrame; + class DebuggerExitFrame : public Frame { - VPTR_VTABLE_CLASS(DebuggerExitFrame, Frame) - public: #ifndef DACCESS_COMPILE - DebuggerExitFrame() + DebuggerExitFrame() : Frame(FrameIdentifier::DebuggerExitFrame) { WRAPPER_NO_CONTRACT; Push(); } #endif - virtual int GetFrameType() + int GetFrameType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TYPE_EXIT; @@ -2669,7 +2463,7 @@ class DebuggerExitFrame : public Frame // returnSP - the location returnIP is pushed onto the stack // during the call. // - virtual void GetUnmanagedCallSite(TADDR* ip, + void GetUnmanagedCallSite_Impl(TADDR* ip, TADDR* returnIP, TADDR* returnSP) { @@ -2683,9 +2477,6 @@ class DebuggerExitFrame : public Frame if (returnSP) *returnSP = 0; } - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_DTOR(DebuggerExitFrame) }; //--------------------------------------------------------------------------------------- @@ -2699,33 +2490,30 @@ class DebuggerExitFrame : public Frame // Currently this frame is only used in code:DispatchInfo.InvokeMember, which is an U2M transition. // +typedef DPTR(class DebuggerU2MCatchHandlerFrame) PTR_DebuggerU2MCatchHandlerFrame; + class DebuggerU2MCatchHandlerFrame : public Frame { - VPTR_VTABLE_CLASS(DebuggerU2MCatchHandlerFrame, Frame) - public: #ifndef DACCESS_COMPILE - DebuggerU2MCatchHandlerFrame() + DebuggerU2MCatchHandlerFrame() : Frame(FrameIdentifier::DebuggerU2MCatchHandlerFrame) { WRAPPER_NO_CONTRACT; Frame::Push(); } - DebuggerU2MCatchHandlerFrame(Thread * pThread) + DebuggerU2MCatchHandlerFrame(Thread * pThread) : Frame(FrameIdentifier::DebuggerU2MCatchHandlerFrame) { WRAPPER_NO_CONTRACT; Frame::Push(pThread); } #endif - ETransitionType GetTransitionType() + ETransitionType GetTransitionType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TT_U2M; } - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_DTOR(DebuggerU2MCatchHandlerFrame) }; // Frame for the Reverse PInvoke (i.e. UnmanagedCallersOnlyAttribute). @@ -2748,10 +2536,8 @@ typedef DPTR(class InlinedCallFrame) PTR_InlinedCallFrame; class InlinedCallFrame : public Frame { - VPTR_VTABLE_CLASS(InlinedCallFrame, Frame) - public: - virtual MethodDesc *GetFunction() + MethodDesc *GetFunction_Impl() { WRAPPER_NO_CONTRACT; if (FrameHasActiveCall(this) && HasFunction()) @@ -2775,7 +2561,7 @@ class InlinedCallFrame : public Frame // Retrieves the return address into the code that called out // to managed code - virtual TADDR GetReturnAddressPtr() + TADDR GetReturnAddressPtr_Impl() { WRAPPER_NO_CONTRACT; @@ -2786,7 +2572,7 @@ class InlinedCallFrame : public Frame return 0; } - virtual BOOL NeedsUpdateRegDisplay() + BOOL NeedsUpdateRegDisplay_Impl() { WRAPPER_NO_CONTRACT; return FrameHasActiveCall(this); @@ -2803,7 +2589,7 @@ class InlinedCallFrame : public Frame return PTR_MethodDesc(*PTR_TADDR(addr)); } - virtual void UpdateRegDisplay(const PREGDISPLAY, bool updateFloats = false); + void UpdateRegDisplay_Impl(const PREGDISPLAY, bool updateFloats = false); // m_Datum contains MethodDesc ptr or // - on 64 bit host: CALLI target address (if lowest bit is set) @@ -2859,7 +2645,7 @@ class InlinedCallFrame : public Frame SUPPORTS_DAC; return pFrame && pFrame != FRAME_TOP && - InlinedCallFrame::GetMethodFrameVPtr() == pFrame->GetVTablePtr() && + FrameIdentifier::InlinedCallFrame == pFrame->GetFrameIdentifier() && dac_cast(dac_cast(pFrame)->m_pCallerReturnAddress) != 0; } @@ -2869,13 +2655,13 @@ class InlinedCallFrame : public Frame m_pCallerReturnAddress = 0; } - int GetFrameType() + int GetFrameType_Impl() { LIMITED_METHOD_DAC_CONTRACT; return TYPE_EXIT; } - virtual BOOL IsTransitionToNativeFrame() + BOOL IsTransitionToNativeFrame_Impl() { LIMITED_METHOD_CONTRACT; return TRUE; @@ -2895,9 +2681,6 @@ class InlinedCallFrame : public Frame // Set the vptr and GSCookie VOID Init(); - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(InlinedCallFrame) }; // TODO [DAVBR]: For the full fix for VsWhidbey 450273, this @@ -2926,10 +2709,10 @@ bool isRetAddr(TADDR retAddr, TADDR* whereCalled); // as tail calls on interface calls are uncommon. //------------------------------------------------------------------------ +typedef DPTR(class TailCallFrame) PTR_TailCallFrame; + class TailCallFrame : public Frame { - VPTR_VTABLE_CLASS(TailCallFrame, Frame) - TADDR m_CallerAddress; // the address the tailcall was initiated from CalleeSavedRegisters m_regs; // callee saved registers - the stack walk assumes that all non-JIT frames have them TADDR m_ReturnAddress; // the return address of the tailcall @@ -2939,9 +2722,9 @@ class TailCallFrame : public Frame { LIMITED_METHOD_CONTRACT; // loop through the frame chain - while (pFrame->GetVTablePtr() != TailCallFrame::GetMethodFrameVPtr()) + while (pFrame->GetFrameIdentifier() != FrameIdentifier::TailCallFrame) pFrame = pFrame->m_Next; - return (TailCallFrame*)pFrame; + return dac_cast(pFrame); } TADDR GetCallerAddress() @@ -2950,23 +2733,19 @@ class TailCallFrame : public Frame return m_CallerAddress; } - virtual TADDR GetReturnAddressPtr() + TADDR GetReturnAddressPtr_Impl() { LIMITED_METHOD_DAC_CONTRACT; return PTR_HOST_MEMBER_TADDR(TailCallFrame, this, m_ReturnAddress); } - virtual BOOL NeedsUpdateRegDisplay() + BOOL NeedsUpdateRegDisplay_Impl() { return TRUE; } - virtual void UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats = false); - -private: - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(TailCallFrame) + void UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats = false); }; #endif // TARGET_X86 && !UNIX_X86_ABI @@ -2975,14 +2754,15 @@ class TailCallFrame : public Frame // life is to set SHADOW_SP_FILTER_DONE during unwind from exception filter. //------------------------------------------------------------------------ +typedef DPTR(class ExceptionFilterFrame) PTR_ExceptionFilterFrame; + class ExceptionFilterFrame : public Frame { - VPTR_VTABLE_CLASS(ExceptionFilterFrame, Frame) size_t* m_pShadowSP; public: #ifndef DACCESS_COMPILE - ExceptionFilterFrame(size_t* pShadowSP) + ExceptionFilterFrame(size_t* pShadowSP) : Frame(FrameIdentifier::ExceptionFilterFrame) { WRAPPER_NO_CONTRACT; m_pShadowSP = pShadowSP; @@ -3010,29 +2790,27 @@ class ExceptionFilterFrame : public Frame } } #endif - -private: - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(ExceptionFilterFrame) }; #ifdef _DEBUG // We use IsProtectedByGCFrame to check if some OBJECTREF pointers are protected // against GC. That function doesn't know if a byref is from managed stack thus -// protected by JIT. AssumeByrefFromJITStack is used to bypass that check if an +// protected by JIT. AssumeByrefFromJITStackFrame is used to bypass that check if an // OBJECTRef pointer is passed from managed code to an FCall and it's in stack. -class AssumeByrefFromJITStack : public Frame + +typedef DPTR(class AssumeByrefFromJITStackFrame) PTR_AssumeByrefFromJITStackFrame; + +class AssumeByrefFromJITStackFrame : public Frame { - VPTR_VTABLE_CLASS(AssumeByrefFromJITStack, Frame) public: #ifndef DACCESS_COMPILE - AssumeByrefFromJITStack(OBJECTREF *pObjRef) + AssumeByrefFromJITStackFrame(OBJECTREF *pObjRef) : Frame(FrameIdentifier::AssumeByrefFromJITStackFrame) { m_pObjRef = pObjRef; } #endif - BOOL Protects(OBJECTREF *ppORef) + BOOL Protects_Impl(OBJECTREF *ppORef) { LIMITED_METHOD_CONTRACT; return ppORef == m_pObjRef; @@ -3040,176 +2818,10 @@ class AssumeByrefFromJITStack : public Frame private: OBJECTREF *m_pObjRef; - - // Keep as last entry in class - DEFINE_VTABLE_GETTER_AND_DTOR(AssumeByrefFromJITStack) -}; //AssumeByrefFromJITStack - -#endif //_DEBUG - -//----------------------------------------------------------------------------- -// FrameWithCookie is used to declare a Frame in source code with a cookie -// immediately preceding it. -// This is just a specialized version of GSCookieFor -// -// For Frames that are set up by stubs, the stub is responsible for setting up -// the GSCookie. -// -// Note that we have to play all these games for the GSCookie as the GSCookie -// needs to precede the vtable pointer, so that the GSCookie is guaranteed to -// catch any stack-buffer-overrun corruptions that overwrite the Frame data. -// -//----------------------------------------------------------------------------- - -class DebuggerEval; - -class GCSafeCollection; - -template -class FrameWithCookie -{ -protected: - - GSCookie m_gsCookie; - FrameType m_frame; - -public: - - // - // Overload all the required constructors - // - - FrameWithCookie() : - m_gsCookie(GetProcessGSCookie()), m_frame() { WRAPPER_NO_CONTRACT; } - - FrameWithCookie(Thread * pThread) : - m_gsCookie(GetProcessGSCookie()), m_frame(pThread) { WRAPPER_NO_CONTRACT; } - - FrameWithCookie(T_CONTEXT * pContext) : - m_gsCookie(GetProcessGSCookie()), m_frame(pContext) { WRAPPER_NO_CONTRACT; } - - FrameWithCookie(TransitionBlock * pTransitionBlock) : - m_gsCookie(GetProcessGSCookie()), m_frame(pTransitionBlock) { WRAPPER_NO_CONTRACT; } - - FrameWithCookie(TransitionBlock * pTransitionBlock, MethodDesc * pMD) : - m_gsCookie(GetProcessGSCookie()), m_frame(pTransitionBlock, pMD) { WRAPPER_NO_CONTRACT; } - - FrameWithCookie(TransitionBlock * pTransitionBlock, VASigCookie * pVASigCookie, PCODE pUnmanagedTarget) : - m_gsCookie(GetProcessGSCookie()), m_frame(pTransitionBlock, pVASigCookie, pUnmanagedTarget) { WRAPPER_NO_CONTRACT; } - - FrameWithCookie(TransitionBlock * pTransitionBlock, int frameFlags) : - m_gsCookie(GetProcessGSCookie()), m_frame(pTransitionBlock, frameFlags) { WRAPPER_NO_CONTRACT; } - - - // GCFrame - FrameWithCookie(Thread * pThread, OBJECTREF *pObjRefs, UINT numObjRefs, BOOL maybeInterior) : - m_gsCookie(GetProcessGSCookie()), m_frame(pThread, pObjRefs, numObjRefs, maybeInterior) { WRAPPER_NO_CONTRACT; } - - FrameWithCookie(OBJECTREF *pObjRefs, UINT numObjRefs, BOOL maybeInterior) : - m_gsCookie(GetProcessGSCookie()), m_frame(pObjRefs, numObjRefs, maybeInterior) { WRAPPER_NO_CONTRACT; } - - // GCSafeCollectionFrame - FrameWithCookie(GCSafeCollection *gcSafeCollection) : - m_gsCookie(GetProcessGSCookie()), m_frame(gcSafeCollection) { WRAPPER_NO_CONTRACT; } - - // HijackFrame - FrameWithCookie(LPVOID returnAddress, Thread *thread, HijackArgs *args) : - m_gsCookie(GetProcessGSCookie()), m_frame(returnAddress, thread, args) { WRAPPER_NO_CONTRACT; } - -#ifdef DEBUGGING_SUPPORTED - // FuncEvalFrame - FrameWithCookie(DebuggerEval *pDebuggerEval, TADDR returnAddress, BOOL showFrame) : - m_gsCookie(GetProcessGSCookie()), m_frame(pDebuggerEval, returnAddress, showFrame) { WRAPPER_NO_CONTRACT; } -#endif // DEBUGGING_SUPPORTED - -#ifndef DACCESS_COMPILE - // GSCookie for HelperMethodFrames is initialized in a common HelperMethodFrame init method - - // HelperMethodFrame - FORCEINLINE FrameWithCookie(void* fCallFtnEntry, unsigned attribs = 0) : - m_frame(fCallFtnEntry, attribs) { WRAPPER_NO_CONTRACT; } - - // HelperMethodFrame_1OBJ - FORCEINLINE FrameWithCookie(void* fCallFtnEntry, unsigned attribs, OBJECTREF * aGCPtr1) : - m_frame(fCallFtnEntry, attribs, aGCPtr1) { WRAPPER_NO_CONTRACT; } - - // HelperMethodFrame_2OBJ - FORCEINLINE FrameWithCookie(void* fCallFtnEntry, unsigned attribs, OBJECTREF * aGCPtr1, OBJECTREF * aGCPtr2) : - m_frame(fCallFtnEntry, attribs, aGCPtr1, aGCPtr2) { WRAPPER_NO_CONTRACT; } - - // HelperMethodFrame_3OBJ - FORCEINLINE FrameWithCookie(void* fCallFtnEntry, unsigned attribs, OBJECTREF * aGCPtr1, OBJECTREF * aGCPtr2, OBJECTREF * aGCPtr3) : - m_frame(fCallFtnEntry, attribs, aGCPtr1, aGCPtr2, aGCPtr3) { WRAPPER_NO_CONTRACT; } - - // HelperMethodFrame_PROTECTOBJ - FORCEINLINE FrameWithCookie(void* fCallFtnEntry, unsigned attribs, OBJECTREF* pObjRefs, int numObjRefs) : - m_frame(fCallFtnEntry, attribs, pObjRefs, numObjRefs) { WRAPPER_NO_CONTRACT; } - -#endif // DACCESS_COMPILE - - // ProtectByRefsFrame - FrameWithCookie(Thread * pThread, ByRefInfo * pByRefs) : - m_gsCookie(GetProcessGSCookie()), m_frame(pThread, pByRefs) { WRAPPER_NO_CONTRACT; } - - // ProtectValueClassFrame - FrameWithCookie(Thread * pThread, ValueClassInfo * pValueClasses) : - m_gsCookie(GetProcessGSCookie()), m_frame(pThread, pValueClasses) { WRAPPER_NO_CONTRACT; } - - // ExceptionFilterFrame - FrameWithCookie(size_t* pShadowSP) : - m_gsCookie(GetProcessGSCookie()), m_frame(pShadowSP) { WRAPPER_NO_CONTRACT; } - -#ifdef _DEBUG - // AssumeByrefFromJITStack - FrameWithCookie(OBJECTREF *pObjRef) : - m_gsCookie(GetProcessGSCookie()), m_frame(pObjRef) { WRAPPER_NO_CONTRACT; } - - void SetAddrOfHaveCheckedRestoreState(BOOL* pDoneCheck) - { - WRAPPER_NO_CONTRACT; - m_frame.SetAddrOfHaveCheckedRestoreState(pDoneCheck); - } +}; //AssumeByrefFromJITStackFrame #endif //_DEBUG - // - // Overload some common Frame methods for easy redirection - // - - void Push() { WRAPPER_NO_CONTRACT; m_frame.Push(); } - void Pop() { WRAPPER_NO_CONTRACT; m_frame.Pop(); } - void Push(Thread * pThread) { WRAPPER_NO_CONTRACT; m_frame.Push(pThread); } - void Pop(Thread * pThread) { WRAPPER_NO_CONTRACT; m_frame.Pop(pThread); } - PCODE GetReturnAddress() { WRAPPER_NO_CONTRACT; return m_frame.GetReturnAddress(); } - T_CONTEXT * GetContext() { WRAPPER_NO_CONTRACT; return m_frame.GetContext(); } - FrameType* operator&() { LIMITED_METHOD_CONTRACT; return &m_frame; } - LazyMachState * MachineState() { WRAPPER_NO_CONTRACT; return m_frame.MachineState(); } - Thread * GetThread() { WRAPPER_NO_CONTRACT; return m_frame.GetThread(); } - BOOL EnsureInit(struct MachState* unwindState) - { WRAPPER_NO_CONTRACT; return m_frame.EnsureInit(unwindState); } - void Poll() { WRAPPER_NO_CONTRACT; m_frame.Poll(); } - void SetStackPointerPtr(TADDR sp) { WRAPPER_NO_CONTRACT; m_frame.SetStackPointerPtr(sp); } - void InitAndLink(T_CONTEXT *pContext) { WRAPPER_NO_CONTRACT; m_frame.InitAndLink(pContext); } - void InitAndLink(Thread *pThread) { WRAPPER_NO_CONTRACT; m_frame.InitAndLink(pThread); } - void Init(Thread *pThread, OBJECTREF *pObjRefs, UINT numObjRefs, BOOL maybeInterior) - { WRAPPER_NO_CONTRACT; m_frame.Init(pThread, pObjRefs, numObjRefs, maybeInterior); } - ValueClassInfo ** GetValueClassInfoList() { WRAPPER_NO_CONTRACT; return m_frame.GetValueClassInfoList(); } - -#if 0 - // - // Access to the underlying Frame - // You should only need to use this if none of the above overloads work for you - // Consider adding the required overload to the list above - // - - FrameType& operator->() { LIMITED_METHOD_CONTRACT; return m_frame; } -#endif - - // Since the "&" operator is overloaded, use this function to get to the - // address of FrameWithCookie, rather than that of FrameWithCookie::m_frame. - GSCookie * GetGSCookiePtr() { LIMITED_METHOD_CONTRACT; return &m_gsCookie; } -}; - //------------------------------------------------------------------------ // These macros GC-protect OBJECTREF pointers on the EE's behalf. // In between these macros, the GC can move but not discard the protected @@ -3346,14 +2958,14 @@ class FrameWithCookie /*pointer points to GC heap, the FCall still needs to protect it explicitly */ \ ASSERT_ADDRESS_IN_STACK (__objRef); \ do { \ - FrameWithCookie __dummyAssumeByrefFromJITStack ((__objRef)); \ - __dummyAssumeByrefFromJITStack.Push (); \ + AssumeByrefFromJITStackFrame __dummyAssumeByrefFromJITStackFrame ((__objRef)); \ + __dummyAssumeByrefFromJITStackFrame.Push (); \ /* work around unreachable code warning */ \ if (true) { DEBUG_ASSURE_NO_RETURN_BEGIN(GC_PROTECT) #define ASSUME_BYREF_FROM_JIT_STACK_END() \ DEBUG_ASSURE_NO_RETURN_END(GC_PROTECT) } \ - __dummyAssumeByrefFromJITStack.Pop(); } while(0) + __dummyAssumeByrefFromJITStackFrame.Pop(); } while(0) #else //defined (_DEBUG) && !defined (DACCESS_COMPILE) #define ASSUME_BYREF_FROM_JIT_STACK_BEGIN(__objRef) #define ASSUME_BYREF_FROM_JIT_STACK_END() diff --git a/src/coreclr/vm/gccover.cpp b/src/coreclr/vm/gccover.cpp index 3df7fe4448322f..0ab784723c291b 100644 --- a/src/coreclr/vm/gccover.cpp +++ b/src/coreclr/vm/gccover.cpp @@ -864,7 +864,7 @@ void DoGcStress (PCONTEXT regs, NativeCodeVersion nativeCodeVersion) // If we redirect for gc stress, we don't need this frame on the stack, // the redirection will push a resumable frame. // - FrameWithCookie frame(regs); + ResumableFrame frame(regs); if (!Thread::UseRedirectForGcStress()) { frame.Push(pThread); @@ -1179,7 +1179,7 @@ void DoGcStress (PCONTEXT regs, NativeCodeVersion nativeCodeVersion) // If we redirect for gc stress, we don't need this frame on the stack, // the redirection will push a resumable frame. // - FrameWithCookie frame(regs); + ResumableFrame frame(regs); if (!Thread::UseRedirectForGcStress()) { frame.Push(pThread); diff --git a/src/coreclr/vm/gcenv.ee.common.cpp b/src/coreclr/vm/gcenv.ee.common.cpp index 43373bc591c5c6..34d40e85a2e5dd 100644 --- a/src/coreclr/vm/gcenv.ee.common.cpp +++ b/src/coreclr/vm/gcenv.ee.common.cpp @@ -104,9 +104,9 @@ inline bool SafeToReportGenericParamContext(CrawlFrame* pCF) { LIMITED_METHOD_CONTRACT; - if (!pCF->IsFrameless() && pCF->GetFrame()->GetVTablePtr() == StubDispatchFrame::GetMethodFrameVPtr()) + if (!pCF->IsFrameless() && pCF->GetFrame()->GetFrameIdentifier() == FrameIdentifier::StubDispatchFrame) { - return !((StubDispatchFrame*)pCF->GetFrame())->SuppressParamTypeArg(); + return !(dac_cast(pCF->GetFrame()))->SuppressParamTypeArg(); } if (!pCF->IsFrameless() || !(pCF->IsActiveFrame() || pCF->IsInterrupted())) diff --git a/src/coreclr/vm/gcenv.ee.cpp b/src/coreclr/vm/gcenv.ee.cpp index 55329274905a5d..9525de49fd83b2 100644 --- a/src/coreclr/vm/gcenv.ee.cpp +++ b/src/coreclr/vm/gcenv.ee.cpp @@ -143,7 +143,7 @@ static void ScanStackRoots(Thread * pThread, promote_func* fn, ScanContext* sc) if (InlinedCallFrame::FrameHasActiveCall(pTopFrame)) { // It is an InlinedCallFrame with active call. Get SP from it. - InlinedCallFrame* pInlinedFrame = (InlinedCallFrame*)pTopFrame; + InlinedCallFrame* pInlinedFrame = dac_cast(pTopFrame); topStack = (Object **)pInlinedFrame->GetCallSiteSP(); } #endif // FEATURE_CONSERVATIVE_GC || USE_FEF diff --git a/src/coreclr/vm/i386/PInvokeStubs.asm b/src/coreclr/vm/i386/PInvokeStubs.asm index a0bc18d616bce1..67262c8b093b9a 100644 --- a/src/coreclr/vm/i386/PInvokeStubs.asm +++ b/src/coreclr/vm/i386/PInvokeStubs.asm @@ -20,8 +20,6 @@ option casemap:none .code -extern _s_gsCookie:DWORD -extern ??_7InlinedCallFrame@@6B@:DWORD extern _g_TrapReturningThreads:DWORD extern _JIT_PInvokeEndRarePath@0:proc @@ -37,13 +35,8 @@ extern _JIT_PInvokeEndRarePath@0:proc ; _JIT_PInvokeBegin@4 PROC public - mov eax, dword ptr [_s_gsCookie] - mov dword ptr [ecx], eax - add ecx, SIZEOF_GSCookie - - ;; set first slot to the value of InlinedCallFrame::`vftable' (checked by runtime code) - lea eax,[??_7InlinedCallFrame@@6B@] - mov dword ptr [ecx], eax + ;; set first slot to the value of InlinedCallFrame identifier (checked by runtime code) + mov dword ptr [ecx], FRAMETYPE_InlinedCallFrame mov dword ptr [ecx + InlinedCallFrame__m_Datum], edx @@ -81,8 +74,6 @@ _JIT_PInvokeBegin@4 ENDP ; _JIT_PInvokeEnd@4 PROC public - add ecx, SIZEOF_GSCookie - ;; edx = GetThread(). Trashes eax INLINE_GETTHREAD edx, eax diff --git a/src/coreclr/vm/i386/asmconstants.h b/src/coreclr/vm/i386/asmconstants.h index 396381f6c1f539..280f4f6c51904e 100644 --- a/src/coreclr/vm/i386/asmconstants.h +++ b/src/coreclr/vm/i386/asmconstants.h @@ -32,6 +32,14 @@ #define DBG_FRE(dbg,fre) fre #endif +#define FRAMETYPE_InlinedCallFrame 0x1 +ASMCONSTANTS_C_ASSERT(FRAMETYPE_InlinedCallFrame == (int)FrameIdentifier::InlinedCallFrame) + +#if defined(TARGET_X86) && !defined(UNIX_X86_ABI) +#define FRAMETYPE_TailCallFrame 0x2 +ASMCONSTANTS_C_ASSERT(FRAMETYPE_TailCallFrame == (int)FrameIdentifier::TailCallFrame) +#endif + #define INITIAL_SUCCESS_COUNT 0x100 #define DynamicHelperFrameFlags_Default 0 @@ -147,8 +155,6 @@ ASMCONSTANTS_C_ASSERT(VASigCookie__StubOffset == offsetof(VASigCookie, pNDirectI ASMCONSTANTS_C_ASSERT(SIZEOF_TailCallFrame == sizeof(TailCallFrame)) #endif // !UNIX_X86_ABI -#define SIZEOF_GSCookie 4 - // ICodeManager::SHADOW_SP_IN_FILTER from clr/src/inc/eetwain.h #define SHADOW_SP_IN_FILTER_ASM 0x1 ASMCONSTANTS_C_ASSERT(SHADOW_SP_IN_FILTER_ASM == ICodeManager::SHADOW_SP_IN_FILTER) diff --git a/src/coreclr/vm/i386/asmhelpers.asm b/src/coreclr/vm/i386/asmhelpers.asm index 2f1d12c6d9a71e..6bbd62a31624dc 100644 --- a/src/coreclr/vm/i386/asmhelpers.asm +++ b/src/coreclr/vm/i386/asmhelpers.asm @@ -1222,14 +1222,12 @@ _GenericComCallStub@0 proc public push edi push eax ; UnmanagedToManagedFrame::m_pvDatum = ComCallMethodDesc* - sub esp, (SIZEOF_GSCookie + OFFSETOF__UnmanagedToManagedFrame__m_pvDatum) + sub esp, OFFSETOF__UnmanagedToManagedFrame__m_pvDatum - lea eax, [esp+SIZEOF_GSCookie] - - push eax + push esp call _COMToCLRWorker@4 - add esp, (SIZEOF_GSCookie + OFFSETOF__UnmanagedToManagedFrame__m_pvDatum) + add esp, OFFSETOF__UnmanagedToManagedFrame__m_pvDatum ; pop the ComCallMethodDesc* pop ecx @@ -1272,10 +1270,10 @@ _ComCallPreStub@0 proc public push edi push eax ; ComCallMethodDesc* - sub esp, 5*4 ; next, vtable, gscookie, 64-bit error return + sub esp, 4*4 ; next, vtable, 64-bit error return - lea edi, [esp] - lea esi, [esp+3*4] + lea edi, [esp] ; Point at the 64-bit error return + lea esi, [esp+2*4] ; Leave space for the 64-bit error return push edi ; pErrorReturn push esi ; pFrame @@ -1285,7 +1283,7 @@ _ComCallPreStub@0 proc public cmp eax, 0 je nostub ; oops we could not create a stub - add esp, 6*4 + add esp, 5*4 ; Pop off 64-bit error return, vtable, next and ComCallMethodDesc* ; pop CalleeSavedRegisters pop edi @@ -1308,7 +1306,7 @@ nostub: mov eax, [edi] mov edx, [edi+4] - add esp, 6*4 + add esp, 5*4 ; Pop off 64-bit error return, vtable, next and ComCallMethodDesc* ; pop CalleeSavedRegisters pop edi diff --git a/src/coreclr/vm/i386/cgenx86.cpp b/src/coreclr/vm/i386/cgenx86.cpp index c4fe9b265ed62e..86325672575d64 100644 --- a/src/coreclr/vm/i386/cgenx86.cpp +++ b/src/coreclr/vm/i386/cgenx86.cpp @@ -137,7 +137,7 @@ void EHContext::UpdateFrame(PREGDISPLAY regs) } #endif // FEATURE_EH_FUNCLETS -void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void TransitionFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACT_VOID { @@ -155,7 +155,7 @@ void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) UpdateRegDisplayHelper(pRD, pFunc->CbStackPop()); - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK TransitionFrame::UpdateRegDisplay(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK TransitionFrame::UpdateRegDisplay_Impl(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); RETURN; } @@ -207,7 +207,7 @@ void TransitionFrame::UpdateRegDisplayHelper(const PREGDISPLAY pRD, UINT cbStack RETURN; } -void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void HelperMethodFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACT_VOID { @@ -386,7 +386,7 @@ EXTERN_C MachState* STDCALL HelperMethodFrameConfirmState(HelperMethodFrame* fra } #endif -void ExternalMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void ExternalMethodFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACT_VOID { @@ -399,13 +399,13 @@ void ExternalMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFlo UpdateRegDisplayHelper(pRD, CbStackPopUsingGCRefMap(GetGCRefMap())); - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK ExternalMethodFrane::UpdateRegDisplay(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK ExternalMethodFrane::UpdateRegDisplay_Impl(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); RETURN; } -void StubDispatchFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void StubDispatchFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACT_VOID { @@ -424,7 +424,7 @@ void StubDispatchFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloat else if (GetFunction() != NULL) { - FramedMethodFrame::UpdateRegDisplay(pRD); + FramedMethodFrame::UpdateRegDisplay_Impl(pRD); } else { @@ -438,12 +438,12 @@ void StubDispatchFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloat pRD->ControlPC = GetAdjustedCallAddress(pRD->ControlPC); } - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK StubDispatchFrame::UpdateRegDisplay(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK StubDispatchFrame::UpdateRegDisplay_Impl(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); RETURN; } -PCODE StubDispatchFrame::GetReturnAddress() +PCODE StubDispatchFrame::GetReturnAddress_Impl() { CONTRACTL { @@ -452,7 +452,7 @@ PCODE StubDispatchFrame::GetReturnAddress() } CONTRACTL_END; - PCODE retAddress = FramedMethodFrame::GetReturnAddress(); + PCODE retAddress = FramedMethodFrame::GetReturnAddress_Impl(); if (GetFunction() == NULL && GetGCRefMap() == NULL) { // See comment in code:StubDispatchFrame::UpdateRegDisplay @@ -461,7 +461,7 @@ PCODE StubDispatchFrame::GetReturnAddress() return retAddress; } -void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void FaultingExceptionFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACT_VOID { @@ -512,12 +512,12 @@ void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool update #endif // FEATURE_EH_FUNCLETS - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK FaultingExceptionFrame::UpdateRegDisplay(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK FaultingExceptionFrame::UpdateRegDisplay_Impl(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); RETURN; } -void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void InlinedCallFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACT_VOID { @@ -595,7 +595,7 @@ void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats #endif // FEATURE_EH_FUNCLETS - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK InlinedCallFrame::UpdateRegDisplay(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK InlinedCallFrame::UpdateRegDisplay_Impl(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); RETURN; } @@ -604,13 +604,13 @@ void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats //========================== // Resumable Exception Frame // -TADDR ResumableFrame::GetReturnAddressPtr() +TADDR ResumableFrame::GetReturnAddressPtr_Impl() { LIMITED_METHOD_DAC_CONTRACT; return dac_cast(m_Regs) + offsetof(CONTEXT, Eip); } -void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void ResumableFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACT_VOID { @@ -683,14 +683,14 @@ void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) #endif // !FEATURE_EH_FUNCLETS - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK ResumableFrame::UpdateRegDisplay(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK ResumableFrame::UpdateRegDisplay_Impl(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); RETURN; } // The HijackFrame has to know the registers that are pushed by OnHijackTripThread // -> HijackFrame::UpdateRegDisplay should restore all the registers pushed by OnHijackTripThread -void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void HijackFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACTL { NOTHROW; @@ -741,12 +741,12 @@ void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) #endif // FEATURE_EH_FUNCLETS - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK HijackFrame::UpdateRegDisplay(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK HijackFrame::UpdateRegDisplay_Impl(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); } #endif // FEATURE_HIJACK -void PInvokeCalliFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void PInvokeCalliFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACT_VOID { @@ -760,13 +760,13 @@ void PInvokeCalliFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloat VASigCookie *pVASigCookie = GetVASigCookie(); UpdateRegDisplayHelper(pRD, pVASigCookie->sizeOfArgs); - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK PInvokeCalliFrame::UpdateRegDisplay(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK PInvokeCalliFrame::UpdateRegDisplay_Impl(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); RETURN; } #ifndef UNIX_X86_ABI -void TailCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void TailCallFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACT_VOID { @@ -806,14 +806,14 @@ void TailCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) #endif - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK TailCallFrame::UpdateRegDisplay(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK TailCallFrame::UpdateRegDisplay_Impl(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); RETURN; } #endif // !UNIX_X86_ABI #ifdef FEATURE_READYTORUN -void DynamicHelperFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void DynamicHelperFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { WRAPPER_NO_CONTRACT; UpdateRegDisplayHelper(pRD, 0); @@ -877,30 +877,25 @@ Stub *GenerateInitPInvokeFrameHelper() CORINFO_EE_INFO::InlinedCallFrameInfo FrameInfo; InlinedCallFrame::GetEEInfo(&FrameInfo); - // EDI contains address of the frame on stack (the frame ptr, not its negspace) - unsigned negSpace = FrameInfo.offsetOfFrameVptr; + // EDI contains address of the frame on stack // mov esi, GetThread() psl->X86EmitCurrentThreadFetch(kESI, (1 << kEDI) | (1 << kEBX) | (1 << kECX) | (1 << kEDX)); - // mov [edi + FrameInfo.offsetOfGSCookie], GetProcessGSCookie() - psl->X86EmitOffsetModRM(0xc7, (X86Reg)0x0, kEDI, FrameInfo.offsetOfGSCookie - negSpace); - psl->Emit32(GetProcessGSCookie()); - - // mov [edi + FrameInfo.offsetOfFrameVptr], InlinedCallFrame::GetFrameVtable() - psl->X86EmitOffsetModRM(0xc7, (X86Reg)0x0, kEDI, FrameInfo.offsetOfFrameVptr - negSpace); - psl->Emit32(InlinedCallFrame::GetMethodFrameVPtr()); + // mov [edi], InlinedCallFrame::GetFrameVtable() + psl->X86EmitOffsetModRM(0xc7, (X86Reg)0x0, kEDI, 0); + psl->Emit32((DWORD)FrameIdentifier::InlinedCallFrame); // mov eax, [esi + offsetof(Thread, m_pFrame)] // mov [edi + FrameInfo.offsetOfFrameLink], eax psl->X86EmitIndexRegLoad(kEAX, kESI, offsetof(Thread, m_pFrame)); - psl->X86EmitIndexRegStore(kEDI, FrameInfo.offsetOfFrameLink - negSpace, kEAX); + psl->X86EmitIndexRegStore(kEDI, FrameInfo.offsetOfFrameLink, kEAX); // mov [edi + FrameInfo.offsetOfCalleeSavedEbp], ebp - psl->X86EmitIndexRegStore(kEDI, FrameInfo.offsetOfCalleeSavedFP - negSpace, kEBP); + psl->X86EmitIndexRegStore(kEDI, FrameInfo.offsetOfCalleeSavedFP, kEBP); // mov [edi + FrameInfo.offsetOfReturnAddress], 0 - psl->X86EmitOffsetModRM(0xc7, (X86Reg)0x0, kEDI, FrameInfo.offsetOfReturnAddress - negSpace); + psl->X86EmitOffsetModRM(0xc7, (X86Reg)0x0, kEDI, FrameInfo.offsetOfReturnAddress); psl->Emit32(0); // mov [esi + offsetof(Thread, m_pFrame)], edi diff --git a/src/coreclr/vm/i386/excepx86.cpp b/src/coreclr/vm/i386/excepx86.cpp index 2fbae9d9e724d2..84410a0937bc8a 100644 --- a/src/coreclr/vm/i386/excepx86.cpp +++ b/src/coreclr/vm/i386/excepx86.cpp @@ -651,7 +651,7 @@ CPFH_RealFirstPassHandler( // ExceptionContinueSearch, etc. #if defined(USE_FEF) BOOL bPopFaultingExceptionFrame = FALSE; - FrameWithCookie faultingExceptionFrame; + FaultingExceptionFrame faultingExceptionFrame; #endif // USE_FEF ExInfo* pExInfo = &(pThread->GetExceptionState()->m_currentExInfo); @@ -690,7 +690,7 @@ CPFH_RealFirstPassHandler( // ExceptionContinueSearch, etc. if (fIsManagedCode && fPGCDisabledOnEntry && (pThread->m_pFrame == FRAME_TOP || - pThread->m_pFrame->GetVTablePtr() != FaultingExceptionFrame::GetMethodFrameVPtr() || + pThread->m_pFrame->GetFrameIdentifier() != FrameIdentifier::FaultingExceptionFrame || (size_t)pThread->m_pFrame > (size_t)pEstablisherFrame)) { // setup interrupted frame so that GC during calls to init won't collect the frames @@ -2167,7 +2167,7 @@ StackWalkAction COMPlusThrowCallback( // SWA value if (pData->pPrevExceptionRecord) { // FCALLS have an extra SEH record in debug because of the desctructor // associated with ForbidGC checking. This is benign, so just ignore it. - if (pFrame) _ASSERTE(pData->pPrevExceptionRecord < pFrame || pFrame->GetVTablePtr() == HelperMethodFrame::GetMethodFrameVPtr()); + if (pFrame) _ASSERTE(pData->pPrevExceptionRecord < pFrame || pFrame->GetFrameIdentifier() == FrameIdentifier::HelperMethodFrame); if (pCf->IsFrameless()) _ASSERTE((ULONG_PTR)pData->pPrevExceptionRecord <= GetRegdisplaySP(pCf->GetRegisterSet())); } } @@ -2668,7 +2668,7 @@ StackWalkAction COMPlusUnwindCallback (CrawlFrame *pCf, ThrowCallbackType *pData // Make the filter as done. See comment in CallJitEHFilter // on why we have to do it here. Frame* pFilterFrame = pThread->GetFrame(); - _ASSERTE(pFilterFrame->GetVTablePtr() == ExceptionFilterFrame::GetMethodFrameVPtr()); + _ASSERTE(pFilterFrame->GetFrameIdentifier() == FrameIdentifier::ExceptionFilterFrame); ((ExceptionFilterFrame*)pFilterFrame)->SetFilterDone(); // Inform the profiler that we're leaving, and what pass we're on @@ -3115,7 +3115,7 @@ int CallJitEHFilter(CrawlFrame* pCf, BYTE* startPC, EE_ILEXCEPTION_CLAUSE *EHCla // GC holes. The stack would be in inconsistent state when we trigger gc just before // returning from UnwindFrames. - FrameWithCookie exceptionFilterFrame(pShadowSP); + ExceptionFilterFrame exceptionFilterFrame(pShadowSP); ETW::ExceptionLog::ExceptionFilterBegin(pCf->GetCodeInfo()->GetMethodDesc(), (PVOID)pCf->GetCodeInfo()->GetStartAddress()); diff --git a/src/coreclr/vm/i386/jithelp.asm b/src/coreclr/vm/i386/jithelp.asm index 54fce3385044c9..58b4200a871b62 100644 --- a/src/coreclr/vm/i386/jithelp.asm +++ b/src/coreclr/vm/i386/jithelp.asm @@ -58,9 +58,7 @@ endif ; _DEBUG ifdef FEATURE_HIJACK EXTERN JIT_TailCallHelper:PROC endif -EXTERN _g_TailCallFrameVptr:DWORD EXTERN @JIT_FailFast@0:PROC -EXTERN _s_gsCookie:DWORD EXTERN g_pPollGC:DWORD EXTERN g_TrapReturningThreads:DWORD @@ -723,26 +721,18 @@ VSDHelperLabel: ; m_regs ; m_CallerAddress ; m_pThread -; vtbl -; GSCookie +; frame identifier ; &VSDHelperLabel -OffsetOfTailCallFrame = 8 +OffsetOfTailCallFrame = 4 ; Offset to start of TailCallFrame, includes only the &VSDHelperLabel ; ebx = pThread -ifdef _DEBUG - mov esi, _s_gsCookie ; GetProcessGSCookie() - cmp dword ptr [esp+OffsetOfTailCallFrame-SIZEOF_GSCookie], esi - je TailCallFrameGSCookieIsValid - call @JIT_FailFast@0 - TailCallFrameGSCookieIsValid: -endif ; remove the padding frame from the chain mov esi, dword ptr [esp+OffsetOfTailCallFrame+4] ; esi = TailCallFrame::m_Next mov dword ptr [ebx + Thread_m_pFrame], esi ; skip the frame - add esp, 20 ; &VSDHelperLabel, GSCookie, vtbl, m_Next, m_CallerAddress + add esp, 16 ; &VSDHelperLabel, vtbl, m_Next, m_CallerAddress pop edi ; restore callee saved registers pop esi @@ -914,7 +904,7 @@ VSDTailCall: ; If there is sufficient space, we will setup the frame and then slide ; the arguments up the stack. Else, we first need to slide the arguments ; down the stack to make space for the TailCallFrame - sub edi, (SIZEOF_GSCookie + SIZEOF_TailCallFrame) + sub edi, (SIZEOF_TailCallFrame) cmp edi, esi jae VSDSpaceForFrameChecked @@ -954,29 +944,25 @@ VSDSpaceForFrameChecked: ; At this point, we have enough space on the stack for the TailCallFrame, ; and we may already have slided down the arguments - mov eax, _s_gsCookie ; GetProcessGSCookie() - mov dword ptr [edi], eax ; set GSCookie - mov eax, _g_TailCallFrameVptr ; vptr mov edx, dword ptr [esp+OrigRetAddr] ; orig return address - mov dword ptr [edi+SIZEOF_GSCookie], eax ; TailCallFrame::vptr - mov dword ptr [edi+SIZEOF_GSCookie+28], edx ; TailCallFrame::m_ReturnAddress + mov dword ptr [edi], FRAMETYPE_TailCallFrame ; FrameIdentifier::TailCallFrame + mov dword ptr [edi+28], edx ; TailCallFrame::m_ReturnAddress mov eax, dword ptr [esp+CallersEdi] ; restored edi mov edx, dword ptr [esp+CallersEsi] ; restored esi - mov dword ptr [edi+SIZEOF_GSCookie+12], eax ; TailCallFrame::m_regs::edi - mov dword ptr [edi+SIZEOF_GSCookie+16], edx ; TailCallFrame::m_regs::esi - mov dword ptr [edi+SIZEOF_GSCookie+20], ebx ; TailCallFrame::m_regs::ebx - mov dword ptr [edi+SIZEOF_GSCookie+24], ebp ; TailCallFrame::m_regs::ebp + mov dword ptr [edi+12], eax ; TailCallFrame::m_regs::edi + mov dword ptr [edi+16], edx ; TailCallFrame::m_regs::esi + mov dword ptr [edi+20], ebx ; TailCallFrame::m_regs::ebx + mov dword ptr [edi+24], ebp ; TailCallFrame::m_regs::ebp mov ebx, dword ptr [esp+pThread] ; ebx = pThread mov eax, dword ptr [ebx+Thread_m_pFrame] - lea edx, [edi+SIZEOF_GSCookie] - mov dword ptr [edi+SIZEOF_GSCookie+4], eax ; TailCallFrame::m_pNext - mov dword ptr [ebx+Thread_m_pFrame], edx ; hook the new frame into the chain + mov dword ptr [edi+4], eax ; TailCallFrame::m_pNext + mov dword ptr [ebx+Thread_m_pFrame], edi ; hook the new frame into the chain ; setup ebp chain - lea ebp, [edi+SIZEOF_GSCookie+24] ; TailCallFrame::m_regs::ebp + lea ebp, [edi+24] ; TailCallFrame::m_regs::ebp ; Do not copy arguments again if they are in place already ; Otherwise, we will need to slide the new arguments up the stack @@ -987,7 +973,7 @@ VSDSpaceForFrameChecked: ; or the TailCallFrame is a perfect fit ; set the caller address mov edx, dword ptr [esp+ExtraSpace+RetAddr] ; caller address - mov dword ptr [edi+SIZEOF_GSCookie+8], edx ; TailCallFrame::m_CallerAddress + mov dword ptr [edi+8], edx ; TailCallFrame::m_CallerAddress ; adjust edi as it would by copying neg ecx @@ -998,7 +984,7 @@ VSDSpaceForFrameChecked: VSDTailCallFrameInserted_DoSlideUpArgs: ; set the caller address mov edx, dword ptr [esp+ExtraSpace+RetAddr] ; caller address - mov dword ptr [edi+SIZEOF_GSCookie+8], edx ; TailCallFrame::m_CallerAddress + mov dword ptr [edi+8], edx ; TailCallFrame::m_CallerAddress ; copy the arguments to the final destination test ecx, ecx diff --git a/src/coreclr/vm/i386/jitinterfacex86.cpp b/src/coreclr/vm/i386/jitinterfacex86.cpp index d8fcd90ba63bb7..ba5273606fedcd 100644 --- a/src/coreclr/vm/i386/jitinterfacex86.cpp +++ b/src/coreclr/vm/i386/jitinterfacex86.cpp @@ -97,11 +97,6 @@ extern "C" void STDCALL WriteBarrierAssert(BYTE* ptr, Object* obj) #endif // _DEBUG /*********************************************************************/ -#ifndef UNIX_X86_ABI -extern "C" void* g_TailCallFrameVptr; -void* g_TailCallFrameVptr; -#endif // !UNI_X86_ABI - #ifdef FEATURE_HIJACK extern "C" void STDCALL JIT_TailCallHelper(Thread * pThread); void STDCALL JIT_TailCallHelper(Thread * pThread) @@ -908,11 +903,6 @@ void InitJITHelpers1() #endif // Leave the patched region writable for StompWriteBarrierEphemeral(), StompWriteBarrierResize() - -#ifndef UNIX_X86_ABI - // Initialize g_TailCallFrameVptr for JIT_TailCall helper - g_TailCallFrameVptr = (void*)TailCallFrame::GetMethodFrameVPtr(); -#endif // !UNIX_X86_ABI } #pragma warning (default : 4731) diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 81d3481124ef1a..fe5564e299060d 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -1826,8 +1826,7 @@ HCIMPL1(void, IL_Throw, Object* obj) { Thread *pThread = GetThread(); - FrameWithCookie exceptionFrame; - *(&exceptionFrame)->GetGSCookiePtr() = GetProcessGSCookie(); + SoftwareExceptionFrame exceptionFrame; RtlCaptureContext(exceptionFrame.GetContext()); exceptionFrame.InitAndLink(pThread); @@ -1917,8 +1916,7 @@ HCIMPL0(void, IL_Rethrow) { Thread *pThread = GetThread(); - FrameWithCookie exceptionFrame; - *(&exceptionFrame)->GetGSCookiePtr() = GetProcessGSCookie(); + SoftwareExceptionFrame exceptionFrame; RtlCaptureContext(exceptionFrame.GetContext()); exceptionFrame.InitAndLink(pThread); @@ -2470,7 +2468,7 @@ static PCODE PatchpointOptimizationPolicy(TransitionBlock* pTransitionBlock, int Thread::ObjectRefFlush(CURRENT_THREAD); #endif - FrameWithCookie frame(pTransitionBlock, 0); + DynamicHelperFrame frame(pTransitionBlock, 0); DynamicHelperFrame * pFrame = &frame; pFrame->Push(CURRENT_THREAD); @@ -2556,7 +2554,7 @@ static PCODE PatchpointRequiredPolicy(TransitionBlock* pTransitionBlock, int* co Thread::ObjectRefFlush(CURRENT_THREAD); #endif - FrameWithCookie frame(pTransitionBlock, 0); + DynamicHelperFrame frame(pTransitionBlock, 0); DynamicHelperFrame * pFrame = &frame; pFrame->Push(CURRENT_THREAD); diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index bcf4017ae2f1ce..87c0b89e593d04 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -10142,19 +10142,17 @@ void InlinedCallFrame::GetEEInfo(CORINFO_EE_INFO::InlinedCallFrameInfo *pInfo) { LIMITED_METHOD_CONTRACT; - pInfo->size = sizeof(GSCookie) + sizeof(InlinedCallFrame); - pInfo->sizeWithSecretStubArg = sizeof(GSCookie) + sizeof(InlinedCallFrame) + sizeof(PTR_VOID); - - pInfo->offsetOfGSCookie = 0; - pInfo->offsetOfFrameVptr = sizeof(GSCookie); - pInfo->offsetOfFrameLink = sizeof(GSCookie) + Frame::GetOffsetOfNextLink(); - pInfo->offsetOfCallSiteSP = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_pCallSiteSP); - pInfo->offsetOfCalleeSavedFP = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_pCalleeSavedFP); - pInfo->offsetOfCallTarget = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_Datum); - pInfo->offsetOfReturnAddress = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_pCallerReturnAddress); - pInfo->offsetOfSecretStubArg = sizeof(GSCookie) + sizeof(InlinedCallFrame); + pInfo->size = sizeof(InlinedCallFrame); + pInfo->sizeWithSecretStubArg = sizeof(InlinedCallFrame) + sizeof(PTR_VOID); + + pInfo->offsetOfFrameLink = Frame::GetOffsetOfNextLink(); + pInfo->offsetOfCallSiteSP = offsetof(InlinedCallFrame, m_pCallSiteSP); + pInfo->offsetOfCalleeSavedFP = offsetof(InlinedCallFrame, m_pCalleeSavedFP); + pInfo->offsetOfCallTarget = offsetof(InlinedCallFrame, m_Datum); + pInfo->offsetOfReturnAddress = offsetof(InlinedCallFrame, m_pCallerReturnAddress); + pInfo->offsetOfSecretStubArg = sizeof(InlinedCallFrame); #ifdef TARGET_ARM - pInfo->offsetOfSPAfterProlog = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_pSPAfterProlog); + pInfo->offsetOfSPAfterProlog = offsetof(InlinedCallFrame, m_pSPAfterProlog); #endif // TARGET_ARM } diff --git a/src/coreclr/vm/loongarch64/asmconstants.h b/src/coreclr/vm/loongarch64/asmconstants.h index bc78b33707f9f2..cd786de16827a6 100644 --- a/src/coreclr/vm/loongarch64/asmconstants.h +++ b/src/coreclr/vm/loongarch64/asmconstants.h @@ -30,6 +30,9 @@ #define DBG_FRE(dbg,fre) fre #endif +#define FRAMETYPE_InlinedCallFrame 0x1 +ASMCONSTANTS_C_ASSERT(FRAMETYPE_InlinedCallFrame == (int)FrameIdentifier::InlinedCallFrame) + #define DynamicHelperFrameFlags_Default 0 #define DynamicHelperFrameFlags_ObjectArg 1 #define DynamicHelperFrameFlags_ObjectArg2 2 @@ -98,9 +101,6 @@ ASMCONSTANTS_C_ASSERT(LazyMachState_captureIp == offsetof(LazyMachState, capture #define VASigCookie__pNDirectILStub 0x8 ASMCONSTANTS_C_ASSERT(VASigCookie__pNDirectILStub == offsetof(VASigCookie, pNDirectILStub)) -#define SIZEOF__GSCookie 0x8 -ASMCONSTANTS_C_ASSERT(SIZEOF__GSCookie == sizeof(GSCookie)); - #define SIZEOF__Frame 0x10 ASMCONSTANTS_C_ASSERT(SIZEOF__Frame == sizeof(Frame)); diff --git a/src/coreclr/vm/loongarch64/asmhelpers.S b/src/coreclr/vm/loongarch64/asmhelpers.S index 951807d9305f20..b2abecbafb5f31 100644 --- a/src/coreclr/vm/loongarch64/asmhelpers.S +++ b/src/coreclr/vm/loongarch64/asmhelpers.S @@ -597,8 +597,8 @@ NESTED_ENTRY TheUMEntryPrestub, _TEXT, UnhandledExceptionHandlerUnix NESTED_END TheUMEntryPrestub, _TEXT // Make sure the `FaultingExceptionFrame_StackAlloc` is 16-byte aligned. -#define FaultingExceptionFrame_StackAlloc (SIZEOF__GSCookie + SIZEOF__FaultingExceptionFrame + 0x8) -#define FaultingExceptionFrame_FrameOffset SIZEOF__GSCookie +#define FaultingExceptionFrame_StackAlloc (SIZEOF__FaultingExceptionFrame) +#define FaultingExceptionFrame_FrameOffset 0 .macro GenerateRedirectedStubWithFrame stub, target diff --git a/src/coreclr/vm/loongarch64/pinvokestubs.S b/src/coreclr/vm/loongarch64/pinvokestubs.S index 15d4398785b614..e902c74d8278f3 100644 --- a/src/coreclr/vm/loongarch64/pinvokestubs.S +++ b/src/coreclr/vm/loongarch64/pinvokestubs.S @@ -76,8 +76,7 @@ // ------------------------------------------------------------------ // IN: -// InlinedCallFrame ($a0) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right -// before actual InlinedCallFrame data) +// InlinedCallFrame ($a0) = pointer to the InlinedCallFrame data // // NESTED_ENTRY JIT_PInvokeBegin, _TEXT, NoHandler @@ -87,15 +86,11 @@ NESTED_ENTRY JIT_PInvokeBegin, _TEXT, NoHandler // $s0=23. PROLOG_SAVE_REG 23, 16 //the stack slot at $sp+24 is empty for 16 byte alignment - PREPARE_EXTERNAL_VAR s_gsCookie, $t0 - ld.d $t4, $t0, 0 - st.d $t4, $a0, 0 - addi.d $s0, $a0, SIZEOF__GSCookie + move $s0, $a0 // s0 = pFrame - // set first slot to the value of InlinedCallFrame::`vftable' (checked by runtime code) - PREPARE_EXTERNAL_VAR _ZTV16InlinedCallFrame, $t0 - addi.d $t4, $t0, 16 + // set first slot to the value of InlinedCallFrame identifier (checked by runtime code) + li.d $t0, FRAMETYPE_InlinedCallFrame st.d $t4, $s0, 0 st.d $zero, $s0, InlinedCallFrame__m_Datum @@ -136,7 +131,6 @@ NESTED_END JIT_PInvokeBegin, _TEXT // LEAF_ENTRY JIT_PInvokeEnd, _TEXT - addi.d $a0, $a0, SIZEOF__GSCookie ld.d $a1, $a0, InlinedCallFrame__m_pThread // $a0 = pFrame // $a1 = pThread diff --git a/src/coreclr/vm/loongarch64/stubs.cpp b/src/coreclr/vm/loongarch64/stubs.cpp index d636410940a704..aaeea378333349 100644 --- a/src/coreclr/vm/loongarch64/stubs.cpp +++ b/src/coreclr/vm/loongarch64/stubs.cpp @@ -431,7 +431,7 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, unwoundstate->_isValid = TRUE; } -void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void HelperMethodFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACTL { @@ -602,7 +602,7 @@ void UpdateRegDisplayFromCalleeSavedRegisters(REGDISPLAY * pRD, CalleeSavedRegis pContextPointers->Ra = (PDWORD64)&pCalleeSaved->ra; } -void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void TransitionFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { #ifndef DACCESS_COMPILE if (updateFloats) @@ -630,10 +630,10 @@ void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) // Finally, syncup the regdisplay with the context SyncRegDisplayToCurrentContext(pRD); - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK TransitionFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK TransitionFrame::UpdateRegDisplay_Impl(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); } -void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void FaultingExceptionFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { LIMITED_METHOD_DAC_CONTRACT; @@ -662,10 +662,10 @@ void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool update pRD->IsCallerContextValid = FALSE; pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK FaultingExceptionFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK FaultingExceptionFrame::UpdateRegDisplay_Impl(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); } -void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void InlinedCallFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACT_VOID { @@ -721,19 +721,19 @@ void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats // Update the frame pointer in the current context. pRD->pCurrentContextPointers->Fp = &m_pCalleeSavedFP; - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK InlinedCallFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK InlinedCallFrame::UpdateRegDisplay_Impl(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); RETURN; } #ifdef FEATURE_HIJACK -TADDR ResumableFrame::GetReturnAddressPtr(void) +TADDR ResumableFrame::GetReturnAddressPtr_Impl(void) { LIMITED_METHOD_DAC_CONTRACT; return dac_cast(m_Regs) + offsetof(T_CONTEXT, Pc); } -void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void ResumableFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACT_VOID { @@ -784,12 +784,12 @@ void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) pRD->IsCallerContextValid = FALSE; pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK ResumableFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK ResumableFrame::UpdateRegDisplay_Impl(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); RETURN; } -void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void HijackFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { LIMITED_METHOD_CONTRACT; @@ -834,7 +834,7 @@ void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) pRD->pCurrentContextPointers->Ra = NULL; SyncRegDisplayToCurrentContext(pRD); - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK HijackFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK HijackFrame::UpdateRegDisplay_Impl(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); } #endif // FEATURE_HIJACK diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp index ce3353e64a4314..d9a4697abdf6f9 100644 --- a/src/coreclr/vm/prestub.cpp +++ b/src/coreclr/vm/prestub.cpp @@ -2640,7 +2640,7 @@ extern "C" PCODE STDCALL PreStubWorker(TransitionBlock* pTransitionBlock, Method Thread::ObjectRefFlush(CURRENT_THREAD); #endif - FrameWithCookie frame(pTransitionBlock, pMD); + PrestubMethodFrame frame(pTransitionBlock, pMD); PrestubMethodFrame* pPFrame = &frame; pPFrame->Push(CURRENT_THREAD); @@ -3161,7 +3161,7 @@ EXTERN_C PCODE STDCALL ExternalMethodFixupWorker(TransitionBlock * pTransitionBl Thread::ObjectRefFlush(CURRENT_THREAD); #endif - FrameWithCookie frame(pTransitionBlock); + ExternalMethodFrame frame(pTransitionBlock); ExternalMethodFrame * pEMFrame = &frame; #if defined(TARGET_X86) || defined(TARGET_AMD64) @@ -4104,7 +4104,7 @@ extern "C" SIZE_T STDCALL DynamicHelperWorker(TransitionBlock * pTransitionBlock Thread::ObjectRefFlush(CURRENT_THREAD); #endif - FrameWithCookie frame(pTransitionBlock, frameFlags); + DynamicHelperFrame frame(pTransitionBlock, frameFlags); DynamicHelperFrame * pFrame = &frame; pFrame->Push(CURRENT_THREAD); diff --git a/src/coreclr/vm/proftoeeinterfaceimpl.cpp b/src/coreclr/vm/proftoeeinterfaceimpl.cpp index fb86e2770b6cd9..4889972ad18913 100644 --- a/src/coreclr/vm/proftoeeinterfaceimpl.cpp +++ b/src/coreclr/vm/proftoeeinterfaceimpl.cpp @@ -8088,7 +8088,7 @@ StackWalkAction ProfilerStackWalkCallback(CrawlFrame *pCf, PROFILER_STACK_WALK_D if (g_isNewExceptionHandlingEnabled && !pCf->IsFrameless() && InlinedCallFrame::FrameHasActiveCall(pCf->GetFrame())) { // Skip new exception handling helpers - InlinedCallFrame *pInlinedCallFrame = (InlinedCallFrame *)pCf->GetFrame(); + InlinedCallFrame *pInlinedCallFrame = dac_cast(pCf->GetFrame()); PTR_NDirectMethodDesc pMD = pInlinedCallFrame->m_Datum; TADDR datum = dac_cast(pMD); if ((datum & (TADDR)InlinedCallFrameMarker::Mask) == (TADDR)InlinedCallFrameMarker::ExceptionHandlingHelper) @@ -8199,7 +8199,7 @@ static BOOL EnsureFrameInitialized(Frame * pFrame) return TRUE; } - HelperMethodFrame * pHMF = (HelperMethodFrame *) pFrame; + HelperMethodFrame * pHMF = dac_cast(pFrame); if (pHMF->EnsureInit( NULL // unwindState diff --git a/src/coreclr/vm/reflectioninvocation.cpp b/src/coreclr/vm/reflectioninvocation.cpp index 8fa0bbd817d55c..4637d307e0e384 100644 --- a/src/coreclr/vm/reflectioninvocation.cpp +++ b/src/coreclr/vm/reflectioninvocation.cpp @@ -416,7 +416,7 @@ extern "C" void QCALLTYPE RuntimeMethodHandle_InvokeMethod( GCStress::MaybeTrigger(); - FrameWithCookie *pProtectValueClassFrame = NULL; + ProtectValueClassFrame *pProtectValueClassFrame = NULL; ValueClassInfo *pValueClasses = NULL; // if we have the magic Value Class return, we need to allocate that class @@ -565,8 +565,8 @@ extern "C" void QCALLTYPE RuntimeMethodHandle_InvokeMethod( if (pValueClasses != NULL) { - pProtectValueClassFrame = new (_alloca (sizeof (FrameWithCookie))) - FrameWithCookie(pThread, pValueClasses); + pProtectValueClassFrame = new (_alloca (sizeof (ProtectValueClassFrame))) + ProtectValueClassFrame(pThread, pValueClasses); } // Call the method diff --git a/src/coreclr/vm/riscv64/asmconstants.h b/src/coreclr/vm/riscv64/asmconstants.h index a79476b33eda27..47f02c8a75cdfc 100644 --- a/src/coreclr/vm/riscv64/asmconstants.h +++ b/src/coreclr/vm/riscv64/asmconstants.h @@ -25,6 +25,9 @@ #define DBG_FRE(dbg,fre) fre #endif +#define FRAMETYPE_InlinedCallFrame 0x1 +ASMCONSTANTS_C_ASSERT(FRAMETYPE_InlinedCallFrame == (int)FrameIdentifier::InlinedCallFrame) + #define DynamicHelperFrameFlags_Default 0 #define DynamicHelperFrameFlags_ObjectArg 1 #define DynamicHelperFrameFlags_ObjectArg2 2 @@ -93,9 +96,6 @@ ASMCONSTANTS_C_ASSERT(LazyMachState_captureIp == offsetof(LazyMachState, capture #define VASigCookie__pNDirectILStub 0x8 ASMCONSTANTS_C_ASSERT(VASigCookie__pNDirectILStub == offsetof(VASigCookie, pNDirectILStub)) -#define SIZEOF__GSCookie 0x8 -ASMCONSTANTS_C_ASSERT(SIZEOF__GSCookie == sizeof(GSCookie)); - #define SIZEOF__Frame 0x10 ASMCONSTANTS_C_ASSERT(SIZEOF__Frame == sizeof(Frame)); diff --git a/src/coreclr/vm/riscv64/asmhelpers.S b/src/coreclr/vm/riscv64/asmhelpers.S index 75c5f7609c93bf..d28639f6ff862f 100644 --- a/src/coreclr/vm/riscv64/asmhelpers.S +++ b/src/coreclr/vm/riscv64/asmhelpers.S @@ -508,8 +508,8 @@ NESTED_ENTRY TheUMEntryPrestub, _TEXT, UnhandledExceptionHandlerUnix NESTED_END TheUMEntryPrestub, _TEXT // Make sure the `FaultingExceptionFrame_StackAlloc` is 16-byte aligned. -#define FaultingExceptionFrame_StackAlloc (SIZEOF__GSCookie + SIZEOF__FaultingExceptionFrame + 0x8) -#define FaultingExceptionFrame_FrameOffset SIZEOF__GSCookie +#define FaultingExceptionFrame_StackAlloc (SIZEOF__FaultingExceptionFrame) +#define FaultingExceptionFrame_FrameOffset 0 .macro GenerateRedirectedStubWithFrame stub, target diff --git a/src/coreclr/vm/riscv64/pinvokestubs.S b/src/coreclr/vm/riscv64/pinvokestubs.S index d96a581b8d8570..9f065a37e474d1 100644 --- a/src/coreclr/vm/riscv64/pinvokestubs.S +++ b/src/coreclr/vm/riscv64/pinvokestubs.S @@ -74,23 +74,18 @@ // ------------------------------------------------------------------ // IN: -// InlinedCallFrame (x0) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right -// before actual InlinedCallFrame data) +// InlinedCallFrame (x0) = pointer to the InlinedCallFrame data // // NESTED_ENTRY JIT_PInvokeBegin, _TEXT, NoHandler PROLOG_SAVE_REG_PAIR_INDEXED fp, ra, 32 PROLOG_SAVE_REG s1, 16 // the stack slot at sp+24 is empty for 16 byte alignment - PREPARE_EXTERNAL_VAR s_gsCookie, t0 - ld t4, 0(t0) - sd t4, 0(a0) - addi s1, a0, SIZEOF__GSCookie + mv s1, a0 // s1 = pFrame - // set first slot to the value of InlinedCallFrame::`vftable' (checked by runtime code) - PREPARE_EXTERNAL_VAR _ZTV16InlinedCallFrame, t0 - addi t4, t0, 16 + // set first slot to the value of InlinedCallFrame identifier (checked by runtime code) + li t4, FRAMETYPE_InlinedCallFrame sd t4, 0(s1) sd zero, (InlinedCallFrame__m_Datum)(s1) @@ -125,13 +120,11 @@ // ------------------------------------------------------------------ // IN: -// InlinedCallFrame (x0) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right -// before actual InlinedCallFrame data) +// InlinedCallFrame (x0) = pointer to the InlinedCallFrame data // // LEAF_ENTRY JIT_PInvokeEnd, _TEXT - addi a0, a0, SIZEOF__GSCookie ld a1, (InlinedCallFrame__m_pThread)(a0) // a0 = pFrame // a1 = pThread diff --git a/src/coreclr/vm/riscv64/stubs.cpp b/src/coreclr/vm/riscv64/stubs.cpp index 0d3d0e2f80d7cd..1f98212b231771 100644 --- a/src/coreclr/vm/riscv64/stubs.cpp +++ b/src/coreclr/vm/riscv64/stubs.cpp @@ -330,7 +330,7 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, unwoundstate->_isValid = TRUE; } -void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void HelperMethodFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACTL { @@ -528,7 +528,7 @@ void UpdateRegDisplayFromCalleeSavedRegisters(REGDISPLAY * pRD, CalleeSavedRegis pContextPointers->Ra = (PDWORD64)&pCalleeSaved->ra; } -void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void TransitionFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { #ifndef DACCESS_COMPILE if (updateFloats) @@ -556,10 +556,10 @@ void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) // Finally, syncup the regdisplay with the context SyncRegDisplayToCurrentContext(pRD); - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK TransitionFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK TransitionFrame::UpdateRegDisplay_Impl(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); } -void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void FaultingExceptionFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { LIMITED_METHOD_DAC_CONTRACT; @@ -592,10 +592,10 @@ void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool update pRD->IsCallerContextValid = FALSE; pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK FaultingExceptionFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK FaultingExceptionFrame::UpdateRegDisplay_Impl(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); } -void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void InlinedCallFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACT_VOID { @@ -655,19 +655,19 @@ void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats // Update the frame pointer in the current context. pRD->pCurrentContextPointers->Fp = &m_pCalleeSavedFP; - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK InlinedCallFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK InlinedCallFrame::UpdateRegDisplay_Impl(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); RETURN; } #ifdef FEATURE_HIJACK -TADDR ResumableFrame::GetReturnAddressPtr(void) +TADDR ResumableFrame::GetReturnAddressPtr_Impl(void) { LIMITED_METHOD_DAC_CONTRACT; return dac_cast(m_Regs) + offsetof(T_CONTEXT, Pc); } -void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void ResumableFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { CONTRACT_VOID { @@ -719,12 +719,12 @@ void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) pRD->IsCallerContextValid = FALSE; pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK ResumableFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK ResumableFrame::UpdateRegDisplay_Impl(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); RETURN; } -void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +void HijackFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats) { LIMITED_METHOD_CONTRACT; @@ -778,7 +778,7 @@ void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) pRD->pCurrentContextPointers->Ra = NULL; SyncRegDisplayToCurrentContext(pRD); - LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK HijackFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK HijackFrame::UpdateRegDisplay_Impl(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); } #endif // FEATURE_HIJACK diff --git a/src/coreclr/vm/runtimecallablewrapper.cpp b/src/coreclr/vm/runtimecallablewrapper.cpp index ca442078ade3f9..04eff1d909f30f 100644 --- a/src/coreclr/vm/runtimecallablewrapper.cpp +++ b/src/coreclr/vm/runtimecallablewrapper.cpp @@ -110,7 +110,7 @@ IUnknown *ComClassFactory::CreateInstanceFromClassFactory(IClassFactory *pClassF if (FAILED(SafeQueryInterface(pClassFact, IID_IClassFactory2, (IUnknown**)&pClassFact2)) || m_pClassMT == NULL) { - FrameWithCookie __def; + DebuggerExitFrame __def; { GCX_PREEMP(); hr = pClassFact->CreateInstance(punkOuter, IID_IUnknown, (void **)&pUnk); @@ -196,7 +196,7 @@ IUnknown *ComClassFactory::CreateInstanceFromClassFactory(IClassFactory *pClassF // Create the instance if (SUCCEEDED(hr)) { - FrameWithCookie __def; + DebuggerExitFrame __def; { GCX_PREEMP(); if (fDesignTime || bstrKey == NULL) @@ -322,7 +322,7 @@ OBJECTREF ComClassFactory::CreateAggregatedInstance(MethodTable* pMTClass, BOOL if (pCallbackMT && !pCallbackMT->IsComImport()) bUseDelegate = TRUE; - FrameWithCookie __def; + DebuggerExitFrame __def; // get the IUnknown interface for the managed object pOuter = ComCallWrapper::GetComIPFromCCW(pComWrap, IID_IUnknown, NULL); diff --git a/src/coreclr/vm/stackwalk.cpp b/src/coreclr/vm/stackwalk.cpp index ef81c5bd0e93af..c84c6105fcff30 100644 --- a/src/coreclr/vm/stackwalk.cpp +++ b/src/coreclr/vm/stackwalk.cpp @@ -231,11 +231,6 @@ inline void CrawlFrame::GotoNextFrame() // pFrame = pFrame->Next(); - - if (pFrame != FRAME_TOP) - { - SetCurGSCookie(Frame::SafeGetGSCookiePtr(pFrame)); - } } //****************************************************************************** @@ -701,13 +696,13 @@ void Thread::DebugLogStackWalkInfo(CrawlFrame* pCF, _In_z_ LPCSTR pszTag, UINT32 } else { - LOG((LF_GCROOTS, LL_INFO10000, "STACKWALK: [%03x] %s: EXPLICIT : PC=" FMT_ADDR " SP=" FMT_ADDR " Frame=" FMT_ADDR" vtbl=" FMT_ADDR "\n", + LOG((LF_GCROOTS, LL_INFO10000, "STACKWALK: [%03x] %s: EXPLICIT : PC=" FMT_ADDR " SP=" FMT_ADDR " Frame=" FMT_ADDR" FrameId=" FMT_ADDR "\n", uFramesProcessed, pszTag, DBG_ADDR(GetControlPC(pCF->pRD)), DBG_ADDR(GetRegdisplaySP(pCF->pRD)), DBG_ADDR(pCF->pFrame), - DBG_ADDR((pCF->pFrame != FRAME_TOP) ? pCF->pFrame->GetVTablePtr() : (TADDR)NULL))); + DBG_ADDR((pCF->pFrame != FRAME_TOP) ? (TADDR)pCF->pFrame->GetFrameIdentifier() : (TADDR)NULL))); } } #endif // _DEBUG @@ -1067,11 +1062,6 @@ BOOL StackFrameIterator::Init(Thread * pThread, } INDEBUG(m_pRealStartFrame = m_crawl.pFrame); - if (m_crawl.pFrame != FRAME_TOP && !(m_flags & SKIP_GSCOOKIE_CHECK)) - { - m_crawl.SetCurGSCookie(Frame::SafeGetGSCookiePtr(m_crawl.pFrame)); - } - m_crawl.pRD = pRegDisp; m_codeManFlags = (ICodeManagerFlags) @@ -1173,11 +1163,6 @@ BOOL StackFrameIterator::ResetRegDisp(PREGDISPLAY pRegDisp, _ASSERTE(m_crawl.pFrame != NULL); } - if (m_crawl.pFrame != FRAME_TOP && !(m_flags & SKIP_GSCOOKIE_CHECK)) - { - m_crawl.SetCurGSCookie(Frame::SafeGetGSCookiePtr(m_crawl.pFrame)); - } - m_crawl.pRD = pRegDisp; m_codeManFlags = (ICodeManagerFlags) @@ -1414,11 +1399,11 @@ BOOL StackFrameIterator::IsValid(void) _ASSERTE(GCStress::IsEnabled()); _ASSERTE(m_pRealStartFrame != NULL); _ASSERTE(m_pRealStartFrame != FRAME_TOP); - _ASSERTE(m_pRealStartFrame->GetVTablePtr() == InlinedCallFrame::GetMethodFrameVPtr()); + _ASSERTE(m_pRealStartFrame->GetFrameIdentifier() == FrameIdentifier::InlinedCallFrame); _ASSERTE(m_pThread->GetFrame() != NULL); _ASSERTE(m_pThread->GetFrame() != FRAME_TOP); - bIsRealStartFrameUnchanged = (m_pThread->GetFrame()->GetVTablePtr() == ResumableFrame::GetMethodFrameVPtr()) - || (m_pThread->GetFrame()->GetVTablePtr() == RedirectedThreadFrame::GetMethodFrameVPtr()); + bIsRealStartFrameUnchanged = (m_pThread->GetFrame()->GetFrameIdentifier() == FrameIdentifier::ResumableFrame) + || (m_pThread->GetFrame()->GetFrameIdentifier() == FrameIdentifier::RedirectedThreadFrame); } #endif // FEATURE_HIJACK @@ -2365,7 +2350,7 @@ StackWalkAction StackFrameIterator::NextRaw(void) // make sure we're not skipping a different transition if (m_crawl.pFrame->NeedsUpdateRegDisplay()) { - if (m_crawl.pFrame->GetVTablePtr() == InlinedCallFrame::GetMethodFrameVPtr()) + if (m_crawl.pFrame->GetFrameIdentifier() == FrameIdentifier::InlinedCallFrame) { // ControlPC may be different as the InlinedCallFrame stays active throughout // the STOP_FOR_GC callout but we can use the stack/frame pointer for the assert. @@ -2502,7 +2487,7 @@ StackWalkAction StackFrameIterator::NextRaw(void) // pushed on the stack after the frame is running _ASSERTE((m_crawl.pFrame == FRAME_TOP) || ((TADDR)GetRegdisplaySP(m_crawl.pRD) < dac_cast(m_crawl.pFrame)) || - (m_crawl.pFrame->GetVTablePtr() == FaultingExceptionFrame::GetMethodFrameVPtr())); + (m_crawl.pFrame->GetFrameIdentifier() == FrameIdentifier::FaultingExceptionFrame)); #endif // !defined(ELIMINATE_FEF) // Get rid of the frame (actually, it isn't really popped) @@ -2847,7 +2832,7 @@ void StackFrameIterator::ProcessCurrentFrame(void) // the next frame is one of them, we don't want to override it. THIS IS PROBABLY BAD!!! if ( (pContextSP < dac_cast(m_crawl.pFrame)) && ((m_crawl.GetFrame() == FRAME_TOP) || - (m_crawl.GetFrame()->GetVTablePtr() != FaultingExceptionFrame::GetMethodFrameVPtr() ) ) ) + (m_crawl.GetFrame()->GetFrameIdentifier() != FrameIdentifier::FaultingExceptionFrame ) ) ) { // // If the REGDISPLAY represents an unmanaged stack frame above (closer to the leaf than) an @@ -3006,7 +2991,7 @@ BOOL StackFrameIterator::CheckForSkippedFrames(void) // Note that code:InlinedCallFrame.GetFunction may return NULL in this case because // the call is made using the CALLI instruction. m_crawl.pFrame != FRAME_TOP && - m_crawl.pFrame->GetVTablePtr() == InlinedCallFrame::GetMethodFrameVPtr() && + m_crawl.pFrame->GetFrameIdentifier() == FrameIdentifier::InlinedCallFrame && m_crawl.pFunc != NULL && m_crawl.pFunc->IsILStub() && m_crawl.pFunc->AsDynamicMethodDesc()->HasMDContextArg(); diff --git a/src/coreclr/vm/threads.cpp b/src/coreclr/vm/threads.cpp index 8951a68905a237..51462ddd278a02 100644 --- a/src/coreclr/vm/threads.cpp +++ b/src/coreclr/vm/threads.cpp @@ -305,7 +305,7 @@ bool Thread::DetectHandleILStubsForDebugger() while (pFrame != FRAME_TOP) { // Check for HMF's. See the comment at the beginning of this function. - if (pFrame->GetVTablePtr() == HelperMethodFrame::GetMethodFrameVPtr()) + if (pFrame->GetFrameIdentifier() == FrameIdentifier::HelperMethodFrame) { break; } @@ -7206,7 +7206,7 @@ static void ManagedThreadBase_DispatchOuter(ManagedThreadCallState *pCallState) // The sole purpose of having this frame is to tell the debugger that we have a catch handler here // which may swallow managed exceptions. The debugger needs this in order to send a // CatchHandlerFound (CHF) notification. - FrameWithCookie catchFrame; + DebuggerU2MCatchHandlerFrame catchFrame; TryParam param(pCallState); param.pFrame = &catchFrame; diff --git a/src/coreclr/vm/threadsuspend.cpp b/src/coreclr/vm/threadsuspend.cpp index 2da1584cdb5da7..42ce5cbb355863 100644 --- a/src/coreclr/vm/threadsuspend.cpp +++ b/src/coreclr/vm/threadsuspend.cpp @@ -2512,7 +2512,7 @@ bool ThreadStore::IsTrappingThreadsForSuspension() #ifdef FEATURE_HIJACK -void RedirectedThreadFrame::ExceptionUnwind() +void RedirectedThreadFrame::ExceptionUnwind_Impl() { CONTRACTL { @@ -2671,7 +2671,7 @@ void Thread::RestoreContextSimulated(Thread* pThread, CONTEXT* pCtx, void* pFram RaiseException(EXCEPTION_HIJACK, 0, 0, NULL); } __except (++filter_count == 1 - ? RedirectedHandledJITCaseExceptionFilter(GetExceptionInformation(), (RedirectedThreadFrame*)pFrame, pCtx, dwLastError) + ? RedirectedHandledJITCaseExceptionFilter(GetExceptionInformation(), dac_cast(pFrame), pCtx, dwLastError) : EXCEPTION_CONTINUE_SEARCH) { _ASSERTE(!"Reached body of __except in Thread::RedirectedHandledJITCase"); @@ -2699,7 +2699,7 @@ void __stdcall Thread::RedirectedHandledJITCase(RedirectReason reason) INDEBUG(Thread::ObjectRefFlush(pThread)); // Create a frame on the stack - FrameWithCookie frame(pCtx); + RedirectedThreadFrame frame(pCtx); STRESS_LOG5(LF_SYNC, LL_INFO1000, "In RedirectedHandledJITcase reason 0x%x pFrame = %p pc = %p sp = %p fp = %p", reason, &frame, GetIP(pCtx), GetSP(pCtx), GetFP(pCtx)); @@ -3766,10 +3766,9 @@ ThrowControlForThread( } #if defined(FEATURE_EH_FUNCLETS) - *(TADDR*)pfef = FaultingExceptionFrame::GetMethodFrameVPtr(); - *pfef->GetGSCookiePtr() = GetProcessGSCookie(); + ((Frame*)pfef)->Init(FrameIdentifier::FaultingExceptionFrame); #else // FEATURE_EH_FUNCLETS - FrameWithCookie fef; + FaultingExceptionFrame fef; FaultingExceptionFrame *pfef = &fef; #endif // FEATURE_EH_FUNCLETS pfef->InitAndLink(pThread->m_OSContext); @@ -4843,7 +4842,8 @@ StackWalkAction SWCB_GetExecutionState(CrawlFrame *pCF, VOID *pData) } HijackFrame::HijackFrame(LPVOID returnAddress, Thread *thread, HijackArgs *args) - : m_ReturnAddress((TADDR)returnAddress), + : Frame(FrameIdentifier::HijackFrame), + m_ReturnAddress((TADDR)returnAddress), m_Thread(thread), m_Args(args) { @@ -4879,7 +4879,7 @@ void STDCALL OnHijackWorker(HijackArgs * pArgs) // Build a frame so that stack crawling can proceed from here back to where // we will resume execution. - FrameWithCookie frame((void *)pArgs->ReturnAddress, thread, pArgs); + HijackFrame frame((void *)pArgs->ReturnAddress, thread, pArgs); #ifdef _DEBUG BOOL GCOnTransition = FALSE; @@ -5805,7 +5805,7 @@ void HandleSuspensionForInterruptedThread(CONTEXT *interruptedContext) { // If the thread is at a GC safe point, push a RedirectedThreadFrame with // the interrupted context and pulse the GC mode so that GC can proceed. - FrameWithCookie frame(interruptedContext); + RedirectedThreadFrame frame(interruptedContext); frame.Push(pThread); diff --git a/src/coreclr/vm/virtualcallstub.cpp b/src/coreclr/vm/virtualcallstub.cpp index 84a044422c65b5..a2bfb6f2c49604 100644 --- a/src/coreclr/vm/virtualcallstub.cpp +++ b/src/coreclr/vm/virtualcallstub.cpp @@ -1298,7 +1298,7 @@ PCODE VSD_ResolveWorker(TransitionBlock * pTransitionBlock, Thread::ObjectRefFlush(CURRENT_THREAD); #endif - FrameWithCookie frame(pTransitionBlock); + StubDispatchFrame frame(pTransitionBlock); StubDispatchFrame * pSDFrame = &frame; PCODE returnAddress = pSDFrame->GetUnadjustedReturnAddress(); From 108c5154f55423f7b369891f61a6223777de3d25 Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Tue, 11 Feb 2025 18:54:21 +0000 Subject: [PATCH 07/20] Update the exception message to reflect current behavior. (#112355) --- src/libraries/System.Text.Json/src/Resources/Strings.resx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Text.Json/src/Resources/Strings.resx b/src/libraries/System.Text.Json/src/Resources/Strings.resx index cd8a5e392ca66e..1a4f9421de95d9 100644 --- a/src/libraries/System.Text.Json/src/Resources/Strings.resx +++ b/src/libraries/System.Text.Json/src/Resources/Strings.resx @@ -492,7 +492,7 @@ The '$id', '$ref' or '$type' metadata properties must be JSON strings. Current token type is '{0}'. - Properties that start with '$' are not allowed in types that support metadata. Either escape the character or disable reference preservation and polymorphic deserialization. + Properties that start with '$' are not allowed in types that support metadata. Either replace the character or disable reference preservation and polymorphic deserialization. The metadata property is either not supported by the type or is not the first property in the deserialized JSON object. @@ -827,4 +827,4 @@ Mixing UTF encodings in a single multi-segment JSON string is not supported. The previous segment's encoding was '{0}' and the current segment's encoding is '{1}'. - \ No newline at end of file + From 6626fca7f9f25f57c0f70c1e04fe5490113b6ae3 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Tue, 11 Feb 2025 19:57:03 +0100 Subject: [PATCH 08/20] Remove duplicate definition of CORECLR_HOSTING_API_LINKAGE (#112096) --- src/coreclr/hosts/inc/coreclrhost.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/coreclr/hosts/inc/coreclrhost.h b/src/coreclr/hosts/inc/coreclrhost.h index b57ed1beb38e9d..0a72016cebf8aa 100644 --- a/src/coreclr/hosts/inc/coreclrhost.h +++ b/src/coreclr/hosts/inc/coreclrhost.h @@ -14,12 +14,6 @@ #define CORECLR_CALLING_CONVENTION #endif -#ifdef __cplusplus -#define CORECLR_HOSTING_API_LINKAGE extern "C" -#else -#define CORECLR_HOSTING_API_LINKAGE -#endif - #include #ifdef __cplusplus From 4da708a7060d238354d79823e58839c1d92f7fd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Fi=C5=A1era?= Date: Tue, 11 Feb 2025 20:00:03 +0100 Subject: [PATCH 09/20] Fingerprint dotnet.js if writing import map to html is enabled (#112407) --- .../build/Microsoft.NET.Sdk.WebAssembly.Browser.targets | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets b/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets index 8fa97e16cb21b7..5e4f39455f76ad 100644 --- a/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets +++ b/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets @@ -191,6 +191,7 @@ Copyright (c) .NET Foundation. All rights reserved. <_WasmFingerprintAssets Condition="'$(_WasmFingerprintAssets)' == '' and '$(_TargetingNET90OrLater)' == 'true'">true <_WasmFingerprintAssets Condition="'$(_WasmFingerprintAssets)' == ''">false <_WasmFingerprintDotnetJs>$(WasmFingerprintDotnetJs) + <_WasmFingerprintDotnetJs Condition="'$(_WasmFingerprintDotnetJs)' == ''">$(WriteImportMapToHtml) <_WasmFingerprintDotnetJs Condition="'$(_WasmFingerprintDotnetJs)' == ''">false <_WasmBootConfigFileName>$(WasmBootConfigFileName) <_WasmBootConfigFileName Condition="'$(_WasmBootConfigFileName)' == ''">blazor.boot.json From b0ad53eb09018945dcdb108982b26ad64b801971 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 11 Feb 2025 21:30:40 +0100 Subject: [PATCH 10/20] Prevent returning disposed HTTP/1.1 connections to the pool (#112383) There are race conditions in HTTP 1.1 response stream reading methods that may prevent the exceptional termination of those methods despite cancellation callbacks firing and disposing the connection, see the discussion starting with https://github.com/dotnet/runtime/issues/31254#issuecomment-2648840680. As a result, these methods may call `CompleteResponse` returning the disposed connection to the pool. This is a minimal fix for the mentioned issue by guarding against `_disposed` in `CompleteResponse`. Fixes #31254 Fixes #110577 --- .../Net/Http/SocketsHttpHandler/HttpConnection.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs index 0b03489d93aff3..e2b49083df744d 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs @@ -2056,9 +2056,14 @@ private void CompleteResponse() _connectionClose = true; } - // If the connection is no longer in use (i.e. for NT authentication), then we can return it to the pool now. - // Otherwise, it will be returned when the connection is no longer in use (i.e. Release above is called). - if (!_inUse) + // If the connection is no longer in use (i.e. for NT authentication), then we can + // return it to the pool now; otherwise, it will be returned by the Release method later. + // The cancellation logic in HTTP/1.1 response stream reading methods is prone to race conditions + // where CancellationTokenRegistration callbacks may dispose the connection without the disposal + // leading to an actual cancellation of the response reading methods by an OperationCanceledException. + // To guard against these cases, it is necessary to check if the connection is disposed before + // attempting to return it to the pool. + if (!_inUse && !_disposed) { ReturnConnectionToPool(); } @@ -2097,6 +2102,7 @@ public async ValueTask DrainResponseAsync(HttpResponseMessage response, Cancella private void ReturnConnectionToPool() { + Debug.Assert(!_disposed, "Connection should not be disposed."); Debug.Assert(_currentRequest == null, "Connection should no longer be associated with a request."); Debug.Assert(_readAheadTask == default, "Expected a previous initial read to already be consumed."); Debug.Assert(_readAheadTaskStatus == ReadAheadTask_NotStarted, "Expected SendAsync to reset the read-ahead task status."); From 7e82ad9a9888b4b637faf6e420f50ac4f09383a3 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 11 Feb 2025 14:01:25 -0800 Subject: [PATCH 11/20] Wait to complete the test before releasing the agile reference. (#112387) Otherwise we can end up with a use-after-free --- src/tests/Interop/COM/ComWrappers/API/Program.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tests/Interop/COM/ComWrappers/API/Program.cs b/src/tests/Interop/COM/ComWrappers/API/Program.cs index 8204ce75f6a903..a87ba2e79a6906 100644 --- a/src/tests/Interop/COM/ComWrappers/API/Program.cs +++ b/src/tests/Interop/COM/ComWrappers/API/Program.cs @@ -1084,6 +1084,7 @@ public unsafe void CrossApartmentQueryInterface_NoDeadlock() staThread.Start(); mtaThread.Start(); + testCompleted.WaitOne(); } finally { @@ -1092,8 +1093,6 @@ public unsafe void CrossApartmentQueryInterface_NoDeadlock() Marshal.Release(agileReference); } } - - testCompleted.WaitOne(); } [DllImport("ole32.dll")] From b1ab309161278d3bb81efe2718399cf9f0dfad41 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Wed, 12 Feb 2025 00:31:56 +0100 Subject: [PATCH 12/20] Never use heap for return buffers (#112060) Co-authored-by: jakobbotsch --- docs/design/coreclr/botr/clr-abi.md | 8 +-- .../design/features/tailcalls-with-helpers.md | 6 +- src/coreclr/inc/readytorun.h | 5 +- src/coreclr/jit/compiler.h | 7 ++- src/coreclr/jit/flowgraph.cpp | 36 ++++++++++++ src/coreclr/jit/gentree.cpp | 2 +- src/coreclr/jit/importer.cpp | 57 ++++++++++++++++--- src/coreclr/jit/lclvars.cpp | 2 +- src/coreclr/jit/rationalize.cpp | 2 +- .../nativeaot/Runtime/inc/ModuleHeaders.h | 2 +- .../Common/Internal/Runtime/ModuleHeaders.cs | 2 +- .../ReadyToRun/GCRefMapBuilder.cs | 7 --- src/coreclr/vm/frames.cpp | 14 ----- src/coreclr/vm/reflectioninvocation.cpp | 31 +++++++++- 14 files changed, 130 insertions(+), 51 deletions(-) diff --git a/docs/design/coreclr/botr/clr-abi.md b/docs/design/coreclr/botr/clr-abi.md index 7da3805324eb62..0eed53cd415e58 100644 --- a/docs/design/coreclr/botr/clr-abi.md +++ b/docs/design/coreclr/botr/clr-abi.md @@ -108,9 +108,7 @@ Passing/returning structs according to hardware floating-point calling conventio ## Return buffers -The same applies to some return buffers. See `MethodTable::IsStructRequiringStackAllocRetBuf()`. When that returns `false`, the return buffer might be on the heap, either due to reflection/remoting code paths mentioned previously or due to a JIT optimization where a call with a return buffer that then assigns to a field (on the GC heap) are changed into passing the field reference as the return buffer. Conversely, when it returns true, the JIT does not need to use a write barrier when storing to the return buffer, but it is still not guaranteed to be a compiler temp, and as such the JIT should not introduce spurious writes to the return buffer. - -NOTE: This optimization is now disabled for all platforms (`IsStructRequiringStackAllocRetBuf()` always returns `false`). +Since .NET 10, return buffers must always be allocated on the stack by the caller. After the call, the caller is responsible for copying the return buffer to the final destination using write barriers if necessary. The JIT can assume that the return buffer is always on the stack and may optimize accordingly, such as by omitting write barriers when writing GC pointers to the return buffer. In addition, the buffer is allowed to be used for temporary storage within the method since its content must not be aliased or cross-thread visible. ARM64-only: When a method returns a structure that is larger than 16 bytes the caller reserves a return buffer of sufficient size and alignment to hold the result. The address of the buffer is passed as an argument to the method in `R8` (defined in the JIT as `REG_ARG_RET_BUFF`). The callee isn't required to preserve the value stored in `R8`. @@ -778,9 +776,7 @@ The return value is handled as follows: 1. Floating-point values are returned on the top of the hardware FP stack. 2. Integers up to 32 bits long are returned in EAX. 3. 64-bit integers are passed with EAX holding the least significant 32 bits and EDX holding the most significant 32 bits. -4. All other cases require the use of a return buffer, through which the value is returned. - -In addition, there is a guarantee that if a return buffer is used a value is stored there only upon ordinary exit from the method. The buffer is not allowed to be used for temporary storage within the method and its contents will be unaltered if an exception occurs while executing the method. +4. All other cases require the use of a return buffer, through which the value is returned. See [Return buffers](#return-buffers). # Control Flow Guard (CFG) support on Windows diff --git a/docs/design/features/tailcalls-with-helpers.md b/docs/design/features/tailcalls-with-helpers.md index 69a9aafd11748d..c99af8269d21a0 100644 --- a/docs/design/features/tailcalls-with-helpers.md +++ b/docs/design/features/tailcalls-with-helpers.md @@ -259,9 +259,9 @@ stack, even on ARM architectures, due to its return address hijacking mechanism. When the result is returned by value the JIT will introduce a local and pass a pointer to it in the second argument. For ret bufs the JIT will typically -directly pass along its own return buffer parameter to DispatchTailCalls. It is -possible that this return buffer is pointing into GC heap, so the result is -always tracked as a byref in the mechanism. +directly pass along its own return buffer parameter to DispatchTailCalls. The +return buffer is always located on the stack, so the result does not need to be +tracked as a byref. In certain cases the target function pointer is also stored. For some targets this might require the JIT to perform the equivalent of `ldvirtftn` or `ldftn` diff --git a/src/coreclr/inc/readytorun.h b/src/coreclr/inc/readytorun.h index 1ca6b12b594132..b097179f9bf67c 100644 --- a/src/coreclr/inc/readytorun.h +++ b/src/coreclr/inc/readytorun.h @@ -19,10 +19,10 @@ // src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h // If you update this, ensure you run `git grep MINIMUM_READYTORUN_MAJOR_VERSION` // and handle pending work. -#define READYTORUN_MAJOR_VERSION 11 +#define READYTORUN_MAJOR_VERSION 12 #define READYTORUN_MINOR_VERSION 0x0000 -#define MINIMUM_READYTORUN_MAJOR_VERSION 11 +#define MINIMUM_READYTORUN_MAJOR_VERSION 12 // R2R Version 2.1 adds the InliningInfo section // R2R Version 2.2 adds the ProfileDataInfo section @@ -39,6 +39,7 @@ // R2R Version 10.0 adds support for the statics being allocated on a per type basis instead of on a per module basis, disable support for LogMethodEnter helper // R2R Version 10.1 adds Unbox_TypeTest helper // R2R Version 11 uses GCInfo v4, which encodes safe points without -1 offset and does not track return kinds in GCInfo +// R2R Version 12 requires all return buffers to be always on the stack struct READYTORUN_CORE_HEADER { diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index e3077cfac9ac12..b62a38222233ca 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -4938,7 +4938,7 @@ class Compiler Statement** pAfterStmt = nullptr, const DebugInfo& di = DebugInfo(), BasicBlock* block = nullptr); - GenTree* impStoreStructPtr(GenTree* destAddr, GenTree* value, unsigned curLevel); + GenTree* impStoreStructPtr(GenTree* destAddr, GenTree* value, unsigned curLevel, GenTreeFlags indirFlags = GTF_EMPTY); GenTree* impGetNodeAddr(GenTree* val, unsigned curLevel, GenTreeFlags* pDerefFlags); @@ -5228,8 +5228,8 @@ class Compiler static LONG jitNestingLevel; #endif // DEBUG - static bool impIsInvariant(const GenTree* tree); - static bool impIsAddressInLocal(const GenTree* tree, GenTree** lclVarTreeOut = nullptr); + bool impIsInvariant(const GenTree* tree); + bool impIsAddressInLocal(const GenTree* tree, GenTree** lclVarTreeOut = nullptr); void impMakeDiscretionaryInlineObservations(InlineInfo* pInlineInfo, InlineResult* inlineResult); @@ -6793,6 +6793,7 @@ class Compiler public: bool fgAddrCouldBeNull(GenTree* addr); + bool fgAddrCouldBeHeap(GenTree* addr); void fgAssignSetVarDef(GenTree* tree); private: diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index 369b7b7a30241c..70b0e7c5667486 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -928,6 +928,42 @@ bool Compiler::fgAddrCouldBeNull(GenTree* addr) return true; // default result: addr could be null. } +//------------------------------------------------------------------------------ +// fgAddrCouldBeHeap: Check whether the address tree may represent a heap address. +// +// Arguments: +// addr - Address to check +// +// Return Value: +// True if address could be a heap address; false otherwise (i.e. stack, native memory, etc.) +// +bool Compiler::fgAddrCouldBeHeap(GenTree* addr) +{ + GenTree* op = addr; + while (op->OperIs(GT_FIELD_ADDR) && op->AsFieldAddr()->IsInstance()) + { + op = op->AsFieldAddr()->GetFldObj(); + } + + target_ssize_t offset; + gtPeelOffsets(&op, &offset); + + // Ignore the offset for locals + + if (op->OperIs(GT_LCL_ADDR)) + { + return false; + } + + if (op->OperIsScalarLocal() && (op->AsLclVarCommon()->GetLclNum() == impInlineRoot()->info.compRetBuffArg)) + { + // RetBuf is known to be on the stack + return false; + } + + return true; +} + //------------------------------------------------------------------------------ // fgOptimizeDelegateConstructor: try and optimize construction of a delegate // diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index ea02025450b39a..f7e3cdf86aa0b2 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -18301,7 +18301,7 @@ bool GenTreeIndir::IsAddressNotOnHeap(Compiler* comp) return true; } - if (HasBase() && Base()->gtSkipReloadOrCopy()->OperIs(GT_LCL_ADDR)) + if (HasBase() && !comp->fgAddrCouldBeHeap(Base()->gtSkipReloadOrCopy())) { return true; } diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index d3de5273c0b613..65c1323b0db870 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -843,7 +843,23 @@ GenTree* Compiler::impStoreStruct(GenTree* store, // TODO-Bug?: verify if flags matter here GenTreeFlags indirFlags = GTF_EMPTY; GenTree* destAddr = impGetNodeAddr(store, CHECK_SPILL_ALL, &indirFlags); - NewCallArg newArg = NewCallArg::Primitive(destAddr).WellKnown(wellKnownArgType); + + // Make sure we don't pass something other than a local address to the return buffer arg. + // It is allowed to pass current's method return buffer as it is a local too. + if (fgAddrCouldBeHeap(destAddr) && !eeIsByrefLike(srcCall->gtRetClsHnd)) + { + unsigned tmp = lvaGrabTemp(false DEBUGARG("stack copy for value returned via return buffer")); + lvaSetStruct(tmp, srcCall->gtRetClsHnd, false); + + GenTree* spilledCall = gtNewStoreLclVarNode(tmp, srcCall); + spilledCall = impStoreStruct(spilledCall, curLevel, pAfterStmt, di, block); + store->Data() = gtNewOperNode(GT_COMMA, store->TypeGet(), spilledCall, + gtNewLclvNode(tmp, lvaGetDesc(tmp)->TypeGet())); + + return impStoreStruct(store, curLevel, pAfterStmt, di, block); + } + + NewCallArg newArg = NewCallArg::Primitive(destAddr).WellKnown(wellKnownArgType); if (destAddr->OperIs(GT_LCL_ADDR)) { @@ -953,6 +969,27 @@ GenTree* Compiler::impStoreStruct(GenTree* store, // TODO-Bug?: verify if flags matter here GenTreeFlags indirFlags = GTF_EMPTY; GenTree* destAddr = impGetNodeAddr(store, CHECK_SPILL_ALL, &indirFlags); + + // Make sure we don't pass something other than a local address to the return buffer arg. + // It is allowed to pass current's method return buffer as it is a local too. + if (fgAddrCouldBeHeap(destAddr) && !eeIsByrefLike(call->gtRetClsHnd)) + { + unsigned tmp = lvaGrabTemp(false DEBUGARG("stack copy for value returned via return buffer")); + lvaSetStruct(tmp, call->gtRetClsHnd, false); + destAddr = gtNewLclVarAddrNode(tmp, TYP_I_IMPL); + + // Insert address of temp into existing call + NewCallArg retBufArg = NewCallArg::Primitive(destAddr).WellKnown(WellKnownArg::RetBuffer); + call->gtArgs.InsertAfterThisOrFirst(this, retBufArg); + + // Now the store needs to copy from the new temp instead. + call->gtType = TYP_VOID; + src->gtType = TYP_VOID; + var_types tmpType = lvaGetDesc(tmp)->TypeGet(); + store->Data() = gtNewOperNode(GT_COMMA, tmpType, src, gtNewLclvNode(tmp, tmpType)); + return impStoreStruct(store, CHECK_SPILL_ALL, pAfterStmt, di, block); + } + call->gtArgs.InsertAfterThisOrFirst(this, NewCallArg::Primitive(destAddr).WellKnown(WellKnownArg::RetBuffer)); @@ -1010,9 +1047,10 @@ GenTree* Compiler::impStoreStruct(GenTree* store, // impStoreStructPtr: Store (copy) the structure from 'src' to 'destAddr'. // // Arguments: -// destAddr - address of the destination of the store -// value - value to store -// curLevel - stack level for which a spill may be being done +// destAddr - address of the destination of the store +// value - value to store +// curLevel - stack level for which a spill may be being done +// indirFlags - flags to be used on the store node // // Return Value: // The tree that should be appended to the statement list that represents the store. @@ -1020,11 +1058,11 @@ GenTree* Compiler::impStoreStruct(GenTree* store, // Notes: // Temp stores may be appended to impStmtList if spilling is necessary. // -GenTree* Compiler::impStoreStructPtr(GenTree* destAddr, GenTree* value, unsigned curLevel) +GenTree* Compiler::impStoreStructPtr(GenTree* destAddr, GenTree* value, unsigned curLevel, GenTreeFlags indirFlags) { var_types type = value->TypeGet(); ClassLayout* layout = (type == TYP_STRUCT) ? value->GetLayout(this) : nullptr; - GenTree* store = gtNewStoreValueNode(type, layout, destAddr, value); + GenTree* store = gtNewStoreValueNode(type, layout, destAddr, value, indirFlags); store = impStoreStruct(store, curLevel); return store; @@ -11247,18 +11285,19 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode) if (info.compRetBuffArg != BAD_VAR_NUM) { + var_types retBuffType = lvaGetDesc(info.compRetBuffArg)->TypeGet(); // Assign value to return buff (first param) GenTree* retBuffAddr = - gtNewLclvNode(info.compRetBuffArg, TYP_BYREF DEBUGARG(impCurStmtDI.GetLocation().GetOffset())); + gtNewLclvNode(info.compRetBuffArg, retBuffType DEBUGARG(impCurStmtDI.GetLocation().GetOffset())); - op2 = impStoreStructPtr(retBuffAddr, op2, CHECK_SPILL_ALL); + op2 = impStoreStructPtr(retBuffAddr, op2, CHECK_SPILL_ALL, GTF_IND_TGT_NOT_HEAP); impAppendTree(op2, CHECK_SPILL_NONE, impCurStmtDI); // There are cases where the address of the implicit RetBuf should be returned explicitly. // if (compMethodReturnsRetBufAddr()) { - op1 = gtNewOperNode(GT_RETURN, TYP_BYREF, gtNewLclvNode(info.compRetBuffArg, TYP_BYREF)); + op1 = gtNewOperNode(GT_RETURN, retBuffType, gtNewLclvNode(info.compRetBuffArg, retBuffType)); } else { diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 4cfd2c3d560204..3565ae3d0d9946 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -485,7 +485,7 @@ void Compiler::lvaInitRetBuffArg(InitVarDscInfo* varDscInfo, bool useFixedRetBuf info.compRetBuffArg = varDscInfo->varNum; LclVarDsc* varDsc = varDscInfo->varDsc; - varDsc->lvType = TYP_BYREF; + varDsc->lvType = TYP_I_IMPL; varDsc->lvIsParam = 1; varDsc->lvIsRegArg = 0; diff --git a/src/coreclr/jit/rationalize.cpp b/src/coreclr/jit/rationalize.cpp index 572240b6298e55..de23305c145b7f 100644 --- a/src/coreclr/jit/rationalize.cpp +++ b/src/coreclr/jit/rationalize.cpp @@ -157,7 +157,7 @@ void Rationalizer::RewriteNodeAsCall(GenTree** use, tmpNum = comp->lvaGrabTemp(true DEBUGARG("return buffer for hwintrinsic")); comp->lvaSetStruct(tmpNum, sig->retTypeClass, false); - GenTree* destAddr = comp->gtNewLclVarAddrNode(tmpNum, TYP_BYREF); + GenTree* destAddr = comp->gtNewLclVarAddrNode(tmpNum, TYP_I_IMPL); NewCallArg newArg = NewCallArg::Primitive(destAddr).WellKnown(WellKnownArg::RetBuffer); call->gtArgs.InsertAfterThisOrFirst(comp, newArg); diff --git a/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h b/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h index 358807e6ab563e..305901d7626a59 100644 --- a/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h +++ b/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h @@ -11,7 +11,7 @@ struct ReadyToRunHeaderConstants { static const uint32_t Signature = 0x00525452; // 'RTR' - static const uint32_t CurrentMajorVersion = 11; + static const uint32_t CurrentMajorVersion = 12; static const uint32_t CurrentMinorVersion = 0; }; diff --git a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs index bca68c323f6523..10ed724001d54d 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs @@ -15,7 +15,7 @@ internal struct ReadyToRunHeaderConstants { public const uint Signature = 0x00525452; // 'RTR' - public const ushort CurrentMajorVersion = 11; + public const ushort CurrentMajorVersion = 12; public const ushort CurrentMinorVersion = 0; } #if READYTORUN diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapBuilder.cs index ba8468c37d737c..dc77206257acf9 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapBuilder.cs @@ -182,13 +182,6 @@ private void FakeGcScanRoots(MethodDesc method, ArgIterator argit, CORCOMPILE_GC return; } - // Also if the method has a return buffer, then it is the first argument, and could be an interior ref, - // so always promote it. - if (argit.HasRetBuffArg()) - { - frame[_transitionBlock.GetRetBuffArgOffset(argit.HasThis)] = CORCOMPILE_GCREFMAP_TOKENS.GCREFMAP_INTERIOR; - } - // // Now iterate the arguments // diff --git a/src/coreclr/vm/frames.cpp b/src/coreclr/vm/frames.cpp index f5628896728d2d..18e8f886410c23 100644 --- a/src/coreclr/vm/frames.cpp +++ b/src/coreclr/vm/frames.cpp @@ -1552,13 +1552,6 @@ void TransitionFrame::PromoteCallerStackHelper(promote_func* fn, ScanContext* sc (fn)(PTR_PTR_Object(pThis), sc, CHECK_APP_DOMAIN); } - if (argit.HasRetBuffArg()) - { - PTR_PTR_VOID pRetBuffArg = dac_cast(pTransitionBlock + argit.GetRetBuffArgOffset()); - LOG((LF_GC, INFO3, " ret buf Argument promoted from" FMT_ADDR "\n", DBG_ADDR(*pRetBuffArg) )); - PromoteCarefully(fn, PTR_PTR_Object(pRetBuffArg), sc, GC_CALL_INTERIOR|CHECK_APP_DOMAIN); - } - int argOffset; while ((argOffset = argit.GetNextOffset()) != TransitionBlock::InvalidOffset) { @@ -2147,13 +2140,6 @@ void FakeGcScanRoots(MetaSig& msig, ArgIterator& argit, MethodDesc * pMD, BYTE * return; } - // Also if the method has a return buffer, then it is the first argument, and could be an interior ref, - // so always promote it. - if (argit.HasRetBuffArg()) - { - FakePromote((Object **)(pFrame + argit.GetRetBuffArgOffset()), &sc, GC_CALL_INTERIOR); - } - // // Now iterate the arguments // diff --git a/src/coreclr/vm/reflectioninvocation.cpp b/src/coreclr/vm/reflectioninvocation.cpp index 4637d307e0e384..f65613c98ea46a 100644 --- a/src/coreclr/vm/reflectioninvocation.cpp +++ b/src/coreclr/vm/reflectioninvocation.cpp @@ -492,6 +492,9 @@ extern "C" void QCALLTYPE RuntimeMethodHandle_InvokeMethod( // If an exception occurs a gc may happen but we are going to dump the stack anyway and we do // not need to protect anything. + // Allocate a local buffer for the return buffer if necessary + PVOID pLocalRetBuf = nullptr; + { BEGINFORBIDGC(); #ifdef _DEBUG @@ -501,8 +504,19 @@ extern "C" void QCALLTYPE RuntimeMethodHandle_InvokeMethod( // Take care of any return arguments if (fHasRetBuffArg) { - PVOID pRetBuff = gc.retVal->GetData(); - *((LPVOID*) (pTransitionBlock + argit.GetRetBuffArgOffset())) = pRetBuff; + _ASSERT(hasValueTypeReturn); + PTR_MethodTable pMT = retTH.GetMethodTable(); + size_t localRetBufSize = retTH.GetSize(); + + // Allocate a local buffer. The invoked method will write the return value to this + // buffer which will be copied to gc.retVal later. + pLocalRetBuf = _alloca(localRetBufSize); + ZeroMemory(pLocalRetBuf, localRetBufSize); + *((LPVOID*) (pTransitionBlock + argit.GetRetBuffArgOffset())) = pLocalRetBuf; + if (pMT->ContainsGCPointers()) + { + pValueClasses = new (_alloca(sizeof(ValueClassInfo))) ValueClassInfo(pLocalRetBuf, pMT, pValueClasses); + } } // copy args @@ -572,6 +586,19 @@ extern "C" void QCALLTYPE RuntimeMethodHandle_InvokeMethod( // Call the method CallDescrWorkerWithHandler(&callDescrData); + if (fHasRetBuffArg) + { + // Copy the return value from the return buffer to the object + if (retTH.GetMethodTable()->ContainsGCPointers()) + { + memmoveGCRefs(gc.retVal->GetData(), pLocalRetBuf, retTH.GetSize()); + } + else + { + memcpyNoGCRefs(gc.retVal->GetData(), pLocalRetBuf, retTH.GetSize()); + } + } + // It is still illegal to do a GC here. The return type might have/contain GC pointers. if (fConstructor) { From 08b488a711682ea254d4046d0d20e910e413b53e Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Tue, 11 Feb 2025 19:39:57 -0500 Subject: [PATCH 13/20] Bring up android+coreclr windows build. (#112256) This pull request includes various changes to improve the build process for Android and cross-compiling on Windows. The most important changes include updates to build scripts, configuration files, and the addition of new scripts. A side benefit of this change is that it sets the table for being able to cross compile other non-Windows configurations on Windows. Contributes to https://github.com/dotnet/runtime/issues/111491 --------- Co-authored-by: Jeremy Koritzinsky --- Directory.Build.props | 1 + eng/Subsets.props | 3 +- eng/native/build-commons.sh | 5 +- eng/native/configureplatform.cmake | 7 +- eng/native/configuretools.cmake | 15 ++- eng/native/functions.cmake | 91 ++++++++++----- eng/native/gen-buildsys.cmd | 28 +++++ eng/native/generateversionscript.ps1 | 34 ++++++ eng/native/tryrun.cmake | 11 +- eng/native/version/copy_version_files.ps1 | 27 +++++ src/coreclr/CMakeLists.txt | 31 +++-- src/coreclr/build-runtime.cmd | 29 ++++- src/coreclr/debug/runtimeinfo/CMakeLists.txt | 3 +- src/coreclr/dlls/mscordac/CMakeLists.txt | 55 ++++++--- src/coreclr/generateredefinesfile.ps1 | 40 +++++++ .../Runtime/eventpipe/CMakeLists.txt | 7 +- src/coreclr/nativeresources/processrc.ps1 | 98 ++++++++++++++++ src/coreclr/pal/src/configure.cmake | 1 + src/coreclr/runtime-prereqs.proj | 18 ++- src/coreclr/runtime.proj | 24 ++-- src/coreclr/scripts/genEventing.py | 48 ++++---- src/coreclr/vm/eventing/CMakeLists.txt | 7 +- src/mono/mono/eventpipe/gen-eventing.cmake | 6 +- .../sample/Android/AndroidSampleApp.csproj | 5 +- .../corehost/apphost/static/CMakeLists.txt | 4 +- src/native/corehost/corehost.proj | 18 ++- src/native/libs/build-native.cmd | 15 ++- src/native/libs/build-native.proj | 18 ++- src/tasks/AndroidAppBuilder/ApkBuilder.cs | 110 +++++------------- src/tasks/Common/AndroidSdkHelper.cs | 15 ++- src/tasks/Common/JavaCompiler.cs | 2 +- .../Android/AndroidProject.cs | 6 +- .../TestExclusionListTasks.csproj | 1 + 33 files changed, 585 insertions(+), 198 deletions(-) create mode 100644 eng/native/generateversionscript.ps1 create mode 100644 eng/native/version/copy_version_files.ps1 create mode 100644 src/coreclr/generateredefinesfile.ps1 create mode 100644 src/coreclr/nativeresources/processrc.ps1 diff --git a/Directory.Build.props b/Directory.Build.props index bed931fe34d414..bff6874d7bbe4d 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -56,6 +56,7 @@ Minimum target OS versions, keep in sync with: - eng/native/configurecompiler.cmake - eng/native/build-commons.sh + - eng/native/gen-buildsys.cmd - src/native/libs/build-native.sh - src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/MachObjectWriter.cs - src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets diff --git a/eng/Subsets.props b/eng/Subsets.props index 1ef526826cce1a..1bc750f58a0f7c 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -60,7 +60,7 @@ clr+mono+libs+tools+host+packs mono+libs+packs - clr.runtime+clr.alljits+clr.corelib+clr.nativecorelib+clr.tools+clr.packages+mono+libs+host+packs + clr+mono+libs+host+packs clr.nativeaotruntime+clr.nativeaotlibs+mono+libs+packs clr.nativeaotruntime+clr.nativeaotlibs+mono+libs+host+packs clr.nativeaotruntime+clr.nativeaotlibs+libs+packs @@ -100,6 +100,7 @@ clr.native+clr.corelib+clr.tools+clr.nativecorelib+clr.packages+clr.nativeaotlibs+clr.crossarchtools+host.native clr.native+clr.corelib+clr.tools+clr.nativecorelib+clr.packages+clr.nativeaotlibs+clr.crossarchtools + clr.native+clr.corelib+clr.tools+clr.nativecorelib+clr.packages+clr.nativeaotlibs+clr.crossarchtools clr.iltools+clr.packages diff --git a/eng/native/build-commons.sh b/eng/native/build-commons.sh index bf17618d972ade..b27eae7765a0d3 100755 --- a/eng/native/build-commons.sh +++ b/eng/native/build-commons.sh @@ -86,10 +86,7 @@ build_native() exit 1 fi - # cmake cache scripts can't see command line args - export ANDROID_BUILD=1 - - cmakeArgs="-C $__RepoRootDir/eng/native/tryrun.cmake $cmakeArgs" + cmakeArgs="-DANDROID_BUILD=1 -C $__RepoRootDir/eng/native/tryrun.cmake $cmakeArgs" cmakeArgs="-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_ROOT/build/cmake/android.toolchain.cmake -DANDROID_PLATFORM=android-${ANDROID_API_LEVEL} -DANDROID_NATIVE_API_LEVEL=${ANDROID_API_LEVEL} $cmakeArgs" # Don't try to set CC/CXX in init-compiler.sh - it's handled in android.toolchain.cmake already diff --git a/eng/native/configureplatform.cmake b/eng/native/configureplatform.cmake index 6f70e39f30c502..fc207977125c3e 100644 --- a/eng/native/configureplatform.cmake +++ b/eng/native/configureplatform.cmake @@ -368,6 +368,11 @@ if(CLR_CMAKE_HOST_LINUX_MUSL OR CLR_CMAKE_TARGET_OS STREQUAL alpine) set(CLR_CMAKE_TARGET_LINUX_MUSL 1) endif(CLR_CMAKE_HOST_LINUX_MUSL OR CLR_CMAKE_TARGET_OS STREQUAL alpine) +macro(set_cache_value) + set(${ARGV0} ${ARGV1} CACHE STRING "Result from TRY_RUN" FORCE) + set(${ARGV0}__TRYRUN_OUTPUT "dummy output" CACHE STRING "Output from TRY_RUN" FORCE) +endmacro() + if(CLR_CMAKE_TARGET_OS STREQUAL android) set(CLR_CMAKE_TARGET_UNIX 1) set(CLR_CMAKE_TARGET_LINUX 1) @@ -471,7 +476,7 @@ if(CLR_CMAKE_TARGET_OS STREQUAL windows) endif() # check if host & target os/arch combination are valid -if (NOT (CLR_CMAKE_TARGET_OS STREQUAL CLR_CMAKE_HOST_OS) AND NOT CLR_CMAKE_TARGET_WASI) +if (NOT (CLR_CMAKE_TARGET_OS STREQUAL CLR_CMAKE_HOST_OS) AND NOT CLR_CMAKE_TARGET_WASI AND NOT CLR_CMAKE_TARGET_ANDROID) if(NOT (CLR_CMAKE_HOST_OS STREQUAL windows)) message(FATAL_ERROR "Invalid host and target os/arch combination. Host OS: ${CLR_CMAKE_HOST_OS}") endif() diff --git a/eng/native/configuretools.cmake b/eng/native/configuretools.cmake index 6898f88578df13..de4571f905a5e5 100644 --- a/eng/native/configuretools.cmake +++ b/eng/native/configuretools.cmake @@ -77,10 +77,17 @@ endif() if (NOT CLR_CMAKE_HOST_WIN32) # detect linker - execute_process(COMMAND sh -c "${CMAKE_C_COMPILER} ${CMAKE_SHARED_LINKER_FLAGS} -Wl,--version | head -1" - ERROR_QUIET - OUTPUT_VARIABLE ldVersionOutput - OUTPUT_STRIP_TRAILING_WHITESPACE) + if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + execute_process(COMMAND ${CMAKE_C_COMPILER} -Wl,--version + ERROR_QUIET + OUTPUT_VARIABLE ldVersionOutput + OUTPUT_STRIP_TRAILING_WHITESPACE) + else() + execute_process(COMMAND sh -c "${CMAKE_C_COMPILER} ${CMAKE_SHARED_LINKER_FLAGS} -Wl,--version | head -1" + ERROR_QUIET + OUTPUT_VARIABLE ldVersionOutput + OUTPUT_STRIP_TRAILING_WHITESPACE) + endif() if("${ldVersionOutput}" MATCHES "LLD") set(LD_LLVM 1) diff --git a/eng/native/functions.cmake b/eng/native/functions.cmake index 2dee8bf0c50986..581dbd28fb2bad 100644 --- a/eng/native/functions.cmake +++ b/eng/native/functions.cmake @@ -338,39 +338,66 @@ function(generate_exports_file) list(GET INPUT_LIST -1 outputFilename) list(REMOVE_AT INPUT_LIST -1) - if(CLR_CMAKE_TARGET_APPLE) - set(SCRIPT_NAME generateexportedsymbols.sh) + # Win32 may be false when cross compiling + if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set(SCRIPT_NAME ${CLR_ENG_NATIVE_DIR}/generateversionscript.ps1) + + add_custom_command( + OUTPUT ${outputFilename} + COMMAND powershell -NoProfile -ExecutionPolicy ByPass -File "${SCRIPT_NAME}" ${INPUT_LIST} >${outputFilename} + DEPENDS ${INPUT_LIST} ${SCRIPT_NAME} + COMMENT "Generating exports file ${outputFilename}" + ) else() - set(SCRIPT_NAME generateversionscript.sh) + if(CLR_CMAKE_TARGET_APPLE) + set(SCRIPT_NAME ${CLR_ENG_NATIVE_DIR}/generateexportedsymbols.sh) + else() + set(SCRIPT_NAME ${CLR_ENG_NATIVE_DIR}/generateversionscript.sh) + endif() + + add_custom_command( + OUTPUT ${outputFilename} + COMMAND ${SCRIPT_NAME} ${INPUT_LIST} >${outputFilename} + DEPENDS ${INPUT_LIST} ${SCRIPT_NAME} + COMMENT "Generating exports file ${outputFilename}" + ) endif() - add_custom_command( - OUTPUT ${outputFilename} - COMMAND ${CLR_ENG_NATIVE_DIR}/${SCRIPT_NAME} ${INPUT_LIST} >${outputFilename} - DEPENDS ${INPUT_LIST} ${CLR_ENG_NATIVE_DIR}/${SCRIPT_NAME} - COMMENT "Generating exports file ${outputFilename}" - ) set_source_files_properties(${outputFilename} PROPERTIES GENERATED TRUE) endfunction() function(generate_exports_file_prefix inputFilename outputFilename prefix) - if(CMAKE_SYSTEM_NAME STREQUAL Darwin) set(SCRIPT_NAME generateexportedsymbols.sh) else() - set(SCRIPT_NAME generateversionscript.sh) + # Win32 may be false when cross compiling + if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set(SCRIPT_NAME ${CLR_ENG_NATIVE_DIR}/generateversionscript.ps1) + else() + set(SCRIPT_NAME ${CLR_ENG_NATIVE_DIR}/generateversionscript.sh) + endif() + if (NOT ${prefix} STREQUAL "") set(EXTRA_ARGS ${prefix}) endif() endif(CMAKE_SYSTEM_NAME STREQUAL Darwin) - add_custom_command( - OUTPUT ${outputFilename} - COMMAND ${CLR_ENG_NATIVE_DIR}/${SCRIPT_NAME} ${inputFilename} ${EXTRA_ARGS} >${outputFilename} - DEPENDS ${inputFilename} ${CLR_ENG_NATIVE_DIR}/${SCRIPT_NAME} - COMMENT "Generating exports file ${outputFilename}" - ) + if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + add_custom_command( + OUTPUT ${outputFilename} + COMMAND powershell -NoProfile -ExecutionPolicy ByPass -File \"${SCRIPT_NAME}\" ${inputFilename} ${EXTRA_ARGS} >${outputFilename} + DEPENDS ${inputFilename} ${SCRIPT_NAME} + COMMENT "Generating exports file ${outputFilename}" + ) + else() + add_custom_command( + OUTPUT ${outputFilename} + COMMAND ${SCRIPT_NAME} ${inputFilename} ${EXTRA_ARGS} >${outputFilename} + DEPENDS ${inputFilename} ${SCRIPT_NAME} + COMMENT "Generating exports file ${outputFilename}" + ) + endif() set_source_files_properties(${outputFilename} PROPERTIES GENERATED TRUE) endfunction() @@ -445,16 +472,28 @@ function(strip_symbols targetName outputFilename) COMMAND ${strip_command} ) else (CLR_CMAKE_TARGET_APPLE) - - add_custom_command( - TARGET ${targetName} - POST_BUILD - VERBATIM - COMMAND sh -c "echo Stripping symbols from $(basename '${strip_source_file}') into $(basename '${strip_destination_file}')" - COMMAND ${CMAKE_OBJCOPY} --only-keep-debug ${strip_source_file} ${strip_destination_file} - COMMAND ${CMAKE_OBJCOPY} --strip-debug --strip-unneeded ${strip_source_file} - COMMAND ${CMAKE_OBJCOPY} --add-gnu-debuglink=${strip_destination_file} ${strip_source_file} + # Win32 may be false when cross compiling + if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + add_custom_command( + TARGET ${targetName} + POST_BUILD + VERBATIM + COMMAND powershell -C "echo Stripping symbols from $(Split-Path -Path '${strip_source_file}' -Leaf) into $(Split-Path -Path '${strip_destination_file}' -Leaf)" + COMMAND ${CMAKE_OBJCOPY} --only-keep-debug ${strip_source_file} ${strip_destination_file} + COMMAND ${CMAKE_OBJCOPY} --strip-debug --strip-unneeded ${strip_source_file} + COMMAND ${CMAKE_OBJCOPY} --add-gnu-debuglink=${strip_destination_file} ${strip_source_file} ) + else() + add_custom_command( + TARGET ${targetName} + POST_BUILD + VERBATIM + COMMAND sh -c "echo Stripping symbols from $(basename '${strip_source_file}') into $(basename '${strip_destination_file}')" + COMMAND ${CMAKE_OBJCOPY} --only-keep-debug ${strip_source_file} ${strip_destination_file} + COMMAND ${CMAKE_OBJCOPY} --strip-debug --strip-unneeded ${strip_source_file} + COMMAND ${CMAKE_OBJCOPY} --add-gnu-debuglink=${strip_destination_file} ${strip_source_file} + ) + endif() endif (CLR_CMAKE_TARGET_APPLE) endif(CLR_CMAKE_HOST_UNIX) endfunction() diff --git a/eng/native/gen-buildsys.cmd b/eng/native/gen-buildsys.cmd index 83682d69cfc393..c198ec33d05edb 100644 --- a/eng/native/gen-buildsys.cmd +++ b/eng/native/gen-buildsys.cmd @@ -80,6 +80,33 @@ if /i "%__Arch%" == "wasm" ( set __ExtraCmakeParams=%__ExtraCmakeParams% "-DCMAKE_SYSTEM_VERSION=10.0" ) +if /i "%__Os%" == "android" ( + :: Keep in sync with $(AndroidApiLevelMin) in Directory.Build.props in the repository rooot + set __ANDROID_API_LEVEL=21 + if "%ANDROID_NDK_ROOT%" == "" ( + echo Error: You need to set the ANDROID_NDK_ROOT environment variable pointing to the Android NDK root. + exit /B 1 + ) + + set __ExtraCmakeParams=!__ExtraCmakeParams! "-DANDROID_BUILD=1" "-DANDROID_CPP_FEATURES='no-rtti exceptions'" + set __ExtraCmakeParams=!__ExtraCmakeParams! "-DANDROID_PLATFORM=android-!__ANDROID_API_LEVEL!" "-DANDROID_NATIVE_API_LEVEL=!__ANDROID_API_LEVEL!" + + if "%__Arch%" == "x64" ( + set __ExtraCmakeParams=!__ExtraCmakeParams! "-DANDROID_ABI=x86_64" + ) + if "%__Arch%" == "x86" ( + set __ExtraCmakeParams=!__ExtraCmakeParams! "-DANDROID_ABI=x86" + ) + if "%__Arch%" == "arm64" ( + set __ExtraCmakeParams=!__ExtraCmakeParams! "-DANDROID_ABI=arm64-v8a" + ) + if "%__Arch%" == "x64" ( + set __ExtraCmakeParams=!__ExtraCmakeParams! "-DANDROID_ABI=armeabi-v7a" + ) + + set __ExtraCmakeParams=!__ExtraCmakeParams! "-DCMAKE_TOOLCHAIN_FILE='%ANDROID_NDK_ROOT:\=/%/build/cmake/android.toolchain.cmake'" "-C %__repoRoot%/eng/native/tryrun.cmake" +) + :loop if [%6] == [] goto end_loop set __ExtraCmakeParams=%__ExtraCmakeParams% %6 @@ -111,6 +138,7 @@ if not "%__ConfigureOnly%" == "1" ( if /i "%__UseEmcmake%" == "1" ( call "!EMSDK_PATH!/emsdk_env.cmd" > nul 2>&1 && emcmake "%CMakePath%" %__ExtraCmakeParams% --no-warn-unused-cli -G "%__CmakeGenerator%" -B %__IntermediatesDir% -S %__SourceDir% ) else ( + echo "%CMakePath% %__ExtraCmakeParams% --no-warn-unused-cli -G %__CmakeGenerator% -B %__IntermediatesDir% -S %__SourceDir%" "%CMakePath%" %__ExtraCmakeParams% --no-warn-unused-cli -G "%__CmakeGenerator%" -B %__IntermediatesDir% -S %__SourceDir% ) diff --git a/eng/native/generateversionscript.ps1 b/eng/native/generateversionscript.ps1 new file mode 100644 index 00000000000000..945ab6f706a439 --- /dev/null +++ b/eng/native/generateversionscript.ps1 @@ -0,0 +1,34 @@ +param ( + [string]$inputFile, + [string]$prefix +) + +# Print the header +Write-Output "V1.0 {" +Write-Output " global:" + +# Read the input file line by line +Get-Content $inputFile | ForEach-Object { + $line = $_.Trim() + + # Skip empty lines and comment lines starting with semicolon + if ($line -match '^\;.*$' -or $line -match '^[\s]*$') { + return + } + + # Remove the CR character in case the sources are mapped from + # a Windows share and contain CRLF line endings + $line = $line -replace "`r", "" + + # Only prefix the entries that start with "#" + if ($line -match '^#.*$') { + $line = $line -replace '^#', '' + Write-Output " $prefix$line;" + } else { + Write-Output " $line;" + } +} + +# Print the footer +Write-Output " local: *;" +Write-Output "};" \ No newline at end of file diff --git a/eng/native/tryrun.cmake b/eng/native/tryrun.cmake index 8fd127f9e3e802..2397f8dcc8f209 100644 --- a/eng/native/tryrun.cmake +++ b/eng/native/tryrun.cmake @@ -1,6 +1,5 @@ set(CROSS_ROOTFS $ENV{ROOTFS_DIR}) set(TARGET_ARCH_NAME $ENV{TARGET_BUILD_ARCH}) -set(ANDROID_BUILD $ENV{ANDROID_BUILD}) # Also allow building as Android without specifying `-cross`. if(NOT DEFINED TARGET_ARCH_NAME AND DEFINED ANDROID_BUILD) @@ -50,8 +49,8 @@ if(NOT DEFINED ANDROID_BUILD) endif() endif() -if(DARWIN) - if(DEFINED ANDROID_BUILD OR TARGET_ARCH_NAME MATCHES "^(arm64|x64)$") +if(DARWIN AND NOT DEFINED ANDROID_BUILD) + if(TARGET_ARCH_NAME MATCHES "^(arm64|x64)$") set_cache_value(HAS_POSIX_SEMAPHORES_EXITCODE 1) set_cache_value(HAVE_BROKEN_FIFO_KEVENT_EXITCODE 1) set_cache_value(HAVE_BROKEN_FIFO_SELECT_EXITCODE 1) @@ -78,7 +77,7 @@ if(DARWIN) else() message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only arm64 or x64 is supported for OSX cross build!") endif() -elseif(TARGET_ARCH_NAME MATCHES "^(armel|arm|armv6|arm64|loongarch64|riscv64|s390x|ppc64le|x86|x64)$" OR FREEBSD OR ILLUMOS OR TIZEN OR HAIKU) +elseif(DEFINED ANDROID_BUILD OR TARGET_ARCH_NAME MATCHES "^(armel|arm|armv6|arm64|loongarch64|riscv64|s390x|ppc64le|x86|x64)$" OR FREEBSD OR ILLUMOS OR TIZEN OR HAIKU) set_cache_value(HAS_POSIX_SEMAPHORES_EXITCODE 0) set_cache_value(HAVE_CLOCK_MONOTONIC_COARSE_EXITCODE 0) set_cache_value(HAVE_CLOCK_MONOTONIC_EXITCODE 0) @@ -123,8 +122,10 @@ elseif(TARGET_ARCH_NAME MATCHES "^(armel|arm|armv6|arm64|loongarch64|riscv64|s39 set_cache_value(HAVE_CLOCK_MONOTONIC_COARSE_EXITCODE 1) set_cache_value(HAVE_PROCFS_STAT_EXITCODE 1) set_cache_value(HAVE_PROCFS_STATM_EXITCODE 1) + elseif(ANDROID_BUILD) + set_cache_value(ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS 0) endif() -else() +elseif(NOT WIN32) message(FATAL_ERROR "Unsupported platform. OS: ${CMAKE_SYSTEM_NAME}, arch: ${TARGET_ARCH_NAME}") endif() diff --git a/eng/native/version/copy_version_files.ps1 b/eng/native/version/copy_version_files.ps1 new file mode 100644 index 00000000000000..7573abcbb11a5a --- /dev/null +++ b/eng/native/version/copy_version_files.ps1 @@ -0,0 +1,27 @@ +$VersionFolder = $PSScriptRoot +$RepoRoot = (Resolve-Path "$VersionFolder/../../../").Path.TrimEnd("\") + +Get-ChildItem -Path "$VersionFolder" -Filter "_version.*" | ForEach-Object { + $path = $_.FullName + if ($_.Name -eq "_version.c") { + # For _version.c, update the commit ID if it has changed from the last build. + $commit = (git rev-parse HEAD 2>$null) + if (-not $commit) { $commit = "N/A" } + $substitute = "static char sccsid[] __attribute__((used)) = `"@(#)Version N/A @Commit: $commit`";" + $version_file_contents = Get-Content -Path $path | ForEach-Object { $_ -replace "^static.*", $substitute } + $version_file_destination = "$RepoRoot\\artifacts\\obj\\_version.c" + $current_contents = "" + $is_placeholder_file = $false + if (Test-Path -Path $version_file_destination) { + $current_contents = Get-Content -Path $version_file_destination -Raw + $is_placeholder_file = $current_contents -match "@\(#\)Version N/A @Commit:" + } else { + $is_placeholder_file = $true + } + if ($is_placeholder_file -and $version_file_contents -ne $current_contents) { + $version_file_contents | Set-Content -Path $version_file_destination + } + } elseif (-not (Test-Path -Path "$RepoRoot\\artifacts\\obj\\$($_.Name)")) { + Copy-Item -Path $path -Destination "$RepoRoot\\artifacts\\obj\\" + } +} diff --git a/src/coreclr/CMakeLists.txt b/src/coreclr/CMakeLists.txt index e519e1e71e5ae8..405cf527687c1a 100644 --- a/src/coreclr/CMakeLists.txt +++ b/src/coreclr/CMakeLists.txt @@ -215,7 +215,13 @@ if(CLR_CMAKE_HOST_UNIX) set (NATIVE_RESOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/nativeresources) include_directories(${NATIVE_RESOURCE_DIR}) - set (PROCESS_RC_SCRIPT ${NATIVE_RESOURCE_DIR}/processrc.sh) + + # Win32 may be false when cross compiling + if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set (PROCESS_RC_SCRIPT ${NATIVE_RESOURCE_DIR}/processrc.ps1) + else() + set (PROCESS_RC_SCRIPT ${NATIVE_RESOURCE_DIR}/processrc.sh) + endif() set (RESOURCE_STRING_HEADER_DIR ${NATIVE_RESOURCE_DIR}) # Create a command to create a C++ source file containing an array of @@ -230,16 +236,25 @@ if(CLR_CMAKE_HOST_UNIX) set(RESOURCE_ENTRY_ARRAY_CPP ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.cpp) - add_custom_command( - OUTPUT ${RESOURCE_ENTRY_ARRAY_CPP} - # Convert the preprocessed .rc file to a C++ file which will be used to make a static lib. - COMMAND ${PROCESS_RC_SCRIPT} ${PREPROCESSED_SOURCE} ${TARGET_NAME} >${RESOURCE_ENTRY_ARRAY_CPP} - DEPENDS ${PREPROCESSED_SOURCE} ${PROCESS_RC_SCRIPT} - ) + # Win32 may be false when cross compiling + if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + add_custom_command( + OUTPUT ${RESOURCE_ENTRY_ARRAY_CPP} + # Convert the preprocessed .rc file to a C++ file which will be used to make a static lib. + COMMAND powershell -NoProfile -ExecutionPolicy ByPass -File \"${PROCESS_RC_SCRIPT}\" ${PREPROCESSED_SOURCE} ${TARGET_NAME} >${RESOURCE_ENTRY_ARRAY_CPP} + DEPENDS ${PREPROCESSED_SOURCE} ${PROCESS_RC_SCRIPT} + ) + else() + add_custom_command( + OUTPUT ${RESOURCE_ENTRY_ARRAY_CPP} + # Convert the preprocessed .rc file to a C++ file which will be used to make a static lib. + COMMAND ${PROCESS_RC_SCRIPT} ${PREPROCESSED_SOURCE} ${TARGET_NAME} >${RESOURCE_ENTRY_ARRAY_CPP} + DEPENDS ${PREPROCESSED_SOURCE} ${PROCESS_RC_SCRIPT} + ) + endif() include_directories(${RESOURCE_STRING_HEADER_DIR}) set(${TARGET_FILE} ${RESOURCE_ENTRY_ARRAY_CPP} PARENT_SCOPE) - endfunction() add_subdirectory(nativeresources) diff --git a/src/coreclr/build-runtime.cmd b/src/coreclr/build-runtime.cmd index aa8c92500e04cd..5f6964b34a84b7 100644 --- a/src/coreclr/build-runtime.cmd +++ b/src/coreclr/build-runtime.cmd @@ -66,6 +66,7 @@ set __UnprocessedBuildArgs= set __BuildNative=1 set __RestoreOptData=1 +set __HostOS= set __HostArch= set __PgoOptDataPath= set __CMakeArgs= @@ -133,6 +134,7 @@ if [!__PassThroughArgs!]==[] ( set "__PassThroughArgs=%__PassThroughArgs% %1" ) +if /i "%1" == "-hostos" (set __HostOS=%2&shift&shift&goto Arg_Loop) if /i "%1" == "-hostarch" (set __HostArch=%2&shift&shift&goto Arg_Loop) if /i "%1" == "-os" (set __TargetOS=%2&shift&shift&goto Arg_Loop) if /i "%1" == "-outputrid" (set __OutputRid=%2&shift&shift&goto Arg_Loop) @@ -279,7 +281,11 @@ REM ============================================================================ @if defined _echo @echo on -call "%__RepoRootDir%\eng\native\version\copy_version_files.cmd" +if not "%__TargetOS%"=="android" ( + call "%__RepoRootDir%\eng\native\version\copy_version_files.cmd" +) else ( + call powershell -NoProfile -ExecutionPolicy ByPass -File "%__RepoRootDir%\eng\native\version\copy_version_files.ps1" +) REM ========================================================================================= REM === @@ -386,9 +392,24 @@ if %__BuildNative% EQU 1 ( set __ExtraCmakeArgs="-DCMAKE_BUILD_TYPE=!__BuildType!" ) - set __ExtraCmakeArgs=!__ExtraCmakeArgs! "-DCLR_CMAKE_TARGET_ARCH=%__TargetArch%" "-DCLR_CMAKE_TARGET_OS=%__TargetOS%" "-DCLI_CMAKE_FALLBACK_OS=%__HostFallbackOS%" "-DCLR_CMAKE_PGO_INSTRUMENT=%__PgoInstrument%" "-DCLR_CMAKE_OPTDATA_PATH=%__PgoOptDataPath%" "-DCLR_CMAKE_PGO_OPTIMIZE=%__PgoOptimize%" %__CMakeArgs% - echo Calling "%__RepoRootDir%\eng\native\gen-buildsys.cmd" "%__ProjectDir%" "%__IntermediatesDir%" %__VSVersion% %__HostArch% %__TargetOS% !__ExtraCmakeArgs! - call "%__RepoRootDir%\eng\native\gen-buildsys.cmd" "%__ProjectDir%" "%__IntermediatesDir%" %__VSVersion% %__HostArch% %__TargetOS% !__ExtraCmakeArgs! + if /i not "%__HostOS%" == "%__TargetOS%" ( + if /i "%__HostOS%" == "" ( + set __ExtraCmakeArgs=!__ExtraCmakeArgs! "-DCLR_CMAKE_TARGET_ARCH=%__TargetArch%" "-DCLR_CMAKE_TARGET_OS=%__TargetOS%" + ) + ) + + set __ExtraCmakeArgs=!__ExtraCmakeArgs! "-DCLI_CMAKE_FALLBACK_OS=%__HostFallbackOS%" "-DCLR_CMAKE_PGO_INSTRUMENT=%__PgoInstrument%" "-DCLR_CMAKE_OPTDATA_PATH=%__PgoOptDataPath%" "-DCLR_CMAKE_PGO_OPTIMIZE=%__PgoOptimize%" + + if /i "%__TargetOS%" == "android" ( + if not "%__HostOS%" == "" ( + set "__TargetOS=!__HostOS!" + ) + ) + + set __ExtraCmakeArgs=!__ExtraCmakeArgs! %__CMakeArgs% + + echo Calling "%__RepoRootDir%\eng\native\gen-buildsys.cmd" "%__ProjectDir%" "%__IntermediatesDir%" %__VSVersion% %__HostArch% !__TargetOS! !__ExtraCmakeArgs! + call "%__RepoRootDir%\eng\native\gen-buildsys.cmd" "%__ProjectDir%" "%__IntermediatesDir%" %__VSVersion% %__HostArch% !__TargetOS! !__ExtraCmakeArgs! if not !errorlevel! == 0 ( echo %__ErrMsgPrefix%%__MsgPrefix%Error: failed to generate native component build project! goto ExitWithError diff --git a/src/coreclr/debug/runtimeinfo/CMakeLists.txt b/src/coreclr/debug/runtimeinfo/CMakeLists.txt index f7ff177b130a79..791e0ec370479d 100644 --- a/src/coreclr/debug/runtimeinfo/CMakeLists.txt +++ b/src/coreclr/debug/runtimeinfo/CMakeLists.txt @@ -7,7 +7,8 @@ set(RUNTIMEINFO_SOURCES add_library_clr(runtimeinfo STATIC ${RUNTIMEINFO_SOURCES}) function(generate_module_index Target ModuleIndexFile) - if(CLR_CMAKE_HOST_WIN32) + # Win32 may be false when cross compiling + if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") set(scriptExt ".cmd") else() set(scriptExt ".sh") diff --git a/src/coreclr/dlls/mscordac/CMakeLists.txt b/src/coreclr/dlls/mscordac/CMakeLists.txt index ed7d7f03f9522e..0b580604c54bc2 100644 --- a/src/coreclr/dlls/mscordac/CMakeLists.txt +++ b/src/coreclr/dlls/mscordac/CMakeLists.txt @@ -45,7 +45,11 @@ else(CLR_CMAKE_HOST_WIN32) # Generate DAC export file with the DAC_ prefix generate_exports_file_prefix(${DEF_SOURCES} ${EXPORTS_FILE} DAC_) - set(REDEFINES_FILE_SCRIPT ${CMAKE_SOURCE_DIR}/generateredefinesfile.sh) + if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set(REDEFINES_FILE_SCRIPT ${CMAKE_SOURCE_DIR}/generateredefinesfile.ps1) + else() + set(REDEFINES_FILE_SCRIPT ${CMAKE_SOURCE_DIR}/generateredefinesfile.sh) + endif() if (CLR_CMAKE_HOST_ARCH_ARM OR CLR_CMAKE_HOST_ARCH_ARM64 OR CLR_CMAKE_HOST_ARCH_LOONGARCH64) set(JUMP_INSTRUCTION b) @@ -57,23 +61,46 @@ else(CLR_CMAKE_HOST_WIN32) # Generate the palredefines.inc file to map from the imported prefixed APIs (foo to DAC_foo) set(PAL_REDEFINES_INC ${GENERATED_INCLUDE_DIR}/palredefines.inc) - add_custom_command( - OUTPUT ${PAL_REDEFINES_INC} - COMMAND ${REDEFINES_FILE_SCRIPT} ${DEF_SOURCES} ${JUMP_INSTRUCTION} "" DAC_ > ${PAL_REDEFINES_INC} - DEPENDS ${DEF_SOURCES} ${REDEFINES_FILE_SCRIPT} - COMMENT "Generating PAL redefines file -> ${PAL_REDEFINES_INC}" - VERBATIM - ) + + # Win32 may be false when cross compiling + if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + add_custom_command( + OUTPUT ${PAL_REDEFINES_INC} + COMMAND powershell -NoProfile -ExecutionPolicy ByPass -File \"${REDEFINES_FILE_SCRIPT}\" -filename \"${DEF_SOURCES}\" -jump ${JUMP_INSTRUCTION} -prefix1 \"\" -prefix2 \"DAC_\" > ${PAL_REDEFINES_INC} + DEPENDS ${DEF_SOURCES} ${REDEFINES_FILE_SCRIPT} + COMMENT "Generating PAL redefines file -> ${PAL_REDEFINES_INC}" + ) + else() + add_custom_command( + OUTPUT ${PAL_REDEFINES_INC} + COMMAND ${REDEFINES_FILE_SCRIPT} ${DEF_SOURCES} ${JUMP_INSTRUCTION} "" DAC_ > ${PAL_REDEFINES_INC} + DEPENDS ${DEF_SOURCES} ${REDEFINES_FILE_SCRIPT} + COMMENT "Generating PAL redefines file -> ${PAL_REDEFINES_INC}" + VERBATIM + ) + endif() add_custom_target(pal_redefines_file DEPENDS ${PAL_REDEFINES_INC}) # Generate the libredefines.inc file for the DAC to export the prefixed APIs (DAC_foo to foo) set(LIB_REDEFINES_INC ${GENERATED_INCLUDE_DIR}/libredefines.inc) - add_custom_command( - OUTPUT ${LIB_REDEFINES_INC} - COMMAND ${REDEFINES_FILE_SCRIPT} ${DEF_SOURCES} ${JUMP_INSTRUCTION} DAC_ > ${LIB_REDEFINES_INC} - DEPENDS ${DEF_SOURCES} ${REDEFINES_FILE_SCRIPT} - COMMENT "Generating DAC export redefines file -> ${LIB_REDEFINES_INC}" - ) + + # Win32 may be false when cross compiling + if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + add_custom_command( + OUTPUT ${LIB_REDEFINES_INC} + COMMAND powershell -NoProfile -ExecutionPolicy ByPass -File \"${REDEFINES_FILE_SCRIPT}\" -filename \"${DEF_SOURCES}\" -jump ${JUMP_INSTRUCTION} -prefix1 \"DAC_\" > ${LIB_REDEFINES_INC} + DEPENDS ${DEF_SOURCES} ${REDEFINES_FILE_SCRIPT} + COMMENT "Generating DAC export redefines file -> ${LIB_REDEFINES_INC}" + ) + else() + add_custom_command( + OUTPUT ${LIB_REDEFINES_INC} + COMMAND ${REDEFINES_FILE_SCRIPT} ${DEF_SOURCES} ${JUMP_INSTRUCTION} DAC_ > ${LIB_REDEFINES_INC} + DEPENDS ${DEF_SOURCES} ${REDEFINES_FILE_SCRIPT} + COMMENT "Generating DAC export redefines file -> ${LIB_REDEFINES_INC}" + VERBATIM + ) + endif() add_custom_target(lib_redefines_inc DEPENDS ${LIB_REDEFINES_INC}) # Add lib redefines file to DAC diff --git a/src/coreclr/generateredefinesfile.ps1 b/src/coreclr/generateredefinesfile.ps1 new file mode 100644 index 00000000000000..1a37c661d0c5cd --- /dev/null +++ b/src/coreclr/generateredefinesfile.ps1 @@ -0,0 +1,40 @@ +param ( + [string]$filename = "", + [string]$jump = "", + [string]$prefix1 = "", + [string]$prefix2 = "" +) + +# Function to display usage information +function Show-Usage { + Write-Host "Usage:" + Write-Host "generateredefinesfile.ps1 " + exit 1 +} + +if ($filename.Length -eq 0) { + Show-Usage +} + +# Read the file line by line +Get-Content $filename | ForEach-Object { + $line = $_.Trim() + + # Skip empty lines and comment lines starting with semicolon + if ($line -match '^\;.*$' -or $line -match '^[\s]*$') { + return + } + + # Remove the CR character in case the sources are mapped from + # a Windows share and contain CRLF line endings + $line = $line -replace "`r", "" + + # Only process the entries that begin with "#" + if ($line -match '^#.*$') { + $line = $line -replace '^#', '' + Write-Output "LEAF_ENTRY ${prefix1}${line}, _TEXT" + Write-Output " ${jump} EXTERNAL_C_FUNC(${prefix2}${line})" + Write-Output "LEAF_END ${prefix1}${line}, _TEXT" + Write-Output "" + } +} diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/CMakeLists.txt b/src/coreclr/nativeaot/Runtime/eventpipe/CMakeLists.txt index 739738e6743465..6b55b13b76ae19 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/CMakeLists.txt +++ b/src/coreclr/nativeaot/Runtime/eventpipe/CMakeLists.txt @@ -27,9 +27,14 @@ set (EventingHeaders ${GENERATED_INCLUDE_DIR}/clretwallmain.cpp ) +if(CMAKE_CROSSCOMPILING) + set(GEN_EVENTING_TARGETOS --targetos) + set(GEN_EVENTING_TARGETOS_ARG ${CLR_CMAKE_TARGET_OS}) +endif() + add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/aot_eventing_headers.timestamp - COMMAND ${Python_EXECUTABLE} ${GENERATE_PLAT_AGNOSTIC_SCRIPT} --man ${EVENT_MANIFEST} --incdir ${GENERATED_INCLUDE_DIR} --inc ${EVENT_INCLUSION_FILE} --dummy ${GENERATED_INCLUDE_DIR}/etmdummy.h --runtimeflavor nativeaot ${NONEXTERN_ARG} ${NOXPLATHEADER_ARG} + COMMAND ${Python_EXECUTABLE} ${GENERATE_PLAT_AGNOSTIC_SCRIPT} --man ${EVENT_MANIFEST} --incdir ${GENERATED_INCLUDE_DIR} --inc ${EVENT_INCLUSION_FILE} ${GEN_EVENTING_TARGETOS} ${GEN_EVENTING_TARGETOS_ARG} --dummy ${GENERATED_INCLUDE_DIR}/etmdummy.h --runtimeflavor nativeaot ${NONEXTERN_ARG} ${NOXPLATHEADER_ARG} COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/aot_eventing_headers.timestamp DEPENDS ${EVENT_MANIFEST} ${GENERATE_PLAT_AGNOSTIC_SCRIPT} VERBATIM diff --git a/src/coreclr/nativeresources/processrc.ps1 b/src/coreclr/nativeresources/processrc.ps1 new file mode 100644 index 00000000000000..8ff7559e85eaa9 --- /dev/null +++ b/src/coreclr/nativeresources/processrc.ps1 @@ -0,0 +1,98 @@ +param ( + [string]$Filename, + [string]$Targetname +) + +function Evaluate-ComplexExpression { + param ( + [string]$expression + ) + + # Extract the components of the expression + if ($expression -match '\(0x([0-9A-Fa-f]+)\s*\+\s*\(\(\(0x([0-9A-Fa-f]+)\)\s*&\s*0x([0-9A-Fa-f]+)\)\)\)') { + $baseValue = [convert]::ToInt64($matches[1], 16) + $hexValue = [convert]::ToInt64($matches[2], 16) + $mask = [convert]::ToInt64($matches[3], 16) + + # Perform the bitwise AND operation + $maskedValue = $hexValue -band $mask + + # Add the base value to the masked value + $result = $baseValue + $maskedValue + + return $result + } else { + throw "$expression - Input string was not in the correct format" + } +} + +# Function to determine if the input is a simple hex value or a complex expression +function Evaluate-Input { + param ( + [string]$expr + ) + + # Regular expression for a simple hex value + $hexRegex = '^0x[0-9A-Fa-f]+$' + + # Regular expression for a complex expression + $complexRegex = '^\(0x[0-9A-Fa-f]+\s*\+\s*\(\(\(0x[0-9A-Fa-f]+\)\s*&\s*0x[0-9A-Fa-f]+\)\)\)$' + + if ($expr -match $hexRegex) { + # Input is a simple hex value + return [convert]::ToInt64($expr, 16) + } elseif ($expr -match $complexRegex) { + # Input is a complex expression + return Evaluate-ComplexExpression($expr) + } else { + Write-Host "Input string was not in the correct format" + return 0 + } +} + +$ArrayName = "nativeStringResourceArray_$Targetname" +$TableName = "nativeStringResourceTable_$Targetname" + +$InStringTable = $false +$InBeginEnd = $false +$ResourceArray = @{} + +Get-Content $Filename | ForEach-Object { + $line = $_.Trim() + if ($line -match "^STRINGTABLE\s*DISCARDABLE") { + $InStringTable = $true + } elseif ($line -eq "BEGIN") { + $InBeginEnd = $InStringTable + } elseif ($InBeginEnd -and $line -eq "END") { + $InBeginEnd = $false + $InStringTable = $false + } elseif ($InBeginEnd -and $line -notmatch "^\s*$") { + $id = $line -replace '\".*', '' -replace '\(HRESULT\)', '' -replace 'L', '' + $id = $id.Trim() + $id = Evaluate-Input($id) + + if ($line -match '"([^"]+)"') { + $content = $matches[1] + $ResourceArray[$id.ToString("x8")] = $content + } + } +} + +Write-Output "// Licensed to the .NET Foundation under one or more agreements." +Write-Output "// The .NET Foundation licenses this file to you under the MIT license." +Write-Output "//" +Write-Output "// This code was generated by processrc.ps1 and is not meant to be modified manually." +Write-Output "" +Write-Output "#include " +Write-Output "" +Write-Output "extern NativeStringResourceTable $TableName;" +Write-Output "const NativeStringResource $ArrayName[] = {" + +foreach ($id in $ResourceArray.Keys) { + $hexId = "{0:x8}" -f $id + Write-Output " {0x$hexId,`"$($ResourceArray[$id])`"}," +} + +Write-Output "};" +Write-Output "" +Write-Output "NativeStringResourceTable $TableName __attribute__((visibility(`"default`"))) = { $($ResourceArray.Count), $ArrayName };" diff --git a/src/coreclr/pal/src/configure.cmake b/src/coreclr/pal/src/configure.cmake index 4ba3ab6f53ce0d..0dc8c6524d298c 100644 --- a/src/coreclr/pal/src/configure.cmake +++ b/src/coreclr/pal/src/configure.cmake @@ -513,6 +513,7 @@ int main(void) exit(ret != 1); }" ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS) + set(CMAKE_REQUIRED_LIBRARIES pthread) check_cxx_source_runs(" #include diff --git a/src/coreclr/runtime-prereqs.proj b/src/coreclr/runtime-prereqs.proj index b1d1cf8b041df8..a9b63fac2b4b6a 100644 --- a/src/coreclr/runtime-prereqs.proj +++ b/src/coreclr/runtime-prereqs.proj @@ -2,7 +2,7 @@ $(ArtifactsObjDir)_version.h - $(ArtifactsObjDir)_version.c + $(ArtifactsObjDir)_version.c $(ArtifactsObjDir)runtime_version.h $(ArtifactsObjDir)native.sourcelink.json false @@ -14,6 +14,22 @@ + + + + + $(ArtifactsObjDir)_version.h + + + + + $(ArtifactsObjDir)_version.c + + + <_CoreClrBuildArg Condition="!$([MSBuild]::IsOsPlatform(Windows))" + Include="-cmakeargs -DANDROID_CPP_FEATURES="no-rtti exceptions""/> diff --git a/src/coreclr/scripts/genEventing.py b/src/coreclr/scripts/genEventing.py index e1ca570166e708..b7439e2b4f7d68 100644 --- a/src/coreclr/scripts/genEventing.py +++ b/src/coreclr/scripts/genEventing.py @@ -467,7 +467,7 @@ def parseTemplateNodes(templateNodes): return allTemplates -def generateClrallEvents(eventNodes, allTemplates, target_cpp, runtimeFlavor, write_xplatheader, providerName, inclusionList, generatedFileType, user_events): +def generateClrallEvents(eventNodes, allTemplates, target_cpp, runtimeFlavor, is_host_windows, write_xplatheader, providerName, inclusionList, generatedFileType, user_events): clrallEvents = [] for eventNode in eventNodes: eventName = eventNode.getAttribute('symbol') @@ -495,7 +495,7 @@ def generateClrallEvents(eventNodes, allTemplates, target_cpp, runtimeFlavor, wr clrallEvents.append("EventPipeEventEnabled" + eventName + "()") if runtimeFlavor.coreclr or write_xplatheader or runtimeFlavor.nativeaot: - if os.name == 'posix': + if not is_host_windows: if user_events and runtimeFlavor.coreclr: clrallEvents.append(" || UserEventsEventEnabled" + eventName + "()") # native AOT does not support non-windows eventing other than via event pipe @@ -872,8 +872,7 @@ def getKeywordsMaskCombined(keywords, keywordsToMask): return mask -def updateclreventsfile(write_xplatheader, target_cpp, runtimeFlavor, eventpipe_trace_context_typedef, dotnet_trace_context_typedef_windows, user_events_trace_context_typedef, tree, clrallevents, inclusion_list, generatedFileType, user_events): - is_windows = os.name == 'nt' +def updateclreventsfile(write_xplatheader, target_cpp, runtimeFlavor, is_host_windows, eventpipe_trace_context_typedef, dotnet_trace_context_typedef_windows, user_events_trace_context_typedef, tree, clrallevents, inclusion_list, generatedFileType, user_events): with open_for_update(clrallevents) as Clrallevents: Clrallevents.write(stdprolog) if generatedFileType=="header-impl": @@ -907,17 +906,17 @@ def updateclreventsfile(write_xplatheader, target_cpp, runtimeFlavor, eventpipe_ Clrallevents.write('#endif\n\n') # define DOTNET_TRACE_CONTEXT depending on the platform - if is_windows and not runtimeFlavor.nativeaot: + if is_host_windows and not runtimeFlavor.nativeaot: Clrallevents.write(eventpipe_trace_context_typedef) # define EVENTPIPE_TRACE_CONTEXT if runtimeFlavor.coreclr or write_xplatheader: Clrallevents.write(dotnet_trace_context_typedef_windows + "\n") else: Clrallevents.write("\n") - if not is_windows and runtimeFlavor.coreclr: + if not is_host_windows and runtimeFlavor.coreclr: Clrallevents.write(user_events_trace_context_typedef) - if not is_windows and not write_xplatheader and not runtimeFlavor.nativeaot: + if not is_host_windows and not write_xplatheader and not runtimeFlavor.nativeaot: Clrallevents.write(eventpipe_trace_context_typedef) # define EVENTPIPE_TRACE_CONTEXT Clrallevents.write("\n") @@ -929,22 +928,22 @@ def updateclreventsfile(write_xplatheader, target_cpp, runtimeFlavor, eventpipe_ eventNodes = providerNode.getElementsByTagName('event') #vm header: - Clrallevents.write(generateClrallEvents(eventNodes, allTemplates, target_cpp, runtimeFlavor, write_xplatheader, providerName, inclusion_list, generatedFileType, user_events)) + Clrallevents.write(generateClrallEvents(eventNodes, allTemplates, target_cpp, runtimeFlavor, is_host_windows, write_xplatheader, providerName, inclusion_list, generatedFileType, user_events)) providerName = providerNode.getAttribute('name') providerSymbol = providerNode.getAttribute('symbol') eventpipeProviderCtxName = providerSymbol + "_EVENTPIPE_Context" - if is_windows and not (write_xplatheader or runtimeFlavor.nativeaot): + if is_host_windows and not (write_xplatheader or runtimeFlavor.nativeaot): Clrallevents.write(('constexpr ' if target_cpp else 'static const ') + 'EVENTPIPE_TRACE_CONTEXT ' + eventpipeProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n') - if not is_windows and not write_xplatheader and not runtimeFlavor.nativeaot: + if not is_host_windows and not write_xplatheader and not runtimeFlavor.nativeaot: Clrallevents.write('__attribute__((weak)) EVENTPIPE_TRACE_CONTEXT ' + eventpipeProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n') if generatedFileType == "header": Clrallevents.write("#endif // __CLR_ETW_ALL_MAIN_H__\n") -def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern, write_xplatheader, target_cpp, runtimeFlavor, inclusion_list, user_events): +def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern, write_xplatheader, target_cpp, runtimeFlavor, is_host_windows, inclusion_list, user_events): generateEtmDummyHeader(sClrEtwAllMan,etmDummyFile) tree = DOM.parse(sClrEtwAllMan) @@ -1014,16 +1013,14 @@ def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern #endif // DOTNET_TRACE_CONTEXT_DEF """ - is_windows = os.name == 'nt' - # Write the main source(s) for FireETW* functions # nativeaot requires header and source file to be separated as well as a noop implementation if runtimeFlavor.nativeaot: - updateclreventsfile(write_xplatheader, target_cpp, runtimeFlavor, eventpipe_trace_context_typedef, dotnet_trace_context_typedef_windows, user_events_trace_context_typedef, tree, os.path.join(incDir, "clretwallmain.cpp"), inclusion_list, "source-impl", user_events) - updateclreventsfile(write_xplatheader, target_cpp, runtimeFlavor, eventpipe_trace_context_typedef, dotnet_trace_context_typedef_windows, user_events_trace_context_typedef, tree, os.path.join(incDir, "clretwallmain.h"), inclusion_list, "header", user_events) - updateclreventsfile(write_xplatheader, target_cpp, runtimeFlavor, eventpipe_trace_context_typedef, dotnet_trace_context_typedef_windows, user_events_trace_context_typedef, tree, os.path.join(incDir, "disabledclretwallmain.cpp"), inclusion_list, "source-impl-noop", user_events) + updateclreventsfile(write_xplatheader, target_cpp, runtimeFlavor, is_host_windows, eventpipe_trace_context_typedef, dotnet_trace_context_typedef_windows, user_events_trace_context_typedef, tree, os.path.join(incDir, "clretwallmain.cpp"), inclusion_list, "source-impl", user_events) + updateclreventsfile(write_xplatheader, target_cpp, runtimeFlavor, is_host_windows, eventpipe_trace_context_typedef, dotnet_trace_context_typedef_windows, user_events_trace_context_typedef, tree, os.path.join(incDir, "clretwallmain.h"), inclusion_list, "header", user_events) + updateclreventsfile(write_xplatheader, target_cpp, runtimeFlavor, is_host_windows, eventpipe_trace_context_typedef, dotnet_trace_context_typedef_windows, user_events_trace_context_typedef, tree, os.path.join(incDir, "disabledclretwallmain.cpp"), inclusion_list, "source-impl-noop", user_events) else: - updateclreventsfile(write_xplatheader, target_cpp, runtimeFlavor, eventpipe_trace_context_typedef, dotnet_trace_context_typedef_windows, user_events_trace_context_typedef, tree, os.path.join(incDir, "clretwallmain.h"), inclusion_list, "header-impl", user_events) + updateclreventsfile(write_xplatheader, target_cpp, runtimeFlavor, is_host_windows, eventpipe_trace_context_typedef, dotnet_trace_context_typedef_windows, user_events_trace_context_typedef, tree, os.path.join(incDir, "clretwallmain.h"), inclusion_list, "header-impl", user_events) if write_xplatheader: clrproviders = os.path.join(incDir, "clrproviders.h") @@ -1035,7 +1032,7 @@ def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern ULONGLONG const Keyword; } EVENT_DESCRIPTOR; """) - if not is_windows and not runtimeFlavor.nativeaot: + if not is_host_windows and not runtimeFlavor.nativeaot: Clrproviders.write(eventpipe_trace_context_typedef) # define EVENTPIPE_TRACE_CONTEXT Clrproviders.write(lttng_trace_context_typedef) # define LTTNG_TRACE_CONTEXT Clrproviders.write(user_events_trace_context_typedef) @@ -1050,7 +1047,7 @@ def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern providerSymbol = str(providerNode.getAttribute('symbol')) nbProviders += 1 nbKeywords = 0 - if not is_windows and not runtimeFlavor.nativeaot: + if not is_host_windows and not runtimeFlavor.nativeaot: eventpipeProviderCtxName = providerSymbol + "_EVENTPIPE_Context" Clrproviders.write('__attribute__((weak)) EVENTPIPE_TRACE_CONTEXT ' + eventpipeProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n') lttngProviderCtxName = providerSymbol + "_LTTNG_Context" @@ -1077,7 +1074,7 @@ def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern allProviders.append("&" + providerSymbol + "_LTTNG_Context") # define and initialize runtime providers' DOTNET_TRACE_CONTEXT depending on the platform - if not is_windows and not runtimeFlavor.nativeaot: + if not is_host_windows and not runtimeFlavor.nativeaot: Clrproviders.write('#define NB_PROVIDERS ' + str(nbProviders) + '\n') Clrproviders.write(('constexpr ' if target_cpp else 'static const ') + 'LTTNG_TRACE_CONTEXT * ALL_LTTNG_PROVIDERS_CONTEXT[NB_PROVIDERS] = { ') Clrproviders.write(', '.join(allProviders)) @@ -1143,7 +1140,8 @@ def main(argv): required.add_argument('--dummy', type=str,default=None, help='full path to file that will have dummy definitions of FireEtw functions') required.add_argument('--runtimeflavor', type=str,default="CoreCLR", - help='runtime flavor') + help='runtime flavor'), + required.add_argument('--targetos', type=str,default=None), required.add_argument('--nonextern', action='store_true', help='if specified, will not generated extern function stub headers' ) required.add_argument('--noxplatheader', action='store_true', @@ -1163,7 +1161,13 @@ def main(argv): extern = not args.nonextern write_xplatheader = not args.noxplatheader user_events = args.userevents + targetOS = args.targetos + + if targetOS is None: + if os.name == "nt": + targetOS = "windows" + is_host_windows = targetOS == "windows" target_cpp = True if runtimeFlavor.mono: extern = False @@ -1172,7 +1176,7 @@ def main(argv): inclusion_list = parseInclusionList(inclusion_filename) - generatePlatformIndependentFiles(sClrEtwAllMan, incdir, etmDummyFile, extern, write_xplatheader, target_cpp, runtimeFlavor, inclusion_list, user_events) + generatePlatformIndependentFiles(sClrEtwAllMan, incdir, etmDummyFile, extern, write_xplatheader, target_cpp, runtimeFlavor, is_host_windows, inclusion_list, user_events) if __name__ == '__main__': return_code = main(sys.argv[1:]) diff --git a/src/coreclr/vm/eventing/CMakeLists.txt b/src/coreclr/vm/eventing/CMakeLists.txt index 861f50dc160c3a..d6879610e7a0d1 100644 --- a/src/coreclr/vm/eventing/CMakeLists.txt +++ b/src/coreclr/vm/eventing/CMakeLists.txt @@ -28,9 +28,14 @@ endif() set(GENEVENTING_SCRIPT ${CLR_DIR}/scripts/genEventing.py) +if(CMAKE_CROSSCOMPILING) + set(GEN_EVENTING_TARGETOS --targetos) + set(GEN_EVENTING_TARGETOS_ARG ${CLR_CMAKE_TARGET_OS}) +endif() + add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/eventing_headers.timestamp - COMMAND ${Python_EXECUTABLE} ${GENEVENTING_SCRIPT} --man ${EVENT_MANIFEST} --incdir ${GENERATED_INCLUDE_DIR} --dummy ${GENERATED_INCLUDE_DIR}/etmdummy.h ${NONEXTERN_ARG} ${NOXPLATHEADER_ARG} ${USEREVENTS_ARG} + COMMAND ${Python_EXECUTABLE} ${GENEVENTING_SCRIPT} --man ${EVENT_MANIFEST} --incdir ${GENERATED_INCLUDE_DIR} ${GEN_EVENTING_TARGETOS} ${GEN_EVENTING_TARGETOS_ARG} --dummy ${GENERATED_INCLUDE_DIR}/etmdummy.h ${NONEXTERN_ARG} ${NOXPLATHEADER_ARG} ${USEREVENTS_ARG} COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/eventing_headers.timestamp DEPENDS ${EVENT_MANIFEST} ${GENEVENTING_SCRIPT} VERBATIM diff --git a/src/mono/mono/eventpipe/gen-eventing.cmake b/src/mono/mono/eventpipe/gen-eventing.cmake index e3421048114201..906aaeccc5d663 100644 --- a/src/mono/mono/eventpipe/gen-eventing.cmake +++ b/src/mono/mono/eventpipe/gen-eventing.cmake @@ -51,9 +51,13 @@ if(ENABLE_PERFTRACING) set(GEN_ETW_PROVIDER_COMMAND "") endif() + if(CROSS_COMPILING) + set(GEN_EVENTING_TARGETOS --targetos {CLR_CMAKE_TARGET_OS}) + endif() + add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${MONO_DIAGNOSTICS_TRACING_COMPONENT_NAME}-gen-headers.timestamp - COMMAND ${Python_EXECUTABLE} ${GEN_EVENTING_SCRIPT} --man ${EVENT_MANIFEST} --incdir ${MONO_EVENTPIPE_GEN_INCLUDE_PATH} --inc ${EVENT_INCLUSION_FILE} --dummy ${MONO_EVENTPIPE_GEN_INCLUDE_PATH}/etmdummy.h --runtimeflavor mono ${NONEXTERN_ARG} ${NOXPLATHEADER_ARG} + COMMAND ${Python_EXECUTABLE} ${GEN_EVENTING_SCRIPT} --man ${EVENT_MANIFEST} --incdir ${MONO_EVENTPIPE_GEN_INCLUDE_PATH} --inc ${EVENT_INCLUSION_FILE} ${GEN_EVENTING_TARGETOS} --dummy ${MONO_EVENTPIPE_GEN_INCLUDE_PATH}/etmdummy.h --runtimeflavor mono ${NONEXTERN_ARG} ${NOXPLATHEADER_ARG} COMMAND ${GEN_ETW_PROVIDER_COMMAND} COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${MONO_DIAGNOSTICS_TRACING_COMPONENT_NAME}-gen-headers.timestamp DEPENDS ${GEN_EVENTING_SCRIPT} ${EVENT_MANIFEST} ${EVENT_EXCLUSION_FILE} diff --git a/src/mono/sample/Android/AndroidSampleApp.csproj b/src/mono/sample/Android/AndroidSampleApp.csproj index 8917de08365c0e..c10a8ce68ed6e1 100644 --- a/src/mono/sample/Android/AndroidSampleApp.csproj +++ b/src/mono/sample/Android/AndroidSampleApp.csproj @@ -15,6 +15,9 @@ true <_UseAotDataFile Condition="'$(RunAOTCompilation)' == 'true'">false + $(DOTNET_ROOT)/dotnet + ..\..\..\..\dotnet.cmd + ../../../dotnet.sh @@ -28,7 +31,7 @@ Condition="'$(ArchiveTests)' != 'true' and '$(DeployAndRun)' == 'true'" AfterTargets="_AfterAndroidBuild" DependsOnTargets="$(AndroidBuildDependsOn)" > - + $(ArtifactsObjDir)$(OutputRID).$(Configuration)\ $(ArtifactsObjDir)_version.h - $(ArtifactsObjDir)_version.c + $(ArtifactsObjDir)_version.c @@ -91,6 +91,22 @@ + + + + $(ArtifactsObjDir)_version.h + + + + + $(ArtifactsObjDir)_version.c + + + "%__artifactsDir%\obj\native\Directory.Build.props" echo %MSBUILD_EMPTY_PROJECT_CONTENT% > "%__artifactsDir%\obj\native\Directory.Build.targets" +if /i "%__TargetOS%" == "android" ( + set __ExtraCmakeParams=%__ExtraCmakeParams% "-DANDROID_STL=none" +) + +if /i "%__TargetOS%" == "linux-bionic" ( + set __ExtraCmakeParams=%__ExtraCmakeParams% "-DFORCE_ANDROID_OPENSSL=1" "-DANDROID_STL=none" "-DANDROID_FORCE_ICU_DATA_DIR=1" +) + :: Regenerate the VS solution call "%__repoRoot%\eng\native\gen-buildsys.cmd" "%__sourceRootDir%" "%__IntermediatesDir%" %__VSVersion% %__BuildArch% %__TargetOS% %__ExtraCmakeParams% diff --git a/src/native/libs/build-native.proj b/src/native/libs/build-native.proj index 29b0e7f7efca5d..e3f9e73c3c0196 100644 --- a/src/native/libs/build-native.proj +++ b/src/native/libs/build-native.proj @@ -2,7 +2,7 @@ $(ArtifactsObjDir)_version.h - $(ArtifactsObjDir)_version.c + $(ArtifactsObjDir)_version.c .NET Runtime <_BuildNativeTargetOS>$(TargetOS) <_BuildNativeTargetOS Condition="'$(TargetsLinuxBionic)' == 'true'">linux-bionic @@ -73,6 +73,22 @@ + + + + $(ArtifactsObjDir)_version.h + + + + + $(ArtifactsObjDir)_version.c + + + = MinApiLevel and BuildApiLevel >= TargetApiLevel // only if these api levels are not "preview" (not integers) - if (int.TryParse(BuildApiLevel, out int intApi)) + if (int.TryParse(androidSdkHelper.BuildApiLevel, out int intApi)) { if (int.TryParse(MinApiLevel, out int intMinApi) && intApi < intMinApi) { - throw new ArgumentException($"BuildApiLevel={BuildApiLevel} < MinApiLevel={MinApiLevel}. " + + throw new ArgumentException($"BuildApiLevel={androidSdkHelper.BuildApiLevel} < MinApiLevel={MinApiLevel}. " + "Make sure you've downloaded some recent build-tools in Android SDK"); } if (int.TryParse(TargetApiLevel, out int intTargetApi) && intApi < intTargetApi) { - throw new ArgumentException($"BuildApiLevel={BuildApiLevel} < TargetApiLevel={TargetApiLevel}. " + + throw new ArgumentException($"BuildApiLevel={androidSdkHelper.BuildApiLevel} < TargetApiLevel={TargetApiLevel}. " + "Make sure you've downloaded some recent build-tools in Android SDK"); } } - string buildToolsFolder = Path.Combine(AndroidSdk, "build-tools", BuildToolsVersion); - if (!Directory.Exists(buildToolsFolder)) + if (!Enum.TryParse(RuntimeFlavor, true, out parsedRuntimeFlavor)) { - throw new ArgumentException($"{buildToolsFolder} was not found."); + throw new ArgumentException($"Unknown RuntimeFlavor value: {RuntimeFlavor}. '{nameof(RuntimeFlavor)}' must be one of: {string.Join(",", Enum.GetNames(typeof(RuntimeFlavorEnum)))}"); } var assemblerFiles = new StringBuilder(); @@ -241,22 +235,15 @@ public ApkBuilder(TaskLoggingHelper logger) File.Copy(aotlib, Path.Combine(assetsToZipDirectory, Path.GetFileName(aotlib))); } - // tools: - string dx = Path.Combine(buildToolsFolder, "dx"); - string d8 = Path.Combine(buildToolsFolder, "d8"); - string aapt = Path.Combine(buildToolsFolder, "aapt"); - string zipalign = Path.Combine(buildToolsFolder, "zipalign"); - string apksigner = Path.Combine(buildToolsFolder, "apksigner"); - string androidJar = Path.Combine(AndroidSdk, "platforms", "android-" + BuildApiLevel, "android.jar"); + string androidJar = Path.Combine(AndroidSdk, "platforms", "android-" + androidSdkHelper.BuildApiLevel, "android.jar"); string androidToolchain = Path.Combine(AndroidNdk, "build", "cmake", "android.toolchain.cmake"); string javac = "javac"; - string zip = "zip"; - Utils.RunProcess(logger, zip, workingDir: assetsToZipDirectory, args: "-q -r ../assets/assets.zip ."); + ZipFile.CreateFromDirectory(assetsToZipDirectory, Path.Combine(OutputDir, "assets", "assets.zip"), CompressionLevel.SmallestSize, includeBaseDirectory: false); Directory.Delete(assetsToZipDirectory, true); if (!File.Exists(androidJar)) - throw new ArgumentException($"API level={BuildApiLevel} is not downloaded in Android SDK"); + throw new ArgumentException($"API level={androidSdkHelper.BuildApiLevel} is not downloaded in Android SDK"); // 1. Build libmonodroid.so via cmake @@ -339,10 +326,10 @@ public ApkBuilder(TaskLoggingHelper logger) "monodroid-coreclr.c" : (IsLibraryMode) ? "monodroid-librarymode.c" : "monodroid.c"; string cmakeLists = Utils.GetEmbeddedResource("CMakeLists-android.txt") - .Replace("%RuntimeInclude%", runtimeHeaders) - .Replace("%NativeLibrariesToLink%", nativeLibraries) + .Replace("%RuntimeInclude%", NormalizePathToUnix(runtimeHeaders)) + .Replace("%NativeLibrariesToLink%", NormalizePathToUnix(nativeLibraries)) .Replace("%MONODROID_SOURCE%", monodroidSource) - .Replace("%AotSources%", aotSources) + .Replace("%AotSources%", NormalizePathToUnix(aotSources)) .Replace("%AotModulesSource%", string.IsNullOrEmpty(aotSources) ? "" : "modules.c") .Replace("%APP_LINKER_ARGS%", extraLinkerArgs.ToString()); @@ -431,25 +418,25 @@ public ApkBuilder(TaskLoggingHelper logger) Utils.RunProcess(logger, javac, javaCompilerArgs + javaActivityPath, workingDir: OutputDir); Utils.RunProcess(logger, javac, javaCompilerArgs + monoRunnerPath, workingDir: OutputDir); - if (File.Exists(d8)) + if (androidSdkHelper.HasD8) { string[] classFiles = Directory.GetFiles(Path.Combine(OutputDir, "obj"), "*.class", SearchOption.AllDirectories); if (classFiles.Length == 0) throw new InvalidOperationException("Didn't find any .class files"); - Utils.RunProcess(logger, d8, $"--no-desugaring {string.Join(" ", classFiles)}", workingDir: OutputDir); + Utils.RunProcess(logger, androidSdkHelper.D8Path, $"--no-desugaring {string.Join(" ", classFiles)}", workingDir: OutputDir); } else { - Utils.RunProcess(logger, dx, "--dex --output=classes.dex obj", workingDir: OutputDir); + Utils.RunProcess(logger, androidSdkHelper.DxPath, "--dex --output=classes.dex obj", workingDir: OutputDir); } // 3. Generate APK string debugModeArg = StripDebugSymbols ? string.Empty : "--debug-mode"; string apkFile = Path.Combine(OutputDir, "bin", $"{ProjectName}.unaligned.apk"); - Utils.RunProcess(logger, aapt, $"package -f -m -F {apkFile} -A assets -M AndroidManifest.xml -I {androidJar} {debugModeArg}", workingDir: OutputDir); + Utils.RunProcess(logger, androidSdkHelper.AaptPath, $"package -f -m -F {apkFile} -A assets -M AndroidManifest.xml -I {androidJar} {debugModeArg}", workingDir: OutputDir); var dynamicLibs = new List(); dynamicLibs.Add(Path.Combine(OutputDir, "monodroid", "libmonodroid.so")); @@ -506,9 +493,9 @@ public ApkBuilder(TaskLoggingHelper logger) // NOTE: we can run android-strip tool from NDK to shrink native binaries here even more. File.Copy(dynamicLib, Path.Combine(OutputDir, destRelative), true); - Utils.RunProcess(logger, aapt, $"add {apkFile} {destRelative}", workingDir: OutputDir); + Utils.RunProcess(logger, androidSdkHelper.AaptPath, $"add {apkFile} {NormalizePathToUnix(destRelative)}", workingDir: OutputDir); } - Utils.RunProcess(logger, aapt, $"add {apkFile} classes.dex", workingDir: OutputDir); + Utils.RunProcess(logger, androidSdkHelper.AaptPath, $"add {apkFile} classes.dex", workingDir: OutputDir); // Include prebuilt .dex files int sequence = 2; @@ -518,18 +505,18 @@ public ApkBuilder(TaskLoggingHelper logger) var classesFileName = $"classes{sequence++}.dex"; File.Copy(dexFile, Path.Combine(OutputDir, classesFileName)); logger.LogMessage(MessageImportance.High, $"Adding dex file {Path.GetFileName(dexFile)} as {classesFileName}"); - Utils.RunProcess(logger, aapt, $"add {apkFile} {classesFileName}", workingDir: OutputDir); + Utils.RunProcess(logger, androidSdkHelper.AaptPath, $"add {apkFile} {classesFileName}", workingDir: OutputDir); } // 4. Align APK string alignedApk = Path.Combine(OutputDir, "bin", $"{ProjectName}.apk"); - AlignApk(apkFile, alignedApk, zipalign); + AlignApk(apkFile, alignedApk, androidSdkHelper.ZipalignPath); // we don't need the unaligned one any more File.Delete(apkFile); // 5. Generate key (if needed) & sign the apk - SignApk(alignedApk, apksigner); + SignApk(alignedApk, androidSdkHelper.ApksignerPath); logger.LogMessage(MessageImportance.High, $"\nAPK size: {(new FileInfo(alignedApk).Length / 1000_000.0):0.#} Mb.\n"); @@ -569,21 +556,16 @@ public void ZipAndSignApk(string apkPath) if (string.IsNullOrEmpty(AndroidSdk) || !Directory.Exists(AndroidSdk)) throw new ArgumentException($"Android SDK='{AndroidSdk}' was not found or incorrect (can be set via ANDROID_SDK_ROOT envvar)."); - if (string.IsNullOrEmpty(BuildToolsVersion)) - BuildToolsVersion = GetLatestBuildTools(AndroidSdk); + AndroidSdkHelper androidSdkHelper = new AndroidSdkHelper(AndroidSdk, BuildApiLevel, BuildToolsVersion); if (string.IsNullOrEmpty(MinApiLevel)) MinApiLevel = DefaultMinApiLevel; - string buildToolsFolder = Path.Combine(AndroidSdk, "build-tools", BuildToolsVersion); - string zipalign = Path.Combine(buildToolsFolder, "zipalign"); - string apksigner = Path.Combine(buildToolsFolder, "apksigner"); - string alignedApkPath = $"{apkPath}.aligned"; - AlignApk(apkPath, alignedApkPath, zipalign); + AlignApk(apkPath, alignedApkPath, androidSdkHelper.ZipalignPath); logger.LogMessage(MessageImportance.High, $"\nMoving '{alignedApkPath}' to '{apkPath}'.\n"); File.Move(alignedApkPath, apkPath, overwrite: true); - SignApk(apkPath, apksigner); + SignApk(apkPath, androidSdkHelper.ApksignerPath); } public void ReplaceFileInApk(string file) @@ -594,16 +576,11 @@ public void ReplaceFileInApk(string file) if (string.IsNullOrEmpty(AndroidSdk) || !Directory.Exists(AndroidSdk)) throw new ArgumentException($"Android SDK='{AndroidSdk}' was not found or incorrect (can be set via ANDROID_SDK_ROOT envvar)."); - if (string.IsNullOrEmpty(BuildToolsVersion)) - BuildToolsVersion = GetLatestBuildTools(AndroidSdk); + AndroidSdkHelper androidSdkHelper = new AndroidSdkHelper(AndroidSdk, BuildApiLevel, BuildToolsVersion); if (string.IsNullOrEmpty(MinApiLevel)) MinApiLevel = DefaultMinApiLevel; - string buildToolsFolder = Path.Combine(AndroidSdk, "build-tools", BuildToolsVersion); - string aapt = Path.Combine(buildToolsFolder, "aapt"); - string apksigner = Path.Combine(buildToolsFolder, "apksigner"); - string apkPath; if (string.IsNullOrEmpty(ProjectName)) apkPath = Directory.GetFiles(Path.Combine(OutputDir, "bin"), "*.apk").First(); @@ -613,41 +590,16 @@ public void ReplaceFileInApk(string file) if (!File.Exists(apkPath)) throw new Exception($"{apkPath} was not found"); - Utils.RunProcess(logger, aapt, $"remove -v bin/{Path.GetFileName(apkPath)} {file}", workingDir: OutputDir); - Utils.RunProcess(logger, aapt, $"add -v bin/{Path.GetFileName(apkPath)} {file}", workingDir: OutputDir); + Utils.RunProcess(logger, androidSdkHelper.AaptPath, $"remove -v bin/{Path.GetFileName(apkPath)} {file}", workingDir: OutputDir); + Utils.RunProcess(logger, androidSdkHelper.AaptPath, $"add -v bin/{Path.GetFileName(apkPath)} {file}", workingDir: OutputDir); // we need to re-sign the apk - SignApk(apkPath, apksigner); - } - - /// - /// Scan android SDK for build tools (ignore preview versions) - /// - private static string GetLatestBuildTools(string androidSdkDir) - { - string? buildTools = Directory.GetDirectories(Path.Combine(androidSdkDir, "build-tools")) - .Select(Path.GetFileName) - .Where(file => !file!.Contains('-')) - .Select(file => { Version.TryParse(Path.GetFileName(file), out Version? version); return version; }) - .OrderByDescending(v => v) - .FirstOrDefault()?.ToString(); - - if (string.IsNullOrEmpty(buildTools)) - throw new ArgumentException($"Android SDK ({androidSdkDir}) doesn't contain build-tools."); - - return buildTools; + SignApk(apkPath, androidSdkHelper.ApksignerPath); } - /// - /// Scan android SDK for api levels (ignore preview versions) - /// - private static string GetLatestApiLevel(string androidSdkDir) + private static string NormalizePathToUnix(string path) { - return Directory.GetDirectories(Path.Combine(androidSdkDir, "platforms")) - .Select(file => int.TryParse(Path.GetFileName(file).Replace("android-", ""), out int apiLevel) ? apiLevel : -1) - .OrderByDescending(v => v) - .FirstOrDefault() - .ToString(); + return path.Replace("\\", "/"); } [GeneratedRegex(@"\.(\d)")] diff --git a/src/tasks/Common/AndroidSdkHelper.cs b/src/tasks/Common/AndroidSdkHelper.cs index e56e7d65699d2d..1d3a942001725a 100644 --- a/src/tasks/Common/AndroidSdkHelper.cs +++ b/src/tasks/Common/AndroidSdkHelper.cs @@ -42,12 +42,17 @@ public AndroidSdkHelper( public string AndroidJarPath => Path.Combine(_androidSdkPath, "platforms", $"android-{_buildApiLevel}", "android.jar"); - public bool HasD8 => File.Exists(D8Path); - public string D8Path => getToolPath("d8"); - public string DxPath => getToolPath("dx"); + public string BuildApiLevel => _buildApiLevel; - private string getToolPath(string tool) - => Path.Combine(_buildToolsPath, tool); + public bool HasD8 => File.Exists(D8Path); + public string D8Path => GetToolPath("d8", isBatToolOnWindows: true); + public string DxPath => GetToolPath("dx", isBatToolOnWindows: true); + public string AaptPath => GetToolPath("aapt"); + public string ZipalignPath => GetToolPath("zipalign"); + public string ApksignerPath => GetToolPath("apksigner", isBatToolOnWindows: true); + + private string GetToolPath(string tool, bool isBatToolOnWindows = false) + => Path.Combine(_buildToolsPath, tool + (Utils.IsWindows() && isBatToolOnWindows ? ".bat" : "")); /// /// Scan android SDK for api levels (ignore preview versions) diff --git a/src/tasks/Common/JavaCompiler.cs b/src/tasks/Common/JavaCompiler.cs index abeb7c6fd91556..235e7b9ee926c5 100644 --- a/src/tasks/Common/JavaCompiler.cs +++ b/src/tasks/Common/JavaCompiler.cs @@ -17,7 +17,7 @@ public JavaCompiler( string workingDir, string javaVersion = "1.8") { - _javaCompilerArgs = $"-classpath src -bootclasspath {androidSdk.AndroidJarPath} -source {javaVersion} -target {javaVersion}"; + _javaCompilerArgs = $"-classpath src -bootclasspath \"{androidSdk.AndroidJarPath}\" -source {javaVersion} -target {javaVersion}"; _workingDir = workingDir; _logger = logger; } diff --git a/src/tasks/MobileBuildTasks/Android/AndroidProject.cs b/src/tasks/MobileBuildTasks/Android/AndroidProject.cs index c1935a6be12e14..b482731671ac22 100644 --- a/src/tasks/MobileBuildTasks/Android/AndroidProject.cs +++ b/src/tasks/MobileBuildTasks/Android/AndroidProject.cs @@ -33,7 +33,7 @@ public AndroidProject(string projectName, string runtimeIdentifier, TaskLoggingH public AndroidProject(string projectName, string runtimeIdentifier, string androidNdkPath, TaskLoggingHelper logger) { - androidToolchainPath = Path.Combine(androidNdkPath, "build", "cmake", "android.toolchain.cmake"); + androidToolchainPath = Path.Combine(androidNdkPath, "build", "cmake", "android.toolchain.cmake").Replace('\\', '/'); abi = DetermineAbi(runtimeIdentifier); targetArchitecture = GetTargetArchitecture(runtimeIdentifier); @@ -57,7 +57,9 @@ public void GenerateCMake(string workingDir, bool stripDebugSymbols) public void GenerateCMake(string workingDir, string apiLevel = DefaultMinApiLevel, bool stripDebugSymbols = false) { - string cmakeGenArgs = $"-DCMAKE_TOOLCHAIN_FILE={androidToolchainPath} -DANDROID_ABI=\"{Abi}\" -DANDROID_STL=none -DTARGETS_ANDROID=1 " + + // force ninja generator on Windows, the VS generator causes issues with the built-in Android support in VS + var generator = Utils.IsWindows() ? "-G Ninja" : ""; + string cmakeGenArgs = $"{generator} -DCMAKE_TOOLCHAIN_FILE={androidToolchainPath} -DANDROID_ABI=\"{Abi}\" -DANDROID_STL=none -DTARGETS_ANDROID=1 " + $"-DANDROID_PLATFORM=android-{apiLevel} -B {projectName}"; if (stripDebugSymbols) diff --git a/src/tasks/TestExclusionListTasks/TestExclusionListTasks.csproj b/src/tasks/TestExclusionListTasks/TestExclusionListTasks.csproj index e5148d3df97f26..ffc0d16e0ea031 100644 --- a/src/tasks/TestExclusionListTasks/TestExclusionListTasks.csproj +++ b/src/tasks/TestExclusionListTasks/TestExclusionListTasks.csproj @@ -11,6 +11,7 @@ + From 8c92ae710024f0cfa5c5cdd5bf3f6ccaec3ff98a Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Tue, 11 Feb 2025 16:56:48 -0800 Subject: [PATCH 14/20] Update SVE instructions that writes to GC regs (#112389) --- src/coreclr/jit/emitarm64.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index d0dbc6367be2fe..5cc121542b05f1 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -1087,6 +1087,22 @@ bool emitter::emitInsMayWriteToGCReg(instrDesc* id) case IF_SR_1A: // SR_1A ................ ...........ttttt Rt (dc zva, mrs) return ins == INS_mrs_tpid0; + // Below SVE instructions write to GPR and hence GC reg + case IF_SVE_CO_3A: // clasta, clastb + case IF_SVE_BM_1A: // decb, decd, dech, decw, incb, incd, inch, incw + case IF_SVE_BO_1A: // sqdecb, sqdecd, sqdech, sqdecw, sqincb, sqincd, sqinch, sqincw, uqdecb, uqdecd, uqdech, + // uqdecw, uqincb, uqincd, uqinch, uqincw + case IF_SVE_CS_3A: // lasta, lastb + case IF_SVE_DK_3A: // cntp + case IF_SVE_DL_2A: // cntp + case IF_SVE_DM_2A: // decp, incp + case IF_SVE_DO_2A: // sqdecp, sqincp, uqdecp, uqincp + case IF_SVE_BB_2A: // addpl, addvl + case IF_SVE_BC_1A: // rdvl + case IF_SVE_BL_1A: // cntb, cntd, cnth, cntw + case IF_SVE_DS_2A: // ctermeq, ctermne + return true; + default: return false; } From 93dd79997031a32e4034825bd671990dbc1e4ceb Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 21:02:09 -0600 Subject: [PATCH 15/20] [main] Update dependencies from dotnet/roslyn (#112314) * Update dependencies from https://github.com/dotnet/roslyn build 20250208.3 Microsoft.SourceBuild.Intermediate.roslyn , Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.CSharp , Microsoft.Net.Compilers.Toolset From Version 4.14.0-2.25107.8 -> To Version 4.14.0-2.25108.3 * Update dependencies from https://github.com/dotnet/roslyn build 20250210.8 Microsoft.SourceBuild.Intermediate.roslyn , Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.CSharp , Microsoft.Net.Compilers.Toolset From Version 4.14.0-2.25107.8 -> To Version 4.14.0-2.25110.8 --------- Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 16 ++++++++-------- eng/Versions.props | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index c9ceae82ec8700..d3490e2656edd1 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -376,17 +376,17 @@ https://github.com/dotnet/runtime-assets 3faec1bca5963b4ca54741e12939c77b951df604 - + https://github.com/dotnet/roslyn - 651ee91d035cdf8e659c00a384d5d6671aadbe46 + d3972005ce081b597a9dab72761d281e57acdc5a - + https://github.com/dotnet/roslyn - 651ee91d035cdf8e659c00a384d5d6671aadbe46 + d3972005ce081b597a9dab72761d281e57acdc5a - + https://github.com/dotnet/roslyn - 651ee91d035cdf8e659c00a384d5d6671aadbe46 + d3972005ce081b597a9dab72761d281e57acdc5a https://github.com/dotnet/roslyn-analyzers @@ -397,9 +397,9 @@ 8fe7aeb135c64e095f43292c427453858d937184 - + https://github.com/dotnet/roslyn - 651ee91d035cdf8e659c00a384d5d6671aadbe46 + d3972005ce081b597a9dab72761d281e57acdc5a diff --git a/eng/Versions.props b/eng/Versions.props index ff327bd5ac11d1..3b59475db8c96d 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -44,9 +44,9 @@ Any tools that contribute to the design-time experience should use the MicrosoftCodeAnalysisVersion_LatestVS property above to ensure they do not break the local dev experience. --> - 4.14.0-2.25107.8 - 4.14.0-2.25107.8 - 4.14.0-2.25107.8 + 4.14.0-2.25110.8 + 4.14.0-2.25110.8 + 4.14.0-2.25110.8