Skip to content

Commit e520318

Browse files
Merge with master.
2 parents 1e02a09 + 4f025d3 commit e520318

File tree

45 files changed

+778
-407
lines changed

Some content is hidden

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

45 files changed

+778
-407
lines changed

compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/graph/NodeMap.java

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -217,45 +217,57 @@ public T setValue(T newValue) {
217217
};
218218
}
219219

220-
@Override
221-
public Iterable<T> getValues() {
222-
return new Iterable<>() {
220+
// Remove once GR-42126 is fixed
221+
public class NodeMapIterable implements Iterable<T> {
223222

224-
@Override
225-
public Iterator<T> iterator() {
226-
return new Iterator<>() {
223+
int i;
224+
int pos;
227225

228-
int i = 0;
226+
@Override
227+
public Iterator<T> iterator() {
228+
return new Iterator<>() {
229229

230-
@Override
231-
public boolean hasNext() {
232-
forward();
233-
return i < NodeMap.this.values.length;
234-
}
230+
@Override
231+
public boolean hasNext() {
232+
forward();
233+
return i < NodeMap.this.values.length;
234+
}
235235

236-
@SuppressWarnings("unchecked")
237-
@Override
238-
public T next() {
239-
final int pos = i;
240-
final T value = (T) NodeMap.this.values[pos];
236+
@SuppressWarnings("unchecked")
237+
@Override
238+
public T next() {
239+
pos = i;
240+
final T value = (T) NodeMap.this.values[pos];
241+
i++;
242+
forward();
243+
return value;
244+
}
245+
246+
@Override
247+
public void remove() {
248+
throw new UnsupportedOperationException();
249+
}
250+
251+
private void forward() {
252+
while (i < NodeMap.this.values.length && (NodeMap.this.values[i] == null || NodeMap.this.getKey(i) == null)) {
241253
i++;
242-
forward();
243-
return value;
244254
}
255+
}
256+
};
257+
}
245258

246-
@Override
247-
public void remove() {
248-
throw new UnsupportedOperationException();
249-
}
259+
public int getI() {
260+
return i;
261+
}
250262

251-
private void forward() {
252-
while (i < NodeMap.this.values.length && (NodeMap.this.values[i] == null || NodeMap.this.getKey(i) == null)) {
253-
i++;
254-
}
255-
}
256-
};
257-
}
258-
};
263+
public int getPos() {
264+
return pos;
265+
}
266+
}
267+
268+
@Override
269+
public Iterable<T> getValues() {
270+
return new NodeMapIterable();
259271
}
260272

261273
@Override

compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/java/LambdaUtils.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ public final class LambdaUtils {
5555
private static final char[] HEX = "0123456789abcdef".toCharArray();
5656
public static final String LAMBDA_SPLIT_PATTERN;
5757
public static final String LAMBDA_CLASS_NAME_SUBSTRING;
58+
public static final String SERIALIZATION_TEST_LAMBDA_CLASS_SUBSTRING = "$$Lambda";
59+
public static final String SERIALIZATION_TEST_LAMBDA_CLASS_SPLIT_PATTERN = "\\$\\$Lambda";
5860

5961
static {
6062
if (Runtime.version().feature() < 21) {

compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/nodes/loop/LoopFragment.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.graalvm.compiler.graph.Node;
4444
import org.graalvm.compiler.graph.NodeBitMap;
4545
import org.graalvm.compiler.graph.NodeMap;
46+
import org.graalvm.compiler.graph.NodeMap.NodeMapIterable;
4647
import org.graalvm.compiler.graph.iterators.NodeIterable;
4748
import org.graalvm.compiler.nodes.AbstractBeginNode;
4849
import org.graalvm.compiler.nodes.AbstractMergeNode;
@@ -211,9 +212,12 @@ public Node replacement(Node o) {
211212
Formatter f = new Formatter(sb);
212213
StructuredGraph graph = graph();
213214
if (duplicationMap instanceof NodeMap<?>) {
215+
NodeMap<?> nm = (NodeMap<?>) duplicationMap;
216+
@SuppressWarnings("rawtypes")
217+
NodeMap.NodeMapIterable nmIterable = (NodeMapIterable) duplicationNodes;
218+
f.format("GR-42126 iterable data: i=%s pos=%s nmSize=%s %n", nmIterable.getI(), nmIterable.getPos(), nm.capacity());
214219
int nodeCount = graph.getNodeCount();
215220
f.format("GR-42126 data: graph size %s,loop begin node count %s%n", nodeCount, graph.getNodes(LoopBeginNode.TYPE).count());
216-
NodeMap<?> nm = (NodeMap<?>) duplicationMap;
217221
Object[] rawValues = nm.rawValues();
218222
int nullEntries = 0;
219223
for (int i = 0; i < rawValues.length; i++) {

docs/reference-manual/native-image/ReachabilityMetadata.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ Using this pattern has a positive side effect of improving security on the JVM a
349349

350350
Wildcard patterns do the serialization registration only for lambda-proxy classes of an enclosing class. For example, to register lambda serialization in an enclosing class `pkg.LambdaHolder` use:
351351
```java
352-
ObjectInputFilter.Config.createFilter("pkg.LambdaHolder$$Lambda$*;")
352+
ObjectInputFilter.Config.createFilter("pkg.LambdaHolder$$Lambda*;")
353353
```
354354

355355
Patterns like `"pkg.**"` and `"pkg.Prefix*"` will not perform serialization registration as they are too general and would increase image size significantly.

docs/reference-manual/native-image/guides/build-and-run-native-executable-with-remote-jmx.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ Remote management using [Java Management Extensions (JMX)](https://www.oracle.co
1313
1414
This guide covers the steps required to build, run, and interact with such a native executable using JMX.
1515
It also shows you how to register a custom managed bean (MBean), with the JMX server and the additional steps required for it to work with Native Image.
16+
## Currently Supported Features and Limitations
17+
Currently, JMX connection from a client to a remote MBean server is supported. The client, server, or both may be a native executable.
18+
For now, only MXBeans, and standard user-defined MBeans are supported. Dynamic and model MBeans are not currently supported because
19+
their management interfaces are defined at runtime. Although remote management of MXBeans is supported, not all platform MXBean functionality
20+
is implemented or is applicable in SubstrateVM. Additionally, in order to define and use standard MBeans, metadata configuration must be specified.
21+
This is further explained later in this guide.
1622

1723
## Step 1: Create a Demo Application
1824

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoLanguage.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ protected void exitContext(EspressoContext context, ExitMode exitMode, int exitC
295295

296296
@Override
297297
protected void finalizeContext(EspressoContext context) {
298+
context.ensureThreadsJoined();
298299
TruffleSafepoint sp = TruffleSafepoint.getCurrent();
299300
boolean prev = sp.setAllowActions(false);
300301
try {

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,13 @@ public void destroyVM() {
932932
shutdownManager.destroyVM();
933933
}
934934

935+
public void ensureThreadsJoined() {
936+
// shutdownManager could be null if we are closing a pre-initialized context
937+
if (shutdownManager != null) {
938+
shutdownManager.ensureThreadsJoined();
939+
}
940+
}
941+
935942
public boolean isClosing() {
936943
return shutdownManager.isClosing();
937944
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoReferenceDrainer.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,16 @@ void startReferenceDrain() {
115115
}
116116
}
117117

118-
void shutdownAndWaitReferenceDrain() throws InterruptedException {
118+
void shutdownAndWaitReferenceDrain() {
119119
if (hostToGuestReferenceDrainThread != null) {
120120
while (hostToGuestReferenceDrainThread.isAlive()) {
121121
getContext().getEnv().submitThreadLocal(new Thread[]{hostToGuestReferenceDrainThread}, new ExitTLA());
122122
hostToGuestReferenceDrainThread.interrupt();
123-
hostToGuestReferenceDrainThread.join(10);
123+
try {
124+
hostToGuestReferenceDrainThread.join(10);
125+
} catch (InterruptedException e) {
126+
// ignore
127+
}
124128
}
125129
}
126130
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoShutdownHandler.java

Lines changed: 51 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.function.Consumer;
2828

2929
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
30+
import com.oracle.truffle.api.TruffleSafepoint;
3031
import com.oracle.truffle.api.exception.AbstractTruffleException;
3132
import com.oracle.truffle.espresso.blocking.EspressoLock;
3233
import com.oracle.truffle.espresso.blocking.GuestInterruptedException;
@@ -205,6 +206,34 @@ private boolean hasActiveNonDaemon(Thread initiating) {
205206
return false;
206207
}
207208

209+
public void ensureThreadsJoined() {
210+
// wait indefinitely
211+
ensureThreadsJoined(Thread.currentThread(), 0L);
212+
}
213+
214+
private boolean ensureThreadsJoined(Thread initiatingThread, long maxWaitMillis) {
215+
// Unconditionally kill
216+
getContext().getLogger().finer("Teardown: Phase 3: Force kill with host EspressoExitExceptions");
217+
teardownPhase3(initiatingThread);
218+
boolean success = joinThreads(initiatingThread, true, maxWaitMillis);
219+
220+
// Special handling of the reference drainer
221+
referenceDrainer.shutdownAndWaitReferenceDrain();
222+
223+
if (!success) {
224+
getContext().getLogger().severe("Could not gracefully stop executing threads in context closing.");
225+
getContext().getLogger().severe(() -> {
226+
StringBuilder str = new StringBuilder("Threads still alive: ");
227+
for (StaticObject guest : getManagedThreads()) {
228+
str.append(getThreadAccess().getHost(guest));
229+
}
230+
return str.toString();
231+
});
232+
}
233+
234+
return success;
235+
}
236+
208237
@SuppressWarnings("try")
209238
private void teardown() {
210239
assert isClosing();
@@ -216,7 +245,7 @@ private void teardown() {
216245
Thread initiatingThread = Thread.currentThread();
217246

218247
getContext().getLogger().finer("Teardown: Phase 0: wait");
219-
boolean nextPhase = !waitSpin(initiatingThread, false);
248+
boolean nextPhase = !joinNonDaemonThreads(initiatingThread);
220249

221250
if (softExit) {
222251
// These phases give to running java thread a small window in which they can
@@ -225,39 +254,21 @@ private void teardown() {
225254
// Send guest interruptions
226255
getContext().getLogger().finer("Teardown: Phase 1: Interrupt threads.");
227256
teardownPhase1(initiatingThread);
228-
nextPhase = !waitSpin(initiatingThread, false);
257+
nextPhase = !joinNonDaemonThreads(initiatingThread);
229258
}
230259

231260
if (nextPhase) {
232261
// Send guest ThreadDeaths
233262
getContext().getLogger().finer("Teardown: Phase 2: Stop all threads.");
234263
teardownPhase2(initiatingThread);
235-
nextPhase = !waitSpin(initiatingThread, false);
264+
nextPhase = !joinNonDaemonThreads(initiatingThread);
236265
}
237266
}
238267

239-
// Unconditionally kill
240-
getContext().getLogger().finer("Teardown: Phase 3: Force kill with host EspressoExitExceptions");
241-
teardownPhase3(initiatingThread);
242-
nextPhase = !waitSpin(initiatingThread, true);
243-
244-
// Special handling of the reference drainer
245-
try {
246-
referenceDrainer.shutdownAndWaitReferenceDrain();
247-
} catch (InterruptedException e) {
248-
// ignore
249-
}
250-
251-
if (nextPhase) {
252-
getContext().getLogger().severe("Could not gracefully stop executing threads in context closing.");
253-
getContext().getLogger().severe(() -> {
254-
StringBuilder str = new StringBuilder("Threads still alive: ");
255-
for (StaticObject guest : getManagedThreads()) {
256-
str.append(getThreadAccess().getHost(guest));
257-
}
258-
return str.toString();
259-
});
260-
if (getContext().getEspressoEnv().AllowHostExit) {
268+
boolean allowHostExit = getContext().getEspressoEnv().AllowHostExit;
269+
// wait indefinitely if we can't kill the host
270+
if (!ensureThreadsJoined(initiatingThread, allowHostExit ? MAX_KILL_PHASE_WAIT : 0L)) {
271+
if (allowHostExit) {
261272
// Needed until we can release rogue threads from Truffle (GR-28701).
262273
getContext().getLogger().severe("Calling Host System.exit()...");
263274
System.exit(getExitStatus());
@@ -306,31 +317,32 @@ private void teardownLoop(Consumer<StaticObject> action, Thread initiatingThread
306317
}
307318
}
308319

320+
private boolean joinNonDaemonThreads(Thread initiatingThread) {
321+
return joinThreads(initiatingThread, false, MAX_KILL_PHASE_WAIT);
322+
}
323+
309324
/**
310325
* Waits for some time for all non-disposed threads to terminate.
311326
*
327+
* @param maxWaitMillis the timeout for join operations, 0 for unlimited
328+
*
312329
* @return true if all threads are completed, false otherwise.
313330
*/
314-
private boolean waitSpin(Thread initiatingThread, boolean waitForDaemon) {
315-
long tick = System.currentTimeMillis();
316-
spinLoop: //
317-
while (true) {
318-
long time = System.currentTimeMillis() - tick;
319-
if (time > MAX_KILL_PHASE_WAIT) {
320-
return false;
321-
}
322-
for (StaticObject guest : getManagedThreads()) {
323-
Thread t = getThreadAccess().getHost(guest);
324-
if (waitForDaemon || !t.isDaemon()) {
325-
if (t != initiatingThread && t != referenceDrainer.drainHostThread() /*- drain thread gets a custom shutdown */) {
331+
private boolean joinThreads(Thread initiatingThread, boolean waitForDaemon, long maxWaitMillis) {
332+
for (StaticObject guest : getManagedThreads()) {
333+
Thread t = getThreadAccess().getHost(guest);
334+
if (waitForDaemon || !t.isDaemon()) {
335+
if (t != initiatingThread && t != referenceDrainer.drainHostThread() /*- drain thread gets a custom shutdown */) {
336+
if (t.isAlive()) {
337+
TruffleSafepoint.setBlockedThreadInterruptible(null, o -> t.join(maxWaitMillis), null);
326338
if (t.isAlive()) {
327-
continue spinLoop;
339+
return false;
328340
}
329341
}
330342
}
331343
}
332-
return true;
333344
}
345+
return true;
334346
}
335347

336348
private Iterable<StaticObject> getManagedThreads() {

sdk/mx.sdk/mx_sdk_benchmark.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ def requestHeaders(self):
420420
return {}
421421

422422
def inNativeMode(self):
423-
return self.jvm(self.bmSuiteArgs) == "native-image"
423+
return "native-image" in self.jvm(self.bmSuiteArgs)
424424

425425
def createCommandLineArgs(self, benchmarks, bmSuiteArgs):
426426
return self.vmArgs(bmSuiteArgs) + ["-jar", self.applicationPath()]

0 commit comments

Comments
 (0)