use of com.oracle.svm.hosted.image.NativeImageHeap.ObjectInfo in project graal by oracle.
the class NativeImageHeapWriter method writeReference.
void writeReference(RelocatableBuffer buffer, int index, Object target, Object reason) {
assert !(target instanceof WordBase) : "word values are not references";
mustBeReferenceAligned(index);
if (target != null) {
ObjectInfo targetInfo = heap.getObjectInfo(target);
verifyTargetDidNotChange(target, reason, targetInfo);
if (useHeapBase) {
int shift = compressEncoding.getShift();
writeReferenceValue(buffer, index, targetInfo.getAddress() >>> shift);
} else {
addDirectRelocationWithoutAddend(buffer, index, referenceSize(), target);
}
}
}
use of com.oracle.svm.hosted.image.NativeImageHeap.ObjectInfo in project graal by oracle.
the class ObjectGroupHistogram method doPrint.
private void doPrint() {
/*
* To group objects, we process certain known types and traverse objects reachable from
* them. Custom filtering allows to exclude certain fields, in order to cut off the
* processing. Once an object is assigned to a group, it never switches groups again. So the
* order in which types are prcessed matters.
*/
processType(DynamicHub.class, "DynamicHub", true, null, ObjectGroupHistogram::filterDynamicHubField);
processObject(NonmovableArrays.getHostedArray(DynamicHubSupport.getReferenceMapEncoding()), "DynamicHub", true, null, null);
processObject(CodeInfoTable.getImageCodeCache(), "ImageCodeInfo", true, ObjectGroupHistogram::filterCodeInfoObjects, null);
processObject(readGraalSupportField("graphEncoding"), "CompressedGraph", true, ObjectGroupHistogram::filterGraalSupportObjects, null);
processObject(readGraalSupportField("graphObjects"), "CompressedGraph", true, ObjectGroupHistogram::filterGraalSupportObjects, null);
processObject(readGraalSupportField("graphNodeTypes"), "CompressedGraph", true, ObjectGroupHistogram::filterGraalSupportObjects, null);
processType(ResolvedJavaType.class, "Graal Metadata", false, null, null);
processType(ResolvedJavaMethod.class, "Graal Metadata", false, null, null);
processType(ResolvedJavaField.class, "Graal Metadata", false, null, null);
try {
Field field = Class.forName("com.oracle.svm.graal.SubstrateRuntimeProvider").getDeclaredField("graphObjects");
Object object = SubstrateObjectConstant.asObject(heap.getMetaAccess().lookupJavaField(field).readValue(null));
processObject(heap.getObjectInfo(object), "CompressedGraphObjects", true, null, ObjectGroupHistogram::filterObjectConstantField);
} catch (Throwable ex) {
/* Ignore. When we build an image without Graal support, the class is not present. */
}
HeapHistogram totalHistogram = new HeapHistogram();
for (ObjectInfo info : heap.getObjects()) {
totalHistogram.add(info, info.getSize());
addToGroup(info, "Other");
}
totalHistogram.printHeadings("=== Total ===");
totalHistogram.print();
for (Map.Entry<String, HeapHistogram> entry : groupHistograms.entrySet()) {
entry.getValue().printHeadings("=== " + entry.getKey() + " ===");
entry.getValue().print();
}
System.out.println();
System.out.println("=== Summary ===");
for (Map.Entry<String, HeapHistogram> entry : groupHistograms.entrySet()) {
System.out.format("%s; %d; %d\n", entry.getKey(), entry.getValue().getTotalCount(), entry.getValue().getTotalSize());
}
System.out.format("%s; %d; %d\n", "Total", totalHistogram.getTotalCount(), totalHistogram.getTotalSize());
}
use of com.oracle.svm.hosted.image.NativeImageHeap.ObjectInfo in project graal by oracle.
the class MethodPointerInvalidHandlerFeature method printHistogram.
private static void printHistogram(ImageHeapPartition partition, Iterable<ObjectInfo> objects) {
HeapHistogram histogram = new HeapHistogram();
Set<ObjectInfo> uniqueObjectInfo = new HashSet<>();
long uniqueCount = 0L;
long uniqueSize = 0L;
long canonicalizedCount = 0L;
long canonicalizedSize = 0L;
for (ObjectInfo info : objects) {
if (partition == info.getPartition()) {
if (uniqueObjectInfo.add(info)) {
histogram.add(info, info.getSize());
uniqueCount += 1L;
uniqueSize += info.getSize();
} else {
canonicalizedCount += 1L;
canonicalizedSize += info.getSize();
}
}
}
long nonuniqueCount = uniqueCount + canonicalizedCount;
long nonuniqueSize = uniqueSize + canonicalizedSize;
assert partition.getSize() >= nonuniqueSize : "the total size can contain some overhead";
double countPercent = 100.0D * ((double) uniqueCount / (double) nonuniqueCount);
double sizePercent = 100.0D * ((double) uniqueSize / (double) nonuniqueSize);
double sizeOverheadPercent = 100.0D * (1.0D - ((double) partition.getSize() / (double) nonuniqueSize));
histogram.printHeadings(//
String.format(//
"=== Partition: %s count: %d / %d = %.1f%% object size: %d / %d = %.1f%% total size: %d (%.1f%% overhead) ===", //
partition.getName(), //
uniqueCount, //
nonuniqueCount, //
countPercent, //
uniqueSize, //
nonuniqueSize, //
sizePercent, partition.getSize(), sizeOverheadPercent));
histogram.print();
}
use of com.oracle.svm.hosted.image.NativeImageHeap.ObjectInfo in project graal by oracle.
the class LIRNativeImageCodeCache method patchMethods.
/**
* Patch references from code to other code and constant data. Generate relocation information
* in the process. More patching can be done, and correspondingly fewer relocation records
* generated, if the caller passes a non-null rodataDisplacementFromText.
*
* @param relocs a relocation map
*/
@Override
@SuppressWarnings("try")
public void patchMethods(DebugContext debug, RelocatableBuffer relocs, ObjectFile objectFile) {
// in each compilation result...
for (Entry<HostedMethod, CompilationResult> entry : compilations.entrySet()) {
HostedMethod method = entry.getKey();
CompilationResult compilation = entry.getValue();
// the codecache-relative offset of the compilation
int compStart = method.getCodeAddressOffset();
// Build an index of PatchingAnnoations
Map<Integer, HostedPatcher> patches = new HashMap<>();
ByteBuffer targetCode = null;
for (CodeAnnotation codeAnnotation : compilation.getCodeAnnotations()) {
if (codeAnnotation instanceof HostedPatcher) {
HostedPatcher priorValue = patches.put(codeAnnotation.getPosition(), (HostedPatcher) codeAnnotation);
VMError.guarantee(priorValue == null, "Registering two patchers for same position.");
} else if (codeAnnotation instanceof HostedImageHeapConstantPatch) {
HostedImageHeapConstantPatch patch = (HostedImageHeapConstantPatch) codeAnnotation;
ObjectInfo objectInfo = imageHeap.getObjectInfo(SubstrateObjectConstant.asObject(patch.constant));
long objectAddress = objectInfo.getAddress();
if (targetCode == null) {
targetCode = ByteBuffer.wrap(compilation.getTargetCode()).order(target.arch.getByteOrder());
}
int originalValue = targetCode.getInt(patch.getPosition());
long newValue = originalValue + objectAddress;
VMError.guarantee(NumUtil.isInt(newValue), "Image heap size is limited to 2 GByte");
targetCode.putInt(patch.getPosition(), (int) newValue);
}
}
int patchesHandled = 0;
HashSet<Integer> patchedOffsets = new HashSet<>();
// ... patch direct call sites.
for (Infopoint infopoint : compilation.getInfopoints()) {
if (infopoint instanceof Call && ((Call) infopoint).direct) {
Call call = (Call) infopoint;
// NOTE that for the moment, we don't make static calls to external
// (e.g. native) functions. So every static call site has a target
// which is also in the code cache (a.k.a. a section-local call).
// This will change, and we will have to case-split here... but not yet.
int callTargetStart = ((HostedMethod) call.target).getCodeAddressOffset();
// Patch a PC-relative call.
// This code handles the case of section-local calls only.
int pcDisplacement = callTargetStart - (compStart + call.pcOffset);
patches.get(call.pcOffset).patch(compStart, pcDisplacement, compilation.getTargetCode());
boolean noPriorMatch = patchedOffsets.add(call.pcOffset);
VMError.guarantee(noPriorMatch, "Patching same offset twice.");
patchesHandled++;
}
}
for (DataPatch dataPatch : compilation.getDataPatches()) {
Reference ref = dataPatch.reference;
/*
* Constants are allocated offsets in a separate space, which can be emitted as
* read-only (.rodata) section.
*/
patches.get(dataPatch.pcOffset).relocate(ref, relocs, compStart);
boolean noPriorMatch = patchedOffsets.add(dataPatch.pcOffset);
VMError.guarantee(noPriorMatch, "Patching same offset twice.");
patchesHandled++;
}
VMError.guarantee(patchesHandled == patches.size(), "Not all patches applied.");
try (DebugContext.Scope ds = debug.scope("After Patching", method.asJavaMethod())) {
debug.dump(DebugContext.BASIC_LEVEL, compilation, "After patching");
} catch (Throwable e) {
throw VMError.shouldNotReachHere(e);
}
}
}
Aggregations