Skip to content

Commit 99b234f

Browse files
[GR-34588] Add JFR support for threads.
PullRequest: graal/10111
2 parents 77da7e9 + 59ca2d7 commit 99b234f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1949
-570
lines changed
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/*
2+
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.jdk;
26+
27+
import org.graalvm.nativeimage.ImageSingletons;
28+
import org.graalvm.nativeimage.Platform;
29+
import org.graalvm.nativeimage.Platforms;
30+
import org.graalvm.nativeimage.impl.UnmanagedMemorySupport;
31+
import org.graalvm.word.Pointer;
32+
import org.graalvm.word.UnsignedWord;
33+
import org.graalvm.word.WordFactory;
34+
35+
import com.oracle.svm.core.UnmanagedMemoryUtil;
36+
import com.oracle.svm.core.annotate.Uninterruptible;
37+
38+
/**
39+
* An uninterruptible hashtable with a fixed size that uses chaining in case of a collision.
40+
*/
41+
public abstract class AbstractUninterruptibleHashtable<T extends UninterruptibleEntry<T>> implements UninterruptibleHashtable<T> {
42+
private static final int DEFAULT_TABLE_LENGTH = 2053;
43+
44+
private final T[] table;
45+
46+
private int size;
47+
48+
@Platforms(Platform.HOSTED_ONLY.class)
49+
public AbstractUninterruptibleHashtable() {
50+
this(DEFAULT_TABLE_LENGTH);
51+
}
52+
53+
@Platforms(Platform.HOSTED_ONLY.class)
54+
public AbstractUninterruptibleHashtable(int primeLength) {
55+
this.table = createTable(primeLength);
56+
this.size = 0;
57+
}
58+
59+
@Platforms(Platform.HOSTED_ONLY.class)
60+
protected abstract T[] createTable(int length);
61+
62+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
63+
protected abstract boolean isEqual(T a, T b);
64+
65+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
66+
protected abstract T copyToHeap(T valueOnStack);
67+
68+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
69+
protected T copyToHeap(T pointerOnStack, UnsignedWord sizeToAlloc) {
70+
T pointerOnHeap = ImageSingletons.lookup(UnmanagedMemorySupport.class).malloc(sizeToAlloc);
71+
if (pointerOnHeap.isNonNull()) {
72+
UnmanagedMemoryUtil.copy((Pointer) pointerOnStack, (Pointer) pointerOnHeap, sizeToAlloc);
73+
return pointerOnHeap;
74+
}
75+
return WordFactory.nullPointer();
76+
}
77+
78+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
79+
protected abstract void free(T t);
80+
81+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
82+
protected T insertEntry(T valueOnStack) {
83+
int index = Integer.remainderUnsigned(valueOnStack.getHash(), DEFAULT_TABLE_LENGTH);
84+
T newEntry = copyToHeap(valueOnStack);
85+
if (newEntry.isNonNull()) {
86+
T existingEntry = table[index];
87+
newEntry.setNext(existingEntry);
88+
table[index] = newEntry;
89+
size++;
90+
return newEntry;
91+
}
92+
return WordFactory.nullPointer();
93+
}
94+
95+
@Override
96+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
97+
public int getSize() {
98+
return size;
99+
}
100+
101+
@Override
102+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
103+
public T[] getTable() {
104+
return table;
105+
}
106+
107+
@Override
108+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
109+
public T get(T valueOnStack) {
110+
int index = Integer.remainderUnsigned(valueOnStack.getHash(), DEFAULT_TABLE_LENGTH);
111+
T entry = table[index];
112+
while (entry.isNonNull()) {
113+
if (isEqual(valueOnStack, entry)) {
114+
return entry;
115+
}
116+
entry = entry.getNext();
117+
}
118+
return WordFactory.nullPointer();
119+
}
120+
121+
@Override
122+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
123+
public T getOrPut(T valueOnStack) {
124+
assert valueOnStack.isNonNull();
125+
126+
T entry = get(valueOnStack);
127+
if (entry.isNonNull()) {
128+
return WordFactory.nullPointer();
129+
} else {
130+
return insertEntry(valueOnStack);
131+
}
132+
}
133+
134+
@Override
135+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
136+
public boolean putIfAbsent(T valueOnStack) {
137+
assert valueOnStack.isNonNull();
138+
139+
T existingEntry = get(valueOnStack);
140+
if (existingEntry.isNonNull()) {
141+
return false;
142+
} else {
143+
T newEntry = insertEntry(valueOnStack);
144+
return newEntry.isNonNull();
145+
}
146+
}
147+
148+
@Override
149+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
150+
public void clear() {
151+
for (int i = 0; i < table.length; i++) {
152+
T entry = table[i];
153+
while (entry.isNonNull()) {
154+
T tmp = entry;
155+
entry = entry.getNext();
156+
free(tmp);
157+
}
158+
table[i] = WordFactory.nullPointer();
159+
}
160+
size = 0;
161+
}
162+
163+
@Override
164+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
165+
public void teardown() {
166+
clear();
167+
}
168+
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import com.oracle.svm.core.SubstrateOptions;
5555
import com.oracle.svm.core.SubstrateUtil;
5656
import com.oracle.svm.core.annotate.Alias;
57+
import com.oracle.svm.core.annotate.AnnotateOriginal;
5758
import com.oracle.svm.core.annotate.Delete;
5859
import com.oracle.svm.core.annotate.KeepOriginal;
5960
import com.oracle.svm.core.annotate.NeverInline;
@@ -150,6 +151,10 @@ private static Enum<?> valueOf(Class<Enum<?>> enumType, String name) {
150151
throw new IllegalArgumentException("No enum constant " + enumType.getName() + "." + name);
151152
}
152153
}
154+
155+
@AnnotateOriginal
156+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
157+
public native int ordinal();
153158
}
154159

