public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { if (_methods.Count == 0 || relocsOnly) { return new ObjectData( data: Array.Empty<byte>(), relocs: Array.Empty<Relocation>(), alignment: 1, definedSymbols: new ISymbolDefinitionNode[] { this }); } _methods.Sort(new CompilerComparer()); GCRefMapBuilder builder = new GCRefMapBuilder(factory.Target, relocsOnly); builder.Builder.RequireInitialAlignment(4); builder.Builder.AddSymbol(this); // First, emit the initial ref map offset and reserve the offset map entries int offsetCount = _methods.Count / GCREFMAP_LOOKUP_STRIDE; builder.Builder.EmitInt((offsetCount + 1) * sizeof(int)); ObjectDataBuilder.Reservation[] offsets = new ObjectDataBuilder.Reservation[offsetCount]; for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++) { offsets[offsetIndex] = builder.Builder.ReserveInt(); } // Next, generate the actual method GC ref maps and update the offset map int nextOffsetIndex = 0; int nextMethodIndex = GCREFMAP_LOOKUP_STRIDE - 1; for (int methodIndex = 0; methodIndex < _methods.Count; methodIndex++) { IMethodNode methodNode = _methods[methodIndex]; if (methodNode == null) { // Flush an empty GC ref map block to prevent // the indexed records from falling out of sync with methods builder.Flush(); } else { bool isUnboxingStub = false; if (methodNode is DelayLoadHelperImport methodImport) { isUnboxingStub = ((MethodFixupSignature)methodImport.ImportSignature.Target).IsUnboxingStub; } builder.GetCallRefMap(methodNode.Method, isUnboxingStub); } if (methodIndex >= nextMethodIndex) { builder.Builder.EmitInt(offsets[nextOffsetIndex], builder.Builder.CountBytes); nextOffsetIndex++; nextMethodIndex += GCREFMAP_LOOKUP_STRIDE; } } Debug.Assert(nextOffsetIndex == offsets.Length); return builder.Builder.ToObjectData(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { if (_methods.Count == 0 || relocsOnly) { return(new ObjectData( data: Array.Empty <byte>(), relocs: Array.Empty <Relocation>(), alignment: 1, definedSymbols: new ISymbolDefinitionNode[] { this })); } GCRefMapBuilder builder = new GCRefMapBuilder(factory, relocsOnly); builder.Builder.RequireInitialAlignment(4); builder.Builder.AddSymbol(this); // First, emit the initial ref map offset and reserve the offset map entries int offsetCount = _methods.Count / GCREFMAP_LOOKUP_STRIDE; builder.Builder.EmitInt((offsetCount + 1) * sizeof(int)); ObjectDataBuilder.Reservation[] offsets = new ObjectDataBuilder.Reservation[offsetCount]; for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++) { offsets[offsetIndex] = builder.Builder.ReserveInt(); } // Next, generate the actual method GC ref maps and update the offset map int nextOffsetIndex = 0; int nextMethodIndex = GCREFMAP_LOOKUP_STRIDE - 1; for (int methodIndex = 0; methodIndex < _methods.Count; methodIndex++) { if (methodIndex >= nextMethodIndex) { builder.Builder.EmitInt(offsets[nextOffsetIndex], builder.Builder.CountBytes); nextOffsetIndex++; nextMethodIndex += GCREFMAP_LOOKUP_STRIDE; } MethodWithGCInfo methodNode = _methods[methodIndex]; if (methodNode == null || methodNode.IsEmpty) { // Flush an empty GC ref map block to prevent // the indexed records from falling out of sync with methods builder.Flush(); } else { builder.GetCallRefMap(methodNode.Method); } } Debug.Assert(nextOffsetIndex == offsets.Length); return(builder.Builder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { if (_methods.Count == 0 || relocsOnly) { return(new ObjectData( data: Array.Empty <byte>(), relocs: Array.Empty <Relocation>(), alignment: 1, definedSymbols: new ISymbolDefinitionNode[] { this })); } _methods.Sort(new CompilerComparer()); GCRefMapBuilder builder = new GCRefMapBuilder(factory.Target, relocsOnly); builder.Builder.RequireInitialAlignment(4); builder.Builder.AddSymbol(this); // First, emit the initial ref map offset and reserve the offset map entries int offsetCount = _methods.Count / GCREFMAP_LOOKUP_STRIDE; builder.Builder.EmitInt((offsetCount + 1) * sizeof(int)); ObjectDataBuilder.Reservation[] offsets = new ObjectDataBuilder.Reservation[offsetCount]; for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++) { offsets[offsetIndex] = builder.Builder.ReserveInt(); } // Next, generate the actual method GC ref maps and update the offset map int nextOffsetIndex = 0; int nextMethodIndex = GCREFMAP_LOOKUP_STRIDE - 1; for (int methodIndex = 0; methodIndex < _methods.Count; methodIndex++) { IMethodNode methodNode = _methods[methodIndex]; if (methodNode == null || (methodNode is LocalMethodImport localMethod && localMethod.MethodCodeNode.IsEmpty)) { // Flush an empty GC ref map block to prevent // the indexed records from falling out of sync with methods builder.Flush(); }