Skip to content

Commit

Permalink
[GR-34588] Add JFR support for threads.
Browse files Browse the repository at this point in the history
PullRequest: graal/10111
  • Loading branch information
christianhaeubl committed Nov 8, 2021
2 parents 77da7e9 + 59ca2d7 commit 99b234f
Show file tree
Hide file tree
Showing 43 changed files with 1,949 additions and 570 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core.jdk;

import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.impl.UnmanagedMemorySupport;
import org.graalvm.word.Pointer;
import org.graalvm.word.UnsignedWord;
import org.graalvm.word.WordFactory;

import com.oracle.svm.core.UnmanagedMemoryUtil;
import com.oracle.svm.core.annotate.Uninterruptible;

/**
* An uninterruptible hashtable with a fixed size that uses chaining in case of a collision.
*/
public abstract class AbstractUninterruptibleHashtable<T extends UninterruptibleEntry<T>> implements UninterruptibleHashtable<T> {
private static final int DEFAULT_TABLE_LENGTH = 2053;

private final T[] table;

private int size;

@Platforms(Platform.HOSTED_ONLY.class)
public AbstractUninterruptibleHashtable() {
this(DEFAULT_TABLE_LENGTH);
}

@Platforms(Platform.HOSTED_ONLY.class)
public AbstractUninterruptibleHashtable(int primeLength) {
this.table = createTable(primeLength);
this.size = 0;
}

@Platforms(Platform.HOSTED_ONLY.class)
protected abstract T[] createTable(int length);

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
protected abstract boolean isEqual(T a, T b);

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
protected abstract T copyToHeap(T valueOnStack);

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
protected T copyToHeap(T pointerOnStack, UnsignedWord sizeToAlloc) {
T pointerOnHeap = ImageSingletons.lookup(UnmanagedMemorySupport.class).malloc(sizeToAlloc);
if (pointerOnHeap.isNonNull()) {
UnmanagedMemoryUtil.copy((Pointer) pointerOnStack, (Pointer) pointerOnHeap, sizeToAlloc);
return pointerOnHeap;
}
return WordFactory.nullPointer();
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
protected abstract void free(T t);

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
protected T insertEntry(T valueOnStack) {
int index = Integer.remainderUnsigned(valueOnStack.getHash(), DEFAULT_TABLE_LENGTH);
T newEntry = copyToHeap(valueOnStack);
if (newEntry.isNonNull()) {
T existingEntry = table[index];
newEntry.setNext(existingEntry);
table[index] = newEntry;
size++;
return newEntry;
}
return WordFactory.nullPointer();
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public int getSize() {
return size;
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public T[] getTable() {
return table;
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public T get(T valueOnStack) {
int index = Integer.remainderUnsigned(valueOnStack.getHash(), DEFAULT_TABLE_LENGTH);
T entry = table[index];
while (entry.isNonNull()) {
if (isEqual(valueOnStack, entry)) {
return entry;
}
entry = entry.getNext();
}
return WordFactory.nullPointer();
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public T getOrPut(T valueOnStack) {
assert valueOnStack.isNonNull();

T entry = get(valueOnStack);
if (entry.isNonNull()) {
return WordFactory.nullPointer();
} else {
return insertEntry(valueOnStack);
}
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public boolean putIfAbsent(T valueOnStack) {
assert valueOnStack.isNonNull();

T existingEntry = get(valueOnStack);
if (existingEntry.isNonNull()) {
return false;
} else {
T newEntry = insertEntry(valueOnStack);
return newEntry.isNonNull();
}
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public void clear() {
for (int i = 0; i < table.length; i++) {
T entry = table[i];
while (entry.isNonNull()) {
T tmp = entry;
entry = entry.getNext();
free(tmp);
}
table[i] = WordFactory.nullPointer();
}
size = 0;
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public void teardown() {
clear();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.AnnotateOriginal;
import com.oracle.svm.core.annotate.Delete;
import com.oracle.svm.core.annotate.KeepOriginal;
import com.oracle.svm.core.annotate.NeverInline;
Expand Down Expand Up @@ -150,6 +151,10 @@ private static Enum<?> valueOf(Class<Enum<?>> enumType, String name) {
throw new IllegalArgumentException("No enum constant " + enumType.getName() + "." + name);
}
}

@AnnotateOriginal
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public native int ordinal();
}

@TargetClass(java.lang.String.class)
Expand All @@ -160,6 +165,32 @@ public String intern() {
String thisStr = SubstrateUtil.cast(this, String.class);
return ImageSingletons.lookup(StringInternSupport.class).intern(thisStr);
}

@AnnotateOriginal
@TargetElement(onlyWith = JDK11OrLater.class)
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
native boolean isLatin1();

@AnnotateOriginal
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public native int length();

@AnnotateOriginal
@TargetElement(onlyWith = JDK11OrLater.class)
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
native byte coder();

@Alias @TargetElement(name = "value", onlyWith = JDK11OrLater.class) byte[] valueJDK11;

@Alias @TargetElement(name = "value", onlyWith = JDK8OrEarlier.class) char[] valueJDK8;
}

@TargetClass(className = "java.lang.StringUTF16", onlyWith = JDK11OrLater.class)
final class Target_java_lang_StringUTF16 {

@AnnotateOriginal
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
static native char getChar(byte[] val, int index);
}

@TargetClass(java.lang.Throwable.class)
Expand Down Expand Up @@ -663,6 +694,16 @@ final class Target_jdk_internal_loader_ClassLoaders {
/** Dummy class to have a class with the file's name. */
public final class JavaLangSubstitutions {

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public static byte[] getBytes(String string) {
return SubstrateUtil.cast(string, Target_java_lang_String.class).valueJDK11;
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public static boolean isLatin1(String string) {
return SubstrateUtil.cast(string, Target_java_lang_String.class).isLatin1();
}

public static final class ClassValueSupport {

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core.jdk;

import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;

import com.oracle.svm.core.annotate.Uninterruptible;
import com.oracle.svm.core.locks.VMMutex;

/**
* A thread-safe wrapper for an {@link UninterruptibleHashtable}.
*/
public final class SynchronizedUninterruptibleHashtable<T extends UninterruptibleEntry<T>> implements UninterruptibleHashtable<T> {

private final VMMutex mutex;
private final UninterruptibleHashtable<T> hashtable;

@Platforms(Platform.HOSTED_ONLY.class)
public SynchronizedUninterruptibleHashtable(String name, UninterruptibleHashtable<T> hashtable) {
this.hashtable = hashtable;
this.mutex = new VMMutex(name);
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public int getSize() {
mutex.lockNoTransition();
try {
return hashtable.getSize();
} finally {
mutex.unlock();
}
}

/**
* Returns the internal array of the hashtable. There are no guarantees regarding
* synchronization when iterating the table.
*/
@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public T[] getTable() {
return hashtable.getTable();
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public T get(T valueOnStack) {
mutex.lockNoTransition();
try {
return hashtable.get(valueOnStack);
} finally {
mutex.unlock();
}
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public T getOrPut(T valueOnStack) {
mutex.lockNoTransition();
try {
return hashtable.getOrPut(valueOnStack);
} finally {
mutex.unlock();
}
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public boolean putIfAbsent(T valueOnStack) {
mutex.lockNoTransition();
try {
return hashtable.putIfAbsent(valueOnStack);
} finally {
mutex.unlock();
}
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public void clear() {
mutex.lockNoTransition();
try {
hashtable.clear();
} finally {
mutex.unlock();
}
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public void teardown() {
mutex.lockNoTransition();
try {
hashtable.teardown();
} finally {
mutex.unlock();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

/**
* The common interface for the LinkedList entries that can be used in an
* {@link UninterruptibleHashtable}.
* {@link AbstractUninterruptibleHashtable}.
*/
@RawStructure
public interface UninterruptibleEntry<T extends UninterruptibleEntry<T>> extends PointerBase {
Expand All @@ -46,18 +46,6 @@ public interface UninterruptibleEntry<T extends UninterruptibleEntry<T>> extends
@RawField
void setNext(T value);

/**
* Gets the id for the entry.
*/
@RawField
long getId();

/**
* Sets the id for the entry.
*/
@RawField
void setId(long value);

/**
* Get the hashcode for the entry.
*/
Expand Down
Loading

0 comments on commit 99b234f

Please sign in to comment.