private void ScheduleMethods(MosaType type) { var currentType = type; var slots = new bool[TypeLayout.GetMethodTable(type).Count]; while (currentType != null) { foreach (var method in currentType.Methods) { bool contains; lock (invokedMethods) { contains = invokedMethods.Contains(method); } if (contains) { int slot = TypeLayout.GetMethodSlot(method); if (slots[slot]) { continue; } slots[slot] = true; ScheduleMethod(method); } } currentType = currentType.BaseType; // EXPLORE: base types may not need to be considered } }
private LinkerSymbol CreateTypeDefinition(MosaType type, LinkerSymbol assemblyTableSymbol) { // Emit type table var typeNameSymbol = EmitStringWithLength(Metadata.NameString + type.FullName, type.FullName); var typeTableSymbol = Linker.DefineSymbol(Metadata.TypeDefinition + type.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer = new EndianAwareBinaryWriter(typeTableSymbol.Stream, Architecture.Endianness); // 1. Pointer to Name Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, typeNameSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Pointer to Custom Attributes if (type.CustomAttributes.Count > 0) { var customAttributeListSymbol = CreateCustomAttributesTable(type); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, customAttributeListSymbol, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Type Code & Attributes writer.Write(((uint)type.TypeCode << 24) + (uint)type.TypeAttributes, TypeLayout.NativePointerSize); // 4. Size writer.Write((uint)TypeLayout.GetTypeSize(type), TypeLayout.NativePointerSize); // 5. Pointer to Assembly Definition Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, assemblyTableSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 6. Pointer to Base Type if (type.BaseType != null) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, Metadata.TypeDefinition + type.BaseType.FullName, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 7. Pointer to Declaring Type if (type.DeclaringType != null) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, Metadata.TypeDefinition + type.DeclaringType.FullName, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 8. Pointer to Element Type if (type.ElementType != null) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, Metadata.TypeDefinition + type.ElementType.FullName, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 9. Constructor that accepts no parameters, if any, for this type foreach (var method in type.Methods) { if (!method.IsConstructor || method.Signature.Parameters.Count != 0 || method.HasOpenGenericParams) { continue; } var targetMethodData = GetTargetMethodData(method); if (targetMethodData.HasCode) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, Metadata.MethodDefinition + targetMethodData.Method.FullName, 0); } break; } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 10. Properties (if any) if (type.Properties.Count > 0) { var propertiesSymbol = CreatePropertyDefinitions(type); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, propertiesSymbol, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // If the type is not an interface continue, otherwise just pad until the end if (!type.IsInterface) { // 11. Fields (if any) if (type.Fields.Count > 0) { var fieldsSymbol = CreateFieldDefinitions(type); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, fieldsSymbol, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); var interfaces = type.HasOpenGenericParams ? null : GetInterfaces(type); // If the type doesn't use interfaces then skip 9 and 10 if (interfaces != null && interfaces.Count > 0) { // 12. Pointer to Interface Slots var interfaceSlotTableSymbol = CreateInterfaceSlotTable(type, interfaces); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, interfaceSlotTableSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 13. Pointer to Interface Bitmap var interfaceBitmapSymbol = CreateInterfaceBitmap(type, interfaces); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, interfaceBitmapSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); } else { // Fill 12 and 13 with zeros writer.WriteZeroBytes(TypeLayout.NativePointerSize * 2); } // For the next part we'll need to get the list of methods from the MosaTypeLayout var methodList = TypeLayout.GetMethodTable(type) ?? new List <MosaMethod>(); // 14. Number of Methods writer.Write(methodList.Count, TypeLayout.NativePointerSize); // 15. Pointer to Methods foreach (var method in methodList) { var targetMethodData = GetTargetMethodData(method); if (targetMethodData.HasCode) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, targetMethodData.Method.FullName, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); } // 16. Pointer to Method Definitions foreach (var method in methodList) { // Create definition and get the symbol var methodDefinitionSymbol = CreateMethodDefinition(method); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, methodDefinitionSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); } } else { // Fill 11, 12, 13, 14 with zeros, 15 & 16 can be left out. writer.WriteZeroBytes(TypeLayout.NativePointerSize * 4); } return(typeTableSymbol); }
protected void CreateMethodExceptionLookupTable() { // Emit assembly list var methodLookupTable = Linker.CreateSymbol(Metadata.MethodExceptionLookupTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer = new EndianAwareBinaryWriter(methodLookupTable.Stream, Architecture.Endianness); // 1. Number of methods int count = 0; foreach (var module in TypeSystem.Modules) { foreach (var type in module.Types.Values) { if (type.IsModule) { continue; } var methodList = TypeLayout.GetMethodTable(type); if (methodList == null) { continue; } foreach (var method in methodList) { if (method.IsAbstract) { continue; } if (method.ExceptionHandlers.Count == 0) { continue; } count++; } } } writer.Write(count); foreach (var module in TypeSystem.Modules) { foreach (var type in module.Types.Values) { if (type.IsModule) { continue; } var methodList = TypeLayout.GetMethodTable(type); if (methodList == null) { continue; } foreach (var method in methodList) { if (method.IsAbstract) { continue; } if (method.ExceptionHandlers.Count == 0) { continue; } // 1. Pointer to Method Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, (int)writer.Position, 0, method.FullName, SectionKind.Text, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Size of Method Linker.Link(LinkType.Size, NativePatchType, methodLookupTable, (int)writer.Position, 0, method.FullName, SectionKind.Text, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Pointer to Method Definition Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, (int)writer.Position, 0, method.FullName + Metadata.MethodDefinition, SectionKind.ROData, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); } } } }
protected void CreateMethodExceptionLookupTable() { // Emit assembly list var methodLookupTable = Linker.DefineSymbol(Metadata.MethodExceptionLookupTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer = new EndianAwareBinaryWriter(methodLookupTable.Stream, Architecture.Endianness); // 1. Number of methods int count = 0; writer.Write((int)0); foreach (var module in TypeSystem.Modules) { foreach (var type in module.Types.Values) { if (type.IsModule) { continue; } if (!Compiler.MethodScanner.IsTypeAllocated(type)) { continue; } var methodList = TypeLayout.GetMethodTable(type); if (methodList == null) { continue; } foreach (var method in methodList) { if ((!method.HasImplementation && method.IsAbstract) || method.HasOpenGenericParams || method.DeclaringType.HasOpenGenericParams) { continue; } if (method.ExceptionHandlers.Count == 0) { continue; } if (!Compiler.MethodScanner.IsMethodInvoked(method)) { continue; } // 1. Pointer to Method Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, writer.Position, method.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Size of Method Linker.Link(LinkType.Size, NativePatchType, methodLookupTable, writer.Position, method.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Pointer to Method Definition Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, writer.Position, Metadata.MethodDefinition + method.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); count++; } } } writer.Position = 0; writer.Write(count); // emit null entry (FUTURE) //writer.WriteZeroBytes(TypeLayout.NativePointerSize * 3); }
protected override void Finalization() { // Emit assembly list var methodLookupTable = Linker.DefineSymbol(Metadata.MethodLookupTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer = new BinaryWriter(methodLookupTable.Stream); // 1. Number of methods int count = 0; writer.Write(0); foreach (var module in TypeSystem.Modules) { foreach (var type in module.Types.Values) { if (type.IsModule) { continue; } if (!Compiler.MethodScanner.IsTypeAllocated(type)) { continue; } var methodList = TypeLayout.GetMethodTable(type); if (methodList == null) { continue; } foreach (var method in methodList) { var targetMethodData = GetTargetMethodData(method); if (!targetMethodData.HasCode) { continue; } // 1. Pointer to Method Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, writer.GetPosition(), targetMethodData.Method.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Size of Method Linker.Link(LinkType.Size, NativePatchType, methodLookupTable, writer.GetPosition(), targetMethodData.Method.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Pointer to Method Definition Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, writer.GetPosition(), Metadata.MethodDefinition + method.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); count++; } } } writer.SetPosition(0); writer.Write(count); }
private LinkerSymbol CreateTypeDefinition(MosaType type, LinkerSymbol assemblyTableSymbol) { // Emit type table var typeNameSymbol = EmitStringWithLength(Metadata.NameString + type.FullName, type.FullName); var typeDefinitionSymbol = Linker.DefineSymbol(Metadata.TypeDefinition + type.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer = new BinaryWriter(typeDefinitionSymbol.Stream); // 1. Pointer to Name Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), typeNameSymbol, (int)Compiler.ObjectHeaderSize); writer.WriteZeroBytes(NativePointerSize); // 2. Pointer to Custom Attributes if (type.CustomAttributes.Count > 0) { var customAttributeListSymbol = CreateCustomAttributesTable(type); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), customAttributeListSymbol, 0); } writer.WriteZeroBytes(NativePointerSize); // 3. Type Code & Attributes writer.Write(((uint)type.TypeCode << 24) + (uint)type.TypeAttributes, NativePointerSize); // 4. Size writer.Write((uint)TypeLayout.GetTypeSize(type), NativePointerSize); // 5. Pointer to Assembly Definition Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), assemblyTableSymbol, 0); writer.WriteZeroBytes(NativePointerSize); // 6. Pointer to Base Type if (type.BaseType != null) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), Metadata.TypeDefinition + type.BaseType.FullName, 0); } writer.WriteZeroBytes(NativePointerSize); // 7. Pointer to Declaring Type if (type.DeclaringType != null) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), Metadata.TypeDefinition + type.DeclaringType.FullName, 0); } writer.WriteZeroBytes(NativePointerSize); // 8. Pointer to Element Type if (type.ElementType != null) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), Metadata.TypeDefinition + type.ElementType.FullName, 0); } writer.WriteZeroBytes(NativePointerSize); // 9. Constructor that accepts no parameters, if any, for this type foreach (var method in type.Methods) { if (!method.IsConstructor || method.Signature.Parameters.Count != 0 || method.HasOpenGenericParams) { continue; } var targetMethodData = GetTargetMethodData(method); if (targetMethodData.HasCode) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), Metadata.MethodDefinition + targetMethodData.Method.FullName, 0); } break; } writer.WriteZeroBytes(NativePointerSize); // 10. Properties (if any) if (type.Properties.Count > 0) { var propertiesSymbol = CreatePropertyDefinitions(type); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), propertiesSymbol, 0); } writer.WriteZeroBytes(NativePointerSize); LinkerSymbol interfaceSlotTableSymbol = null; // 11. Fields Definitions if (!type.IsInterface && type.Fields.Count > 0) { var fieldsSymbol = CreateFieldDefinitions(type); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), fieldsSymbol, 0); } writer.WriteZeroBytes(NativePointerSize); var interfaces = type.IsInterface || type.HasOpenGenericParams ? null : GetInterfaces(type); if (interfaces != null && interfaces.Count == 0) { interfaces = null; } // 12. Pointer to Interface Slots if (interfaces != null) { interfaceSlotTableSymbol = CreateInterfaceSlotTable(type, interfaces); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), interfaceSlotTableSymbol, 0); } writer.WriteZeroBytes(NativePointerSize); // 13. Pointer to Interface Bitmap if (interfaces != null) { var interfaceBitmapSymbol = CreateInterfaceBitmap(type, interfaces); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), interfaceBitmapSymbol, 0); } writer.WriteZeroBytes(NativePointerSize); var methodList = TypeLayout.GetMethodTable(type); // 14. Number of Methods writer.Write(methodList == null ? 0 : methodList.Count, NativePointerSize); // 15. Method Table if (methodList != null) { foreach (var method in methodList) { var targetMethodData = GetTargetMethodData(method); if (targetMethodData.HasCode) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), targetMethodData.Method.FullName, 0); } writer.WriteZeroBytes(NativePointerSize); } } // 16. Method Definition Table if (!type.IsInterface && methodList != null) { foreach (var method in methodList) { // Create definition and get the symbol var methodDefinitionSymbol = CreateMethodDefinition(method); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), methodDefinitionSymbol, 0); writer.WriteZeroBytes(NativePointerSize); } } return(typeDefinitionSymbol); }
protected void CreateMethodExceptionLookupTable() { // Emit assembly list var exceptionMethodLookupTable = Linker.DefineSymbol(Metadata.MethodExceptionLookupTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer = new EndianAwareBinaryWriter(exceptionMethodLookupTable.Stream, Architecture.Endianness); // 1. Number of methods int count = 0; writer.Write((int)0); foreach (var module in TypeSystem.Modules) { foreach (var type in module.Types.Values) { if (type.IsModule) { continue; } if (!Compiler.MethodScanner.IsTypeAllocated(type)) { continue; } var methodList = TypeLayout.GetMethodTable(type); if (methodList == null) { continue; } foreach (var method in methodList) { var targetMethodData = GetTargetMethodData(method); if (!targetMethodData.HasCode) { continue; } if (!targetMethodData.HasProtectedRegions) { continue; } // 1. Pointer to Method Linker.Link(LinkType.AbsoluteAddress, NativePatchType, exceptionMethodLookupTable, writer.Position, targetMethodData.Method.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Size of Method Linker.Link(LinkType.Size, NativePatchType, exceptionMethodLookupTable, writer.Position, targetMethodData.Method.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Pointer to Method Definition Linker.Link(LinkType.AbsoluteAddress, NativePatchType, exceptionMethodLookupTable, writer.Position, Metadata.MethodDefinition + method.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); count++; } } } writer.Position = 0; writer.Write(count); // emit null entry (FUTURE) //writer.WriteZeroBytes(TypeLayout.NativePointerSize * 3); }