From d1a0facf093195e4ad876024eb0c828452cd52f9 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Fri, 2 Oct 2015 11:19:18 -0700 Subject: [PATCH 1/2] Unify caching pattern between EcmaMethod and EcmaField I have looked a bit at the right pattern to use for caching of metadata {Field|Method}DefinitionHandle vs. {Field|Method}Definition: The conversion from XXXDefinitionHandle to XXXDefinition is cheap. It is sufficient to cache just XXXDefinitionHandle, and recompute XXXDefinition each time - updated EcmaMethod implementation to match. Also, I have removed MethodDefinition and FieldDefiniton helper properties from EcmaMethod and EcmaField because of they were confusing (and JIT have not generated a particularly good code for them). --- src/TypeSystem/src/Ecma/EcmaField.cs | 63 ++++++++++-------- src/TypeSystem/src/Ecma/EcmaMethod.cs | 93 ++++++++++++++------------- src/TypeSystem/src/Ecma/EcmaType.cs | 74 +++++++++------------ src/TypeSystem/src/IL/EcmaMethodIL.cs | 2 +- 4 files changed, 117 insertions(+), 115 deletions(-) diff --git a/src/TypeSystem/src/Ecma/EcmaField.cs b/src/TypeSystem/src/Ecma/EcmaField.cs index 4c88b4f5efa..41a3dbc5879 100644 --- a/src/TypeSystem/src/Ecma/EcmaField.cs +++ b/src/TypeSystem/src/Ecma/EcmaField.cs @@ -21,6 +21,7 @@ static class FieldFlags public const int Static = 0x0002; public const int InitOnly = 0x0004; public const int Literal = 0x0008; + public const int HasRva = 0x0010; public const int AttributeMetadataCache = 0x0100; public const int ThreadStatic = 0x0200; @@ -29,8 +30,10 @@ static class FieldFlags EcmaType _type; FieldDefinitionHandle _handle; - TypeDesc _fieldType; + // Cached values volatile int _fieldFlags; + TypeDesc _fieldType; + string _name; internal EcmaField(EcmaType type, FieldDefinitionHandle handle) { @@ -77,22 +80,15 @@ public FieldDefinitionHandle Handle return _handle; } } - - public FieldDefinition FieldDefinition - { - get - { - return this.MetadataReader.GetFieldDefinition(_handle); - } - } - void ComputeFieldType() + private TypeDesc InitializeFieldType() { - var metadataReader = this.Module.MetadataReader; + var metadataReader = MetadataReader; BlobReader signatureReader = metadataReader.GetBlobReader(metadataReader.GetFieldDefinition(_handle).Signature); - EcmaSignatureParser parser = new EcmaSignatureParser(this.Module, signatureReader); - _fieldType = parser.ParseFieldSignature(); + EcmaSignatureParser parser = new EcmaSignatureParser(Module, signatureReader); + var fieldType = parser.ParseFieldSignature(); + return (_fieldType = fieldType); } public override TypeDesc FieldType @@ -100,7 +96,7 @@ public override TypeDesc FieldType get { if (_fieldType == null) - ComputeFieldType(); + return InitializeFieldType(); return _fieldType; } } @@ -112,9 +108,8 @@ private int InitializeFieldFlags(int mask) if ((mask & FieldFlags.BasicMetadataCache) != 0) { - var fieldDefinition = this.MetadataReader.GetFieldDefinition(_handle); + var fieldAttributes = Attributes; - var fieldAttributes = fieldDefinition.Attributes; if ((fieldAttributes & FieldAttributes.Static) != 0) flags |= FieldFlags.Static; @@ -124,6 +119,9 @@ private int InitializeFieldFlags(int mask) if ((fieldAttributes & FieldAttributes.Literal) != 0) flags |= FieldFlags.Literal; + if ((fieldAttributes & FieldAttributes.HasFieldRVA) != 0) + flags |= FieldFlags.HasRva; + flags |= FieldFlags.BasicMetadataCache; } @@ -200,6 +198,14 @@ public override bool IsInitOnly } } + public override bool HasRva + { + get + { + return (GetFieldFlags(FieldFlags.BasicMetadataCache | FieldFlags.HasRva) & FieldFlags.HasRva) != 0; + } + } + public bool IsLiteral { get @@ -212,32 +218,35 @@ public FieldAttributes Attributes { get { - var fieldDefinition = this.MetadataReader.GetFieldDefinition(_handle); - return fieldDefinition.Attributes; + return MetadataReader.GetFieldDefinition(_handle).Attributes; } } + private string InitializeName() + { + var metadataReader = MetadataReader; + var name = metadataReader.GetString(metadataReader.GetFieldDefinition(_handle).Name); + return (_name = name); + } + public override string Name { get { - var metadataReader = this.MetadataReader; - var fieldDefinition = metadataReader.GetFieldDefinition(_handle); - return metadataReader.GetString(fieldDefinition.Name); + if (_name == null) + return InitializeName(); + return _name; } } - public override bool HasRva + public bool HasCustomAttribute(string customAttributeName) { - get - { - return (FieldDefinition.Attributes & FieldAttributes.HasFieldRVA) != 0; - } + return Module.HasCustomAttribute(MetadataReader.GetFieldDefinition(_handle).GetCustomAttributes(), customAttributeName); } public override string ToString() { - return _type.ToString() + "." + this.Name; + return _type.ToString() + "." + Name; } } } diff --git a/src/TypeSystem/src/Ecma/EcmaMethod.cs b/src/TypeSystem/src/Ecma/EcmaMethod.cs index 4acc02c7848..63b66377135 100644 --- a/src/TypeSystem/src/Ecma/EcmaMethod.cs +++ b/src/TypeSystem/src/Ecma/EcmaMethod.cs @@ -25,18 +25,16 @@ enum MethodFlags EcmaType _type; MethodDefinitionHandle _handle; - MethodDefinition _methodDefinition; - // Cached values - MethodSignature _signature; MethodFlags _methodFlags; + MethodSignature _signature; + string _name; + TypeDesc[] _genericParameters; // TODO: Optional field? internal EcmaMethod(EcmaType type, MethodDefinitionHandle handle) { _type = type; _handle = handle; - - _methodDefinition = type.MetadataReader.GetMethodDefinition(handle); } public override TypeSystemContext Context @@ -55,12 +53,14 @@ public override TypeDesc OwningType } } - void ComputeSignature() + private MethodSignature InitializeSignature() { - BlobReader signatureReader = this.MetadataReader.GetBlobReader(_methodDefinition.Signature); + var metadataReader = MetadataReader; + BlobReader signatureReader = metadataReader.GetBlobReader(metadataReader.GetMethodDefinition(_handle).Signature); - EcmaSignatureParser parser = new EcmaSignatureParser(this.Module, signatureReader); - _signature = parser.ParseMethodSignature(); + EcmaSignatureParser parser = new EcmaSignatureParser(Module, signatureReader); + var signature = parser.ParseMethodSignature(); + return (_signature = signature); } public override MethodSignature Signature @@ -68,7 +68,7 @@ public override MethodSignature Signature get { if (_signature == null) - ComputeSignature(); + return InitializeSignature(); return _signature; } } @@ -97,14 +97,6 @@ public MethodDefinitionHandle Handle } } - public MethodDefinition MethodDefinition - { - get - { - return _methodDefinition; - } - } - [MethodImpl(MethodImplOptions.NoInlining)] private MethodFlags InitializeMethodFlags(MethodFlags mask) { @@ -112,7 +104,8 @@ private MethodFlags InitializeMethodFlags(MethodFlags mask) if ((mask & MethodFlags.BasicMetadataCache) != 0) { - var methodAttributes = _methodDefinition.Attributes; + var methodAttributes = Attributes; + if ((methodAttributes & MethodAttributes.Virtual) != 0) flags |= MethodFlags.Virtual; @@ -157,7 +150,7 @@ public MethodAttributes Attributes { get { - return _methodDefinition.Attributes; + return MetadataReader.GetMethodDefinition(_handle).Attributes; } } @@ -165,56 +158,65 @@ public MethodImplAttributes ImplAttributes { get { - return _methodDefinition.ImplAttributes; + return MetadataReader.GetMethodDefinition(_handle).ImplAttributes; } } + private string InitializeName() + { + var metadataReader = MetadataReader; + var name = metadataReader.GetString(metadataReader.GetMethodDefinition(_handle).Name); + return (_name = name); + } + public override string Name { get { - return this.MetadataReader.GetString(_methodDefinition.Name); + if (_name == null) + return InitializeName(); + return _name; } } - TypeDesc[] _genericParameters; + void ComputeGenericParameters() + { + var genericParameterHandles = MetadataReader.GetMethodDefinition(_handle).GetGenericParameters(); + int count = genericParameterHandles.Count; + if (count > 0) + { + TypeDesc[] genericParameters = new TypeDesc[count]; + int i = 0; + foreach (var genericParameterHandle in genericParameterHandles) + { + genericParameters[i++] = new EcmaGenericParameter(Module, genericParameterHandle); + } + Interlocked.CompareExchange(ref _genericParameters, genericParameters, null); + } + else + { + _genericParameters = TypeDesc.EmptyTypes; + } + } public override Instantiation Instantiation { get { if (_genericParameters == null) - { - var genericParameterHandles = _methodDefinition.GetGenericParameters(); - int count = genericParameterHandles.Count; - if (count > 0) - { - TypeDesc[] genericParameters = new TypeDesc[count]; - int i = 0; - foreach (var genericParameterHandle in genericParameterHandles) - { - genericParameters[i++] = new EcmaGenericParameter(this.Module, genericParameterHandle); - } - Interlocked.CompareExchange(ref _genericParameters, genericParameters, null); - } - else - { - _genericParameters = TypeDesc.EmptyTypes; - } - } - + ComputeGenericParameters(); return new Instantiation(_genericParameters); } } public bool HasCustomAttribute(string customAttributeName) { - return this.Module.HasCustomAttribute(_methodDefinition.GetCustomAttributes(), customAttributeName); + return Module.HasCustomAttribute(MetadataReader.GetMethodDefinition(_handle).GetCustomAttributes(), customAttributeName); } public override string ToString() { - return "[" + Module.GetName().Name + "]" + _type.ToString() + "." + this.Name; + return _type.ToString() + "." + Name; } public bool IsPInvoke() @@ -227,7 +229,8 @@ public string GetPInvokeImportName() if (((int)Attributes & (int)MethodAttributes.PinvokeImpl) == 0) return null; - return this.MetadataReader.GetString(_methodDefinition.GetImport().Name); + var metadataReader = MetadataReader; + return metadataReader.GetString(metadataReader.GetMethodDefinition(_handle).GetImport().Name); } } diff --git a/src/TypeSystem/src/Ecma/EcmaType.cs b/src/TypeSystem/src/Ecma/EcmaType.cs index e8874834d0b..5455a9a13f3 100644 --- a/src/TypeSystem/src/Ecma/EcmaType.cs +++ b/src/TypeSystem/src/Ecma/EcmaType.cs @@ -19,6 +19,12 @@ public sealed class EcmaType : MetadataType TypeDefinition _typeDefinition; + // Cached values + string _name; + TypeDesc[] _genericParameters; + MetadataType _baseType; + TypeDesc[] _implementedInterfaces; + internal EcmaType(EcmaModule module, TypeDefinitionHandle handle) { _module = module; @@ -42,33 +48,32 @@ public override TypeSystemContext Context } } - TypeDesc[] _genericParameters; + void ComputeGenericParameters() + { + var genericParameterHandles = _typeDefinition.GetGenericParameters(); + int count = genericParameterHandles.Count; + if (count > 0) + { + TypeDesc[] genericParameters = new TypeDesc[count]; + int i = 0; + foreach (var genericParameterHandle in genericParameterHandles) + { + genericParameters[i++] = new EcmaGenericParameter(this.Module, genericParameterHandle); + } + Interlocked.CompareExchange(ref _genericParameters, genericParameters, null); + } + else + { + _genericParameters = TypeDesc.EmptyTypes; + } + } public override Instantiation Instantiation { get { if (_genericParameters == null) - { - var genericParameterHandles = _typeDefinition.GetGenericParameters(); - int count = genericParameterHandles.Count; - if (count > 0) - { - TypeDesc[] genericParameters = new TypeDesc[count]; - int i = 0; - foreach (var genericParameterHandle in genericParameterHandles) - { - genericParameters[i++] = new EcmaGenericParameter(this.Module, genericParameterHandle); - } - Interlocked.CompareExchange(ref _genericParameters, genericParameters, null); - } - else - { - _genericParameters = TypeDesc.EmptyTypes; - } - - } - + ComputeGenericParameters(); return new Instantiation(_genericParameters); } } @@ -97,17 +102,6 @@ public TypeDefinitionHandle Handle } } - - public TypeDefinition TypeDefinition - { - get - { - return _typeDefinition; - } - } - - MetadataType _baseType /* = this */; - MetadataType InitializeBaseType() { var baseTypeHandle = _typeDefinition.BaseType; @@ -136,8 +130,6 @@ public override MetadataType BaseType } } - TypeDesc[] _implementedInterfaces; - private TypeDesc[] InitializeImplementedInterfaces() { var interfaceHandles = _typeDefinition.GetInterfaceImplementations(); @@ -206,8 +198,6 @@ protected override TypeFlags ComputeTypeFlags(TypeFlags mask) return flags; } - string _name; - private string InitializeName() { var metadataReader = this.MetadataReader; @@ -336,12 +326,12 @@ public bool HasCustomAttribute(string customAttributeName) public override string ToString() { - return this.Name; + return "[" + Module.GetName().Name + "]" + this.Name; } public override ClassLayoutMetadata GetClassLayout() { - TypeLayout layout = TypeDefinition.GetLayout(); + TypeLayout layout = _typeDefinition.GetLayout(); ClassLayoutMetadata result; result.PackingSize = layout.PackingSize; @@ -350,9 +340,10 @@ public override ClassLayoutMetadata GetClassLayout() // Skip reading field offsets if this is not explicit layout if (IsExplicitLayout) { + var fieldDefinitionHandles = _typeDefinition.GetFields(); var numInstanceFields = 0; - foreach (var handle in _typeDefinition.GetFields()) + foreach (var handle in fieldDefinitionHandles) { var fieldDefinition = MetadataReader.GetFieldDefinition(handle); if ((fieldDefinition.Attributes & FieldAttributes.Static) != 0) @@ -364,7 +355,7 @@ public override ClassLayoutMetadata GetClassLayout() result.Offsets = new FieldAndOffset[numInstanceFields]; int index = 0; - foreach (var handle in _typeDefinition.GetFields()) + foreach (var handle in fieldDefinitionHandles) { var fieldDefinition = MetadataReader.GetFieldDefinition(handle); if ((fieldDefinition.Attributes & FieldAttributes.Static) != 0) @@ -405,8 +396,7 @@ public override bool IsModuleType { get { - // TODO: make this return true if this is the type. - return false; + return Module.GetGlobalModuleType() == this; } } } diff --git a/src/TypeSystem/src/IL/EcmaMethodIL.cs b/src/TypeSystem/src/IL/EcmaMethodIL.cs index 8af8e733b97..d1ab0b0134c 100644 --- a/src/TypeSystem/src/IL/EcmaMethodIL.cs +++ b/src/TypeSystem/src/IL/EcmaMethodIL.cs @@ -19,7 +19,7 @@ public class EcmaMethodIL : MethodIL static public EcmaMethodIL Create(EcmaMethod method) { - var rva = method.MethodDefinition.RelativeVirtualAddress; + var rva = method.MetadataReader.GetMethodDefinition(method.Handle).RelativeVirtualAddress; if (rva == 0) return null; return new EcmaMethodIL(method.Module, method.Module.PEReader.GetMethodBody(rva)); From 1b378d560829677031b01f14c14380b812e7d2a4 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Fri, 2 Oct 2015 11:15:31 -0700 Subject: [PATCH 2/2] Update System.Runtime version to fix build warning --- src/ILToNative/repro/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ILToNative/repro/project.json b/src/ILToNative/repro/project.json index 8948e431181..32af4209501 100644 --- a/src/ILToNative/repro/project.json +++ b/src/ILToNative/repro/project.json @@ -1,6 +1,6 @@ { "dependencies": { - "System.Runtime": "4.0.0", + "System.Runtime": "4.0.20", "System.Resources.ResourceManager": "4.0.0", "System.Reflection.Primitives": "4.0.0", "System.Diagnostics.Debug": "4.0.0",