155160
@TargetClass(java.lang.String.class)
@@ -160,6 +165,32 @@ public String intern() {
160165
String thisStr = SubstrateUtil.cast(this, String.class);
161166
return ImageSingletons.lookup(StringInternSupport.class).intern(thisStr);
162167
}
168+
169+
@AnnotateOriginal
170+
@TargetElement(onlyWith = JDK11OrLater.class)
171+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
172+
native boolean isLatin1();
173+
174+
@AnnotateOriginal
175+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
176+
public native int length();
177+
178+
@AnnotateOriginal
179+
@TargetElement(onlyWith = JDK11OrLater.class)
180+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
181+
native byte coder();
182+
183+
@Alias @TargetElement(name = "value", onlyWith = JDK11OrLater.class) byte[] valueJDK11;
184+
185+
@Alias @TargetElement(name = "value", onlyWith = JDK8OrEarlier.class) char[] valueJDK8;
186+
}
187+
188+
@TargetClass(className = "java.lang.StringUTF16", onlyWith = JDK11OrLater.class)
189+
final class Target_java_lang_StringUTF16 {
190+
191+
@AnnotateOriginal
192+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
193+
static native char getChar(byte[] val, int index);
163194
}
164195

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

697+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
698+
public static byte[] getBytes(String string) {
699+
return SubstrateUtil.cast(string, Target_java_lang_String.class).valueJDK11;
700+
}
701+
702+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
703+
public static boolean isLatin1(String string) {
704+
return SubstrateUtil.cast(string, Target_java_lang_String.class).isLatin1();
705+
}
706+
666707
public static final class ClassValueSupport {
667708

668709
/**
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.jdk;
26+
27+
import org.graalvm.nativeimage.Platform;
28+
import org.graalvm.nativeimage.Platforms;
29+
30+
import com.oracle.svm.core.annotate.Uninterruptible;
31+
import com.oracle.svm.core.locks.VMMutex;
32+
33+
/**
34+
* A thread-safe wrapper for an {@link UninterruptibleHashtable}.
35+
*/
36+
public final class SynchronizedUninterruptibleHashtable<T extends UninterruptibleEntry<T>> implements UninterruptibleHashtable<T> {
37+
38+
private final VMMutex mutex;
39+
private final UninterruptibleHashtable<T> hashtable;
40+
41+
@Platforms(Platform.HOSTED_ONLY.class)
42+
public SynchronizedUninterruptibleHashtable(String name, UninterruptibleHashtable<T> hashtable) {
43+
this.hashtable = hashtable;
44+
this.mutex = new VMMutex(name);
45+
}
46+
47+
@Override
48+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
49+
public int getSize() {
50+
mutex.lockNoTransition();
51+
try {
52+
return hashtable.getSize();
53+
} finally {
54+
mutex.unlock();
55+
}
56+
}
57+
58+
/**
59+
* Returns the internal array of the hashtable. There are no guarantees regarding
60+
* synchronization when iterating the table.
61+
*/
62+
@Override
63+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
64+
public T[] getTable() {
65+
return hashtable.getTable();
66+
}
67+
68+
@Override
69+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
70+
public T get(T valueOnStack) {
71+
mutex.lockNoTransition();
72+
try {
73+
return hashtable.get(valueOnStack);
74+
} finally {
75+
mutex.unlock();
76+
}
77+
}
78+
79+
@Override
80+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
81+
public T getOrPut(T valueOnStack) {
82+
mutex.lockNoTransition();
83+
try {
84+
return hashtable.getOrPut(valueOnStack);
85+
} finally {
86+
mutex.unlock();
87+
}
88+
}
89+
90+
@Override
91+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
92+
public boolean putIfAbsent(T valueOnStack) {
93+
mutex.lockNoTransition();
94+
try {
95+
return hashtable.putIfAbsent(valueOnStack);
96+
} finally {
97+
mutex.unlock();
98+
}
99+
}
100+
101+
@Override
102+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
103+
public void clear() {
104+
mutex.lockNoTransition();
105+
try {
106+
hashtable.clear();
107+
} finally {
108+
mutex.unlock();
109+
}
110+
}
111+
112+
@Override
113+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
114+
public void teardown() {
115+
mutex.lockNoTransition();
116+
try {
117+
hashtable.teardown();
118+
} finally {
119+
mutex.unlock();
120+
}
121+
}
122+
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/UninterruptibleEntry.java

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
/**
3232
* The common interface for the LinkedList entries that can be used in an
33-
* {@link UninterruptibleHashtable}.
33+
* {@link AbstractUninterruptibleHashtable}.
3434
*/
3535
@RawStructure
3636
public interface UninterruptibleEntry<T extends UninterruptibleEntry<T>> extends PointerBase {
@@ -46,18 +46,6 @@ public interface UninterruptibleEntry<T extends UninterruptibleEntry<T>> extends
4646
@RawField
4747
void setNext(T value);
4848

49-
/**
50-
* Gets the id for the entry.
51-
*/
52-
@RawField
53-
long getId();
54-
55-
/**
56-
* Sets the id for the entry.
57-
*/
58-
@RawField
59-
void setId(long value);
60-
6149
/**
6250
* Get the hashcode for the entry.
6351
*/

0 commit comments

Comments
 (0)