Merge branch 'master' into opt-simploop-8346177

This commit is contained in:
katkerem 2026-04-07 18:37:20 +01:00
commit ff9b93333c
14 changed files with 102 additions and 84 deletions

View File

@ -284,9 +284,10 @@ possible, or if you want to use a fully qualified test descriptor, add
<h3 id="gtest">Gtest</h3>
<p><strong>Note:</strong> To be able to run the Gtest suite, you need to
configure your build to be able to find a proper version of the gtest
source. For details, see the section <a
href="building.html#running-tests">"Running Tests" in the build
documentation</a>.</p>
source. For details, see the section <strong>"Running Tests" in the
build documentation</strong> (<a
href="building.html#running-tests">html</a>, <a
href="building.md#running-tests">markdown</a>).</p>
<p>Since the Hotspot Gtest suite is so quick, the default is to run all
tests. This is specified by just <code>gtest</code>, or as a fully
qualified test descriptor <code>gtest:all</code>.</p>

View File

@ -198,8 +198,8 @@ use a fully qualified test descriptor, add `jtreg:`, e.g.
**Note:** To be able to run the Gtest suite, you need to configure your build
to be able to find a proper version of the gtest source. For details, see the
section ["Running Tests" in the build
documentation](building.html#running-tests).
section **"Running Tests" in the build
documentation** ([html](building.html#running-tests), [markdown](building.md#running-tests)).
Since the Hotspot Gtest suite is so quick, the default is to run all tests.
This is specified by just `gtest`, or as a fully qualified test descriptor

View File

@ -1182,12 +1182,12 @@ class CallStubImpl {
public:
// Size of call trampoline stub.
static uint size_call_trampoline() {
return 0; // no call trampolines on this platform
return MacroAssembler::max_trampoline_stub_size();
}
// number of relocations needed by a call trampoline stub
static uint reloc_call_trampoline() {
return 0; // no call trampolines on this platform
return 5; // metadata; call dest; trampoline address; trampoline destination; trampoline_owner_metadata
}
};

View File

@ -89,16 +89,21 @@ void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address
NativeMovConstReg* method_holder
= nativeMovConstReg_at(stub + NativeInstruction::instruction_size);
// In AOT "production" run we have mixture of AOTed and normal JITed code.
// Static call stub in AOTed nmethod always has far jump.
// Normal JITed nmethod may have short or far jump depending on distance.
// Determine actual jump instruction we have in code.
address next_instr = method_holder->next_instruction_address();
bool is_general_jump = nativeInstruction_at(next_instr)->is_general_jump();
#ifdef ASSERT
NativeJump* jump = MacroAssembler::codestub_branch_needs_far_jump()
? nativeGeneralJump_at(method_holder->next_instruction_address())
: nativeJump_at(method_holder->next_instruction_address());
NativeJump* jump = is_general_jump ? nativeGeneralJump_at(next_instr) : nativeJump_at(next_instr);
verify_mt_safe(callee, entry, method_holder, jump);
#endif
// Update stub.
method_holder->set_data((intptr_t)callee());
MacroAssembler::pd_patch_instruction(method_holder->next_instruction_address(), entry);
MacroAssembler::pd_patch_instruction(next_instr, entry);
ICache::invalidate_range(stub, to_interp_stub_size());
// Update jump to call.
set_destination_mt_safe(stub);

View File

@ -952,7 +952,10 @@ void MacroAssembler::emit_static_call_stub() {
}
int MacroAssembler::static_call_stub_size() {
if (!codestub_branch_needs_far_jump()) {
// During AOT production run AOT and JIT compiled code
// are used at the same time. We need this size
// to be the same for both types of code.
if (!codestub_branch_needs_far_jump() && !AOTCodeCache::is_on_for_use()) {
// isb; movk; movz; movz; b
return 5 * NativeInstruction::instruction_size;
}

View File

@ -2341,20 +2341,16 @@ void G1CMTask::drain_local_queue(bool partially) {
}
}
size_t G1CMTask::start_partial_array_processing(oop obj) {
assert(should_be_sliced(obj), "Must be an array object %d and large %zu", obj->is_objArray(), obj->size());
objArrayOop obj_array = objArrayOop(obj);
size_t array_length = obj_array->length();
size_t initial_chunk_size = _partial_array_splitter.start(_task_queue, obj_array, nullptr, array_length);
size_t G1CMTask::start_partial_array_processing(objArrayOop obj) {
assert(obj->length() >= (int)ObjArrayMarkingStride, "Must be a large array object %d", obj->length());
// Mark objArray klass metadata
if (_cm_oop_closure->do_metadata()) {
_cm_oop_closure->do_klass(obj_array->klass());
}
process_klass(obj->klass());
process_array_chunk(obj_array, 0, initial_chunk_size);
size_t array_length = obj->length();
size_t initial_chunk_size = _partial_array_splitter.start(_task_queue, obj, nullptr, array_length);
process_array_chunk(obj, 0, initial_chunk_size);
// Include object header size
return objArrayOopDesc::object_size(checked_cast<int>(initial_chunk_size));

View File

@ -844,12 +844,10 @@ private:
// mark bitmap scan, and so needs to be pushed onto the mark stack.
bool is_below_finger(oop obj, HeapWord* global_finger) const;
template<bool scan> void process_grey_task_entry(G1TaskQueueEntry task_entry, bool stolen);
static bool should_be_sliced(oop obj);
// Start processing the given objArrayOop by first pushing its continuations and
// then scanning the first chunk including the header.
size_t start_partial_array_processing(oop obj);
size_t start_partial_array_processing(objArrayOop obj);
// Process the given continuation. Returns the number of words scanned.
size_t process_partial_array(const G1TaskQueueEntry& task, bool stolen);
// Apply the closure to the given range of elements in the objArray.
@ -918,6 +916,9 @@ public:
template <class T>
inline bool deal_with_reference(T* p);
// Scan the klass and visit its children.
inline void process_klass(Klass* klass);
// Scans an object and visits its children.
inline void process_entry(G1TaskQueueEntry task_entry, bool stolen);

View File

@ -106,9 +106,27 @@ inline void G1CMMarkStack::iterate(Fn fn) const {
}
#endif
inline void G1CMTask::process_klass(Klass* klass) {
_cm_oop_closure->do_klass(klass);
}
// It scans an object and visits its children.
inline void G1CMTask::process_entry(G1TaskQueueEntry task_entry, bool stolen) {
process_grey_task_entry<true>(task_entry, stolen);
assert(task_entry.is_partial_array_state() || _mark_bitmap->is_marked(cast_from_oop<HeapWord*>(task_entry.to_oop())),
"Any stolen object should be a slice or marked");
if (task_entry.is_partial_array_state()) {
_words_scanned += process_partial_array(task_entry, stolen);
} else {
oop obj = task_entry.to_oop();
if (should_be_sliced(obj)) {
_words_scanned += start_partial_array_processing(objArrayOop(obj));
} else {
_words_scanned += obj->oop_iterate_size(_cm_oop_closure);
}
}
check_limits();
}
inline void G1CMTask::push(G1TaskQueueEntry task_entry) {
@ -160,27 +178,6 @@ inline bool G1CMTask::is_below_finger(oop obj, HeapWord* global_finger) const {
return objAddr < global_finger;
}
template<bool scan>
inline void G1CMTask::process_grey_task_entry(G1TaskQueueEntry task_entry, bool stolen) {
assert(scan || (!task_entry.is_partial_array_state() && task_entry.to_oop()->is_typeArray()), "Skipping scan of grey non-typeArray");
assert(task_entry.is_partial_array_state() || _mark_bitmap->is_marked(cast_from_oop<HeapWord*>(task_entry.to_oop())),
"Any stolen object should be a slice or marked");
if (scan) {
if (task_entry.is_partial_array_state()) {
_words_scanned += process_partial_array(task_entry, stolen);
} else {
oop obj = task_entry.to_oop();
if (should_be_sliced(obj)) {
_words_scanned += start_partial_array_processing(obj);
} else {
_words_scanned += obj->oop_iterate_size(_cm_oop_closure);
}
}
}
check_limits();
}
inline bool G1CMTask::should_be_sliced(oop obj) {
return obj->is_objArray() && ((objArrayOop)obj)->length() >= (int)ObjArrayMarkingStride;
}
@ -272,7 +269,6 @@ inline bool G1CMTask::make_reference_grey(oop obj) {
// be pushed on the stack. So, some duplicate work, but no
// correctness problems.
if (is_below_finger(obj, global_finger)) {
G1TaskQueueEntry entry(obj);
if (obj->is_typeArray()) {
// Immediately process arrays of primitive types, rather
// than pushing on the mark stack. This keeps us from
@ -284,8 +280,8 @@ inline bool G1CMTask::make_reference_grey(oop obj) {
// by only doing a bookkeeping update and avoiding the
// actual scan of the object - a typeArray contains no
// references, and the metadata is built-in.
process_grey_task_entry<false>(entry, false /* stolen */);
} else {
G1TaskQueueEntry entry(obj);
push(entry);
}
}

View File

@ -909,9 +909,9 @@ void PhaseIterGVN::verify_step(Node* n) {
}
}
void PhaseIterGVN::trace_PhaseIterGVN(Node* n, Node* nn, const Type* oldtype) {
void PhaseIterGVN::trace_PhaseIterGVN(Node* n, Node* nn, const Type* oldtype, bool progress) {
const Type* newtype = type_or_null(n);
if (nn != n || oldtype != newtype) {
if (progress) {
C->print_method(PHASE_AFTER_ITER_GVN_STEP, 5, n);
}
if (TraceIterativeGVN) {
@ -1092,7 +1092,9 @@ bool PhaseIterGVN::drain_worklist() {
NOT_PRODUCT(const Type* oldtype = type_or_null(n));
// Do the transformation
DEBUG_ONLY(int live_nodes_before = C->live_nodes();)
NOT_PRODUCT(uint progress_before = made_progress();)
Node* nn = transform_old(n);
NOT_PRODUCT(bool progress = (made_progress() - progress_before) > 0;)
DEBUG_ONLY(int live_nodes_after = C->live_nodes();)
// Ensure we did not increase the live node count with more than
// max_live_nodes_increase_per_iteration during the call to transform_old.
@ -1101,7 +1103,7 @@ bool PhaseIterGVN::drain_worklist() {
"excessive live node increase in single iteration of IGVN: %d "
"(should be at most %d)",
increase, max_live_nodes_increase_per_iteration);
NOT_PRODUCT(trace_PhaseIterGVN(n, nn, oldtype);)
NOT_PRODUCT(trace_PhaseIterGVN(n, nn, oldtype, progress);)
} else if (!n->is_top()) {
remove_dead_node(n, NodeOrigin::Graph);
}

View File

@ -548,7 +548,7 @@ public:
#endif
#ifndef PRODUCT
void trace_PhaseIterGVN(Node* n, Node* nn, const Type* old_type);
void trace_PhaseIterGVN(Node* n, Node* nn, const Type* old_type, bool progress);
void init_verifyPhaseIterGVN();
void verify_PhaseIterGVN(bool deep_revisit_converged);
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2026, 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
@ -660,7 +660,7 @@ public final class QuicTLSEngineImpl implements QuicTLSEngine, SSLTransport {
}
Alert alert = ((QuicEngineOutputRecord)
conContext.outputRecord).getAlert();
throw new QuicTransportException(alert.description, keySpace, 0,
throw new QuicTransportException(e.getMessage(), keySpace, 0,
BASE_CRYPTO_ERROR + alert.id, e);
} catch (IOException e) {
throw new RuntimeException(e);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2026, 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
@ -58,6 +58,7 @@ public class MouseInfo {
*
* @throws HeadlessException if GraphicsEnvironment.isHeadless() returns true
* @return location of the mouse pointer
* @see GraphicsConfiguration
* @since 1.5
*/
public static PointerInfo getPointerInfo() throws HeadlessException {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2026, 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
@ -128,6 +128,9 @@ public abstract sealed class TerminationCause {
? new IOException("connection terminated")
: new IOException(fallbackExceptionMsg);
} else if (original instanceof QuicTransportException qte) {
if (qte.getCause() instanceof IOException ioe) {
return ioe;
}
return new IOException(qte.getMessage());
} else if (original instanceof IOException ioe) {
return ioe;

View File

@ -23,10 +23,12 @@
/*
* @test
* @bug 8381316
* @summary Test to ensure the HTTP client throws an appropriate SSL exception
* when SSL context is not valid.
* @library /test/lib
* @library /test/lib /test/jdk/java/net/httpclient/lib
* @build jdk.test.lib.net.SimpleSSLContext
* jdk.httpclient.test.lib.common.HttpServerAdapters
* @run junit/othervm -Djdk.internal.httpclient.debug=true InvalidSSLContextTest
*/
@ -44,14 +46,18 @@ import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSocket;
import java.net.http.HttpClient;
import java.net.http.HttpClient.Version;
import java.net.http.HttpOption;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestServer;
import jdk.test.lib.net.SimpleSSLContext;
import static java.net.http.HttpClient.Builder.NO_PROXY;
import static java.net.http.HttpClient.Version.HTTP_1_1;
import static java.net.http.HttpClient.Version.HTTP_2;
import static java.net.http.HttpClient.Version.*;
import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY;
import static jdk.httpclient.test.lib.common.HttpServerAdapters.createClientBuilderForH3;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
@ -64,25 +70,29 @@ public class InvalidSSLContextTest {
private static final SSLContext sslContext = SimpleSSLContext.findSSLContext();
static volatile SSLServerSocket sslServerSocket;
static volatile String uri;
private static HttpTestServer h3Server;
private static String h3Uri;
public static Object[][] versions() {
return new Object[][]{
{ HTTP_1_1 },
{ HTTP_2 }
{ HTTP_1_1, uri },
{ HTTP_2 , uri },
{ HTTP_3 , h3Uri }
};
}
@ParameterizedTest
@MethodSource("versions")
public void testSync(Version version) throws Exception {
public void testSync(Version version, String uri) throws Exception {
// client-side uses a different context to that of the server-side
HttpClient client = HttpClient.newBuilder()
HttpClient client = createClientBuilderForH3()
.proxy(NO_PROXY)
.sslContext(SSLContext.getDefault())
.build();
HttpRequest request = HttpRequest.newBuilder(URI.create(uri))
.version(version)
.setOption(HttpOption.H3_DISCOVERY, HTTP_3_URI_ONLY)
.build();
try {
@ -90,21 +100,22 @@ public class InvalidSSLContextTest {
Assertions.fail("UNEXPECTED response" + response);
} catch (IOException ex) {
System.out.println("Caught expected: " + ex);
assertExceptionOrCause(SSLException.class, ex);
assertException(SSLException.class, ex);
}
}
@ParameterizedTest
@MethodSource("versions")
public void testAsync(Version version) throws Exception {
public void testAsync(Version version, String uri) throws Exception {
// client-side uses a different context to that of the server-side
HttpClient client = HttpClient.newBuilder()
HttpClient client = createClientBuilderForH3()
.proxy(NO_PROXY)
.sslContext(SSLContext.getDefault())
.build();
HttpRequest request = HttpRequest.newBuilder(URI.create(uri))
.version(version)
.setOption(HttpOption.H3_DISCOVERY, HTTP_3_URI_ONLY)
.build();
assertExceptionally(SSLException.class,
@ -123,26 +134,20 @@ public class InvalidSSLContextTest {
if (cause == null) {
Assertions.fail("Unexpected null cause: " + error);
}
assertExceptionOrCause(clazz, cause);
System.out.println("Caught expected: " + cause);
assertException(clazz, cause);
} else {
assertExceptionOrCause(clazz, error);
System.out.println("Caught expected: " + error);
assertException(clazz, error);
}
return null;
}).join();
}
static void assertExceptionOrCause(Class<? extends Throwable> clazz, Throwable t) {
if (t == null) {
Assertions.fail("Expected " + clazz + ", caught nothing");
}
final Throwable original = t;
do {
if (clazz.isInstance(t)) {
return; // found
}
} while ((t = t.getCause()) != null);
original.printStackTrace(System.out);
Assertions.fail("Expected " + clazz + "in " + original);
static void assertException(Class<? extends Throwable> clazz, Throwable t) {
Assertions.assertInstanceOf(clazz, t);
Assertions.assertTrue(t.getMessage().contains("unable to find valid certification path to requested target"),
"Unexpected exception message: " + t);
}
@BeforeAll
@ -159,7 +164,7 @@ public class InvalidSSLContextTest {
Thread t = new Thread("SSL-Server-Side") {
@Override
public void run() {
while (true) {
while (!sslServerSocket.isClosed()) {
try {
SSLSocket s = (SSLSocket) sslServerSocket.accept();
System.out.println("SERVER: accepted: " + s);
@ -177,7 +182,6 @@ public class InvalidSSLContextTest {
if (!sslServerSocket.isClosed()) {
throw new UncheckedIOException(e);
}
break;
} catch (InterruptedException ie) {
throw new RuntimeException(ie);
}
@ -185,10 +189,16 @@ public class InvalidSSLContextTest {
}
};
t.start();
h3Server = HttpTestServer.create(HTTP_3_URI_ONLY, sslContext);
h3Server.addHandler((exchange) -> exchange.sendResponseHeaders(200, 0), "/hello");
h3Server.start();
h3Uri = "https://" + h3Server.serverAuthority() + "/hello";
}
@AfterAll
public static void teardown() throws Exception {
h3Server.stop();
sslServerSocket.close();
}
}