Skip to content

Commit

Permalink
[GR-51851] Add initial support for native memory tracking.
Browse files Browse the repository at this point in the history
PullRequest: graal/16871
  • Loading branch information
christianhaeubl committed Feb 23, 2024
2 parents 1cbb323 + 48c64d8 commit adab8a8
Show file tree
Hide file tree
Showing 65 changed files with 1,410 additions and 304 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -62,8 +62,7 @@ private UnmanagedMemory() {
/**
* Allocates {@code size} bytes of unmanaged memory. The content of the memory is undefined.
* <p>
* If {@code size} is 0, the method is allowed but not required to return the null pointer. This
* method never returns a the null pointer, but instead throws a {@link OutOfMemoryError} when
* This method never returns a null pointer, but instead throws an {@link OutOfMemoryError} when
* allocation fails.
*
* @since 19.0
Expand All @@ -79,8 +78,7 @@ public static <T extends PointerBase> T malloc(UnsignedWord size) {
/**
* Allocates {@code size} bytes of unmanaged memory. The content of the memory is undefined.
* <p>
* If {@code size} is 0, the method is allowed but not required to return the null pointer. This
* method never returns a the null pointer, but instead throws a {@link OutOfMemoryError} when
* This method never returns a null pointer, but instead throws an {@link OutOfMemoryError} when
* allocation fails.
*
* @since 19.0
Expand All @@ -92,8 +90,7 @@ public static <T extends PointerBase> T malloc(int size) {
/**
* Allocates {@code size} bytes of unmanaged memory. The content of the memory is set to 0.
* <p>
* If {@code size} is 0, the method is allowed but not required to return the null pointer. This
* method never returns a the null pointer, but instead throws a {@link OutOfMemoryError} when
* This method never returns a null pointer, but instead throws an {@link OutOfMemoryError} when
* allocation fails.
*
* @since 19.0
Expand All @@ -109,8 +106,7 @@ public static <T extends PointerBase> T calloc(UnsignedWord size) {
/**
* Allocates {@code size} bytes of unmanaged memory. The content of the memory is set to 0.
* <p>
* If {@code size} is 0, the method is allowed but not required to return the null pointer. This
* method never returns a the null pointer, but instead throws a {@link OutOfMemoryError} when
* This method never returns a null pointer, but instead throws an {@link OutOfMemoryError} when
* allocation fails.
*
* @since 19.0
Expand All @@ -124,9 +120,8 @@ public static <T extends PointerBase> T calloc(int size) {
* If the new size is larger than the old size, the content of the additional memory is
* undefined.
* <p>
* If {@code size} is 0, the method is allowed but not required to return the null pointer. This
* method never returns a the null pointer, but instead throws a {@link OutOfMemoryError} when
* allocation fails.
* This method never returns a null pointer, but instead throws an {@link OutOfMemoryError} when
* allocation fails. In that case, the old data is not deallocated and remains unchanged.
*
* @since 19.0
*/
Expand All @@ -139,7 +134,8 @@ public static <T extends PointerBase> T realloc(T ptr, UnsignedWord size) {
}

/**
* Frees unmanaged memory that was previously allocated using methods of this class.
* Frees unmanaged memory that was previously allocated using methods of this class. This method
* is a no-op if the given pointer is {@code null}.
*
* @since 19.0
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -43,7 +43,7 @@
import org.graalvm.word.PointerBase;
import org.graalvm.word.UnsignedWord;

/** Implemented by operating-system specific code. */
/** Implemented by platform or operating-system specific code. */
public interface UnmanagedMemorySupport {
<T extends PointerBase> T malloc(UnsignedWord size);

Expand Down
1 change: 1 addition & 0 deletions substratevm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This changelog summarizes major changes to GraalVM Native Image.
* (GR-51106) Fields that are accessed via a `VarHandle` or `MethodHandle` are no longer marked as "unsafe accessed" when the `VarHandle`/`MethodHandle` can be fully intrinsified.
* (GR-49996) Ensure explicitly set image name (e.g., via `-o imagename`) is not accidentally overwritten by `-jar jarfile` option.
* (GR-48683) Together with Red Hat, we added partial support for the JFR event `OldObjectSample`.
* (GR-51851) Together with Red Hat, we added initial support for native memory tracking (`--enable-monitoring=nmt`).
* (GR-47109) Together with Red Hat, we added support for JFR event throttling and the event `ObjectAllocationSample`.
* (GR-52030) Add a stable name for `Proxy` types in Native Image. The name `$Proxy[id]` is replaced by `$Proxy.s[hashCode]` where `hashCode` is computed using the names of the `Proxy` interfaces, the name of the class loader and the name of the module if it is not a dynamic module.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,6 @@
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Supplier;

import com.oracle.svm.core.jni.headers.JNIMode;
import jdk.graal.compiler.core.common.NumUtil;
import jdk.graal.compiler.java.LambdaUtils;
import org.graalvm.nativeimage.StackValue;
import org.graalvm.nativeimage.UnmanagedMemory;
import org.graalvm.nativeimage.c.function.CEntryPoint;
Expand All @@ -88,6 +85,7 @@
import com.oracle.svm.core.jni.headers.JNIEnvironment;
import com.oracle.svm.core.jni.headers.JNIFieldId;
import com.oracle.svm.core.jni.headers.JNIMethodId;
import com.oracle.svm.core.jni.headers.JNIMode;
import com.oracle.svm.core.jni.headers.JNINativeMethod;
import com.oracle.svm.core.jni.headers.JNIObjectHandle;
import com.oracle.svm.core.jni.headers.JNIValue;
Expand All @@ -106,6 +104,9 @@
import com.oracle.svm.jvmtiagentbase.jvmti.JvmtiInterface;
import com.oracle.svm.jvmtiagentbase.jvmti.JvmtiLocationFormat;

import jdk.graal.compiler.core.common.NumUtil;
import jdk.graal.compiler.java.LambdaUtils;

/**
* Intercepts events of interest via breakpoints in Java code.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

import com.oracle.svm.core.BaseProcessPropertiesSupport;
import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue;
import com.oracle.svm.core.headers.LibC;
import com.oracle.svm.core.memory.UntrackedNullableNativeMemory;
import com.oracle.svm.core.posix.headers.Dlfcn;
import com.oracle.svm.core.posix.headers.Signal;
import com.oracle.svm.core.posix.headers.Stdlib;
Expand Down Expand Up @@ -103,7 +103,7 @@ public String getObjectFile(PointerBase symbolAddress) {
try {
return CTypeConversion.toJavaString(realpath);
} finally {
LibC.free(realpath);
UntrackedNullableNativeMemory.free(realpath);
}
}

Expand Down Expand Up @@ -157,14 +157,14 @@ protected static String realpath(String path) {
* pointer to it, so I have to free it.
*/
try (CCharPointerHolder pathHolder = CTypeConversion.toCString(path)) {
final CCharPointer realpathPointer = Stdlib.realpath(pathHolder.get(), WordFactory.nullPointer());
if (realpathPointer.isNull()) {
CCharPointer realpath = Stdlib.realpath(pathHolder.get(), WordFactory.nullPointer());
if (realpath.isNull()) {
/* Failure to find a real path. */
return null;
} else {
/* Success */
final String result = CTypeConversion.toJavaString(realpathPointer);
LibC.free(realpathPointer);
String result = CTypeConversion.toJavaString(realpath);
UntrackedNullableNativeMemory.free(realpath);
return result;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.c.type.CCharPointer;
import org.graalvm.nativeimage.c.type.CTypeConversion;
import org.graalvm.nativeimage.impl.UnmanagedMemorySupport;
import org.graalvm.word.Pointer;
import org.graalvm.word.SignedWord;
import org.graalvm.word.UnsignedWord;
Expand All @@ -42,6 +41,7 @@
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.headers.LibC;
import com.oracle.svm.core.memory.UntrackedNullableNativeMemory;
import com.oracle.svm.core.os.AbstractRawFileOperationSupport;
import com.oracle.svm.core.os.AbstractRawFileOperationSupport.RawFileOperationSupportHolder;
import com.oracle.svm.core.posix.headers.Errno;
Expand All @@ -58,7 +58,7 @@ public PosixRawFileOperationSupport(boolean useNativeByteOrder) {
@Override
public CCharPointer allocateCPath(String path) {
byte[] data = path.getBytes();
CCharPointer filename = ImageSingletons.lookup(UnmanagedMemorySupport.class).malloc(WordFactory.unsigned(data.length + 1));
CCharPointer filename = UntrackedNullableNativeMemory.malloc(WordFactory.unsigned(data.length + 1));
if (filename.isNull()) {
return WordFactory.nullPointer();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue;
import com.oracle.svm.core.headers.LibC;
import com.oracle.svm.core.jdk.SystemPropertiesSupport;
import com.oracle.svm.core.memory.UntrackedNullableNativeMemory;
import com.oracle.svm.core.posix.PosixSystemPropertiesSupport;
import com.oracle.svm.core.posix.headers.Limits;
import com.oracle.svm.core.posix.headers.Stdlib;
Expand Down Expand Up @@ -105,7 +105,7 @@ protected String osVersionValue() {
CCharPointer osVersionStr = Foundation.systemVersionPlatform();
if (osVersionStr.isNonNull()) {
osVersionValue = CTypeConversion.toJavaString(osVersionStr);
LibC.free(osVersionStr);
UntrackedNullableNativeMemory.free(osVersionStr);
return osVersionValue;
}
} else {
Expand All @@ -120,7 +120,7 @@ protected String osVersionValue() {
CCharPointer osVersionStr = Foundation.systemVersionPlatformFallback();
if (osVersionStr.isNonNull()) {
osVersionValue = CTypeConversion.toJavaString(osVersionStr);
LibC.free(osVersionStr);
UntrackedNullableNativeMemory.free(osVersionStr);
return osVersionValue;
}
return osVersionValue = "Unknown";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,12 @@

import java.nio.ByteBuffer;

import jdk.graal.compiler.core.common.NumUtil;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.StackValue;
import org.graalvm.nativeimage.UnmanagedMemory;
import org.graalvm.nativeimage.c.type.CCharPointer;
import org.graalvm.nativeimage.c.type.CTypeConversion;
import org.graalvm.nativeimage.impl.UnmanagedMemorySupport;
import org.graalvm.word.Pointer;
import org.graalvm.word.WordFactory;

Expand All @@ -64,6 +61,8 @@
import com.oracle.svm.core.jvmstat.PerfManager;
import com.oracle.svm.core.jvmstat.PerfMemoryPrologue;
import com.oracle.svm.core.jvmstat.PerfMemoryProvider;
import com.oracle.svm.core.memory.NullableNativeMemory;
import com.oracle.svm.core.nmt.NmtCategory;
import com.oracle.svm.core.os.RawFileOperationSupport;
import com.oracle.svm.core.os.RawFileOperationSupport.RawFileDescriptor;
import com.oracle.svm.core.os.VirtualMemoryProvider;
Expand All @@ -80,6 +79,8 @@
import com.oracle.svm.core.posix.headers.Signal;
import com.oracle.svm.core.posix.headers.Unistd;

import jdk.graal.compiler.core.common.NumUtil;

/**
* This class uses high-level JDK features at the moment. In the future, we will need to rewrite
* this code so that it can be executed during the isolate startup (i.e., in uninterruptible code),
Expand Down Expand Up @@ -157,7 +158,7 @@ private static String getUserName(int uid) {
}

/* Retrieve the username and copy it to a String object. */
CCharPointer pwBuf = ImageSingletons.lookup(UnmanagedMemorySupport.class).malloc(WordFactory.unsigned(bufSize));
CCharPointer pwBuf = NullableNativeMemory.malloc(WordFactory.unsigned(bufSize), NmtCategory.JvmStat);
if (pwBuf.isNull()) {
return null;
}
Expand All @@ -182,7 +183,7 @@ private static String getUserName(int uid) {

return CTypeConversion.toJavaString(pwName);
} finally {
UnmanagedMemory.free(pwBuf);
NullableNativeMemory.free(pwBuf);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,16 @@
*/
package com.oracle.svm.core.posix.thread;

import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platform.HOSTED_ONLY;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.StackValue;
import org.graalvm.nativeimage.UnmanagedMemory;
import org.graalvm.nativeimage.c.function.CFunctionPointer;
import org.graalvm.nativeimage.c.struct.SizeOf;
import org.graalvm.nativeimage.c.type.CTypeConversion;
import org.graalvm.nativeimage.c.type.CTypeConversion.CCharPointerHolder;
import org.graalvm.nativeimage.c.type.VoidPointer;
import org.graalvm.nativeimage.c.type.WordPointer;
import org.graalvm.nativeimage.impl.UnmanagedMemorySupport;
import org.graalvm.word.Pointer;
import org.graalvm.word.PointerBase;
import org.graalvm.word.UnsignedWord;
Expand All @@ -50,6 +47,8 @@
import com.oracle.svm.core.annotate.TargetClass;
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue;
import com.oracle.svm.core.memory.NativeMemory;
import com.oracle.svm.core.nmt.NmtCategory;
import com.oracle.svm.core.posix.PosixUtils;
import com.oracle.svm.core.posix.headers.Errno;
import com.oracle.svm.core.posix.headers.Pthread;
Expand Down Expand Up @@ -321,7 +320,7 @@ final class PosixParker extends Parker {
// Allocate mutex and condition in a single step so that they are adjacent in memory.
UnsignedWord mutexSize = SizeOf.unsigned(pthread_mutex_t.class);
UnsignedWord condSize = SizeOf.unsigned(pthread_cond_t.class);
Pointer memory = UnmanagedMemory.malloc(mutexSize.add(condSize.multiply(2)));
Pointer memory = NativeMemory.malloc(mutexSize.add(condSize.multiply(2)), NmtCategory.Threading);
mutex = (pthread_mutex_t) memory;
relativeCond = (pthread_cond_t) memory.add(mutexSize);
absoluteCond = (pthread_cond_t) memory.add(mutexSize).add(condSize);
Expand Down Expand Up @@ -437,7 +436,7 @@ protected void release() {

status = Pthread.pthread_mutex_destroy(mutex);
assert status == 0;
ImageSingletons.lookup(UnmanagedMemorySupport.class).free(mutex);
NativeMemory.free(mutex);
mutex = WordFactory.nullPointer();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue;
import com.oracle.svm.core.headers.LibC;
import com.oracle.svm.core.jdk.SystemPropertiesSupport;
import com.oracle.svm.core.memory.NullableNativeMemory;
import com.oracle.svm.core.nmt.NmtCategory;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.core.windows.headers.FileAPI;
import com.oracle.svm.core.windows.headers.LibLoaderAPI;
Expand Down Expand Up @@ -245,29 +246,29 @@ public Pair<String, String> getOsNameAndVersion() {
break;
}

VoidPointer versionInfo = LibC.malloc(WordFactory.unsigned(versionSize));
VoidPointer versionInfo = NullableNativeMemory.malloc(WordFactory.unsigned(versionSize), NmtCategory.Internal);
if (versionInfo.isNull()) {
break;
}
try {
if (WinVer.GetFileVersionInfoW(kernel32Path, 0, versionSize, versionInfo) == 0) {
break;
}

if (WinVer.GetFileVersionInfoW(kernel32Path, 0, versionSize, versionInfo) == 0) {
LibC.free(versionInfo);
break;
}
WindowsLibC.WCharPointer rootPath = NonmovableArrays.addressOf(NonmovableArrays.fromImageHeap(ROOT_PATH), 0);
WordPointer fileInfoPointer = UnsafeStackValue.get(WordPointer.class);
CIntPointer lengthPointer = UnsafeStackValue.get(CIntPointer.class);
if (WinVer.VerQueryValueW(versionInfo, rootPath, fileInfoPointer, lengthPointer) == 0) {
break;
}

WindowsLibC.WCharPointer rootPath = NonmovableArrays.addressOf(NonmovableArrays.fromImageHeap(ROOT_PATH), 0);
WordPointer fileInfoPointer = UnsafeStackValue.get(WordPointer.class);
CIntPointer lengthPointer = UnsafeStackValue.get(CIntPointer.class);
if (WinVer.VerQueryValueW(versionInfo, rootPath, fileInfoPointer, lengthPointer) == 0) {
LibC.free(versionInfo);
break;
VerRsrc.VS_FIXEDFILEINFO fileInfo = fileInfoPointer.read();
majorVersion = (short) (fileInfo.dwProductVersionMS() >> 16); // HIWORD
minorVersion = (short) fileInfo.dwProductVersionMS(); // LOWORD
buildNumber = (short) (fileInfo.dwProductVersionLS() >> 16); // HIWORD
} finally {
NullableNativeMemory.free(versionInfo);
}

VerRsrc.VS_FIXEDFILEINFO fileInfo = fileInfoPointer.read();
majorVersion = (short) (fileInfo.dwProductVersionMS() >> 16); // HIWORD
minorVersion = (short) fileInfo.dwProductVersionMS(); // LOWORD
buildNumber = (short) (fileInfo.dwProductVersionLS() >> 16); // HIWORD
LibC.free(versionInfo);
} while (false);

String osVersion = majorVersion + "." + minorVersion;
Expand Down
Loading

0 comments on commit adab8a8

Please sign in to comment.