From 8bd3cd51562ff9e76fa0e3d49d38e6e19210f878 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Sun, 4 Aug 2024 15:42:51 +0000 Subject: [PATCH 01/77] 8337716: ByteBuffer hashCode implementations are inconsistent Reviewed-by: alanb, liach --- .../java/nio/Heap-X-Buffer.java.template | 7 ------ .../java/nio/Buffer/EqualsCompareTest.java | 24 ++++++++++++++++++- .../openjdk/bench/java/nio/ByteBuffers.java | 7 +----- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template b/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template index 8fbc1a3b69dfa..4820725d6c4ea 100644 --- a/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template +++ b/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template @@ -29,7 +29,6 @@ package java.nio; import java.lang.foreign.MemorySegment; import java.util.Objects; -import jdk.internal.util.ArraysSupport; /** #if[rw] @@ -706,9 +705,6 @@ class Heap$Type$Buffer$RW$ addr, segment))); } - public int hashCode() { - return ArraysSupport.hashCode(hb, ix(position()), remaining(), 1); - } #end[byte] @@ -737,9 +733,6 @@ class Heap$Type$Buffer$RW$ offset, segment); } - public int hashCode() { - return ArraysSupport.hashCode(hb, ix(position()), remaining(), 1); - } #end[char] diff --git a/test/jdk/java/nio/Buffer/EqualsCompareTest.java b/test/jdk/java/nio/Buffer/EqualsCompareTest.java index baee641208411..03bd7c26a584a 100644 --- a/test/jdk/java/nio/Buffer/EqualsCompareTest.java +++ b/test/jdk/java/nio/Buffer/EqualsCompareTest.java @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import java.io.IOException; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -36,13 +37,21 @@ import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.LongBuffer; +import java.nio.MappedByteBuffer; import java.nio.ShortBuffer; +import java.nio.channels.FileChannel; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.function.BiFunction; import java.util.function.LongFunction; import java.util.stream.IntStream; +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.nio.file.StandardOpenOption.*; + /* * @test * @bug 8193085 8199773 @@ -713,4 +722,17 @@ static int[] ranges(int from, int to) { .distinct().toArray(); } } + + @Test + void testHashCode() throws IOException { + byte[] bytes = "hello world".getBytes(UTF_8); + Path path = Files.createTempFile("", ""); + Files.write(path, bytes); + try (FileChannel fc = FileChannel.open(path, READ, DELETE_ON_CLOSE)) { + MappedByteBuffer one = fc.map(FileChannel.MapMode.READ_ONLY, 0, bytes.length); + ByteBuffer two = ByteBuffer.wrap(bytes); + Assert.assertEquals(one, two); + Assert.assertEquals(one.hashCode(), two.hashCode()); + } + } } diff --git a/test/micro/org/openjdk/bench/java/nio/ByteBuffers.java b/test/micro/org/openjdk/bench/java/nio/ByteBuffers.java index c2f4e93313c91..48f75a3ec8117 100644 --- a/test/micro/org/openjdk/bench/java/nio/ByteBuffers.java +++ b/test/micro/org/openjdk/bench/java/nio/ByteBuffers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -923,9 +923,4 @@ public double testDirectLoopGetDouble() { } return r; } - - @Benchmark - public int testHeapHashCode() { - return heapByteBuffer.hashCode(); - } } From dabdae6b355b3e7a2795f6b01ba475652d483288 Mon Sep 17 00:00:00 2001 From: Julian Waters Date: Mon, 5 Aug 2024 05:13:08 +0000 Subject: [PATCH 02/77] 8334599: Improve code from JDK-8302671 Reviewed-by: aivanov, stuefe, prr --- .../windows/native/libawt/windows/awt_Component.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp index 4f87e8ef4c113..640b06d0521a9 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp @@ -3362,10 +3362,10 @@ BOOL AwtComponent::IsNumPadKey(UINT vkey, BOOL extended) return FALSE; } static void -resetKbdState( BYTE kstate[256]) { - BYTE tmpState[256]; +resetKbdState( BYTE (&kstate)[AwtToolkit::KB_STATE_SIZE]) { + BYTE tmpState[AwtToolkit::KB_STATE_SIZE]; WCHAR wc[2]; - memmove(tmpState, kstate, 256 * sizeof(BYTE)); + memmove(tmpState, kstate, sizeof(kstate)); tmpState[VK_SHIFT] = 0; tmpState[VK_CONTROL] = 0; tmpState[VK_MENU] = 0; From fbe8a81d1900d0de1920ad1df6ad574f3da4bd51 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Mon, 5 Aug 2024 05:57:41 +0000 Subject: [PATCH 03/77] 8333144: docker tests do not work when ubsan is configured Reviewed-by: clanger, stuefe --- test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java | 1 + 1 file changed, 1 insertion(+) diff --git a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java index 2404394690ebd..c87796da47e7e 100644 --- a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java +++ b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java @@ -323,6 +323,7 @@ private static void generateDockerFile(Path dockerfile, String baseImage, String baseImageVersion) throws Exception { String template = "FROM %s:%s\n" + + "RUN apt-get install libubsan1\n" + "COPY /jdk /jdk\n" + "ENV JAVA_HOME=/jdk\n" + "CMD [\"/bin/bash\"]\n"; From be34730fb4e6818ac13c46b34b735c967351e5cd Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Mon, 5 Aug 2024 09:52:07 +0000 Subject: [PATCH 04/77] 8335257: Refactor code to create Initialized Assertion Predicates into separate class Reviewed-by: kvn, epeter --- src/hotspot/share/opto/cfgnode.hpp | 4 + src/hotspot/share/opto/ifnode.cpp | 4 +- src/hotspot/share/opto/loopPredicate.cpp | 12 +-- src/hotspot/share/opto/loopTransform.cpp | 82 +++++++--------- src/hotspot/share/opto/loopnode.hpp | 9 +- src/hotspot/share/opto/predicates.cpp | 118 +++++++++++++++++++---- src/hotspot/share/opto/predicates.hpp | 61 ++++++++---- src/hotspot/share/opto/split_if.cpp | 24 ++--- 8 files changed, 206 insertions(+), 108 deletions(-) diff --git a/src/hotspot/share/opto/cfgnode.hpp b/src/hotspot/share/opto/cfgnode.hpp index 18d7577d9e621..5edd31fa71695 100644 --- a/src/hotspot/share/opto/cfgnode.hpp +++ b/src/hotspot/share/opto/cfgnode.hpp @@ -449,6 +449,10 @@ class IfNode : public MultiBranchNode { static const TypeInt* filtered_int_type(PhaseGVN* phase, Node* val, Node* if_proj); #ifndef PRODUCT + AssertionPredicateType assertion_predicate_type() const { + return _assertion_predicate_type; + } + virtual void dump_spec(outputStream *st) const; #endif diff --git a/src/hotspot/share/opto/ifnode.cpp b/src/hotspot/share/opto/ifnode.cpp index cedbc66bbb444..8e5cd2702137a 100644 --- a/src/hotspot/share/opto/ifnode.cpp +++ b/src/hotspot/share/opto/ifnode.cpp @@ -1843,10 +1843,10 @@ void IfProjNode::pin_array_access_nodes(PhaseIterGVN* igvn) { #ifndef PRODUCT void IfNode::dump_spec(outputStream* st) const { switch (_assertion_predicate_type) { - case AssertionPredicateType::Init_value: + case AssertionPredicateType::InitValue: st->print("#Init Value Assertion Predicate "); break; - case AssertionPredicateType::Last_value: + case AssertionPredicateType::LastValue: st->print("#Last Value Assertion Predicate "); break; case AssertionPredicateType::None: diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp index b22931e56630e..5e585a406f20c 100644 --- a/src/hotspot/share/opto/loopPredicate.cpp +++ b/src/hotspot/share/opto/loopPredicate.cpp @@ -374,10 +374,10 @@ IfProjNode* PhaseIdealLoop::clone_assertion_predicate_for_unswitched_loops(IfNod IfProjNode* predicate, Deoptimization::DeoptReason reason, ParsePredicateSuccessProj* parse_predicate_proj) { - TemplateAssertionPredicateExpression template_assertion_predicate_expression( - template_assertion_predicate->in(1)->as_Opaque4()); - Opaque4Node* cloned_opaque4_node = template_assertion_predicate_expression.clone(parse_predicate_proj->in(0)->in(0), this); - IfProjNode* if_proj = create_new_if_for_predicate(parse_predicate_proj, nullptr, reason, template_assertion_predicate->Opcode(), false); + TemplateAssertionExpression template_assertion_expression(template_assertion_predicate->in(1)->as_Opaque4()); + Opaque4Node* cloned_opaque4_node = template_assertion_expression.clone(parse_predicate_proj->in(0)->in(0), this); + IfProjNode* if_proj = create_new_if_for_predicate(parse_predicate_proj, nullptr, reason, + template_assertion_predicate->Opcode(), false); _igvn.replace_input_of(if_proj->in(0), 1, cloned_opaque4_node); _igvn.replace_input_of(parse_predicate_proj->in(0), 0, if_proj); set_idom(parse_predicate_proj->in(0), if_proj, dom_depth(if_proj)); @@ -1324,7 +1324,7 @@ IfTrueNode* PhaseIdealLoop::add_template_assertion_predicate(IfNode* iff, IdealL C->add_template_assertion_predicate_opaq(opaque_bol); register_new_node(opaque_bol, upper_bound_proj); IfTrueNode* new_proj = create_new_if_for_predicate(parse_predicate_proj, nullptr, reason, overflow ? Op_If : iff->Opcode(), - false NOT_PRODUCT(COMMA AssertionPredicateType::Init_value)); + false NOT_PRODUCT(COMMA AssertionPredicateType::InitValue)); _igvn.replace_input_of(new_proj->in(0), 1, opaque_bol); assert(opaque_init->outcnt() > 0, "should be used"); @@ -1350,7 +1350,7 @@ IfTrueNode* PhaseIdealLoop::add_template_assertion_predicate(IfNode* iff, IdealL C->add_template_assertion_predicate_opaq(opaque_bol); register_new_node(opaque_bol, new_proj); new_proj = create_new_if_for_predicate(parse_predicate_proj, nullptr, reason, overflow ? Op_If : iff->Opcode(), - false NOT_PRODUCT(COMMA AssertionPredicateType::Last_value)); + false NOT_PRODUCT(COMMA AssertionPredicateType::LastValue)); _igvn.replace_input_of(new_proj->in(0), 1, opaque_bol); assert(max_value->outcnt() > 0, "should be used"); assert(assertion_predicate_has_loop_opaque_node(new_proj->in(0)->as_If()), "unexpected"); diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 6ca7bb51fb458..99742a598e858 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -1373,17 +1373,12 @@ void PhaseIdealLoop::copy_assertion_predicates_to_main_loop_helper(const Predica Node* bol = iff->in(1); assert(!bol->is_OpaqueInitializedAssertionPredicate(), "should not find an Initialized Assertion Predicate"); if (bol->is_Opaque4()) { - assert(assertion_predicate_has_loop_opaque_node(iff), "must find OpaqueLoop* nodes"); // Clone the Assertion Predicate twice and initialize one with the initial // value of the loop induction variable. Leave the other predicate // to be initialized when increasing the stride during loop unrolling. - prev_proj = clone_assertion_predicate_and_initialize(iff, opaque_init, nullptr, predicate_proj, uncommon_proj, - current_proj, outer_loop, prev_proj); - assert(assertion_predicate_has_loop_opaque_node(prev_proj->in(0)->as_If()), ""); - - prev_proj = clone_assertion_predicate_and_initialize(iff, init, stride, predicate_proj, uncommon_proj, - current_proj, outer_loop, prev_proj); - assert(!assertion_predicate_has_loop_opaque_node(prev_proj->in(0)->as_If()), ""); + prev_proj = clone_template_assertion_predicate(iff, opaque_init, predicate_proj, uncommon_proj, + current_proj, outer_loop, prev_proj); + prev_proj = create_initialized_assertion_predicate(iff, init, stride, prev_proj); // Rewire any control inputs from the cloned Assertion Predicates down to the main and post loop for data nodes // that are part of the main loop (and were cloned to the pre and post loop). @@ -1460,7 +1455,7 @@ void PhaseIdealLoop::count_opaque_loop_nodes(Node* n, uint& init, uint& stride) wq.push(n); for (uint i = 0; i < wq.size(); i++) { Node* n = wq.at(i); - if (TemplateAssertionPredicateExpressionNode::is_maybe_in_expression(n)) { + if (TemplateAssertionExpressionNode::is_maybe_in_expression(n)) { if (n->is_OpaqueLoopInit()) { init++; } else if (n->is_OpaqueLoopStride()) { @@ -1477,27 +1472,28 @@ void PhaseIdealLoop::count_opaque_loop_nodes(Node* n, uint& init, uint& stride) } } -// Clone an Assertion Predicate for the main loop. new_init and new_stride are set as new inputs. Since the predicates -// cannot fail at runtime, Halt nodes are inserted instead of uncommon traps. -Node* PhaseIdealLoop::clone_assertion_predicate_and_initialize(Node* iff, Node* new_init, Node* new_stride, Node* predicate, - Node* uncommon_proj, Node* control, IdealLoopTree* outer_loop, - Node* input_proj) { - TemplateAssertionPredicateExpression template_assertion_predicate_expression(iff->in(1)->as_Opaque4()); - Node* new_opaque_node; - if (new_stride == nullptr) { - // Clone the Template Assertion Predicate and set a new OpaqueLoopInitNode to create a new Template Assertion Predicate. - // This is done when creating a new Template Assertion Predicate for the main loop which requires a new init node. - // We keep the Opaque4 node since it's still a template. - assert(new_init->is_OpaqueLoopInit(), "only for creating new Template Assertion Predicates"); - new_opaque_node = template_assertion_predicate_expression.clone_and_replace_init(new_init, control, this); - } else { - // Create an Initialized Assertion Predicate from the Template Assertion Predicate. - new_opaque_node = template_assertion_predicate_expression.clone_and_replace_init_and_stride(new_init, new_stride, - control, this); - // Since this is an Initialized Assertion Predicate, we use the dedicated opaque node. - new_opaque_node = new OpaqueInitializedAssertionPredicateNode(new_opaque_node->in(1)->as_Bool(), C); - register_new_node(new_opaque_node, control); - } +// Create an Initialized Assertion Predicate from the template_assertion_predicate +IfTrueNode* PhaseIdealLoop::create_initialized_assertion_predicate(IfNode* template_assertion_predicate, Node* new_init, + Node* new_stride, Node* control) { + assert(assertion_predicate_has_loop_opaque_node(template_assertion_predicate), + "must find OpaqueLoop* nodes for Template Assertion Predicate"); + InitializedAssertionPredicate initialized_assertion_predicate(template_assertion_predicate, new_init, new_stride, this); + IfTrueNode* success_proj = initialized_assertion_predicate.create(control); + assert(!assertion_predicate_has_loop_opaque_node(success_proj->in(0)->as_If()), + "Initialized Assertion Predicates do not have OpaqueLoop* nodes in the bool expression anymore"); + return success_proj; +} + +// Clone the Template Assertion Predicate and set a new OpaqueLoopInitNode to create a new Template Assertion Predicate. +// This is done when creating a new Template Assertion Predicate for the main loop which requires a new init node. +// We keep the Opaque4 node since it's still a template. Since the templates are eventually removed after loop opts, +// these are never executed. We therefore insert a Halt node instead of an uncommon trap. +Node* PhaseIdealLoop::clone_template_assertion_predicate(IfNode* iff, Node* new_init, Node* predicate, Node* uncommon_proj, + Node* control, IdealLoopTree* outer_loop, Node* input_proj) { + assert(assertion_predicate_has_loop_opaque_node(iff), "must find OpaqueLoop* nodes for Template Assertion Predicate"); + TemplateAssertionExpression template_assertion_expression(iff->in(1)->as_Opaque4()); + assert(new_init->is_OpaqueLoopInit(), "only for creating new Template Assertion Predicates"); + Opaque4Node* new_opaque_node = template_assertion_expression.clone_and_replace_init(new_init, control, this); Node* proj = predicate->clone(); Node* other_proj = uncommon_proj->clone(); Node* new_iff = iff->clone(); @@ -1506,8 +1502,7 @@ Node* PhaseIdealLoop::clone_assertion_predicate_and_initialize(Node* iff, Node* other_proj->set_req(0, new_iff); Node* frame = new ParmNode(C->start(), TypeFunc::FramePtr); register_new_node(frame, C->start()); - // It's impossible for the predicate to fail at runtime. Use a Halt node. - Node* halt = new HaltNode(other_proj, frame, "duplicated predicate failed which is impossible"); + Node* halt = new HaltNode(other_proj, frame, "Template Assertion Predicates are always removed before code generation"); _igvn.add_input_to(C->root(), halt); new_iff->set_req(0, input_proj); @@ -1515,6 +1510,8 @@ Node* PhaseIdealLoop::clone_assertion_predicate_and_initialize(Node* iff, Node* register_control(proj, outer_loop == _ltree_root ? _ltree_root : outer_loop->_parent, new_iff); register_control(other_proj, _ltree_root, new_iff); register_control(halt, _ltree_root, other_proj); + assert(assertion_predicate_has_loop_opaque_node(proj->in(0)->as_If()), + "Template Assertion Predicates must have OpaqueLoop* nodes in the bool expression"); return proj; } @@ -1967,9 +1964,7 @@ void PhaseIdealLoop::update_main_loop_assertion_predicates(Node* ctrl, CountedLo // Create an Initialized Assertion Predicates for it accordingly: // - For the initial access a[init] (same as before) // - For the last access a[init+new_stride-orig_stride] (with the new unroll stride) - prev_proj = clone_assertion_predicate_and_initialize(iff, init, max_value, entry, proj, ctrl, outer_loop, - prev_proj); - assert(!assertion_predicate_has_loop_opaque_node(prev_proj->in(0)->as_If()), "unexpected"); + prev_proj = create_initialized_assertion_predicate(iff, init, max_value, prev_proj); } else { // Ignore Opaque4 from a non-null-check for an intrinsic or unsafe access. This could happen when we maximally // unroll a non-main loop with such an If with an Opaque4 node directly above the loop entry. @@ -2008,10 +2003,7 @@ void PhaseIdealLoop::copy_assertion_predicates_to_post_loop(LoopNode* main_loop_ } if (iff->in(1)->is_Opaque4()) { // Initialize from Template Assertion Predicate. - assert(assertion_predicate_has_loop_opaque_node(iff), "must find OpaqueLoop* nodes"); - prev_proj = clone_assertion_predicate_and_initialize(iff, init, stride, ctrl, proj, post_loop_entry, - post_loop, prev_proj); - assert(!assertion_predicate_has_loop_opaque_node(prev_proj->in(0)->as_If()), "must not find OpaqueLoop* nodes"); + prev_proj = create_initialized_assertion_predicate(iff, init, stride, prev_proj); } ctrl = ctrl->in(0)->in(0); } @@ -2030,9 +2022,7 @@ void PhaseIdealLoop::initialize_assertion_predicates_for_peeled_loop(const Predi if (!predicate_block->has_parse_predicate()) { return; } - Node* control = outer_loop_head->in(LoopNode::EntryControl); - Node* input_proj = control; - + Node* input_proj = outer_loop_head->in(LoopNode::EntryControl); const Node* parse_predicate_uncommon_trap = predicate_block->parse_predicate()->uncommon_trap(); Node* next_regular_predicate_proj = predicate_block->skip_parse_predicate(); while (next_regular_predicate_proj->is_IfProj()) { @@ -2046,9 +2036,7 @@ void PhaseIdealLoop::initialize_assertion_predicates_for_peeled_loop(const Predi assert(!bol->is_OpaqueInitializedAssertionPredicate(), "should not find an Initialized Assertion Predicate"); if (bol->is_Opaque4()) { // Initialize from Template Assertion Predicate. - assert(assertion_predicate_has_loop_opaque_node(iff), "must find OpaqueLoop* nodes"); - input_proj = clone_assertion_predicate_and_initialize(iff, init, stride, next_regular_predicate_proj, uncommon_proj, control, - outer_loop, input_proj); + input_proj = create_initialized_assertion_predicate(iff, init, stride, input_proj); // Rewire any control inputs from the old Assertion Predicates above the peeled iteration down to the initialized // Assertion Predicates above the peeled loop. @@ -3018,7 +3006,7 @@ void PhaseIdealLoop::do_range_check(IdealLoopTree *loop, Node_List &old_new) { // unrolling or splitting this main-loop further. loop_entry = add_range_check_elimination_assertion_predicate( loop, loop_entry, scale_con, int_offset, int_limit, stride_con, opaque_init, true - NOT_PRODUCT(COMMA AssertionPredicateType::Init_value)); + NOT_PRODUCT(COMMA AssertionPredicateType::InitValue)); assert(assertion_predicate_has_loop_opaque_node(loop_entry->in(0)->as_If()), "unexpected"); Node* opaque_stride = new OpaqueLoopStrideNode(C, cl->stride()); @@ -3032,7 +3020,7 @@ void PhaseIdealLoop::do_range_check(IdealLoopTree *loop, Node_List &old_new) { register_new_node(max_value, loop_entry); loop_entry = add_range_check_elimination_assertion_predicate( loop, loop_entry, scale_con, int_offset, int_limit, stride_con, max_value, true - NOT_PRODUCT(COMMA AssertionPredicateType::Last_value)); + NOT_PRODUCT(COMMA AssertionPredicateType::LastValue)); assert(assertion_predicate_has_loop_opaque_node(loop_entry->in(0)->as_If()), "unexpected"); } else { diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index 24101ea07a002..94632be268d58 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -952,9 +952,10 @@ class PhaseIdealLoop : public PhaseTransform { LoopNode* outer_main_head, uint dd_main_head, uint idx_before_pre_post, uint idx_after_post_before_pre, Node* zero_trip_guard_proj_main, Node* zero_trip_guard_proj_post, const Node_List& old_new); - Node* clone_assertion_predicate_and_initialize(Node* iff, Node* new_init, Node* new_stride, Node* predicate, - Node* uncommon_proj, Node* control, IdealLoopTree* outer_loop, - Node* input_proj); + Node* clone_template_assertion_predicate(IfNode* iff, Node* new_init, Node* predicate, Node* uncommon_proj, Node* control, + IdealLoopTree* outer_loop, Node* input_proj); + IfTrueNode* create_initialized_assertion_predicate(IfNode* template_assertion_predicate, Node* new_init, + Node* new_stride, Node* control); static void count_opaque_loop_nodes(Node* n, uint& init, uint& stride); static bool assertion_predicate_has_loop_opaque_node(IfNode* iff); static void get_assertion_predicates(Node* predicate, Unique_Node_List& list, bool get_opaque = false); @@ -1774,7 +1775,7 @@ class PhaseIdealLoop : public PhaseTransform { bool clone_cmp_loadklass_down(Node* n, const Node* blk1, const Node* blk2); void clone_loadklass_nodes_at_cmp_index(const Node* n, Node* cmp, int i); bool clone_cmp_down(Node* n, const Node* blk1, const Node* blk2); - void clone_template_assertion_predicate_expression_down(Node* node); + void clone_template_assertion_expression_down(Node* node); Node* similar_subtype_check(const Node* x, Node* r_in); diff --git a/src/hotspot/share/opto/predicates.cpp b/src/hotspot/share/opto/predicates.cpp index 5b0de2e02d5f0..3887e8a5f6cdf 100644 --- a/src/hotspot/share/opto/predicates.cpp +++ b/src/hotspot/share/opto/predicates.cpp @@ -27,6 +27,7 @@ #include "opto/loopnode.hpp" #include "opto/node.hpp" #include "opto/predicates.hpp" +#include "opto/rootnode.hpp" // Walk over all Initialized Assertion Predicates and return the entry into the first Initialized Assertion Predicate // (i.e. not belonging to an Initialized Assertion Predicate anymore) @@ -239,27 +240,27 @@ class ReplaceInitAndStrideStrategy : public TransformStrategyForOpaqueLoopNodes } }; -// Creates an identical clone of this Template Assertion Predicate Expression (i.e.cloning all nodes from the Opaque4Node -// to and including the OpaqueLoop* nodes). The cloned nodes are rewired to reflect the same graph structure as found for -// this Template Assertion Predicate Expression. The cloned nodes get 'new_ctrl' as ctrl. There is no other update done -// for the cloned nodes. Return the newly cloned Opaque4Node. -Opaque4Node* TemplateAssertionPredicateExpression::clone(Node* new_ctrl, PhaseIdealLoop* phase) { +// Creates an identical clone of this Template Assertion Expression (i.e.cloning all nodes from the Opaque4Node to and +// including the OpaqueLoop* nodes). The cloned nodes are rewired to reflect the same graph structure as found for this +// Template Assertion Expression. The cloned nodes get 'new_ctrl' as ctrl. There is no other update done for the cloned +// nodes. Return the newly cloned Opaque4Node. +Opaque4Node* TemplateAssertionExpression::clone(Node* new_ctrl, PhaseIdealLoop* phase) { CloneStrategy clone_init_and_stride_strategy(phase, new_ctrl); return clone(clone_init_and_stride_strategy, new_ctrl, phase); } // Same as clone() but instead of cloning the OpaqueLoopInitNode, we replace it with the provided 'new_init' node. -Opaque4Node* TemplateAssertionPredicateExpression::clone_and_replace_init(Node* new_init, Node* new_ctrl, - PhaseIdealLoop* phase) { +Opaque4Node* TemplateAssertionExpression::clone_and_replace_init(Node* new_init, Node* new_ctrl, + PhaseIdealLoop* phase) { ReplaceInitAndCloneStrideStrategy replace_init_and_clone_stride_strategy(new_init, new_ctrl, phase); return clone(replace_init_and_clone_stride_strategy, new_ctrl, phase); } // Same as clone() but instead of cloning the OpaqueLoopInit and OpaqueLoopStride node, we replace them with the provided // 'new_init' and 'new_stride' nodes, respectively. -Opaque4Node* TemplateAssertionPredicateExpression::clone_and_replace_init_and_stride(Node* new_init, Node* new_stride, - Node* new_ctrl, - PhaseIdealLoop* phase) { +Opaque4Node* TemplateAssertionExpression::clone_and_replace_init_and_stride(Node* new_init, Node* new_stride, + Node* new_ctrl, + PhaseIdealLoop* phase) { ReplaceInitAndStrideStrategy replace_init_and_stride_strategy(new_init, new_stride); return clone(replace_init_and_stride_strategy, new_ctrl, phase); } @@ -307,8 +308,7 @@ class DataNodesOnPathsToTargets : public StackObj { // Do a BFS from the start_node to collect all target nodes. We can then do another BFS from the target nodes to // find all nodes on the paths from start->target(s). // Note: We could do a single DFS pass to search targets and backtrack in one walk. But this is much more complex. - // Given that the typical Template Assertion Predicate Expression only consists of a few nodes, we aim for - // simplicity here. + // Given that the typical Template Assertion Expression only consists of a few nodes, we aim for simplicity here. void collect_target_nodes(Node* start_node) { _nodes_to_visit.push(start_node); for (uint i = 0; i < _nodes_to_visit.size(); i++) { @@ -342,14 +342,14 @@ class DataNodesOnPathsToTargets : public StackObj { } }; -// Clones this Template Assertion Predicate Expression and applies the given strategy to transform the OpaqueLoop* nodes. -Opaque4Node* TemplateAssertionPredicateExpression::clone(const TransformStrategyForOpaqueLoopNodes& transform_strategy, - Node* new_ctrl, PhaseIdealLoop* phase) { +// Clones this Template Assertion Expression and applies the given strategy to transform the OpaqueLoop* nodes. +Opaque4Node* TemplateAssertionExpression::clone(const TransformStrategyForOpaqueLoopNodes& transform_strategy, + Node* new_ctrl, PhaseIdealLoop* phase) { ResourceMark rm; auto is_opaque_loop_node = [](const Node* node) { return node->is_Opaque1(); }; - DataNodesOnPathsToTargets data_nodes_on_path_to_targets(TemplateAssertionPredicateExpressionNode::is_maybe_in_expression, + DataNodesOnPathsToTargets data_nodes_on_path_to_targets(TemplateAssertionExpressionNode::is_maybe_in_expression, is_opaque_loop_node); const Unique_Node_List& collected_nodes = data_nodes_on_path_to_targets.collect(_opaque4_node); DataNodeGraph data_node_graph(collected_nodes, phase); @@ -359,8 +359,8 @@ Opaque4Node* TemplateAssertionPredicateExpression::clone(const TransformStrategy return opaque4_clone->as_Opaque4(); } -// Check if this node belongs a Template Assertion Predicate Expression (including OpaqueLoop* nodes). -bool TemplateAssertionPredicateExpressionNode::is_in_expression(Node* node) { +// Check if this node belongs a Template Assertion Expression (including OpaqueLoop* nodes). +bool TemplateAssertionExpressionNode::is_in_expression(Node* node) { if (is_maybe_in_expression(node)) { ResourceMark rm; Unique_Node_List list; @@ -377,10 +377,90 @@ bool TemplateAssertionPredicateExpressionNode::is_in_expression(Node* node) { return false; } -bool TemplateAssertionPredicateExpressionNode::is_template_assertion_predicate(Node* node) { +bool TemplateAssertionExpressionNode::is_template_assertion_predicate(Node* node) { return node->is_If() && node->in(1)->is_Opaque4(); } +InitializedAssertionPredicate::InitializedAssertionPredicate(IfNode* template_assertion_predicate, Node* new_init, + Node* new_stride, PhaseIdealLoop* phase) + : _template_assertion_predicate(template_assertion_predicate), + _new_init(new_init), + _new_stride(new_stride), + _phase(phase) {} + +// Create an Initialized Assertion Predicate at the provided control from the _template_assertion_predicate. +// We clone the Template Assertion Expression and replace: +// - Opaque4 with OpaqueInitializedAssertionPredicate +// - OpaqueLoop*Nodes with _new_init and _new_stride, respectively. +// +// / init stride +// | | | +// | OpaqueLoopInitNode OpaqueLoopStrideNode / _new_init _new_stride +// Template | \ / | \ / +// Assertion | ... Assertion | ... +// Expression | | Expression | | +// | Bool | new Bool +// | | | | +// \ Opaque4 ======> control \ OpaqueInitializedAssertionPredicate +// | \ / +// If new If +// / \ / \ +// success fail path new success new Halt +// proj (Halt or UCT) proj +// +IfTrueNode* InitializedAssertionPredicate::create(Node* control) { + IdealLoopTree* loop = _phase->get_loop(control); + OpaqueInitializedAssertionPredicateNode* assertion_expression = create_assertion_expression(control); + IfNode* if_node = create_if_node(control, assertion_expression, loop); + create_fail_path(if_node, loop); + return create_success_path(if_node, loop); +} + +// Create a new Assertion Expression to be used as bool input for the Initialized Assertion Predicate IfNode. +OpaqueInitializedAssertionPredicateNode* InitializedAssertionPredicate::create_assertion_expression(Node* control) { + Opaque4Node* template_opaque = _template_assertion_predicate->in(1)->as_Opaque4(); + TemplateAssertionExpression template_assertion_expression(template_opaque); + Opaque4Node* tmp_opaque = template_assertion_expression.clone_and_replace_init_and_stride(_new_init, _new_stride, + control, _phase); + OpaqueInitializedAssertionPredicateNode* assertion_expression = + new OpaqueInitializedAssertionPredicateNode(tmp_opaque->in(1)->as_Bool(), _phase->C); + _phase->register_new_node(assertion_expression, control); + return assertion_expression; +} + +IfNode* InitializedAssertionPredicate::create_if_node(Node* control, + OpaqueInitializedAssertionPredicateNode* assertion_expression, + IdealLoopTree* loop) { + const int if_opcode = _template_assertion_predicate->Opcode(); + NOT_PRODUCT(const AssertionPredicateType assertion_predicate_type = _template_assertion_predicate->assertion_predicate_type();) + IfNode* if_node = if_opcode == Op_If ? + new IfNode(control, assertion_expression, PROB_MAX, COUNT_UNKNOWN NOT_PRODUCT(COMMA assertion_predicate_type)) : + new RangeCheckNode(control, assertion_expression, PROB_MAX, COUNT_UNKNOWN NOT_PRODUCT(COMMA assertion_predicate_type)); + _phase->register_control(if_node, loop, control); + return if_node; +} + +IfTrueNode* InitializedAssertionPredicate::create_success_path(IfNode* if_node, IdealLoopTree* loop) { + IfTrueNode* success_proj = new IfTrueNode(if_node); + _phase->register_control(success_proj, loop, if_node); + return success_proj; +} + +void InitializedAssertionPredicate::create_fail_path(IfNode* if_node, IdealLoopTree* loop) { + IfFalseNode* fail_proj = new IfFalseNode(if_node); + _phase->register_control(fail_proj, loop, if_node); + create_halt_node(fail_proj, loop); +} + +void InitializedAssertionPredicate::create_halt_node(IfFalseNode* fail_proj, IdealLoopTree* loop) { + StartNode* start_node = _phase->C->start(); + Node* frame = new ParmNode(start_node, TypeFunc::FramePtr); + _phase->register_new_node(frame, start_node); + Node* halt = new HaltNode(fail_proj, frame, "Initialized Assertion Predicate cannot fail"); + _phase->igvn().add_input_to(_phase->C->root(), halt); + _phase->register_control(halt, loop, fail_proj); +} + // Is current node pointed to by iterator a predicate? bool PredicateEntryIterator::has_next() const { return ParsePredicate::is_predicate(_current) || diff --git a/src/hotspot/share/opto/predicates.hpp b/src/hotspot/share/opto/predicates.hpp index 08aa64f03e583..96f5c438b802f 100644 --- a/src/hotspot/share/opto/predicates.hpp +++ b/src/hotspot/share/opto/predicates.hpp @@ -29,6 +29,8 @@ #include "opto/connode.hpp" #include "opto/opaquenode.hpp" +class IdealLoopTree; + /* * There are different kinds of predicates throughout the code. We differentiate between the following predicates: * @@ -198,8 +200,8 @@ // value of a range check in the last iteration of a loop. enum class AssertionPredicateType { None, // Not an Assertion Predicate - Init_value, - Last_value + InitValue, + LastValue }; #endif // NOT PRODUCT @@ -294,20 +296,20 @@ class RuntimePredicate : public StackObj { static bool is_success_proj(Node* node, Deoptimization::DeoptReason deopt_reason); }; -// Interface to transform OpaqueLoopInit and OpaqueLoopStride nodes of a Template Assertion Predicate Expression. +// Interface to transform OpaqueLoopInit and OpaqueLoopStride nodes of a Template Assertion Expression. class TransformStrategyForOpaqueLoopNodes : public StackObj { public: virtual Node* transform_opaque_init(OpaqueLoopInitNode* opaque_init) const = 0; virtual Node* transform_opaque_stride(OpaqueLoopStrideNode* opaque_stride) const = 0; }; -// A Template Assertion Predicate Expression represents the Opaque4Node for the initial value or the last value of a +// A Template Assertion Predicate represents the Opaque4Node for the initial value or the last value of a // Template Assertion Predicate and all the nodes up to and including the OpaqueLoop* nodes. -class TemplateAssertionPredicateExpression : public StackObj { +class TemplateAssertionExpression : public StackObj { Opaque4Node* _opaque4_node; public: - explicit TemplateAssertionPredicateExpression(Opaque4Node* opaque4_node) : _opaque4_node(opaque4_node) {} + explicit TemplateAssertionExpression(Opaque4Node* opaque4_node) : _opaque4_node(opaque4_node) {} private: Opaque4Node* clone(const TransformStrategyForOpaqueLoopNodes& transform_strategy, Node* new_ctrl, PhaseIdealLoop* phase); @@ -318,29 +320,29 @@ class TemplateAssertionPredicateExpression : public StackObj { Opaque4Node* clone_and_replace_init_and_stride(Node* new_init, Node* new_stride, Node* new_ctrl, PhaseIdealLoop* phase); }; -// Class to represent a node being part of a Template Assertion Predicate Expression. +// Class to represent a node being part of a Template Assertion Expression. Note that this is not an IR node. // // The expression itself can belong to no, one, or two Template Assertion Predicates: // - None: This node is already dead (i.e. we replaced the Bool condition of the Template Assertion Predicate). // - Two: A OpaqueLoopInitNode could be part of two Template Assertion Predicates. // - One: In all other cases. -class TemplateAssertionPredicateExpressionNode : public StackObj { +class TemplateAssertionExpressionNode : public StackObj { Node* const _node; public: - explicit TemplateAssertionPredicateExpressionNode(Node* node) : _node(node) { + explicit TemplateAssertionExpressionNode(Node* node) : _node(node) { assert(is_in_expression(node), "must be valid"); } - NONCOPYABLE(TemplateAssertionPredicateExpressionNode); + NONCOPYABLE(TemplateAssertionExpressionNode); private: static bool is_template_assertion_predicate(Node* node); public: - // Check whether the provided node is part of a Template Assertion Predicate Expression or not. + // Check whether the provided node is part of a Template Assertion Expression or not. static bool is_in_expression(Node* node); - // Check if the opcode of node could be found in a Template Assertion Predicate Expression. + // Check if the opcode of node could be found in a Template Assertion Expression. // This also provides a fast check whether a node is unrelated. static bool is_maybe_in_expression(const Node* node) { const int opcode = node->Opcode(); @@ -377,21 +379,44 @@ class TemplateAssertionPredicateExpressionNode : public StackObj { callback(next->as_If()); DEBUG_ONLY(template_counter++;) } else { - assert(!next->is_CFG(), "no CFG expected in Template Assertion Predicate Expression"); + assert(!next->is_CFG(), "no CFG expected in Template Assertion Expression"); list.push_outputs_of(next); } } - // Each node inside a Template Assertion Predicate Expression is in between a Template Assertion Predicate and - // its OpaqueLoop* nodes (or an OpaqueLoop* node itself). The OpaqueLoop* nodes do not common up. Therefore, each - // Template Assertion Predicate Expression node belongs to a single expression - except for OpaqueLoopInitNodes. - // An OpaqueLoopInitNode is shared between the init and last value Template Assertion Predicate at creation. - // Later, when cloning the expressions, they are no longer shared. + // Each node inside a Template Assertion Expression is in between a Template Assertion Predicate and its OpaqueLoop* + // nodes (or an OpaqueLoop* node itself). The OpaqueLoop* nodes do not common up. Therefore, each Template Assertion + // Expression node belongs to a single expression - except for OpaqueLoopInitNodes. An OpaqueLoopInitNode is shared + // between the init and last value Template Assertion Predicate at creation. Later, when cloning the expressions, + // they are no longer shared. assert(template_counter <= 2, "a node cannot be part of more than two templates"); assert(template_counter <= 1 || _node->is_OpaqueLoopInit(), "only OpaqueLoopInit nodes can be part of two templates"); } }; +// This class creates a new Initialized Assertion Predicate. +class InitializedAssertionPredicate : public StackObj { + IfNode* const _template_assertion_predicate; + Node* const _new_init; + Node* const _new_stride; + PhaseIdealLoop* const _phase; + + public: + InitializedAssertionPredicate(IfNode* template_assertion_predicate, Node* new_init, Node* new_stride, + PhaseIdealLoop* phase); + NONCOPYABLE(InitializedAssertionPredicate); + + IfTrueNode* create(Node* control); + + private: + OpaqueInitializedAssertionPredicateNode* create_assertion_expression(Node* control); + IfNode* create_if_node(Node* control, OpaqueInitializedAssertionPredicateNode* assertion_expression, IdealLoopTree* loop); + void create_fail_path(IfNode* if_node, IdealLoopTree* loop); + void create_halt_node(IfFalseNode* fail_proj, IdealLoopTree* loop); + IfTrueNode* create_success_path(IfNode* if_node, IdealLoopTree* loop); +}; + + // This class represents a Predicate Block (i.e. either a Loop Predicate Block, a Profiled Loop Predicate Block, // or a Loop Limit Check Predicate Block). It contains zero or more Regular Predicates followed by a Parse Predicate // which, however, does not need to exist (we could already have decided to remove Parse Predicates for this loop). diff --git a/src/hotspot/share/opto/split_if.cpp b/src/hotspot/share/opto/split_if.cpp index ad4053e2c98c4..1eff44ab7834f 100644 --- a/src/hotspot/share/opto/split_if.cpp +++ b/src/hotspot/share/opto/split_if.cpp @@ -95,7 +95,7 @@ bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) { return true; } - clone_template_assertion_predicate_expression_down(n); + clone_template_assertion_expression_down(n); if (n->Opcode() == Op_OpaqueZeroTripGuard) { // If this Opaque1 is part of the zero trip guard for a loop: @@ -409,25 +409,25 @@ bool PhaseIdealLoop::clone_cmp_down(Node* n, const Node* blk1, const Node* blk2) return false; } -// 'n' could be a node belonging to a Template Assertion Predicate Expression (i.e. any node between a Template -// Assertion Predicate and its OpaqueLoop* nodes (included)). We cannot simply split this node up since this would -// create a phi node inside the Template Assertion Predicate Expression - making it unrecognizable as such. Therefore, -// we completely clone the entire Template Assertion Predicate Expression "down". This ensures that we have an -// untouched copy that is still recognized by the Template Assertion Predicate matching code. -void PhaseIdealLoop::clone_template_assertion_predicate_expression_down(Node* node) { - if (!TemplateAssertionPredicateExpressionNode::is_in_expression(node)) { +// 'n' could be a node belonging to a Template Assertion Expression (i.e. any node between a Template Assertion Predicate +// and its OpaqueLoop* nodes (included)). We cannot simply split this node up since this would create a phi node inside +// the Template Assertion Expression - making it unrecognizable as such. Therefore, we completely clone the entire +// Template Assertion Expression "down". This ensures that we have an untouched copy that is still recognized by the +// Template Assertion Predicate matching code. +void PhaseIdealLoop::clone_template_assertion_expression_down(Node* node) { + if (!TemplateAssertionExpressionNode::is_in_expression(node)) { return; } - TemplateAssertionPredicateExpressionNode template_assertion_predicate_expression_node(node); + TemplateAssertionExpressionNode template_assertion_expression_node(node); auto clone_expression = [&](IfNode* template_assertion_predicate) { Opaque4Node* opaque4_node = template_assertion_predicate->in(1)->as_Opaque4(); - TemplateAssertionPredicateExpression template_assertion_predicate_expression(opaque4_node); + TemplateAssertionExpression template_assertion_expression(opaque4_node); Node* new_ctrl = template_assertion_predicate->in(0); - Opaque4Node* cloned_opaque4_node = template_assertion_predicate_expression.clone(new_ctrl, this); + Opaque4Node* cloned_opaque4_node = template_assertion_expression.clone(new_ctrl, this); igvn().replace_input_of(template_assertion_predicate, 1, cloned_opaque4_node); }; - template_assertion_predicate_expression_node.for_each_template_assertion_predicate(clone_expression); + template_assertion_expression_node.for_each_template_assertion_predicate(clone_expression); } //------------------------------register_new_node------------------------------ From d3e7b0c12afde03985f1b06e6e7d789928971090 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 5 Aug 2024 10:56:21 +0000 Subject: [PATCH 05/77] 8336462: ConcurrentSkipListSet Javadoc incorrectly warns about size method complexity Reviewed-by: jpai --- .../java/util/concurrent/ConcurrentSkipListSet.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java index 3a72c4f4189a4..2a2fbc54d8618 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java @@ -189,14 +189,9 @@ public ConcurrentSkipListSet clone() { * contains more than {@code Integer.MAX_VALUE} elements, it * returns {@code Integer.MAX_VALUE}. * - *

Beware that, unlike in most collections, this method is - * NOT a constant-time operation. Because of the - * asynchronous nature of these sets, determining the current - * number of elements requires traversing them all to count them. - * Additionally, it is possible for the size to change during - * execution of this method, in which case the returned result - * will be inaccurate. Thus, this method is typically not very - * useful in concurrent applications. + *

It is possible for the size to change during execution of this method, + * in which case the returned result will be inaccurate. + * Thus, this method is typically not very useful in concurrent applications. * * @return the number of elements in this set */ From 2e093b06916b72b4feae5635aa8c5aa90679172b Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Mon, 5 Aug 2024 13:17:32 +0000 Subject: [PATCH 06/77] 8337779: test/jdk/jdk/jfr/jvm/TestHiddenWait.java is a bit fragile Reviewed-by: mgronlun --- test/jdk/jdk/jfr/jvm/TestHiddenWait.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/jdk/jdk/jfr/jvm/TestHiddenWait.java b/test/jdk/jdk/jfr/jvm/TestHiddenWait.java index f4b810f192e48..b064285329c0f 100644 --- a/test/jdk/jdk/jfr/jvm/TestHiddenWait.java +++ b/test/jdk/jdk/jfr/jvm/TestHiddenWait.java @@ -77,6 +77,15 @@ public static void main(String... args) throws Exception { s.start(); } List events = Events.fromRecording(r); + // Only keep events from the test thread and the JFR threads + String testThread = Thread.currentThread().getName(); + events.removeIf(event -> { + String threadName = event.getThread().getJavaName(); + if (threadName.equals(testThread) || threadName.contains("JFR")) { + return false; + } + return true; + }); for (RecordedEvent event : events) { if (!event.getEventType().getName().equals(PERIODIC_EVENT_NAME)) { System.out.println(event); From 7e925d727f716e5c366b0d85b9c0de24efe43103 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Mon, 5 Aug 2024 14:05:00 +0000 Subject: [PATCH 07/77] 8337283: configure.log is truncated when build dir is on different filesystem Reviewed-by: phh, stuefe, clanger, ihse --- make/autoconf/configure.ac | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/make/autoconf/configure.ac b/make/autoconf/configure.ac index 6afa36ac18d33..f7e9844a64301 100644 --- a/make/autoconf/configure.ac +++ b/make/autoconf/configure.ac @@ -313,9 +313,11 @@ AC_OUTPUT # After AC_OUTPUT, we need to do final work CUSTOM_CONFIG_OUTPUT_GENERATED_HOOK -BASIC_POST_CONFIG_OUTPUT # Finally output some useful information to the user HELP_PRINT_SUMMARY_AND_WARNINGS CUSTOM_SUMMARY_AND_WARNINGS_HOOK HELP_REPEAT_WARNINGS + +# All output is done. Do the post-config output management. +BASIC_POST_CONFIG_OUTPUT From c095c0e6a58b1665d51ff19381e32f168e99e8f5 Mon Sep 17 00:00:00 2001 From: Carlo Refice Date: Mon, 5 Aug 2024 14:09:54 +0000 Subject: [PATCH 08/77] 8336489: Track scoped accesses in JVMCI compiled code Reviewed-by: dnsimon, never --- .../share/jvmci/jvmciCodeInstaller.cpp | 3 +++ src/hotspot/share/jvmci/jvmciRuntime.cpp | 3 ++- src/hotspot/share/jvmci/jvmciRuntime.hpp | 3 ++- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 1 + .../ci/hotspot/HotSpotCompiledCodeStream.java | 1 + .../vm/ci/hotspot/HotSpotCompiledNmethod.java | 20 ++++++++++++++++++- .../HotSpotResolvedJavaMethodImpl.java | 15 ++++++++++++-- .../jdk/vm/ci/hotspot/HotSpotVMConfig.java | 1 + .../jdk/vm/ci/meta/ResolvedJavaMethod.java | 10 ++++++++++ .../runtime/test/TestResolvedJavaMethod.java | 18 +++++++++++++++++ .../jdk/vm/ci/runtime/test/TypeUniverse.java | 3 ++- 11 files changed, 72 insertions(+), 6 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp index 79bc97f53ac6b..6bca2aa644e55 100644 --- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp +++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp @@ -722,6 +722,7 @@ JVMCI::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, jint entry_bci = -1; JVMCICompileState* compile_state = nullptr; bool has_unsafe_access = false; + bool has_scoped_access = false; jint id = -1; if (is_nmethod) { @@ -729,6 +730,7 @@ JVMCI::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, entry_bci = is_nmethod ? stream->read_s4("entryBCI") : -1; compile_state = (JVMCICompileState*) stream->read_u8("compileState"); has_unsafe_access = stream->read_bool("hasUnsafeAccess"); + has_scoped_access = stream->read_bool("hasScopedAccess"); id = stream->read_s4("id"); } stream->set_code_desc(name, method); @@ -795,6 +797,7 @@ JVMCI::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, id, _has_monitors, has_unsafe_access, + has_scoped_access, _has_wide_vector, compiled_code, mirror, diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index ad0430787aa13..8241fc2498c39 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -2078,6 +2078,7 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV, int compile_id, bool has_monitors, bool has_unsafe_access, + bool has_scoped_access, bool has_wide_vector, JVMCIObject compiled_code, JVMCIObject nmethod_mirror, @@ -2183,7 +2184,7 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV, nm->set_has_unsafe_access(has_unsafe_access); nm->set_has_wide_vectors(has_wide_vector); nm->set_has_monitors(has_monitors); - nm->set_has_scoped_access(true); // conservative + nm->set_has_scoped_access(has_scoped_access); JVMCINMethodData* data = nm->jvmci_nmethod_data(); assert(data != nullptr, "must be"); diff --git a/src/hotspot/share/jvmci/jvmciRuntime.hpp b/src/hotspot/share/jvmci/jvmciRuntime.hpp index bc5bee4edebee..99738393b5b0d 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.hpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, 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 @@ -452,6 +452,7 @@ class JVMCIRuntime: public CHeapObj { int compile_id, bool has_monitors, bool has_unsafe_access, + bool has_scoped_access, bool has_wide_vector, JVMCIObject compiled_code, JVMCIObject nmethod_mirror, diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 1e2ca0e990edb..ac895cc93f2f7 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -655,6 +655,7 @@ declare_constant(ConstMethodFlags::_misc_intrinsic_candidate) \ declare_constant(ConstMethodFlags::_misc_reserved_stack_access) \ declare_constant(ConstMethodFlags::_misc_changes_current_thread) \ + declare_constant(ConstMethodFlags::_misc_is_scoped) \ \ declare_constant(CounterData::count_off) \ \ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java index 87c6ecde07b6e..ab7a57f2759d4 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java @@ -563,6 +563,7 @@ private String codeDesc() { writeInt("entryBCI", nmethod.entryBCI); writeLong("compileState", nmethod.compileState); writeBoolean("hasUnsafeAccess", nmethod.hasUnsafeAccess); + writeBoolean("hasScopedAccess", nmethod.hasScopedAccess()); writeInt("id", nmethod.id); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java index c364af7ad410c..b1be3dee25cd8 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, 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 @@ -100,4 +100,22 @@ public String toString() { public String getInstallationFailureMessage() { return installationFailureMessage; } + + /** + * Determines if {@code methods} contains at least one entry for which {@code HotSpotResolvedJavaMethod.isScoped()} returns true. + */ + public boolean hasScopedAccess() { + if (methods == null) { + return false; + } + for (ResolvedJavaMethod method : methods) { + if (method instanceof HotSpotResolvedJavaMethod hotSpotMethod) { + if (hotSpotMethod.isScoped()) { + return true; + } + } + } + return false; + } + } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 4c9dc509ce1dc..4fbd479602437 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -170,7 +170,7 @@ public int hashCode() { * @return flags of this method */ private int getFlags() { - return UNSAFE.getShort(getMethodPointer() + config().methodFlagsOffset); + return UNSAFE.getInt(getMethodPointer() + config().methodFlagsOffset); } /** @@ -179,7 +179,7 @@ private int getFlags() { * @return flags of this method's ConstMethod */ private int getConstMethodFlags() { - return UNSAFE.getChar(getConstMethod() + config().constMethodFlagsOffset); + return UNSAFE.getInt(getConstMethod() + config().constMethodFlagsOffset); } @Override @@ -324,6 +324,17 @@ public boolean hasReservedStackAccess() { return (getConstMethodFlags() & config().constMethodFlagsReservedStackAccess) != 0; } + /** + * Returns true if this method has a + * {@code jdk.internal.misc.ScopedMemoryAccess.Scoped} annotation. + * + * @return true if Scoped annotation present, false otherwise + */ + @Override + public boolean isScoped() { + return (getConstMethodFlags() & config().constMethodFlagsIsScoped) != 0; + } + /** * Sets flags on {@code method} indicating that it should never be inlined or compiled by the * VM. diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java index 57f9473c90209..954e1f6b20173 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -194,6 +194,7 @@ long prototypeMarkWord() { final int constMethodFlagsReservedStackAccess = getConstant("ConstMethodFlags::_misc_reserved_stack_access", Integer.class); final int constMethodFlagsCallerSensitive = getConstant("ConstMethodFlags::_misc_caller_sensitive", Integer.class); final int constMethodFlagsIntrinsicCandidate = getConstant("ConstMethodFlags::_misc_intrinsic_candidate", Integer.class); + final int constMethodFlagsIsScoped = getConstant("ConstMethodFlags::_misc_is_scoped", Integer.class); final int constMethodHasLineNumberTable = getConstant("ConstMethodFlags::_misc_has_linenumber_table", Integer.class); final int constMethodHasLocalVariableTable = getConstant("ConstMethodFlags::_misc_has_localvariable_table", Integer.class); final int constMethodHasMethodAnnotations = getConstant("ConstMethodFlags::_misc_has_method_annotations", Integer.class); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java index 41eccc9d1c65d..fa42dc26ac8da 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java @@ -463,6 +463,16 @@ default boolean isJavaLangObjectInit() { return getDeclaringClass().isJavaLangObject() && getName().equals(""); } + /** + * Returns true if this method has a + * {@code jdk.internal.misc.ScopedMemoryAccess.Scoped} annotation. + * + * @return true if Scoped annotation present, false otherwise. + */ + default boolean isScoped() { + throw new UnsupportedOperationException(); + } + /** * Gets a speculation log that can be used when compiling this method to make new speculations * and query previously failed speculations. The implementation may return a new diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java index 00973fd78c29d..98d7d168ba718 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java @@ -475,6 +475,24 @@ public void isJavaLangObjectInitTest() throws NoSuchMethodException { } } + @Test + public void isScopedTest() throws NoSuchMethodException, ClassNotFoundException { + // Must use reflection as ScopedMemoryAccess$Scoped is package-private + Class scopedAnnotationClass = Class.forName("jdk.internal.misc.ScopedMemoryAccess$Scoped").asSubclass(Annotation.class); + boolean scopedMethodFound = false; + for (Map.Entry e : methods.entrySet()) { + ResolvedJavaMethod m = e.getValue(); + Method key = e.getKey(); + boolean expect = key.isAnnotationPresent(scopedAnnotationClass); + boolean actual = m.isScoped(); + assertEquals(m.toString(), expect, actual); + if (expect) { + scopedMethodFound = true; + } + } + assertTrue("At least one scoped method must be present", scopedMethodFound); + } + abstract static class UnlinkedType { abstract void abstractMethod(); diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TypeUniverse.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TypeUniverse.java index 2420a133b63f9..13003095ee6a2 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TypeUniverse.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TypeUniverse.java @@ -51,6 +51,7 @@ import org.junit.Test; import jdk.internal.misc.Unsafe; +import jdk.internal.misc.ScopedMemoryAccess; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.MetaAccessProvider; @@ -115,7 +116,7 @@ protected class ProtectedInnerClass { byte[][].class, short[][].class, char[][].class, int[][].class, float[][].class, long[][].class, double[][].class, Object[][].class, Class[][].class, List[][].class, ClassLoader.class, String.class, Serializable.class, Cloneable.class, Test.class, TestMetaAccessProvider.class, List.class, Collection.class, Map.class, Queue.class, HashMap.class, LinkedHashMap.class, IdentityHashMap.class, AbstractCollection.class, AbstractList.class, ArrayList.class, InnerClass.class, InnerStaticClass.class, - InnerStaticFinalClass.class, PrivateInnerClass.class, ProtectedInnerClass.class}; + InnerStaticFinalClass.class, PrivateInnerClass.class, ProtectedInnerClass.class, ScopedMemoryAccess.class}; for (Class c : initialClasses) { addClass(c); } From 97afbd9603ba8ec1956c4cedf542667d33988661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Sj=C3=B6len?= Date: Mon, 5 Aug 2024 14:49:38 +0000 Subject: [PATCH 09/77] 8336410: runtime/NMT/TotalMallocMmapDiffTest.java Total malloc diff is incorrect. Expected malloc diff range Reviewed-by: gziemski, stuefe --- .../jtreg/runtime/NMT/TotalMallocMmapDiffTest.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/hotspot/jtreg/runtime/NMT/TotalMallocMmapDiffTest.java b/test/hotspot/jtreg/runtime/NMT/TotalMallocMmapDiffTest.java index 3ba94c6a31a86..cd89bded57827 100644 --- a/test/hotspot/jtreg/runtime/NMT/TotalMallocMmapDiffTest.java +++ b/test/hotspot/jtreg/runtime/NMT/TotalMallocMmapDiffTest.java @@ -32,7 +32,7 @@ * java.management * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=summary -Xms32m -Xmx32m TotalMallocMmapDiffTest + * @run main/othervm -Xbootclasspath/a:. -XX:TieredStopAtLevel=1 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=summary -Xms32m -Xmx32m TotalMallocMmapDiffTest * */ @@ -43,9 +43,10 @@ public class TotalMallocMmapDiffTest { private static final WhiteBox wb = WhiteBox.getWhiteBox(); private static final long ALLOCATE_SIZE = 250 * 1024 * 1024; // 250MB - private static final double FUDGE_FACTOR = 0.2; - private static final double UPPER_BOUND = ALLOCATE_SIZE * (1 + FUDGE_FACTOR); - private static final double LOWER_BOUND = ALLOCATE_SIZE * (1 - FUDGE_FACTOR); + private static final double FUDGE_FACTOR_UPPER = 0.3; + private static final double FUDGE_FACTOR_LOWER = 0.2; + private static final double UPPER_BOUND = ALLOCATE_SIZE * (1 + FUDGE_FACTOR_UPPER); + private static final double LOWER_BOUND = ALLOCATE_SIZE * (1 - FUDGE_FACTOR_LOWER); public static void main(String[] args) throws Exception { From 219e1eb13a688532705e603e276799c0157f5f28 Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Mon, 5 Aug 2024 15:06:38 +0000 Subject: [PATCH 10/77] 8337712: Wrong javadoc in java.util.Date#toString(): "61" and right parenthesis Reviewed-by: rgiulietti --- src/java.base/share/classes/java/util/Date.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/util/Date.java b/src/java.base/share/classes/java/util/Date.java index 1850564d8b290..aa16f2a75ee60 100644 --- a/src/java.base/share/classes/java/util/Date.java +++ b/src/java.base/share/classes/java/util/Date.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2024, 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 @@ -1012,7 +1012,7 @@ public int hashCode() { *

  • {@code mm} is the minute within the hour ({@code 00} through * {@code 59}), as two decimal digits. *
  • {@code ss} is the second within the minute ({@code 00} through - * {@code 61}, as two decimal digits. + * {@code 61}), as two decimal digits. *
  • {@code zzz} is the time zone (and may reflect daylight saving * time). Standard time zone abbreviations include those * recognized by the method {@code parse}. If time zone From 98562166e4a4c8921709014423c6cbc993aa0d97 Mon Sep 17 00:00:00 2001 From: Zdenek Zambersky Date: Mon, 5 Aug 2024 15:09:45 +0000 Subject: [PATCH 11/77] 8336928: GHA: Bundle artifacts removal broken Reviewed-by: ihse --- .github/workflows/main.yml | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 067548b9768e3..b16335b7091c2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -363,26 +363,23 @@ jobs: - test-windows-x64 steps: - # Hack to get hold of the api environment variables that are only defined for actions - - name: 'Get API configuration' - id: api - uses: actions/github-script@v7 - with: - script: 'return { url: process.env["ACTIONS_RUNTIME_URL"], token: process.env["ACTIONS_RUNTIME_TOKEN"] }' - - name: 'Remove bundle artifacts' run: | # Find and remove all bundle artifacts - ALL_ARTIFACT_URLS="$(curl -s \ - -H 'Accept: application/json;api-version=6.0-preview' \ - -H 'Authorization: Bearer ${{ fromJson(steps.api.outputs.result).token }}' \ - '${{ fromJson(steps.api.outputs.result).url }}_apis/pipelines/workflows/${{ github.run_id }}/artifacts?api-version=6.0-preview')" - BUNDLE_ARTIFACT_URLS="$(echo "$ALL_ARTIFACT_URLS" | jq -r -c '.value | map(select(.name|startswith("bundles-"))) | .[].url')" - for url in $BUNDLE_ARTIFACT_URLS; do - echo "Removing $url" - curl -s \ - -H 'Accept: application/json;api-version=6.0-preview' \ - -H 'Authorization: Bearer ${{ fromJson(steps.api.outputs.result).token }}' \ - -X DELETE "$url" \ + # See: https://docs.github.com/en/rest/actions/artifacts?apiVersion=2022-11-28 + ALL_ARTIFACT_IDS="$(curl -sL \ + -H 'Accept: application/vnd.github+json' \ + -H 'Authorization: Bearer ${{ github.token }}' \ + -H 'X-GitHub-Api-Version: 2022-11-28' \ + '${{ github.api_url }}/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts')" + BUNDLE_ARTIFACT_IDS="$(echo "$ALL_ARTIFACT_IDS" | jq -r -c '.artifacts | map(select(.name|startswith("bundles-"))) | .[].id')" + for id in $BUNDLE_ARTIFACT_IDS; do + echo "Removing $id" + curl -sL \ + -X DELETE \ + -H 'Accept: application/vnd.github+json' \ + -H 'Authorization: Bearer ${{ github.token }}' \ + -H 'X-GitHub-Api-Version: 2022-11-28' \ + "${{ github.api_url }}/repos/${{ github.repository }}/actions/artifacts/$id" \ || echo "Failed to remove bundle" done From e68df528f80cff3a5564a12b7ec71a920800ce28 Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Mon, 5 Aug 2024 16:48:18 +0000 Subject: [PATCH 12/77] 8337054: JDK 23 RDP2 L10n resource files update Reviewed-by: naoto, jlu --- .../tools/javac/resources/compiler_de.properties | 9 +++++---- .../tools/javac/resources/compiler_ja.properties | 9 +++++---- .../javac/resources/compiler_zh_CN.properties | 15 ++++++++------- .../javac/resources/launcher_zh_CN.properties | 2 +- .../toolkit/resources/doclets_de.properties | 4 ++-- .../toolkit/resources/doclets_ja.properties | 4 ++-- .../toolkit/resources/doclets_zh_CN.properties | 4 ++-- 7 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties index dfbeb0fd0b715..33063b6558d3a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties @@ -2305,13 +2305,14 @@ compiler.err.this.as.identifier=Ab Release 8 ist "this" nur als Parametername f compiler.err.receiver.parameter.not.applicable.constructor.toplevel.class=receiver-Parameter nicht für Konstruktor der obersten Klasse anwendbar -# TODO 308: make a better error message +# 0: fragment, 1: symbol, 2: annotated-type +compiler.err.type.annotation.inadmissible={0} wurde hier nicht erwartet\n(Um einen qualifizierten Typ zu annotieren, schreiben Sie {1}.{2}) + # 0: annotation -compiler.err.cant.type.annotate.scoping.1=Scoping-Konstrukt kann nicht mit type-use-Annotation versehen werden: {0} +compiler.misc.type.annotation.1=Typannotation {0} ist -# TODO 308: make a better error message # 0: list of annotation -compiler.err.cant.type.annotate.scoping=Scoping-Konstrukt kann nicht mit type-use-Annotationen versehen werden: {0} +compiler.misc.type.annotation=Typannotationen {0} sind # 0: type, 1: type compiler.err.incorrect.receiver.name=Der Empfängername stimmt nicht mit dem einschließenden Klassentyp überein\nErforderlich: {0}\nErmittelt: {1} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties index 4d98e4cabccba..818b5fb70668b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties @@ -2305,13 +2305,14 @@ compiler.err.this.as.identifier=リリース8から''this''は受信タイプの compiler.err.receiver.parameter.not.applicable.constructor.toplevel.class=受取り側パラメータは最上位レベル・クラスのコンストラクタに適用できません -# TODO 308: make a better error message +# 0: fragment, 1: symbol, 2: annotated-type +compiler.err.type.annotation.inadmissible=ここでは{0}は予期されていません\n(修飾されたタイプに注釈を付けるには、{1}.{2}と記述します) + # 0: annotation -compiler.err.cant.type.annotate.scoping.1=スコープ・コンストラクトを型使用注釈で注釈付けすることはできません: {0} +compiler.misc.type.annotation.1=タイプ注釈{0}は -# TODO 308: make a better error message # 0: list of annotation -compiler.err.cant.type.annotate.scoping=スコープ・コンストラクトを型使用注釈で注釈付けすることはできません: {0} +compiler.misc.type.annotation=タイプ注釈{0}は # 0: type, 1: type compiler.err.incorrect.receiver.name=受取り側の名前が、包含するクラス・タイプと一致しません\n必須: {0}\n検出: {1} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties index 81452f23a0d55..54298cb23b912 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties @@ -93,7 +93,7 @@ compiler.err.abstract.cant.be.instantiated={0}是抽象的; 无法实例化 compiler.err.abstract.meth.cant.have.body=抽象方法不能有主体 # 0: kind name, 1: symbol -compiler.err.already.annotated={0} {1}已进行注释 +compiler.err.already.annotated={0} {1} 已进行批注 # 0: kind name, 1: symbol, 2: kind name, 3: symbol compiler.err.already.defined=已在{2} {3}中定义了{0} {1} @@ -642,7 +642,7 @@ compiler.err.malformed.fp.lit=浮点文字的格式错误 compiler.err.method.does.not.override.superclass=方法不会覆盖或实现超类型的方法 -compiler.err.static.methods.cannot.be.annotated.with.override=不能使用 @Override 注释静态方法 +compiler.err.static.methods.cannot.be.annotated.with.override=不能使用 @Override 对静态方法进行批注 compiler.err.missing.meth.body.or.decl.abstract=缺少方法主体, 或声明抽象 @@ -1638,7 +1638,7 @@ compiler.warn.unchecked.varargs.non.reifiable.type=参数化 vararg 类型{0}的 # 0: symbol compiler.warn.varargs.unsafe.use.varargs.param=Varargs 方法可能导致来自不可具体化 varargs 参数 {0} 的堆污染 -compiler.warn.missing.deprecated.annotation=未使用 @Deprecated 对已过时的项目进行注释 +compiler.warn.missing.deprecated.annotation=未使用 @Deprecated 对已过时的项目进行批注 # 0: kind name compiler.warn.deprecated.annotation.has.no.effect=@Deprecated 批注对此 {0} 声明没有任何效果 @@ -2305,13 +2305,14 @@ compiler.err.this.as.identifier=从发行版 8 开始,''this'' 只能作为接 compiler.err.receiver.parameter.not.applicable.constructor.toplevel.class=接收方参数不适用于顶层类的构造器 -# TODO 308: make a better error message +# 0: fragment, 1: symbol, 2: annotated-type +compiler.err.type.annotation.inadmissible={0} 不应出现在此处\n(要对限定类型进行批注,请编写 {1}.{2}) + # 0: annotation -compiler.err.cant.type.annotate.scoping.1=无法使用 type-use 批注 {0} 来批注确定作用域结构 +compiler.misc.type.annotation.1=类型批注 {0} 为 -# TODO 308: make a better error message # 0: list of annotation -compiler.err.cant.type.annotate.scoping=无法使用 type-use 批注 {0} 来批注确定作用域结构 +compiler.misc.type.annotation=类型批注 {0} 为 # 0: type, 1: type compiler.err.incorrect.receiver.name=接收方名称与封闭类类型不匹配\n需要: {0}\n找到: {1} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_zh_CN.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_zh_CN.properties index ee666cc02c11d..9382ac9e348e4 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_zh_CN.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_zh_CN.properties @@ -120,7 +120,7 @@ launcher.err.cant.read.file=读取源文件 {0} 时出错:{1} launcher.err.no.value.for.option=没有为选项 {0} 指定值 # 0: string -launcher.err.invalid.value.for.source=--source 选项的值无效:{0}\n +launcher.err.invalid.value.for.source=--source 选项的值无效:{0} launcher.err.unnamed.pkg.not.allowed.named.modules=命名模块中不允许未命名程序包 diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_de.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_de.properties index 4e84cdc52c77f..7ab2d3fc1dcaf 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_de.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_de.properties @@ -278,9 +278,9 @@ doclet.record_constructor_doc.param_name=Wert für die Datensatzkomponente {0} doclet.record_equals_doc.fullbody.head=Gibt an, ob ein anderes Objekt diesem gleich ("equal to") ist. Die Objekte sind gleich, wenn das andere Objekt der gleichen Klasse angehört und alle Datensatzkomponenten gleich sind. -doclet.record_equals_doc.fullbody.tail.both=Referenzkomponenten werden verglichen mit {@link java.util.Objects#equals(Object,Object) Objects::equals(Object,Object)}; primitive Komponenten werden verglichen mit "==". +doclet.record_equals_doc.fullbody.tail.both=Referenzkomponenten werden verglichen mit {@link java.util.Objects#equals(Object,Object) Objects::equals(Object,Object)}. Primitive Komponenten werden mit der compare-Methode aus den entsprechenden Wrapper-Klassen verglichen. -doclet.record_equals_doc.fullbody.tail.primitive=Alle Komponenten in dieser Datensatzklasse werden verglichen mit "==". +doclet.record_equals_doc.fullbody.tail.primitive=Alle Komponenten dieser Datensatzklasse werden mit der compare-Methode aus den entsprechenden Wrapper-Klassen verglichen. doclet.record_equals_doc.fullbody.tail.reference=Alle Komponenten in dieser Datensatzklasse werden verglichen mit {@link java.util.Objects#equals(Object,Object) Objects::equals(Object,Object)}. diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties index 515df706272d8..1b00ea9fbc02c 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties @@ -278,9 +278,9 @@ doclet.record_constructor_doc.param_name={0}レコード・コンポーネント doclet.record_equals_doc.fullbody.head=他のオブジェクトがこれと"等しい"かどうかを示します。他のオブジェクトが同じクラスであり、すべてのレコード・コンポーネントが等しい場合、オブジェクトは等しくなります。 -doclet.record_equals_doc.fullbody.tail.both=参照コンポーネントは{@link java.util.Objects#equals(Object,Object) Objects::equals(Object,Object)}と比較され、プリミティブ・コンポーネントは'=='と比較されます。 +doclet.record_equals_doc.fullbody.tail.both=参照コンポーネントは{@link java.util.Objects#equals(Object,Object) Objects::equals(Object,Object)}と比較され、プリミティブ・コンポーネントは対応するラッパー・クラスのcompareメソッドで比較されます。 -doclet.record_equals_doc.fullbody.tail.primitive=このレコード・クラスのすべてのコンポーネントは'=='と比較されます。 +doclet.record_equals_doc.fullbody.tail.primitive=このレコード・クラスのすべてのコンポーネントは対応するラッパー・クラスのcompareメソッドで比較されます。 doclet.record_equals_doc.fullbody.tail.reference=このレコード・クラスのすべてのコンポーネントは{@link java.util.Objects#equals(Object,Object) Objects::equals(Object,Object)}と比較されます。 diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties index d01d42faa56a4..e9786173c5f1d 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties @@ -278,9 +278,9 @@ doclet.record_constructor_doc.param_name={0} 记录组件的值 doclet.record_equals_doc.fullbody.head=指示某个其他对象是否“等于”此对象。如果两个对象属于同一个类,而且所有记录组件都相等,则这两个对象相等。 -doclet.record_equals_doc.fullbody.tail.both=使用 {@link java.util.Objects#equals(Object,Object) Objects::equals(Object,Object)} 对参考组件进行比较;使用 '==' 对基元组件进行比较 +doclet.record_equals_doc.fullbody.tail.both=使用 {@link java.util.Objects#equals(Object,Object) Objects::equals(Object,Object)} 对参考组件进行比较;使用 compare 方法从对应的包装类对基元组件进行比较。 -doclet.record_equals_doc.fullbody.tail.primitive=此记录类中的所有组件都使用 '==' 进行比较。 +doclet.record_equals_doc.fullbody.tail.primitive=此记录类中的所有组件都使用 compare 方法从对应的包装类进行比较。 doclet.record_equals_doc.fullbody.tail.reference=此记录类中的所有组件都使用 {@link java.util.Objects#equals(Object,Object) Objects::equals(Object,Object)} 进行比较。 From 807186ffc6a0a9f2515a66329c2a98a43385463c Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Mon, 5 Aug 2024 16:53:30 +0000 Subject: [PATCH 13/77] 8337784: Fix simple -Wzero-as-null-pointer-constant warnings in linux/posix code Reviewed-by: stefank, shade --- src/hotspot/os/linux/os_linux.cpp | 4 ++-- src/hotspot/os/posix/perfMemory_posix.cpp | 4 ++-- src/hotspot/os/posix/signals_posix.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 1c735f1b3c9d8..d4699567733b2 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -864,7 +864,7 @@ static void *thread_native_entry(Thread *thread) { log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", os::current_thread_id(), (uintx) pthread_self()); - return 0; + return nullptr; } // On Linux, glibc places static TLS blocks (for __thread variables) on @@ -4449,7 +4449,7 @@ void os::init(void) { check_pax(); // Check the availability of MADV_POPULATE_WRITE. - FLAG_SET_DEFAULT(UseMadvPopulateWrite, (::madvise(0, 0, MADV_POPULATE_WRITE) == 0)); + FLAG_SET_DEFAULT(UseMadvPopulateWrite, (::madvise(nullptr, 0, MADV_POPULATE_WRITE) == 0)); os::Posix::init(); } diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp index 4339a21ae4e92..56bc8a1ef6b81 100644 --- a/src/hotspot/os/posix/perfMemory_posix.cpp +++ b/src/hotspot/os/posix/perfMemory_posix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2021 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1329,7 +1329,7 @@ void PerfMemory::attach(int vmid, char** addrp, size_t* sizep, TRAPS) { // void PerfMemory::detach(char* addr, size_t bytes) { - assert(addr != 0, "address sanity check"); + assert(addr != nullptr, "address sanity check"); assert(bytes > 0, "capacity sanity check"); if (PerfMemory::contains(addr) || PerfMemory::contains(addr + bytes - 1)) { diff --git a/src/hotspot/os/posix/signals_posix.cpp b/src/hotspot/os/posix/signals_posix.cpp index a9d3bb9284c49..6a14d0a485643 100644 --- a/src/hotspot/os/posix/signals_posix.cpp +++ b/src/hotspot/os/posix/signals_posix.cpp @@ -1719,7 +1719,7 @@ static int SR_initialize() { struct sigaction act; char *s; // Get signal number to use for suspend/resume - if ((s = ::getenv("_JAVA_SR_SIGNUM")) != 0) { + if ((s = ::getenv("_JAVA_SR_SIGNUM")) != nullptr) { int sig; bool result = parse_integer(s, &sig); if (result && sig > MAX2(SIGSEGV, SIGBUS) && // See 4355769. @@ -1742,7 +1742,7 @@ static int SR_initialize() { pthread_sigmask(SIG_BLOCK, nullptr, &act.sa_mask); remove_error_signals_from_set(&(act.sa_mask)); - if (sigaction(PosixSignals::SR_signum, &act, 0) == -1) { + if (sigaction(PosixSignals::SR_signum, &act, nullptr) == -1) { return -1; } From 42652b2e5350bcab6fceb0148be8bf3d65a0e173 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Mon, 5 Aug 2024 16:57:11 +0000 Subject: [PATCH 14/77] 8337787: Fix -Wzero-as-null-pointer-constant warnings when JVMTI feature is disabled Reviewed-by: ayang, sspitsyn --- src/hotspot/share/prims/jvmtiExport.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/prims/jvmtiExport.hpp b/src/hotspot/share/prims/jvmtiExport.hpp index 36df28f271677..e98020aef1d3b 100644 --- a/src/hotspot/share/prims/jvmtiExport.hpp +++ b/src/hotspot/share/prims/jvmtiExport.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -287,10 +287,10 @@ class JvmtiExport : public AllStatic { } // field access management - static address get_field_access_count_addr() NOT_JVMTI_RETURN_(0); + static address get_field_access_count_addr() NOT_JVMTI_RETURN_(nullptr); // field modification management - static address get_field_modification_count_addr() NOT_JVMTI_RETURN_(0); + static address get_field_modification_count_addr() NOT_JVMTI_RETURN_(nullptr); // ----------------- From 08f697f4fcbcdd912c3aa5f331fbf8212906465f Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Mon, 5 Aug 2024 17:58:12 +0000 Subject: [PATCH 15/77] 8337819: Update GHA JDKs to 22.0.2 Reviewed-by: mbaesken, ihse, shade --- make/conf/github-actions.conf | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/make/conf/github-actions.conf b/make/conf/github-actions.conf index deb5e36f60572..3cb56b47b50b8 100644 --- a/make/conf/github-actions.conf +++ b/make/conf/github-actions.conf @@ -29,17 +29,17 @@ GTEST_VERSION=1.14.0 JTREG_VERSION=7.4+1 LINUX_X64_BOOT_JDK_EXT=tar.gz -LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk22/830ec9fcccef480bb3e73fb7ecafe059/36/GPL/openjdk-22_linux-x64_bin.tar.gz -LINUX_X64_BOOT_JDK_SHA256=4d65cc6ed28711768fd72c2043a7925f7c83f5f51bb64970bd9d52f7791fc6ac - -MACOS_X64_BOOT_JDK_EXT=tar.gz -MACOS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk22/830ec9fcccef480bb3e73fb7ecafe059/36/GPL/openjdk-22_macos-x64_bin.tar.gz -MACOS_X64_BOOT_JDK_SHA256=ae31fe10916429e3fe284266095067a5ce9fecbdc03ff1a079d20459f731ca36 +LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk22.0.2/c9ecb94cd31b495da20a27d4581645e8/9/GPL/openjdk-22.0.2_linux-x64_bin.tar.gz +LINUX_X64_BOOT_JDK_SHA256=41536f115668308ecf4eba92aaf6acaeb0936225828b741efd83b6173ba82963 MACOS_AARCH64_BOOT_JDK_EXT=tar.gz -MACOS_AARCH64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk22/830ec9fcccef480bb3e73fb7ecafe059/36/GPL/openjdk-22_macos-aarch64_bin.tar.gz -MACOS_AARCH64_BOOT_JDK_SHA256=d10f82429d01047968c52c7975c326388cb5d212791e14c1de21c987463a4b53 +MACOS_AARCH64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk22.0.2/c9ecb94cd31b495da20a27d4581645e8/9/GPL/openjdk-22.0.2_macos-aarch64_bin.tar.gz +MACOS_AARCH64_BOOT_JDK_SHA256=3dab98730234e1a87aec14bcb8171d2cae101e96ff4eed1dab96abbb08e843fd + +MACOS_X64_BOOT_JDK_EXT=tar.gz +MACOS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk22.0.2/c9ecb94cd31b495da20a27d4581645e8/9/GPL/openjdk-22.0.2_macos-x64_bin.tar.gz +MACOS_X64_BOOT_JDK_SHA256=e8b3ec7a7077711223d31156e771f11723cd7af31c2017f1bd2eda20855940fb WINDOWS_X64_BOOT_JDK_EXT=zip -WINDOWS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk22/830ec9fcccef480bb3e73fb7ecafe059/36/GPL/openjdk-22_windows-x64_bin.zip -WINDOWS_X64_BOOT_JDK_SHA256=8f5138fecb53c08c20abd4fa6812f9400051f3852582a2142ffda0dff73a5824 +WINDOWS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk22.0.2/c9ecb94cd31b495da20a27d4581645e8/9/GPL/openjdk-22.0.2_windows-x64_bin.zip +WINDOWS_X64_BOOT_JDK_SHA256=f2a9b9ab944e71a64637fcdc6b13a1188cf02d4eb9ecf71dc927e98b3e45f5dc From e2c07d5044587476fc0fff14260e2b73816d2062 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Mon, 5 Aug 2024 18:42:27 +0000 Subject: [PATCH 16/77] 8337299: vmTestbase/nsk/jdb/stop_at/stop_at002/stop_at002.java failure goes undetected Reviewed-by: amenkov, sspitsyn --- .../jdb/stop_at/stop_at002/stop_at002.java | 64 ++++++++++++++----- .../jdb/stop_at/stop_at002/stop_at002a.java | 8 ++- 2 files changed, 52 insertions(+), 20 deletions(-) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at002/stop_at002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at002/stop_at002.java index 620c50fa2ae22..9dae8c17cfc36 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at002/stop_at002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at002/stop_at002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 @@ -82,17 +82,10 @@ public static int run(String argv[], PrintStream out) { static final String DEBUGGEE_CLASS = TEST_CLASS + "a"; static final String FIRST_BREAK = DEBUGGEE_CLASS + ".main"; static final String LAST_BREAK = DEBUGGEE_CLASS + ".lastBreak"; - static final String DEBUGGEE_LOCATION1 = DEBUGGEE_CLASS + "$Nested$DeeperNested$DeepestNested:43"; - static final String DEBUGGEE_LOCATION2 = DEBUGGEE_CLASS + "$Inner$MoreInner:57"; - static final String FAILURE_PATTERN = "Unable to set"; + static final String DEBUGGEE_LOCATION1 = DEBUGGEE_CLASS + "$Nested$DeeperNested$DeepestNested:64"; + static final String DEBUGGEE_LOCATION2 = DEBUGGEE_CLASS + "$Inner$MoreInner:78"; protected void runCases() { - String[] reply; - Paragrep grep; - int count; - Vector v; - String found; - if (!checkStop(DEBUGGEE_LOCATION1)) { success = false; } @@ -101,25 +94,62 @@ protected void runCases() { success = false; } - jdb.contToExit(3); + if (!checkBreakpointHit(DEBUGGEE_LOCATION1)) { + success = false; + } + + if (!checkBreakpointHit(DEBUGGEE_LOCATION2)) { + success = false; + } + + jdb.contToExit(1); } - private boolean checkStop (String location) { + private boolean checkStop(String location) { Paragrep grep; String[] reply; String found; - boolean result = true; log.display("Trying to set breakpoint at line: " + location); reply = jdb.receiveReplyFor(JdbCommand.stop_at + location); grep = new Paragrep(reply); - found = grep.findFirst(FAILURE_PATTERN); + found = grep.findFirst("Deferring breakpoint " + location); + if (found.length() == 0) { + log.complain("jdb failed to setup deferred breakpoint at line: " + location); + return false; + } + + return true; + } + + private boolean checkBreakpointHit(String location) { + Paragrep grep; + String[] reply; + String found; + + log.display("continuing to breakpoint at line: " + location); + reply = jdb.receiveReplyFor(JdbCommand.cont); + grep = new Paragrep(reply); + + found = grep.findFirst("Unable to set deferred breakpoint"); if (found.length() > 0) { - log.complain("jdb failed to set line breakpoint at line: " + found); - result = false; + log.complain("jdb failed to set deferred breakpoint at line: " + location); + return false; + } + + found = grep.findFirst("Set deferred breakpoint " + location); + if (found.length() == 0) { + log.complain("jdb failed to set deferred breakpoint at line: " + location); + return false; + } + + found = grep.findFirst("Breakpoint hit: \"thread=main\", "); + if (found.length() == 0) { + log.complain("jdb failed to hit breakpoint at line: " + location); + return false; } - return result; + return true; } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at002/stop_at002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at002/stop_at002a.java index 9195dd2698612..d4a40689372d4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at002/stop_at002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at002/stop_at002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 @@ -21,6 +21,8 @@ * questions. */ +// THIS TEST IS LINE NUMBER SENSITIVE + package nsk.jdb.stop_at.stop_at002; import nsk.share.*; @@ -59,7 +61,7 @@ class Nested { class DeeperNested { class DeepestNested { public void foo(boolean input) { - flag = input; /* <-------- This is line number 43 */ + flag = input; /* <-------- This is line number 64 */ } } } @@ -73,7 +75,7 @@ public MoreInner() { content = ""; } public void foo(String input) { - content += input; /* <-------- This is line number 57 */ + content += input; /* <-------- This is line number 78 */ } } } From 431d4f7e18369466eedd00926a5162a1461d0b25 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Mon, 5 Aug 2024 19:53:49 +0000 Subject: [PATCH 17/77] 8337785: Fix simple -Wzero-as-null-pointer-constant warnings in x86 code Reviewed-by: jwaters, ayang, shade --- src/hotspot/cpu/x86/frame_x86.cpp | 6 +++--- src/hotspot/cpu/x86/macroAssembler_x86_sha.cpp | 6 +++--- src/hotspot/cpu/x86/methodHandles_x86.cpp | 4 ++-- src/hotspot/cpu/x86/vm_version_x86.cpp | 8 ++++---- src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/hotspot/cpu/x86/frame_x86.cpp b/src/hotspot/cpu/x86/frame_x86.cpp index 2366d31992d6e..aeb77763e7fff 100644 --- a/src/hotspot/cpu/x86/frame_x86.cpp +++ b/src/hotspot/cpu/x86/frame_x86.cpp @@ -279,7 +279,7 @@ void frame::patch_pc(Thread* thread, address pc) { assert(!Continuation::is_return_barrier_entry(*pc_addr), "return barrier"); - assert(_pc == *pc_addr || pc == *pc_addr || *pc_addr == 0, ""); + assert(_pc == *pc_addr || pc == *pc_addr || *pc_addr == nullptr, ""); DEBUG_ONLY(address old_pc = _pc;) *pc_addr = pc; _pc = pc; // must be set before call to get_deopt_original_pc @@ -483,10 +483,10 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const { bool frame::is_interpreted_frame_valid(JavaThread* thread) const { assert(is_interpreted_frame(), "Not an interpreted frame"); // These are reasonable sanity checks - if (fp() == 0 || (intptr_t(fp()) & (wordSize-1)) != 0) { + if (fp() == nullptr || (intptr_t(fp()) & (wordSize-1)) != 0) { return false; } - if (sp() == 0 || (intptr_t(sp()) & (wordSize-1)) != 0) { + if (sp() == nullptr || (intptr_t(sp()) & (wordSize-1)) != 0) { return false; } if (fp() + interpreter_frame_initial_sp_offset < sp()) { diff --git a/src/hotspot/cpu/x86/macroAssembler_x86_sha.cpp b/src/hotspot/cpu/x86/macroAssembler_x86_sha.cpp index c4e9e836fd312..090de71425f17 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86_sha.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86_sha.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016, 2021, Intel Corporation. All rights reserved. +* Copyright (c) 2016, 2024, Intel Corporation. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -689,7 +689,7 @@ void MacroAssembler::sha256_AVX2(XMMRegister msg, XMMRegister state0, XMMRegiste address K256_W = StubRoutines::x86::k256_W_addr(); address pshuffle_byte_flip_mask = StubRoutines::x86::pshuffle_byte_flip_mask_addr(); - address pshuffle_byte_flip_mask_addr = 0; + address pshuffle_byte_flip_mask_addr = nullptr; const XMMRegister& SHUF_00BA = xmm10; // ymm10: shuffle xBxA -> 00BA const XMMRegister& SHUF_DC00 = xmm12; // ymm12: shuffle xDxC -> DC00 @@ -1247,7 +1247,7 @@ void MacroAssembler::sha512_AVX2(XMMRegister msg, XMMRegister state0, XMMRegiste address K512_W = StubRoutines::x86::k512_W_addr(); address pshuffle_byte_flip_mask_sha512 = StubRoutines::x86::pshuffle_byte_flip_mask_addr_sha512(); - address pshuffle_byte_flip_mask_addr = 0; + address pshuffle_byte_flip_mask_addr = nullptr; const XMMRegister& XFER = xmm0; // YTMP0 const XMMRegister& BYTE_FLIP_MASK = xmm9; // ymm9 diff --git a/src/hotspot/cpu/x86/methodHandles_x86.cpp b/src/hotspot/cpu/x86/methodHandles_x86.cpp index de897d71facef..3a8c104876677 100644 --- a/src/hotspot/cpu/x86/methodHandles_x86.cpp +++ b/src/hotspot/cpu/x86/methodHandles_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -572,7 +572,7 @@ void trace_method_handle_stub(const char* adaptername, frame cur_frame = os::current_frame(); - if (cur_frame.fp() != 0) { // not walkable + if (cur_frame.fp() != nullptr) { // not walkable // Robust search of trace_calling_frame (independent of inlining). // Assumes saved_regs comes from a pusha in the trace_calling_frame. diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 02e147743cb1d..6216cf44b887a 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -53,13 +53,13 @@ const char* VM_Version::_features_names[] = { CPU_FEATURE_FLAGS(DECLARE_CPU_FEAT #undef DECLARE_CPU_FEATURE_FLAG // Address of instruction which causes SEGV -address VM_Version::_cpuinfo_segv_addr = 0; +address VM_Version::_cpuinfo_segv_addr = nullptr; // Address of instruction after the one which causes SEGV -address VM_Version::_cpuinfo_cont_addr = 0; +address VM_Version::_cpuinfo_cont_addr = nullptr; // Address of instruction which causes APX specific SEGV -address VM_Version::_cpuinfo_segv_addr_apx = 0; +address VM_Version::_cpuinfo_segv_addr_apx = nullptr; // Address of instruction after the one which causes APX specific SEGV -address VM_Version::_cpuinfo_cont_addr_apx = 0; +address VM_Version::_cpuinfo_cont_addr_apx = nullptr; static BufferBlob* stub_blob; static const int stub_size = 2000; diff --git a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp index 78988dd4fd005..0d5d07fc8a804 100644 --- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp +++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp @@ -224,7 +224,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, if (info != nullptr && uc != nullptr && thread != nullptr) { pc = (address) os::Posix::ucontext_get_pc(uc); - if (sig == SIGSEGV && info->si_addr == 0 && info->si_code == SI_KERNEL) { + if (sig == SIGSEGV && info->si_addr == nullptr && info->si_code == SI_KERNEL) { // An irrecoverable SI_KERNEL SIGSEGV has occurred. // It's likely caused by dereferencing an address larger than TASK_SIZE. return false; From 7146daee68788bf9a33d6eed6fb0614a82644cbc Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Mon, 5 Aug 2024 20:05:07 +0000 Subject: [PATCH 18/77] 8337783: Use THROW_NULL instead of THROW_0 in pointer contexts in misc runtime code Reviewed-by: stefank, shade --- src/hotspot/os/posix/perfMemory_posix.cpp | 6 +-- src/hotspot/share/classfile/javaClasses.cpp | 2 +- .../share/classfile/systemDictionary.cpp | 2 +- src/hotspot/share/oops/objArrayKlass.cpp | 2 +- src/hotspot/share/runtime/perfData.cpp | 16 ++++---- src/hotspot/share/runtime/reflection.cpp | 38 +++++++++---------- 6 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp index 56bc8a1ef6b81..4eb46169878cd 100644 --- a/src/hotspot/os/posix/perfMemory_posix.cpp +++ b/src/hotspot/os/posix/perfMemory_posix.cpp @@ -499,11 +499,11 @@ static char* get_user_name_slow(int vmid, int nspid, TRAPS) { // short circuit the directory search if the process doesn't even exist. if (kill(vmid, 0) == OS_ERR) { if (errno == ESRCH) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), - "Process not found"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), + "Process not found"); } else /* EPERM */ { - THROW_MSG_0(vmSymbols::java_io_IOException(), os::strerror(errno)); + THROW_MSG_NULL(vmSymbols::java_io_IOException(), os::strerror(errno)); } } diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index b1b74bbba05cf..ab9460e2b9b01 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -475,7 +475,7 @@ Handle java_lang_String::externalize_classname(Symbol* java_name, TRAPS) { jchar* java_lang_String::as_unicode_string(oop java_string, int& length, TRAPS) { jchar* result = as_unicode_string_or_null(java_string, length); if (result == nullptr) { - THROW_MSG_0(vmSymbols::java_lang_OutOfMemoryError(), "could not allocate Unicode string"); + THROW_MSG_NULL(vmSymbols::java_lang_OutOfMemoryError(), "could not allocate Unicode string"); } return result; } diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index 3016d41b28923..7f9e6430cc651 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -259,7 +259,7 @@ Handle SystemDictionary::get_loader_lock_or_null(Handle class_loader) { Symbol* SystemDictionary::class_name_symbol(const char* name, Symbol* exception, TRAPS) { if (name == nullptr) { - THROW_MSG_0(exception, "No class name given"); + THROW_MSG_NULL(exception, "No class name given"); } if ((int)strlen(name) > Symbol::max_length()) { // It's impossible to create this class; the name cannot fit diff --git a/src/hotspot/share/oops/objArrayKlass.cpp b/src/hotspot/share/oops/objArrayKlass.cpp index 94d3c6b6b358e..bee010b6d7244 100644 --- a/src/hotspot/share/oops/objArrayKlass.cpp +++ b/src/hotspot/share/oops/objArrayKlass.cpp @@ -173,7 +173,7 @@ oop ObjArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) { for (int i = 0; i < rank - 1; ++i) { sizes += 1; if (*sizes < 0) { - THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", *sizes)); + THROW_MSG_NULL(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", *sizes)); } } } diff --git a/src/hotspot/share/runtime/perfData.cpp b/src/hotspot/share/runtime/perfData.cpp index 5e78baad3ab2a..657427943aa2f 100644 --- a/src/hotspot/share/runtime/perfData.cpp +++ b/src/hotspot/share/runtime/perfData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, 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 @@ -361,7 +361,7 @@ PerfStringConstant* PerfDataManager::create_string_constant(CounterNS ns, if (!p->is_valid()) { // allocation of native resources failed. delete p; - THROW_0(vmSymbols::java_lang_OutOfMemoryError()); + THROW_NULL(vmSymbols::java_lang_OutOfMemoryError()); } add_item(p, false); @@ -379,7 +379,7 @@ PerfLongConstant* PerfDataManager::create_long_constant(CounterNS ns, if (!p->is_valid()) { // allocation of native resources failed. delete p; - THROW_0(vmSymbols::java_lang_OutOfMemoryError()); + THROW_NULL(vmSymbols::java_lang_OutOfMemoryError()); } add_item(p, false); @@ -402,7 +402,7 @@ PerfStringVariable* PerfDataManager::create_string_variable(CounterNS ns, if (!p->is_valid()) { // allocation of native resources failed. delete p; - THROW_0(vmSymbols::java_lang_OutOfMemoryError()); + THROW_NULL(vmSymbols::java_lang_OutOfMemoryError()); } add_item(p, false); @@ -420,7 +420,7 @@ PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns, if (!p->is_valid()) { // allocation of native resources failed. delete p; - THROW_0(vmSymbols::java_lang_OutOfMemoryError()); + THROW_NULL(vmSymbols::java_lang_OutOfMemoryError()); } add_item(p, false); @@ -442,7 +442,7 @@ PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns, if (!p->is_valid()) { // allocation of native resources failed. delete p; - THROW_0(vmSymbols::java_lang_OutOfMemoryError()); + THROW_NULL(vmSymbols::java_lang_OutOfMemoryError()); } add_item(p, true); @@ -460,7 +460,7 @@ PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns, if (!p->is_valid()) { // allocation of native resources failed. delete p; - THROW_0(vmSymbols::java_lang_OutOfMemoryError()); + THROW_NULL(vmSymbols::java_lang_OutOfMemoryError()); } add_item(p, false); @@ -482,7 +482,7 @@ PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns, if (!p->is_valid()) { // allocation of native resources failed. delete p; - THROW_0(vmSymbols::java_lang_OutOfMemoryError()); + THROW_NULL(vmSymbols::java_lang_OutOfMemoryError()); } add_item(p, true); diff --git a/src/hotspot/share/runtime/reflection.cpp b/src/hotspot/share/runtime/reflection.cpp index bc8779158d31d..865d25fa06b8a 100644 --- a/src/hotspot/share/runtime/reflection.cpp +++ b/src/hotspot/share/runtime/reflection.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -325,7 +325,7 @@ static Klass* basic_type_mirror_to_arrayklass(oop basic_type_mirror, TRAPS) { assert(java_lang_Class::is_primitive(basic_type_mirror), "just checking"); BasicType type = java_lang_Class::primitive_type(basic_type_mirror); if (type == T_VOID) { - THROW_0(vmSymbols::java_lang_IllegalArgumentException()); + THROW_NULL(vmSymbols::java_lang_IllegalArgumentException()); } else { return Universe::typeArrayKlass(type); @@ -334,10 +334,10 @@ static Klass* basic_type_mirror_to_arrayklass(oop basic_type_mirror, TRAPS) { arrayOop Reflection::reflect_new_array(oop element_mirror, jint length, TRAPS) { if (element_mirror == nullptr) { - THROW_0(vmSymbols::java_lang_NullPointerException()); + THROW_NULL(vmSymbols::java_lang_NullPointerException()); } if (length < 0) { - THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", length)); + THROW_MSG_NULL(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", length)); } if (java_lang_Class::is_primitive(element_mirror)) { Klass* tak = basic_type_mirror_to_arrayklass(element_mirror, CHECK_NULL); @@ -345,7 +345,7 @@ arrayOop Reflection::reflect_new_array(oop element_mirror, jint length, TRAPS) { } else { Klass* k = java_lang_Class::as_Klass(element_mirror); if (k->is_array_klass() && ArrayKlass::cast(k)->dimension() >= MAX_DIM) { - THROW_0(vmSymbols::java_lang_IllegalArgumentException()); + THROW_NULL(vmSymbols::java_lang_IllegalArgumentException()); } return oopFactory::new_objArray(k, length, THREAD); } @@ -357,19 +357,19 @@ arrayOop Reflection::reflect_new_multi_array(oop element_mirror, typeArrayOop di assert(TypeArrayKlass::cast(dim_array->klass())->element_type() == T_INT, "just checking"); if (element_mirror == nullptr) { - THROW_0(vmSymbols::java_lang_NullPointerException()); + THROW_NULL(vmSymbols::java_lang_NullPointerException()); } int len = dim_array->length(); if (len <= 0 || len > MAX_DIM) { - THROW_0(vmSymbols::java_lang_IllegalArgumentException()); + THROW_NULL(vmSymbols::java_lang_IllegalArgumentException()); } jint dimensions[MAX_DIM]; // C array copy of intArrayOop for (int i = 0; i < len; i++) { int d = dim_array->int_at(i); if (d < 0) { - THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", d)); + THROW_MSG_NULL(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", d)); } dimensions[i] = d; } @@ -383,7 +383,7 @@ arrayOop Reflection::reflect_new_multi_array(oop element_mirror, typeArrayOop di if (klass->is_array_klass()) { int k_dim = ArrayKlass::cast(klass)->dimension(); if (k_dim + len > MAX_DIM) { - THROW_0(vmSymbols::java_lang_IllegalArgumentException()); + THROW_NULL(vmSymbols::java_lang_IllegalArgumentException()); } dim += k_dim; } @@ -977,11 +977,11 @@ static oop invoke(InstanceKlass* klass, } else { // check for null receiver if (receiver.is_null()) { - THROW_0(vmSymbols::java_lang_NullPointerException()); + THROW_NULL(vmSymbols::java_lang_NullPointerException()); } // Check class of receiver against class declaring method if (!receiver->is_a(klass)) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "object is not an instance of declaring class"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "object is not an instance of declaring class"); } // target klass is receiver's klass target_klass = receiver->klass(); @@ -1047,15 +1047,15 @@ static oop invoke(InstanceKlass* klass, reflected_method->name(), reflected_method->signature()); ss.print("'"); - THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), ss.as_string()); + THROW_MSG_NULL(vmSymbols::java_lang_NoSuchMethodError(), ss.as_string()); } assert(ptypes->is_objArray(), "just checking"); int args_len = args.is_null() ? 0 : args->length(); // Check number of arguments if (ptypes->length() != args_len) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), - "wrong number of arguments"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), + "wrong number of arguments"); } // Create object to contain parameters for the JavaCall @@ -1085,14 +1085,14 @@ static oop invoke(InstanceKlass* klass, case T_FLOAT: java_args.push_float(value.f); break; case T_DOUBLE: java_args.push_double(value.d); break; default: - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "argument type mismatch"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "argument type mismatch"); } } else { if (arg != nullptr) { Klass* k = java_lang_Class::as_Klass(type_mirror); if (!arg->is_a(k)) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), - "argument type mismatch"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), + "argument type mismatch"); } } Handle arg_handle(THREAD, arg); // Create handle for argument @@ -1148,7 +1148,7 @@ oop Reflection::invoke_method(oop method_mirror, Handle receiver, objArrayHandle InstanceKlass* klass = InstanceKlass::cast(java_lang_Class::as_Klass(mirror)); Method* m = klass->method_with_idnum(slot); if (m == nullptr) { - THROW_MSG_0(vmSymbols::java_lang_InternalError(), "invoke"); + THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "invoke"); } methodHandle method(THREAD, m); @@ -1165,7 +1165,7 @@ oop Reflection::invoke_constructor(oop constructor_mirror, objArrayHandle args, InstanceKlass* klass = InstanceKlass::cast(java_lang_Class::as_Klass(mirror)); Method* m = klass->method_with_idnum(slot); if (m == nullptr) { - THROW_MSG_0(vmSymbols::java_lang_InternalError(), "invoke"); + THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "invoke"); } methodHandle method(THREAD, m); assert(method->name() == vmSymbols::object_initializer_name(), "invalid constructor"); From 965d6b9cbe2dd882fe3c3c955dfa08685af7d6c2 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Mon, 5 Aug 2024 23:29:17 +0000 Subject: [PATCH 19/77] 8335836: serviceability/jvmti/StartPhase/AllowedFunctions/AllowedFunctions.java fails with unexpected exit code: 112 Reviewed-by: cjplummer, amenkov --- .../AllowedFunctions/libAllowedFunctions.c | 45 +++++++++++++++++-- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/test/hotspot/jtreg/serviceability/jvmti/StartPhase/AllowedFunctions/libAllowedFunctions.c b/test/hotspot/jtreg/serviceability/jvmti/StartPhase/AllowedFunctions/libAllowedFunctions.c index 4299a98d7e63b..97b5cab341eb2 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/StartPhase/AllowedFunctions/libAllowedFunctions.c +++ b/test/hotspot/jtreg/serviceability/jvmti/StartPhase/AllowedFunctions/libAllowedFunctions.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 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. * * This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,8 @@ extern "C" { #define FAILED 2 static jint result = PASSED; +static jrawMonitorID event_mon = NULL; +static jboolean is_vm_dead = JNI_FALSE; static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved); @@ -68,7 +70,7 @@ jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { static void check_jvmti_error(jvmtiEnv *jvmti, char* fname, jvmtiError err) { if (err != JVMTI_ERROR_NONE) { printf(" ## %s error: %d\n", fname, err); - exit(err); + abort(); } } @@ -317,7 +319,7 @@ VMStart(jvmtiEnv *jvmti, JNIEnv* jni) { } static void JNICALL -VMInit(jvmtiEnv *jvmti, JNIEnv* jnii, jthread thread) { +VMInit(jvmtiEnv *jvmti, JNIEnv* jni, jthread thread) { jvmtiPhase phase; printf("VMInit event\n"); @@ -329,22 +331,52 @@ VMInit(jvmtiEnv *jvmti, JNIEnv* jnii, jthread thread) { } } +static void JNICALL +VMDeath(jvmtiEnv *jvmti, JNIEnv* jni) { + jvmtiError err; + + // Block ClassPrepare events while this callback is executed. + err = (*jvmti)->RawMonitorEnter(jvmti, event_mon); + check_jvmti_error(jvmti, "VMDeath event: Failed in RawMonitorEnter", err); + + is_vm_dead = JNI_TRUE; + printf("VMDeath event\n"); + + err = (*jvmti)->RawMonitorExit(jvmti, event_mon); + check_jvmti_error(jvmti, "VMDeath event: Failed in RawMonitorExit", err); +} + static void JNICALL ClassPrepare(jvmtiEnv *jvmti, JNIEnv *env, jthread thread, jclass klass) { static const jint EVENTS_LIMIT = 2; static jint event_no = 0; - jthread cur_thread = get_cur_thread(jvmti); jvmtiPhase phase; intptr_t exp_val = 777; intptr_t act_val; + jvmtiError err; + + // Block VMDeath event and other ClassPrepare events while this callback is executed. + // Sync with VMDeath event and check for is_vm_dead guard against JVMTI_ERROR WRONG_PHASE. + err = (*jvmti)->RawMonitorEnter(jvmti, event_mon); + check_jvmti_error(jvmti, "ClassPrepare event: Failed in RawMonitorEnter", err); + if (is_vm_dead) { + printf("\nIgnoring ClassPrepare event during the dead phase\n"); + err = (*jvmti)->RawMonitorExit(jvmti, event_mon); + check_jvmti_error(jvmti, "ClassPrepare event: Failed in RawMonitorExit", err); + return; + } get_phase(jvmti, &phase); if (phase != JVMTI_PHASE_START && phase != JVMTI_PHASE_LIVE) { printf(" ## Error: unexpected phase: %d, expected: %d or %d\n", phase, JVMTI_PHASE_START, JVMTI_PHASE_LIVE); + result = FAILED; + err = (*jvmti)->RawMonitorExit(jvmti, event_mon); + check_jvmti_error(jvmti, "ClassPrepare event: Failed in RawMonitorExit", err); return; } if (phase == JVMTI_PHASE_START && event_no < EVENTS_LIMIT) { + jthread cur_thread = get_cur_thread(jvmti); printf("\nClassPrepare event during the start phase: #%d\n", event_no); // Test the JVMTI class functions during the start phase test_class_functions(jvmti, env, thread, klass); @@ -360,6 +392,8 @@ ClassPrepare(jvmtiEnv *jvmti, JNIEnv *env, jthread thread, jclass klass) { } event_no++; } + err = (*jvmti)->RawMonitorExit(jvmti, event_mon); + check_jvmti_error(jvmti, "ClassPrepare event: Failed in RawMonitorExit", err); } static @@ -400,6 +434,9 @@ jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { callbacks.VMInit = VMInit; callbacks.ClassPrepare = ClassPrepare; + err = (*jvmti)->CreateRawMonitor(jvmti, "Events Monitor", &event_mon); + check_jvmti_error(jvmti, "## Agent_Initialize: CreateRawMonitor", err); + err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size); check_jvmti_error(jvmti, "## Agent_Initialize: SetEventCallbacks", err); From 73718fb8a3570023e7855137eb008f78b8a1e8ce Mon Sep 17 00:00:00 2001 From: Gui Cao Date: Tue, 6 Aug 2024 02:16:19 +0000 Subject: [PATCH 20/77] 8337788: RISC-V: Cleanup code in MacroAssembler::reserved_stack_check Reviewed-by: fyang, rehn, fjiang --- .../cpu/riscv/macroAssembler_riscv.cpp | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index cd7a4ecf22803..e0b24b7fd66ca 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -4130,29 +4130,25 @@ void MacroAssembler::remove_frame(int framesize) { } void MacroAssembler::reserved_stack_check() { - // testing if reserved zone needs to be enabled - Label no_reserved_zone_enabling; + // testing if reserved zone needs to be enabled + Label no_reserved_zone_enabling; - ld(t0, Address(xthread, JavaThread::reserved_stack_activation_offset())); - bltu(sp, t0, no_reserved_zone_enabling); + ld(t0, Address(xthread, JavaThread::reserved_stack_activation_offset())); + bltu(sp, t0, no_reserved_zone_enabling); - enter(); // RA and FP are live. - mv(c_rarg0, xthread); - rt_call(CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone)); - leave(); + enter(); // RA and FP are live. + mv(c_rarg0, xthread); + rt_call(CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone)); + leave(); - // We have already removed our own frame. - // throw_delayed_StackOverflowError will think that it's been - // called by our caller. - RuntimeAddress target(StubRoutines::throw_delayed_StackOverflowError_entry()); - relocate(target.rspec(), [&] { - int32_t offset; - movptr(t0, target.target(), offset); - jr(t0, offset); - }); - should_not_reach_here(); + // We have already removed our own frame. + // throw_delayed_StackOverflowError will think that it's been + // called by our caller. + la(t0, RuntimeAddress(StubRoutines::throw_delayed_StackOverflowError_entry())); + jr(t0); + should_not_reach_here(); - bind(no_reserved_zone_enabling); + bind(no_reserved_zone_enabling); } // Move the address of the polling page into dest. From 20575949612a750a428316635715737183a2d58c Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 6 Aug 2024 05:34:33 +0000 Subject: [PATCH 21/77] 8337782: Use THROW_NULL instead of THROW_0 in pointer contexts in prims code Reviewed-by: shade, dholmes --- src/hotspot/share/prims/jni.cpp | 16 +++---- src/hotspot/share/prims/jvm.cpp | 54 ++++++++++++------------ src/hotspot/share/prims/nativeLookup.cpp | 4 +- src/hotspot/share/prims/perf.cpp | 16 +++---- src/hotspot/share/prims/unsafe.cpp | 2 +- src/hotspot/share/prims/whitebox.cpp | 2 +- 6 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp index a91d7375761e2..12eba0ff623be 100644 --- a/src/hotspot/share/prims/jni.cpp +++ b/src/hotspot/share/prims/jni.cpp @@ -1074,7 +1074,7 @@ static jmethodID get_method_id(JNIEnv *env, jclass clazz, const char *name_str, TempNewSymbol signature = SymbolTable::probe(sig, (int)strlen(sig)); if (name == nullptr || signature == nullptr) { - THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str); + THROW_MSG_NULL(vmSymbols::java_lang_NoSuchMethodError(), name_str); } oop mirror = JNIHandles::resolve_non_null(clazz); @@ -1084,7 +1084,7 @@ static jmethodID get_method_id(JNIEnv *env, jclass clazz, const char *name_str, // primitive java.lang.Class if (java_lang_Class::is_primitive(mirror)) { ResourceMark rm(THREAD); - THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), err_msg("%s%s.%s%s", is_static ? "static " : "", klass->signature_name(), name_str, sig)); + THROW_MSG_NULL(vmSymbols::java_lang_NoSuchMethodError(), err_msg("%s%s.%s%s", is_static ? "static " : "", klass->signature_name(), name_str, sig)); } // Make sure class is linked and initialized before handing id's out to @@ -1108,7 +1108,7 @@ static jmethodID get_method_id(JNIEnv *env, jclass clazz, const char *name_str, } if (m == nullptr || (m->is_static() != is_static)) { ResourceMark rm(THREAD); - THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), err_msg("%s%s.%s%s", is_static ? "static " : "", klass->signature_name(), name_str, sig)); + THROW_MSG_NULL(vmSymbols::java_lang_NoSuchMethodError(), err_msg("%s%s.%s%s", is_static ? "static " : "", klass->signature_name(), name_str, sig)); } return m->jmethod_id(); } @@ -1762,7 +1762,7 @@ JNI_ENTRY(jfieldID, jni_GetFieldID(JNIEnv *env, jclass clazz, TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig)); if (fieldname == nullptr || signame == nullptr) { ResourceMark rm; - THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig)); + THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig)); } // Make sure class is initialized before handing id's out to fields @@ -1772,7 +1772,7 @@ JNI_ENTRY(jfieldID, jni_GetFieldID(JNIEnv *env, jclass clazz, if (!k->is_instance_klass() || !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) { ResourceMark rm; - THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig)); + THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig)); } // A jfieldID for a non-static field is simply the offset of the field within the instanceOop @@ -1986,7 +1986,7 @@ JNI_ENTRY(jfieldID, jni_GetStaticFieldID(JNIEnv *env, jclass clazz, TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name)); TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig)); if (fieldname == nullptr || signame == nullptr) { - THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name); + THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), (char*) name); } Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)); // Make sure class is initialized before handing id's out to static fields @@ -1995,7 +1995,7 @@ JNI_ENTRY(jfieldID, jni_GetStaticFieldID(JNIEnv *env, jclass clazz, fieldDescriptor fd; if (!k->is_instance_klass() || !InstanceKlass::cast(k)->find_field(fieldname, signame, true, &fd)) { - THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name); + THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), (char*) name); } // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass* @@ -2309,7 +2309,7 @@ JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, js ResourceMark rm(THREAD); stringStream ss; ss.print("Index %d out of bounds for length %d", index, a->length()); - THROW_MSG_0(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string()); + THROW_MSG_NULL(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string()); } JNI_END diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 1e3806474b540..e40c11289661e 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -691,7 +691,7 @@ JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle)) (klass->is_instance_klass() && InstanceKlass::cast(klass)->reference_type() != REF_NONE)) { ResourceMark rm(THREAD); - THROW_MSG_0(vmSymbols::java_lang_CloneNotSupportedException(), klass->external_name()); + THROW_MSG_NULL(vmSymbols::java_lang_CloneNotSupportedException(), klass->external_name()); } // Make shallow object copy @@ -791,7 +791,7 @@ JVM_ENTRY(jclass, JVM_FindPrimitiveClass(JNIEnv* env, const char* utf)) mirror = Universe::java_mirror(t); } if (mirror == nullptr) { - THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), (char*) utf); + THROW_MSG_NULL(vmSymbols::java_lang_ClassNotFoundException(), (char*) utf); } else { return (jclass) JNIHandles::make_local(THREAD, mirror); } @@ -952,7 +952,7 @@ static jclass jvm_lookup_define_class(jclass lookup, const char *name, Klass* lookup_k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(lookup)); // Lookup class must be a non-null instance if (lookup_k == nullptr) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Lookup class is null"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Lookup class is null"); } assert(lookup_k->is_instance_klass(), "Lookup class must be an instance klass"); @@ -979,20 +979,20 @@ static jclass jvm_lookup_define_class(jclass lookup, const char *name, if (!is_hidden) { // classData is only applicable for hidden classes if (classData != nullptr) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "classData is only applicable for hidden classes"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "classData is only applicable for hidden classes"); } if (is_nestmate) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "dynamic nestmate is only applicable for hidden classes"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "dynamic nestmate is only applicable for hidden classes"); } if (!is_strong) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "an ordinary class must be strongly referenced by its defining loader"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "an ordinary class must be strongly referenced by its defining loader"); } if (vm_annotations) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "vm annotations only allowed for hidden classes"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "vm annotations only allowed for hidden classes"); } if (flags != STRONG_LOADER_LINK) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), - err_msg("invalid flag 0x%x", flags)); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), + err_msg("invalid flag 0x%x", flags)); } } @@ -1047,7 +1047,7 @@ static jclass jvm_lookup_define_class(jclass lookup, const char *name, if ((!is_hidden || is_nestmate) && !Reflection::is_same_class_package(lookup_k, ik)) { // non-hidden class or nestmate class must be in the same package as the Lookup class - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Lookup class and defined class are in different packages"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Lookup class and defined class are in different packages"); } if (init) { @@ -1078,7 +1078,7 @@ JVM_ENTRY(jclass, JVM_LookupDefineClass(JNIEnv *env, jclass lookup, const char * jsize len, jobject pd, jboolean initialize, int flags, jobject classData)) if (lookup == nullptr) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Lookup class is null"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Lookup class is null"); } assert(buf != nullptr, "buf must not be null"); @@ -1703,8 +1703,8 @@ JVM_ENTRY(jobjectArray, JVM_GetMethodParameters(JNIEnv *env, jobject method)) bounds_check(cp, index, CHECK_NULL); if (0 != index && !mh->constants()->tag_at(index).is_utf8()) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), - "Wrong type at constant pool index"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), + "Wrong type at constant pool index"); } } @@ -2133,7 +2133,7 @@ JVM_ENTRY(jclass, JVM_ConstantPoolGetClassAt(JNIEnv *env, jobject obj, jobject u bounds_check(cp, index, CHECK_NULL); constantTag tag = cp->tag_at(index); if (!tag.is_klass() && !tag.is_unresolved_klass()) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); } Klass* k = cp->klass_at(index, CHECK_NULL); return (jclass) JNIHandles::make_local(THREAD, k->java_mirror()); @@ -2146,7 +2146,7 @@ JVM_ENTRY(jclass, JVM_ConstantPoolGetClassAtIfLoaded(JNIEnv *env, jobject obj, j bounds_check(cp, index, CHECK_NULL); constantTag tag = cp->tag_at(index); if (!tag.is_klass() && !tag.is_unresolved_klass()) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); } Klass* k = ConstantPool::klass_at_if_loaded(cp, index); if (k == nullptr) return nullptr; @@ -2157,7 +2157,7 @@ JVM_END static jobject get_method_at_helper(const constantPoolHandle& cp, jint index, bool force_resolution, TRAPS) { constantTag tag = cp->tag_at(index); if (!tag.is_method() && !tag.is_interface_method()) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); } int klass_ref = cp->uncached_klass_ref_index_at(index); Klass* k_o; @@ -2172,7 +2172,7 @@ static jobject get_method_at_helper(const constantPoolHandle& cp, jint index, bo Symbol* sig = cp->uncached_signature_ref_at(index); methodHandle m (THREAD, k->find_method(name, sig)); if (m.is_null()) { - THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "Unable to look up method in target class"); + THROW_MSG_NULL(vmSymbols::java_lang_RuntimeException(), "Unable to look up method in target class"); } oop method; if (!m->is_initializer() || m->is_static()) { @@ -2206,7 +2206,7 @@ JVM_END static jobject get_field_at_helper(constantPoolHandle cp, jint index, bool force_resolution, TRAPS) { constantTag tag = cp->tag_at(index); if (!tag.is_field()) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); } int klass_ref = cp->uncached_klass_ref_index_at(index); Klass* k_o; @@ -2222,7 +2222,7 @@ static jobject get_field_at_helper(constantPoolHandle cp, jint index, bool force fieldDescriptor fd; Klass* target_klass = k->find_field(name, sig, &fd); if (target_klass == nullptr) { - THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "Unable to look up field in target class"); + THROW_MSG_NULL(vmSymbols::java_lang_RuntimeException(), "Unable to look up field in target class"); } oop field = Reflection::new_field(&fd, CHECK_NULL); return JNIHandles::make_local(THREAD, field); @@ -2255,7 +2255,7 @@ JVM_ENTRY(jobjectArray, JVM_ConstantPoolGetMemberRefInfoAt(JNIEnv *env, jobject bounds_check(cp, index, CHECK_NULL); constantTag tag = cp->tag_at(index); if (!tag.is_field_or_method()) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); } int klass_ref = cp->uncached_klass_ref_index_at(index); Symbol* klass_name = cp->klass_name_at(klass_ref); @@ -2306,7 +2306,7 @@ JVM_ENTRY(jobjectArray, JVM_ConstantPoolGetNameAndTypeRefInfoAt(JNIEnv *env, job bounds_check(cp, index, CHECK_NULL); constantTag tag = cp->tag_at(index); if (!tag.is_name_and_type()) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); } Symbol* member_name = cp->symbol_at(cp->name_ref_index_at(index)); Symbol* member_sig = cp->symbol_at(cp->signature_ref_index_at(index)); @@ -2374,7 +2374,7 @@ JVM_ENTRY(jstring, JVM_ConstantPoolGetStringAt(JNIEnv *env, jobject obj, jobject bounds_check(cp, index, CHECK_NULL); constantTag tag = cp->tag_at(index); if (!tag.is_string()) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); } oop str = cp->string_at(index, CHECK_NULL); return (jstring) JNIHandles::make_local(THREAD, str); @@ -2388,7 +2388,7 @@ JVM_ENTRY(jstring, JVM_ConstantPoolGetUTF8At(JNIEnv *env, jobject obj, jobject u bounds_check(cp, index, CHECK_NULL); constantTag tag = cp->tag_at(index); if (!tag.is_symbol()) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); } Symbol* sym = cp->symbol_at(index); Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL); @@ -3292,13 +3292,13 @@ JVM_END // resolve array handle and check arguments static inline arrayOop check_array(JNIEnv *env, jobject arr, bool type_array_only, TRAPS) { if (arr == nullptr) { - THROW_0(vmSymbols::java_lang_NullPointerException()); + THROW_NULL(vmSymbols::java_lang_NullPointerException()); } oop a = JNIHandles::resolve_non_null(arr); if (!a->is_array()) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Argument is not an array"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Argument is not an array"); } else if (type_array_only && !a->is_typeArray()) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Argument is not an array of primitive type"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Argument is not an array of primitive type"); } return arrayOop(a); } @@ -3535,7 +3535,7 @@ JVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jo } return res; } else { - THROW_0(vmSymbols::java_lang_StackOverflowError()); + THROW_NULL(vmSymbols::java_lang_StackOverflowError()); } JVM_END diff --git a/src/hotspot/share/prims/nativeLookup.cpp b/src/hotspot/share/prims/nativeLookup.cpp index e838c831ff1ab..78cf7481abfd0 100644 --- a/src/hotspot/share/prims/nativeLookup.cpp +++ b/src/hotspot/share/prims/nativeLookup.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -414,7 +414,7 @@ address NativeLookup::lookup_base(const methodHandle& method, TRAPS) { ss.print("'"); method->print_external_name(&ss); ss.print("'"); - THROW_MSG_0(vmSymbols::java_lang_UnsatisfiedLinkError(), ss.as_string()); + THROW_MSG_NULL(vmSymbols::java_lang_UnsatisfiedLinkError(), ss.as_string()); } diff --git a/src/hotspot/share/prims/perf.cpp b/src/hotspot/share/prims/perf.cpp index 9ff831dded9fa..feef9760d8fdf 100644 --- a/src/hotspot/share/prims/perf.cpp +++ b/src/hotspot/share/prims/perf.cpp @@ -50,7 +50,7 @@ static char* jstr_to_utf(JNIEnv *env, jstring str, TRAPS) { char* utfstr = nullptr; if (str == nullptr) { - THROW_0(vmSymbols::java_lang_NullPointerException()); + THROW_NULL(vmSymbols::java_lang_NullPointerException()); //throw_new(env,"NullPointerException"); } @@ -113,7 +113,7 @@ PERF_ENTRY(jobject, Perf_CreateLong(JNIEnv *env, jobject perf, jstring name, if (units <= 0 || units > PerfData::U_Last) { debug_only(warning("unexpected units argument, units = %d", units)); - THROW_0(vmSymbols::java_lang_IllegalArgumentException()); + THROW_NULL(vmSymbols::java_lang_IllegalArgumentException()); } ResourceMark rm; @@ -128,7 +128,7 @@ PERF_ENTRY(jobject, Perf_CreateLong(JNIEnv *env, jobject perf, jstring name, // check that the PerfData name doesn't already exist if (PerfDataManager::exists(name_utf)) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "PerfLong name already exists"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "PerfLong name already exists"); } switch(variability) { @@ -152,7 +152,7 @@ PERF_ENTRY(jobject, Perf_CreateLong(JNIEnv *env, jobject perf, jstring name, default: /* Illegal Argument */ debug_only(warning("unexpected variability value: %d", variability)); - THROW_0(vmSymbols::java_lang_IllegalArgumentException()); + THROW_NULL(vmSymbols::java_lang_IllegalArgumentException()); break; } @@ -174,21 +174,21 @@ PERF_ENTRY(jobject, Perf_CreateByteArray(JNIEnv *env, jobject perf, // check for valid byte array objects if (name == nullptr || value == nullptr) { - THROW_0(vmSymbols::java_lang_NullPointerException()); + THROW_NULL(vmSymbols::java_lang_NullPointerException()); } // check for valid variability classification if (variability != PerfData::V_Constant && variability != PerfData::V_Variable) { debug_only(warning("unexpected variability value: %d", variability)); - THROW_0(vmSymbols::java_lang_IllegalArgumentException()); + THROW_NULL(vmSymbols::java_lang_IllegalArgumentException()); } // check for valid units if (units != PerfData::U_String) { // only String based ByteArray objects are currently supported debug_only(warning("unexpected units value: %d", variability)); - THROW_0(vmSymbols::java_lang_IllegalArgumentException()); + THROW_NULL(vmSymbols::java_lang_IllegalArgumentException()); } int value_length; @@ -211,7 +211,7 @@ PERF_ENTRY(jobject, Perf_CreateByteArray(JNIEnv *env, jobject perf, // check that the counter name doesn't already exist if (PerfDataManager::exists((char*)name_utf)) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "PerfByteArray name already exists"); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "PerfByteArray name already exists"); } PerfByteArray* pbv = nullptr; diff --git a/src/hotspot/share/prims/unsafe.cpp b/src/hotspot/share/prims/unsafe.cpp index 1be157b2e44eb..239ae480030f5 100644 --- a/src/hotspot/share/prims/unsafe.cpp +++ b/src/hotspot/share/prims/unsafe.cpp @@ -552,7 +552,7 @@ UNSAFE_ENTRY(jobject, Unsafe_StaticFieldBase0(JNIEnv *env, jobject unsafe, jobje int modifiers = java_lang_reflect_Field::modifiers(reflected); if ((modifiers & JVM_ACC_STATIC) == 0) { - THROW_0(vmSymbols::java_lang_IllegalArgumentException()); + THROW_NULL(vmSymbols::java_lang_IllegalArgumentException()); } return JNIHandles::make_local(THREAD, mirror); diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 43e47409c4cb6..6ee33a6107998 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -590,7 +590,7 @@ WB_ENTRY(jobject, WB_G1AuxiliaryMemoryUsage(JNIEnv* env)) Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL); return JNIHandles::make_local(THREAD, h()); } - THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1AuxiliaryMemoryUsage: G1 GC is not enabled"); + THROW_MSG_NULL(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1AuxiliaryMemoryUsage: G1 GC is not enabled"); WB_END WB_ENTRY(jint, WB_G1ActiveMemoryNodeCount(JNIEnv* env, jobject o)) From 0d8ec42969fb60c140aaed7795ea1b9591915b8d Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 6 Aug 2024 06:59:11 +0000 Subject: [PATCH 22/77] 8337642: Remove unused APIs of GCPolicyCounters Reviewed-by: tschatzl --- .../share/gc/parallel/gcAdaptivePolicyCounters.hpp | 4 ---- .../gc/parallel/psGCAdaptivePolicyCounters.hpp | 4 ---- src/hotspot/share/gc/serial/defNewGeneration.cpp | 1 - src/hotspot/share/gc/shared/gcPolicyCounters.hpp | 13 ------------- 4 files changed, 22 deletions(-) diff --git a/src/hotspot/share/gc/parallel/gcAdaptivePolicyCounters.hpp b/src/hotspot/share/gc/parallel/gcAdaptivePolicyCounters.hpp index e83813c78f48f..e21d568955a38 100644 --- a/src/hotspot/share/gc/parallel/gcAdaptivePolicyCounters.hpp +++ b/src/hotspot/share/gc/parallel/gcAdaptivePolicyCounters.hpp @@ -223,10 +223,6 @@ class GCAdaptivePolicyCounters : public GCPolicyCounters { } void set_size_policy(AdaptiveSizePolicy* v) { _size_policy = v; } - - virtual GCPolicyCounters::Name kind() const { - return GCPolicyCounters::GCAdaptivePolicyCountersKind; - } }; #endif // SHARE_GC_PARALLEL_GCADAPTIVEPOLICYCOUNTERS_HPP diff --git a/src/hotspot/share/gc/parallel/psGCAdaptivePolicyCounters.hpp b/src/hotspot/share/gc/parallel/psGCAdaptivePolicyCounters.hpp index ad84eb4368b80..217cd7b9c5c36 100644 --- a/src/hotspot/share/gc/parallel/psGCAdaptivePolicyCounters.hpp +++ b/src/hotspot/share/gc/parallel/psGCAdaptivePolicyCounters.hpp @@ -180,10 +180,6 @@ class PSGCAdaptivePolicyCounters : public GCAdaptivePolicyCounters { // counter or from globals. This is distinguished from counters // that are updated via input parameters. void update_counters(); - - virtual GCPolicyCounters::Name kind() const { - return GCPolicyCounters::PSGCAdaptivePolicyCountersKind; - } }; #endif // SHARE_GC_PARALLEL_PSGCADAPTIVEPOLICYCOUNTERS_HPP diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index 715b82fd38d32..e93b97c85eb12 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -833,7 +833,6 @@ void DefNewGeneration::gc_epilogue(bool full) { assert(!GCLocker::is_active(), "We should not be executing here"); // update the generation and space performance counters update_counters(); - SerialHeap::heap()->counters()->update_counters(); } void DefNewGeneration::update_counters() { diff --git a/src/hotspot/share/gc/shared/gcPolicyCounters.hpp b/src/hotspot/share/gc/shared/gcPolicyCounters.hpp index a631664fcab93..9c7e5788a7eec 100644 --- a/src/hotspot/share/gc/shared/gcPolicyCounters.hpp +++ b/src/hotspot/share/gc/shared/gcPolicyCounters.hpp @@ -46,13 +46,6 @@ class GCPolicyCounters: public CHeapObj { const char* _name_space; public: - enum Name { - NONE, - GCPolicyCountersKind, - GCAdaptivePolicyCountersKind, - PSGCAdaptivePolicyCountersKind - }; - GCPolicyCounters(const char* name, int collectors, int generations); inline PerfVariable* tenuring_threshold() const { @@ -68,12 +61,6 @@ class GCPolicyCounters: public CHeapObj { } const char* name_space() const { return _name_space; } - - virtual void update_counters() {} - - virtual GCPolicyCounters::Name kind() const { - return GCPolicyCounters::GCPolicyCountersKind; - } }; #endif // SHARE_GC_SHARED_GCPOLICYCOUNTERS_HPP From f92c60e1a9968620cbc92b52aa546b57c09da487 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Tue, 6 Aug 2024 07:06:43 +0000 Subject: [PATCH 23/77] 8337810: ProblemList BasicDirectoryModel/LoaderThreadCount.java on Windows Reviewed-by: clanger --- test/jdk/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index f8bdfd26e8f79..bd29d64addf04 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -640,6 +640,7 @@ javax/sound/sampled/Clip/ClipFlushCrash.java 8308395 linux-x64 # jdk_swing javax/swing/plaf/basic/BasicTextUI/8001470/bug8001470.java 8233177 linux-all,windows-all +javax/swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java 8333880 windows-all javax/swing/JFrame/MaximizeWindowTest.java 8321289 linux-all javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedTranslucentPerPixelTranslucentGradient.java 8233582 linux-all From 958786b28ffb532b38746640b6fc11242f056ad9 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Tue, 6 Aug 2024 09:07:44 +0000 Subject: [PATCH 24/77] 8332522: SwitchBootstraps::mappedEnumLookup constructs unused array Reviewed-by: liach, redestad --- .../java/lang/runtime/SwitchBootstraps.java | 112 ++++++++++++------ .../bench/java/lang/runtime/SwitchEnum.java | 105 ++++++++++++++++ 2 files changed, 178 insertions(+), 39 deletions(-) create mode 100644 test/micro/org/openjdk/bench/java/lang/runtime/SwitchEnum.java diff --git a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java index ccb33a0e4dbd1..43f7339c75a96 100644 --- a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java +++ b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java @@ -56,6 +56,7 @@ import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE; import static java.lang.invoke.MethodHandles.Lookup.ClassOption.STRONG; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import static java.util.Objects.requireNonNull; @@ -95,19 +96,13 @@ private SwitchBootstraps() {} private static final ClassDesc CD_Objects = ReferenceClassDescImpl.ofValidated("Ljava/util/Objects;"); private static class StaticHolders { - private static final MethodHandle NULL_CHECK; - private static final MethodHandle IS_ZERO; - private static final MethodHandle MAPPED_ENUM_LOOKUP; + private static final MethodHandle MAPPED_ENUM_SWITCH; static { try { - NULL_CHECK = LOOKUP.findStatic(Objects.class, "isNull", - MethodType.methodType(boolean.class, Object.class)); - IS_ZERO = LOOKUP.findStatic(SwitchBootstraps.class, "isZero", - MethodType.methodType(boolean.class, int.class)); - MAPPED_ENUM_LOOKUP = LOOKUP.findStatic(SwitchBootstraps.class, "mappedEnumLookup", - MethodType.methodType(int.class, Enum.class, MethodHandles.Lookup.class, - Class.class, EnumDesc[].class, EnumMap.class)); + MAPPED_ENUM_SWITCH = LOOKUP.findStatic(SwitchBootstraps.class, "mappedEnumSwitch", + MethodType.methodType(int.class, Enum.class, int.class, MethodHandles.Lookup.class, + Class.class, EnumDesc[].class, MappedEnumCache.class)); } catch (ReflectiveOperationException e) { throw new ExceptionInInitializerError(e); @@ -211,10 +206,6 @@ private static void verifyLabel(Object label, Class selectorType) { } } - private static boolean isZero(int value) { - return value == 0; - } - /** * Bootstrap method for linking an {@code invokedynamic} call site that * implements a {@code switch} on a target of an enum type. The static @@ -286,23 +277,27 @@ public static CallSite enumSwitch(MethodHandles.Lookup lookup, labels = labels.clone(); Class enumClass = invocationType.parameterType(0); - labels = Stream.of(labels).map(l -> convertEnumConstants(lookup, enumClass, l)).toArray(); + boolean constantsOnly = true; + int len = labels.length; + + for (int i = 0; i < len; i++) { + Object convertedLabel = + convertEnumConstants(lookup, enumClass, labels[i]); + labels[i] = convertedLabel; + if (constantsOnly) + constantsOnly = convertedLabel instanceof EnumDesc; + } MethodHandle target; - boolean constantsOnly = Stream.of(labels).allMatch(l -> enumClass.isAssignableFrom(EnumDesc.class)); if (labels.length > 0 && constantsOnly) { //If all labels are enum constants, construct an optimized handle for repeat index 0: //if (selector == null) return -1 //else if (idx == 0) return mappingArray[selector.ordinal()]; //mapping array created lazily //else return "typeSwitch(labels)" - MethodHandle body = - MethodHandles.guardWithTest(MethodHandles.dropArguments(StaticHolders.NULL_CHECK, 0, int.class), - MethodHandles.dropArguments(MethodHandles.constant(int.class, -1), 0, int.class, Object.class), - MethodHandles.guardWithTest(MethodHandles.dropArguments(StaticHolders.IS_ZERO, 1, Object.class), - generateTypeSwitch(lookup, invocationType.parameterType(0), labels), - MethodHandles.insertArguments(StaticHolders.MAPPED_ENUM_LOOKUP, 1, lookup, enumClass, labels, new EnumMap()))); - target = MethodHandles.permuteArguments(body, MethodType.methodType(int.class, Object.class, int.class), 1, 0); + EnumDesc[] enumDescLabels = + Arrays.copyOf(labels, labels.length, EnumDesc[].class); + target = MethodHandles.insertArguments(StaticHolders.MAPPED_ENUM_SWITCH, 2, lookup, enumClass, enumDescLabels, new MappedEnumCache()); } else { target = generateTypeSwitch(lookup, invocationType.parameterType(0), labels); } @@ -331,26 +326,63 @@ private static > Object convertEnumConstants(MethodHandles.Loo } } - private static > int mappedEnumLookup(T value, MethodHandles.Lookup lookup, Class enumClass, EnumDesc[] labels, EnumMap enumMap) { - if (enumMap.map == null) { - T[] constants = SharedSecrets.getJavaLangAccess().getEnumConstantsShared(enumClass); - int[] map = new int[constants.length]; - int ordinal = 0; - - for (T constant : constants) { - map[ordinal] = labels.length; + private static > int mappedEnumSwitch(T value, int restartIndex, MethodHandles.Lookup lookup, Class enumClass, EnumDesc[] labels, MappedEnumCache enumCache) throws Throwable { + if (value == null) { + return -1; + } - for (int i = 0; i < labels.length; i++) { - if (Objects.equals(labels[i].constantName(), constant.name())) { - map[ordinal] = i; - break; + if (restartIndex != 0) { + MethodHandle generatedSwitch = enumCache.generatedSwitch; + if (generatedSwitch == null) { + synchronized (enumCache) { + generatedSwitch = enumCache.generatedSwitch; + + if (generatedSwitch == null) { + generatedSwitch = + generateTypeSwitch(lookup, enumClass, labels) + .asType(MethodType.methodType(int.class, + Enum.class, + int.class)); + enumCache.generatedSwitch = generatedSwitch; } } + } + + return (int) generatedSwitch.invokeExact(value, restartIndex); + } + + int[] constantsMap = enumCache.constantsMap; + + if (constantsMap == null) { + synchronized (enumCache) { + constantsMap = enumCache.constantsMap; - ordinal++; + if (constantsMap == null) { + T[] constants = SharedSecrets.getJavaLangAccess() + .getEnumConstantsShared(enumClass); + constantsMap = new int[constants.length]; + int ordinal = 0; + + for (T constant : constants) { + constantsMap[ordinal] = labels.length; + + for (int i = 0; i < labels.length; i++) { + if (Objects.equals(labels[i].constantName(), + constant.name())) { + constantsMap[ordinal] = i; + break; + } + } + + ordinal++; + } + + enumCache.constantsMap = constantsMap; + } } } - return enumMap.map[value.ordinal()]; + + return constantsMap[value.ordinal()]; } private static final class ResolvedEnumLabels implements BiPredicate { @@ -395,9 +427,11 @@ public boolean test(Integer labelIndex, Object value) { } } - private static final class EnumMap { + private static final class MappedEnumCache { + @Stable + public int[] constantsMap; @Stable - public int[] map; + public MethodHandle generatedSwitch; } /* diff --git a/test/micro/org/openjdk/bench/java/lang/runtime/SwitchEnum.java b/test/micro/org/openjdk/bench/java/lang/runtime/SwitchEnum.java new file mode 100644 index 0000000000000..bfec0d321b29d --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/runtime/SwitchEnum.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2024, 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. + * + * 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 org.openjdk.bench.java.lang.runtime; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS) +@Fork(3) +public class SwitchEnum { + + public E[] inputs; + @Setup + public void setup() { + inputs = E.values(); + } + + @Benchmark + public int enumSwitchWithBootstrap() { + int sum = 0; + for (E e : inputs) { + sum += switch (e) { + case null -> -1; + case E0 -> 10; + case E1 -> 11; + case E2 -> 12; + case E3 -> 13; + case E4 -> 14; + case E5 -> 15; + case E6 -> 16; + case E7 -> 17; + case E8 -> 18; + case E9 -> 19; + default -> 17; + }; + } + return sum; + } + + @Benchmark + public int enumSwitchTraditional() { + int sum = 0; + for (E e : inputs) { + sum += switch (e) { + case E0 -> 10; + case E1 -> 11; + case E2 -> 12; + case E3 -> 13; + case E4 -> 14; + case E5 -> 15; + case E6 -> 16; + case E7 -> 17; + case E8 -> 18; + case E9 -> 19; + default -> 17; + }; + } + return sum; + } + + public static void main(String[] args) { + SwitchEnum s = new SwitchEnum(); + s.setup(); + System.out.println(s.enumSwitchWithBootstrap()); + System.out.println(s.enumSwitchTraditional()); + } + + enum E { + E0, E1, E2, E3, E4, E5, E6, E7, E8, E9; + } +} From f9b8a22062c7ad7ffb150394da6b3ab069785535 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Tue, 6 Aug 2024 09:28:12 +0000 Subject: [PATCH 25/77] 8337798: JFR: Remove jdk/jfr/api/consumer/recordingstream/TestOnEvent.java from ProblemList.txt Reviewed-by: mgronlun --- test/jdk/ProblemList.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index bd29d64addf04..3211f27b5c1e4 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -744,7 +744,6 @@ jdk/jfr/event/runtime/TestResidentSetSizeEvent.java 8309846 aix-ppc6 jdk/jfr/startupargs/TestStartName.java 8214685 windows-x64 jdk/jfr/startupargs/TestStartDuration.java 8214685 windows-x64 jdk/jfr/jvm/TestWaste.java 8282427 generic-all -jdk/jfr/api/consumer/recordingstream/TestOnEvent.java 8255404 linux-x64,linux-aarch64 ############################################################################ From a117945d5a704781944ae15c852c31d090f03adb Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Tue, 6 Aug 2024 09:37:21 +0000 Subject: [PATCH 26/77] 8337344: Redundant javadoc at RasterPrinterJob.isCancelled Reviewed-by: aivanov, prr --- .../share/classes/sun/print/RasterPrinterJob.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java b/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java index 0dfa5e42d9a89..82f47824bfae7 100644 --- a/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java +++ b/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java @@ -2474,11 +2474,7 @@ public void cancel() { } } - /** - * Returns true is a print job is ongoing but will - * be cancelled and the next opportunity. false is - * returned otherwise. - */ + @Override public boolean isCancelled() { boolean cancelled = false; From ef909bdf7f08dfd67bac2665aa85f86c0e303db9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Tue, 6 Aug 2024 11:32:24 +0000 Subject: [PATCH 27/77] 8335121: Native memory leak when not recording any events Reviewed-by: egahlin, shade --- .../share/jfr/recorder/service/jfrRecorderService.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp index fc2043a4d921d..418b774996e4c 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp @@ -639,11 +639,7 @@ static void write_thread_local_buffer(JfrChunkWriter& chunkwriter, Thread* t) { size_t JfrRecorderService::flush() { size_t total_elements = flush_metadata(_chunkwriter); - const size_t storage_elements = flush_storage(_storage, _chunkwriter); - if (0 == storage_elements) { - return total_elements; - } - total_elements += storage_elements; + total_elements += flush_storage(_storage, _chunkwriter); if (_string_pool.is_modified()) { total_elements += flush_stringpool(_string_pool, _chunkwriter); } From 1348ece6df7b460501931533c238e819995a2086 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Tue, 6 Aug 2024 11:34:57 +0000 Subject: [PATCH 28/77] 8332120: Potential compilation failure in istream.cpp:205 - loss of data on conversion Reviewed-by: dholmes, iklam --- src/hotspot/share/utilities/istream.cpp | 8 +------- src/hotspot/share/utilities/istream.hpp | 2 -- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/hotspot/share/utilities/istream.cpp b/src/hotspot/share/utilities/istream.cpp index cb082128c62ca..55fa443af69e9 100644 --- a/src/hotspot/share/utilities/istream.cpp +++ b/src/hotspot/share/utilities/istream.cpp @@ -78,7 +78,6 @@ bool inputStream::next() { void inputStream::set_done() { size_t end = _beg = _end = _content_end; _next = end + NEXT_PHANTOM; - _line_ending = 0; assert(definitely_done(), ""); } @@ -94,7 +93,6 @@ void inputStream::set_error(bool error_condition) { void inputStream::clear_buffer() { _content_end = _beg = _end = _next = 0; - _line_ending = 0; } const char* inputStream::next_content(size_t& next_content_length) const { @@ -146,7 +144,6 @@ bool inputStream::fill_buffer() { else { COV(FIB_L); } if (last_partial) { assert(have_current_line(), ""); - _line_ending = 0; _content_end -= 1; // reverse insertion of phantom newline assert(_next == _content_end + NEXT_PHANTOM, ""); assert(have_current_line(), ""); @@ -224,7 +221,6 @@ void inputStream::set_buffer_content(size_t content_start, if (nl == nullptr) { COV(SBC_N); _next = _end = content_end; - _line_ending = 0; assert(need_to_read(), ""); } else { COV(SBC_L); @@ -247,7 +243,6 @@ void inputStream::set_buffer_content(size_t content_start, // accept '\r' before '\n'. } _end = end; // now this->current_line() points to buf[beg..end] - _line_ending = (int)(_next - end); assert(have_current_line(), ""); assert(current_line() == &_buffer[_beg], ""); assert(current_line_length() == _end - _beg, ""); @@ -299,7 +294,7 @@ void inputStream::dump(const char* what) { bool ntr = (_next == _end), hcl = (_beg < _content_end && _end < _next), ddn = (_beg == _content_end && _next > _content_end); - tty->print_cr("%s%sistream %s%s%s%s%s [%d<%.*s>%d/%d..%d] LE=%d," + tty->print_cr("%s%sistream %s%s%s%s%s [%d<%.*s>%d/%d..%d] " " B=%llx%s[%d], LN=%d, CH=%d", what ? what : "", what ? ": " : "", _buffer == nullptr ? "U" : "", @@ -312,7 +307,6 @@ void inputStream::dump(const char* what) { diff < 0 ? 0 : diff > 10 ? 10 : diff, _buffer ? &_buffer[_beg] : "", (int)_end, (int)_next, (int)_content_end, - _line_ending, (unsigned long long)(intptr_t)_buffer, _buffer == _small_buffer ? "(SB)" : "", (int)_buffer_size, diff --git a/src/hotspot/share/utilities/istream.hpp b/src/hotspot/share/utilities/istream.hpp index b6a58055b937c..dd12028185956 100644 --- a/src/hotspot/share/utilities/istream.hpp +++ b/src/hotspot/share/utilities/istream.hpp @@ -96,7 +96,6 @@ class inputStream : public CHeapObjBase { Input* _input; // where the input comes from or else nullptr IState _input_state; // one of {NTR,EOF,ERR}_STATE - char _line_ending; // one of {0,1,2} for "", "\n", "\r\n" char* _buffer; // scratch buffer holding at least the current line size_t _buffer_size; // allocated size of buffer size_t _content_end; // offset to end of valid contents of buffer @@ -225,7 +224,6 @@ class inputStream : public CHeapObjBase { inputStream() : _input(nullptr), _input_state(IState::NTR_STATE), - _line_ending(0), _buffer(&_small_buffer[0]), _buffer_size(sizeof(_small_buffer)), _content_end(0), From ab509f1b98329b1624a3111e226b640ee76f5969 Mon Sep 17 00:00:00 2001 From: Andrew Dinn Date: Tue, 6 Aug 2024 13:22:55 +0000 Subject: [PATCH 29/77] 8337654: Relocate uncommon trap stub from SharedRuntime to OptoRuntime Reviewed-by: kvn, vlivanov, fyang --- src/hotspot/cpu/aarch64/runtime_aarch64.cpp | 343 ++++++++++++++++ .../cpu/aarch64/sharedRuntime_aarch64.cpp | 349 ---------------- src/hotspot/cpu/arm/runtime_arm.cpp | 141 ++++++- src/hotspot/cpu/arm/sharedRuntime_arm.cpp | 141 ------- src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp | 4 +- src/hotspot/cpu/riscv/runtime_riscv.cpp | 382 ++++++++++++++++++ src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 343 ---------------- src/hotspot/cpu/s390/sharedRuntime_s390.cpp | 4 +- src/hotspot/cpu/x86/runtime_x86_32.cpp | 174 ++++++++ src/hotspot/cpu/x86/runtime_x86_64.cpp | 327 ++++++++++++++- src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp | 177 -------- src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp | 327 --------------- src/hotspot/share/opto/graphKit.cpp | 2 +- src/hotspot/share/opto/lcm.cpp | 2 +- src/hotspot/share/opto/library_call.cpp | 2 +- src/hotspot/share/opto/loopnode.cpp | 2 +- src/hotspot/share/opto/matcher.cpp | 2 +- src/hotspot/share/opto/runtime.cpp | 4 +- src/hotspot/share/opto/runtime.hpp | 4 + src/hotspot/share/opto/stringopts.cpp | 2 +- src/hotspot/share/runtime/sharedRuntime.cpp | 8 - src/hotspot/share/runtime/sharedRuntime.hpp | 9 - 22 files changed, 1378 insertions(+), 1371 deletions(-) create mode 100644 src/hotspot/cpu/riscv/runtime_riscv.cpp diff --git a/src/hotspot/cpu/aarch64/runtime_aarch64.cpp b/src/hotspot/cpu/aarch64/runtime_aarch64.cpp index 61d27e3224248..09bb370f210f7 100644 --- a/src/hotspot/cpu/aarch64/runtime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/runtime_aarch64.cpp @@ -36,6 +36,349 @@ #include "runtime/vframeArray.hpp" #include "utilities/globalDefinitions.hpp" #include "vmreg_aarch64.inline.hpp" + +class SimpleRuntimeFrame { + + public: + + // Most of the runtime stubs have this simple frame layout. + // This class exists to make the layout shared in one place. + // Offsets are for compiler stack slots, which are jints. + enum layout { + // The frame sender code expects that rbp will be in the "natural" place and + // will override any oopMap setting for it. We must therefore force the layout + // so that it agrees with the frame sender code. + // we don't expect any arg reg save area so aarch64 asserts that + // frame::arg_reg_save_area_bytes == 0 + rfp_off = 0, + rfp_off2, + return_off, return_off2, + framesize + }; +}; + +#define __ masm-> + +//------------------------------generate_uncommon_trap_blob-------------------- +void OptoRuntime::generate_uncommon_trap_blob() { + // Allocate space for the code + ResourceMark rm; + // Setup code generation tools + CodeBuffer buffer("uncommon_trap_blob", 2048, 1024); + MacroAssembler* masm = new MacroAssembler(&buffer); + + assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned"); + + address start = __ pc(); + + // Push self-frame. We get here with a return address in LR + // and sp should be 16 byte aligned + // push rfp and retaddr by hand + __ protect_return_address(); + __ stp(rfp, lr, Address(__ pre(sp, -2 * wordSize))); + // we don't expect an arg reg save area +#ifndef PRODUCT + assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area"); +#endif + // compiler left unloaded_class_index in j_rarg0 move to where the + // runtime expects it. + if (c_rarg1 != j_rarg0) { + __ movw(c_rarg1, j_rarg0); + } + + // we need to set the past SP to the stack pointer of the stub frame + // and the pc to the address where this runtime call will return + // although actually any pc in this code blob will do). + Label retaddr; + __ set_last_Java_frame(sp, noreg, retaddr, rscratch1); + + // Call C code. Need thread but NOT official VM entry + // crud. We cannot block on this call, no GC can happen. Call should + // capture callee-saved registers as well as return values. + // + // UnrollBlock* uncommon_trap(JavaThread* thread, jint unloaded_class_index); + // + // n.b. 2 gp args, 0 fp args, integral return type + + __ mov(c_rarg0, rthread); + __ movw(c_rarg2, (unsigned)Deoptimization::Unpack_uncommon_trap); + __ lea(rscratch1, + RuntimeAddress(CAST_FROM_FN_PTR(address, + Deoptimization::uncommon_trap))); + __ blr(rscratch1); + __ bind(retaddr); + + // Set an oopmap for the call site + OopMapSet* oop_maps = new OopMapSet(); + OopMap* map = new OopMap(SimpleRuntimeFrame::framesize, 0); + + // location of rfp is known implicitly by the frame sender code + + oop_maps->add_gc_map(__ pc() - start, map); + + __ reset_last_Java_frame(false); + + // move UnrollBlock* into r4 + __ mov(r4, r0); + +#ifdef ASSERT + { Label L; + __ ldrw(rscratch1, Address(r4, Deoptimization::UnrollBlock::unpack_kind_offset())); + __ cmpw(rscratch1, (unsigned)Deoptimization::Unpack_uncommon_trap); + __ br(Assembler::EQ, L); + __ stop("OptoRuntime::generate_uncommon_trap_blob: expected Unpack_uncommon_trap"); + __ bind(L); + } +#endif + + // Pop all the frames we must move/replace. + // + // Frame picture (youngest to oldest) + // 1: self-frame (no frame link) + // 2: deopting frame (no frame link) + // 3: caller of deopting frame (could be compiled/interpreted). + + // Pop self-frame. We have no frame, and must rely only on r0 and sp. + __ add(sp, sp, (SimpleRuntimeFrame::framesize) << LogBytesPerInt); // Epilog! + + // Pop deoptimized frame (int) + __ ldrw(r2, Address(r4, + Deoptimization::UnrollBlock:: + size_of_deoptimized_frame_offset())); + __ sub(r2, r2, 2 * wordSize); + __ add(sp, sp, r2); + __ ldp(rfp, zr, __ post(sp, 2 * wordSize)); + +#ifdef ASSERT + // Compilers generate code that bang the stack by as much as the + // interpreter would need. So this stack banging should never + // trigger a fault. Verify that it does not on non product builds. + __ ldrw(r1, Address(r4, + Deoptimization::UnrollBlock:: + total_frame_sizes_offset())); + __ bang_stack_size(r1, r2); +#endif + + // Load address of array of frame pcs into r2 (address*) + __ ldr(r2, Address(r4, + Deoptimization::UnrollBlock::frame_pcs_offset())); + + // Load address of array of frame sizes into r5 (intptr_t*) + __ ldr(r5, Address(r4, + Deoptimization::UnrollBlock:: + frame_sizes_offset())); + + // Counter + __ ldrw(r3, Address(r4, + Deoptimization::UnrollBlock:: + number_of_frames_offset())); // (int) + + // Now adjust the caller's stack to make up for the extra locals but + // record the original sp so that we can save it in the skeletal + // interpreter frame and the stack walking of interpreter_sender + // will get the unextended sp value and not the "real" sp value. + + const Register sender_sp = r8; + + __ mov(sender_sp, sp); + __ ldrw(r1, Address(r4, + Deoptimization::UnrollBlock:: + caller_adjustment_offset())); // (int) + __ sub(sp, sp, r1); + + // Push interpreter frames in a loop + Label loop; + __ bind(loop); + __ ldr(r1, Address(r5, 0)); // Load frame size + __ sub(r1, r1, 2 * wordSize); // We'll push pc and rfp by hand + __ ldr(lr, Address(r2, 0)); // Save return address + __ enter(); // and old rfp & set new rfp + __ sub(sp, sp, r1); // Prolog + __ str(sender_sp, Address(rfp, frame::interpreter_frame_sender_sp_offset * wordSize)); // Make it walkable + // This value is corrected by layout_activation_impl + __ str(zr, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize)); + __ mov(sender_sp, sp); // Pass sender_sp to next frame + __ add(r5, r5, wordSize); // Bump array pointer (sizes) + __ add(r2, r2, wordSize); // Bump array pointer (pcs) + __ subsw(r3, r3, 1); // Decrement counter + __ br(Assembler::GT, loop); + __ ldr(lr, Address(r2, 0)); // save final return address + // Re-push self-frame + __ enter(); // & old rfp & set new rfp + + // Use rfp because the frames look interpreted now + // Save "the_pc" since it cannot easily be retrieved using the last_java_SP after we aligned SP. + // Don't need the precise return PC here, just precise enough to point into this code blob. + address the_pc = __ pc(); + __ set_last_Java_frame(sp, rfp, the_pc, rscratch1); + + // Call C code. Need thread but NOT official VM entry + // crud. We cannot block on this call, no GC can happen. Call should + // restore return values to their stack-slots with the new SP. + // Thread is in rdi already. + // + // BasicType unpack_frames(JavaThread* thread, int exec_mode); + // + // n.b. 2 gp args, 0 fp args, integral return type + + // sp should already be aligned + __ mov(c_rarg0, rthread); + __ movw(c_rarg1, (unsigned)Deoptimization::Unpack_uncommon_trap); + __ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames))); + __ blr(rscratch1); + + // Set an oopmap for the call site + // Use the same PC we used for the last java frame + oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0)); + + // Clear fp AND pc + __ reset_last_Java_frame(true); + + // Pop self-frame. + __ leave(); // Epilog + + // Jump to interpreter + __ ret(lr); + + // Make sure all code is generated + masm->flush(); + + _uncommon_trap_blob = UncommonTrapBlob::create(&buffer, oop_maps, + SimpleRuntimeFrame::framesize >> 1); +} + +//------------------------------generate_exception_blob--------------------------- +// creates exception blob at the end +// Using exception blob, this code is jumped from a compiled method. +// (see emit_exception_handler in aarch64.ad file) +// +// Given an exception pc at a call we call into the runtime for the +// handler in this method. This handler might merely restore state +// (i.e. callee save registers) unwind the frame and jump to the +// exception handler for the nmethod if there is no Java level handler +// for the nmethod. +// +// This code is entered with a jmp. +// +// Arguments: +// r0: exception oop +// r3: exception pc +// +// Results: +// r0: exception oop +// r3: exception pc in caller or ??? +// destination: exception handler of caller +// +// Note: the exception pc MUST be at a call (precise debug information) +// Registers r0, r3, r2, r4, r5, r8-r11 are not callee saved. +// + +void OptoRuntime::generate_exception_blob() { + assert(!OptoRuntime::is_callee_saved_register(R3_num), ""); + assert(!OptoRuntime::is_callee_saved_register(R0_num), ""); + assert(!OptoRuntime::is_callee_saved_register(R2_num), ""); + + assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned"); + + // Allocate space for the code + ResourceMark rm; + // Setup code generation tools + CodeBuffer buffer("exception_blob", 2048, 1024); + MacroAssembler* masm = new MacroAssembler(&buffer); + + // TODO check various assumptions made here + // + // make sure we do so before running this + + address start = __ pc(); + + // push rfp and retaddr by hand + // Exception pc is 'return address' for stack walker + __ protect_return_address(); + __ stp(rfp, lr, Address(__ pre(sp, -2 * wordSize))); + // there are no callee save registers and we don't expect an + // arg reg save area +#ifndef PRODUCT + assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area"); +#endif + // Store exception in Thread object. We cannot pass any arguments to the + // handle_exception call, since we do not want to make any assumption + // about the size of the frame where the exception happened in. + __ str(r0, Address(rthread, JavaThread::exception_oop_offset())); + __ str(r3, Address(rthread, JavaThread::exception_pc_offset())); + + // This call does all the hard work. It checks if an exception handler + // exists in the method. + // If so, it returns the handler address. + // If not, it prepares for stack-unwinding, restoring the callee-save + // registers of the frame being removed. + // + // address OptoRuntime::handle_exception_C(JavaThread* thread) + // + // n.b. 1 gp arg, 0 fp args, integral return type + + // the stack should always be aligned + address the_pc = __ pc(); + __ set_last_Java_frame(sp, noreg, the_pc, rscratch1); + __ mov(c_rarg0, rthread); + __ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C))); + __ blr(rscratch1); + // handle_exception_C is a special VM call which does not require an explicit + // instruction sync afterwards. + + // May jump to SVE compiled code + __ reinitialize_ptrue(); + + // Set an oopmap for the call site. This oopmap will only be used if we + // are unwinding the stack. Hence, all locations will be dead. + // Callee-saved registers will be the same as the frame above (i.e., + // handle_exception_stub), since they were restored when we got the + // exception. + + OopMapSet* oop_maps = new OopMapSet(); + + oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0)); + + __ reset_last_Java_frame(false); + + // Restore callee-saved registers + + // rfp is an implicitly saved callee saved register (i.e. the calling + // convention will save restore it in prolog/epilog) Other than that + // there are no callee save registers now that adapter frames are gone. + // and we dont' expect an arg reg save area + __ ldp(rfp, r3, Address(__ post(sp, 2 * wordSize))); + __ authenticate_return_address(r3); + + // r0: exception handler + + // We have a handler in r0 (could be deopt blob). + __ mov(r8, r0); + + // Get the exception oop + __ ldr(r0, Address(rthread, JavaThread::exception_oop_offset())); + // Get the exception pc in case we are deoptimized + __ ldr(r4, Address(rthread, JavaThread::exception_pc_offset())); +#ifdef ASSERT + __ str(zr, Address(rthread, JavaThread::exception_handler_pc_offset())); + __ str(zr, Address(rthread, JavaThread::exception_pc_offset())); #endif + // Clear the exception oop so GC no longer processes it as a root. + __ str(zr, Address(rthread, JavaThread::exception_oop_offset())); + + // r0: exception oop + // r8: exception handler + // r4: exception pc + // Jump to handler + + __ br(r8); + + // Make sure all code is generated + masm->flush(); + + // Set exception blob + _exception_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1); +} +#endif // COMPILER2 diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index bb2554e65ce83..65c026b95abbd 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -68,26 +68,6 @@ const int StackAlignmentInSlots = StackAlignmentInBytes / VMRegImpl::stack_slot_size; -class SimpleRuntimeFrame { - - public: - - // Most of the runtime stubs have this simple frame layout. - // This class exists to make the layout shared in one place. - // Offsets are for compiler stack slots, which are jints. - enum layout { - // The frame sender code expects that rbp will be in the "natural" place and - // will override any oopMap setting for it. We must therefore force the layout - // so that it agrees with the frame sender code. - // we don't expect any arg reg save area so aarch64 asserts that - // frame::arg_reg_save_area_bytes == 0 - rfp_off = 0, - rfp_off2, - return_off, return_off2, - framesize - }; -}; - // FIXME -- this is used by C1 class RegisterSaver { const bool _save_vectors; @@ -2581,197 +2561,6 @@ uint SharedRuntime::out_preserve_stack_slots() { return 0; } -#ifdef COMPILER2 -//------------------------------generate_uncommon_trap_blob-------------------- -void SharedRuntime::generate_uncommon_trap_blob() { - // Allocate space for the code - ResourceMark rm; - // Setup code generation tools - CodeBuffer buffer("uncommon_trap_blob", 2048, 1024); - MacroAssembler* masm = new MacroAssembler(&buffer); - - assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned"); - - address start = __ pc(); - - // Push self-frame. We get here with a return address in LR - // and sp should be 16 byte aligned - // push rfp and retaddr by hand - __ protect_return_address(); - __ stp(rfp, lr, Address(__ pre(sp, -2 * wordSize))); - // we don't expect an arg reg save area -#ifndef PRODUCT - assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area"); -#endif - // compiler left unloaded_class_index in j_rarg0 move to where the - // runtime expects it. - if (c_rarg1 != j_rarg0) { - __ movw(c_rarg1, j_rarg0); - } - - // we need to set the past SP to the stack pointer of the stub frame - // and the pc to the address where this runtime call will return - // although actually any pc in this code blob will do). - Label retaddr; - __ set_last_Java_frame(sp, noreg, retaddr, rscratch1); - - // Call C code. Need thread but NOT official VM entry - // crud. We cannot block on this call, no GC can happen. Call should - // capture callee-saved registers as well as return values. - // Thread is in rdi already. - // - // UnrollBlock* uncommon_trap(JavaThread* thread, jint unloaded_class_index); - // - // n.b. 2 gp args, 0 fp args, integral return type - - __ mov(c_rarg0, rthread); - __ movw(c_rarg2, (unsigned)Deoptimization::Unpack_uncommon_trap); - __ lea(rscratch1, - RuntimeAddress(CAST_FROM_FN_PTR(address, - Deoptimization::uncommon_trap))); - __ blr(rscratch1); - __ bind(retaddr); - - // Set an oopmap for the call site - OopMapSet* oop_maps = new OopMapSet(); - OopMap* map = new OopMap(SimpleRuntimeFrame::framesize, 0); - - // location of rfp is known implicitly by the frame sender code - - oop_maps->add_gc_map(__ pc() - start, map); - - __ reset_last_Java_frame(false); - - // move UnrollBlock* into r4 - __ mov(r4, r0); - -#ifdef ASSERT - { Label L; - __ ldrw(rscratch1, Address(r4, Deoptimization::UnrollBlock::unpack_kind_offset())); - __ cmpw(rscratch1, (unsigned)Deoptimization::Unpack_uncommon_trap); - __ br(Assembler::EQ, L); - __ stop("SharedRuntime::generate_uncommon_trap_blob: expected Unpack_uncommon_trap"); - __ bind(L); - } -#endif - - // Pop all the frames we must move/replace. - // - // Frame picture (youngest to oldest) - // 1: self-frame (no frame link) - // 2: deopting frame (no frame link) - // 3: caller of deopting frame (could be compiled/interpreted). - - // Pop self-frame. We have no frame, and must rely only on r0 and sp. - __ add(sp, sp, (SimpleRuntimeFrame::framesize) << LogBytesPerInt); // Epilog! - - // Pop deoptimized frame (int) - __ ldrw(r2, Address(r4, - Deoptimization::UnrollBlock:: - size_of_deoptimized_frame_offset())); - __ sub(r2, r2, 2 * wordSize); - __ add(sp, sp, r2); - __ ldp(rfp, zr, __ post(sp, 2 * wordSize)); - -#ifdef ASSERT - // Compilers generate code that bang the stack by as much as the - // interpreter would need. So this stack banging should never - // trigger a fault. Verify that it does not on non product builds. - __ ldrw(r1, Address(r4, - Deoptimization::UnrollBlock:: - total_frame_sizes_offset())); - __ bang_stack_size(r1, r2); -#endif - - // Load address of array of frame pcs into r2 (address*) - __ ldr(r2, Address(r4, - Deoptimization::UnrollBlock::frame_pcs_offset())); - - // Load address of array of frame sizes into r5 (intptr_t*) - __ ldr(r5, Address(r4, - Deoptimization::UnrollBlock:: - frame_sizes_offset())); - - // Counter - __ ldrw(r3, Address(r4, - Deoptimization::UnrollBlock:: - number_of_frames_offset())); // (int) - - // Now adjust the caller's stack to make up for the extra locals but - // record the original sp so that we can save it in the skeletal - // interpreter frame and the stack walking of interpreter_sender - // will get the unextended sp value and not the "real" sp value. - - const Register sender_sp = r8; - - __ mov(sender_sp, sp); - __ ldrw(r1, Address(r4, - Deoptimization::UnrollBlock:: - caller_adjustment_offset())); // (int) - __ sub(sp, sp, r1); - - // Push interpreter frames in a loop - Label loop; - __ bind(loop); - __ ldr(r1, Address(r5, 0)); // Load frame size - __ sub(r1, r1, 2 * wordSize); // We'll push pc and rfp by hand - __ ldr(lr, Address(r2, 0)); // Save return address - __ enter(); // and old rfp & set new rfp - __ sub(sp, sp, r1); // Prolog - __ str(sender_sp, Address(rfp, frame::interpreter_frame_sender_sp_offset * wordSize)); // Make it walkable - // This value is corrected by layout_activation_impl - __ str(zr, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize)); - __ mov(sender_sp, sp); // Pass sender_sp to next frame - __ add(r5, r5, wordSize); // Bump array pointer (sizes) - __ add(r2, r2, wordSize); // Bump array pointer (pcs) - __ subsw(r3, r3, 1); // Decrement counter - __ br(Assembler::GT, loop); - __ ldr(lr, Address(r2, 0)); // save final return address - // Re-push self-frame - __ enter(); // & old rfp & set new rfp - - // Use rfp because the frames look interpreted now - // Save "the_pc" since it cannot easily be retrieved using the last_java_SP after we aligned SP. - // Don't need the precise return PC here, just precise enough to point into this code blob. - address the_pc = __ pc(); - __ set_last_Java_frame(sp, rfp, the_pc, rscratch1); - - // Call C code. Need thread but NOT official VM entry - // crud. We cannot block on this call, no GC can happen. Call should - // restore return values to their stack-slots with the new SP. - // Thread is in rdi already. - // - // BasicType unpack_frames(JavaThread* thread, int exec_mode); - // - // n.b. 2 gp args, 0 fp args, integral return type - - // sp should already be aligned - __ mov(c_rarg0, rthread); - __ movw(c_rarg1, (unsigned)Deoptimization::Unpack_uncommon_trap); - __ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames))); - __ blr(rscratch1); - - // Set an oopmap for the call site - // Use the same PC we used for the last java frame - oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0)); - - // Clear fp AND pc - __ reset_last_Java_frame(true); - - // Pop self-frame. - __ leave(); // Epilog - - // Jump to interpreter - __ ret(lr); - - // Make sure all code is generated - masm->flush(); - - _uncommon_trap_blob = UncommonTrapBlob::create(&buffer, oop_maps, - SimpleRuntimeFrame::framesize >> 1); -} -#endif // COMPILER2 - //------------------------------generate_handler_blob------ // @@ -2983,141 +2772,3 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha // frame_size_words or bytes?? return RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_in_words, oop_maps, true); } - -#ifdef COMPILER2 -// This is here instead of runtime_aarch64_64.cpp because it uses SimpleRuntimeFrame -// -//------------------------------generate_exception_blob--------------------------- -// creates exception blob at the end -// Using exception blob, this code is jumped from a compiled method. -// (see emit_exception_handler in x86_64.ad file) -// -// Given an exception pc at a call we call into the runtime for the -// handler in this method. This handler might merely restore state -// (i.e. callee save registers) unwind the frame and jump to the -// exception handler for the nmethod if there is no Java level handler -// for the nmethod. -// -// This code is entered with a jmp. -// -// Arguments: -// r0: exception oop -// r3: exception pc -// -// Results: -// r0: exception oop -// r3: exception pc in caller or ??? -// destination: exception handler of caller -// -// Note: the exception pc MUST be at a call (precise debug information) -// Registers r0, r3, r2, r4, r5, r8-r11 are not callee saved. -// - -void OptoRuntime::generate_exception_blob() { - assert(!OptoRuntime::is_callee_saved_register(R3_num), ""); - assert(!OptoRuntime::is_callee_saved_register(R0_num), ""); - assert(!OptoRuntime::is_callee_saved_register(R2_num), ""); - - assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned"); - - // Allocate space for the code - ResourceMark rm; - // Setup code generation tools - CodeBuffer buffer("exception_blob", 2048, 1024); - MacroAssembler* masm = new MacroAssembler(&buffer); - - // TODO check various assumptions made here - // - // make sure we do so before running this - - address start = __ pc(); - - // push rfp and retaddr by hand - // Exception pc is 'return address' for stack walker - __ protect_return_address(); - __ stp(rfp, lr, Address(__ pre(sp, -2 * wordSize))); - // there are no callee save registers and we don't expect an - // arg reg save area -#ifndef PRODUCT - assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area"); -#endif - // Store exception in Thread object. We cannot pass any arguments to the - // handle_exception call, since we do not want to make any assumption - // about the size of the frame where the exception happened in. - __ str(r0, Address(rthread, JavaThread::exception_oop_offset())); - __ str(r3, Address(rthread, JavaThread::exception_pc_offset())); - - // This call does all the hard work. It checks if an exception handler - // exists in the method. - // If so, it returns the handler address. - // If not, it prepares for stack-unwinding, restoring the callee-save - // registers of the frame being removed. - // - // address OptoRuntime::handle_exception_C(JavaThread* thread) - // - // n.b. 1 gp arg, 0 fp args, integral return type - - // the stack should always be aligned - address the_pc = __ pc(); - __ set_last_Java_frame(sp, noreg, the_pc, rscratch1); - __ mov(c_rarg0, rthread); - __ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C))); - __ blr(rscratch1); - // handle_exception_C is a special VM call which does not require an explicit - // instruction sync afterwards. - - // May jump to SVE compiled code - __ reinitialize_ptrue(); - - // Set an oopmap for the call site. This oopmap will only be used if we - // are unwinding the stack. Hence, all locations will be dead. - // Callee-saved registers will be the same as the frame above (i.e., - // handle_exception_stub), since they were restored when we got the - // exception. - - OopMapSet* oop_maps = new OopMapSet(); - - oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0)); - - __ reset_last_Java_frame(false); - - // Restore callee-saved registers - - // rfp is an implicitly saved callee saved register (i.e. the calling - // convention will save restore it in prolog/epilog) Other than that - // there are no callee save registers now that adapter frames are gone. - // and we dont' expect an arg reg save area - __ ldp(rfp, r3, Address(__ post(sp, 2 * wordSize))); - __ authenticate_return_address(r3); - - // r0: exception handler - - // We have a handler in r0 (could be deopt blob). - __ mov(r8, r0); - - // Get the exception oop - __ ldr(r0, Address(rthread, JavaThread::exception_oop_offset())); - // Get the exception pc in case we are deoptimized - __ ldr(r4, Address(rthread, JavaThread::exception_pc_offset())); -#ifdef ASSERT - __ str(zr, Address(rthread, JavaThread::exception_handler_pc_offset())); - __ str(zr, Address(rthread, JavaThread::exception_pc_offset())); -#endif - // Clear the exception oop so GC no longer processes it as a root. - __ str(zr, Address(rthread, JavaThread::exception_oop_offset())); - - // r0: exception oop - // r8: exception handler - // r4: exception pc - // Jump to handler - - __ br(r8); - - // Make sure all code is generated - masm->flush(); - - // Set exception blob - _exception_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1); -} - -#endif // COMPILER2 diff --git a/src/hotspot/cpu/arm/runtime_arm.cpp b/src/hotspot/cpu/arm/runtime_arm.cpp index 94a9ef553c75e..6f6c0c17e000d 100644 --- a/src/hotspot/cpu/arm/runtime_arm.cpp +++ b/src/hotspot/cpu/arm/runtime_arm.cpp @@ -37,10 +37,146 @@ #include "runtime/vframeArray.hpp" #include "utilities/globalDefinitions.hpp" #include "vmreg_arm.inline.hpp" -#endif #define __ masm-> +//------------------------------generate_uncommon_trap_blob-------------------- +// Ought to generate an ideal graph & compile, but here's some ASM +// instead. +void OptoRuntime::generate_uncommon_trap_blob() { + // allocate space for the code + ResourceMark rm; + + // setup code generation tools +#ifdef _LP64 + CodeBuffer buffer("uncommon_trap_blob", 2700, 512); +#else + // Measured 8/7/03 at 660 in 32bit debug build + CodeBuffer buffer("uncommon_trap_blob", 2000, 512); +#endif + // bypassed when code generation useless + MacroAssembler* masm = new MacroAssembler(&buffer); + const Register Rublock = R6; + const Register Rsender = altFP_7_11; + assert_different_registers(Rublock, Rsender, Rexception_obj, R0, R1, R2, R3, R8, Rtemp); + + // + // This is the entry point for all traps the compiler takes when it thinks + // it cannot handle further execution of compilation code. The frame is + // deoptimized in these cases and converted into interpreter frames for + // execution + // The steps taken by this frame are as follows: + // - push a fake "unpack_frame" + // - call the C routine Deoptimization::uncommon_trap (this function + // packs the current compiled frame into vframe arrays and returns + // information about the number and size of interpreter frames which + // are equivalent to the frame which is being deoptimized) + // - deallocate the "unpack_frame" + // - deallocate the deoptimization frame + // - in a loop using the information returned in the previous step + // push interpreter frames; + // - create a dummy "unpack_frame" + // - call the C routine: Deoptimization::unpack_frames (this function + // lays out values on the interpreter frame which was just created) + // - deallocate the dummy unpack_frame + // - return to the interpreter entry point + // + // Refer to the following methods for more information: + // - Deoptimization::uncommon_trap + // - Deoptimization::unpack_frame + + // the unloaded class index is in R0 (first parameter to this blob) + + __ raw_push(FP, LR); + __ set_last_Java_frame(SP, FP, false, Rtemp); + __ mov(R2, Deoptimization::Unpack_uncommon_trap); + __ mov(R1, R0); + __ mov(R0, Rthread); + __ call(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)); + __ mov(Rublock, R0); + __ reset_last_Java_frame(Rtemp); + __ raw_pop(FP, LR); + +#ifdef ASSERT + { Label L; + __ ldr_s32(Rtemp, Address(Rublock, Deoptimization::UnrollBlock::unpack_kind_offset())); + __ cmp_32(Rtemp, Deoptimization::Unpack_uncommon_trap); + __ b(L, eq); + __ stop("OptoRuntime::generate_uncommon_trap_blob: expected Unpack_uncommon_trap"); + __ bind(L); + } +#endif + + + // Set initial stack state before pushing interpreter frames + __ ldr_s32(Rtemp, Address(Rublock, Deoptimization::UnrollBlock::size_of_deoptimized_frame_offset())); + __ ldr(R2, Address(Rublock, Deoptimization::UnrollBlock::frame_pcs_offset())); + __ ldr(R3, Address(Rublock, Deoptimization::UnrollBlock::frame_sizes_offset())); + + __ add(SP, SP, Rtemp); + + // See if it is enough stack to push deoptimized frames. +#ifdef ASSERT + // Compilers generate code that bang the stack by as much as the + // interpreter would need. So this stack banging should never + // trigger a fault. Verify that it does not on non product builds. + // + // The compiled method that we are deoptimizing was popped from the stack. + // If the stack bang results in a stack overflow, we don't return to the + // method that is being deoptimized. The stack overflow exception is + // propagated to the caller of the deoptimized method. Need to get the pc + // from the caller in LR and restore FP. + __ ldr(LR, Address(R2, 0)); + __ ldr(FP, Address(Rublock, Deoptimization::UnrollBlock::initial_info_offset())); + __ ldr_s32(R8, Address(Rublock, Deoptimization::UnrollBlock::total_frame_sizes_offset())); + __ arm_stack_overflow_check(R8, Rtemp); +#endif + __ ldr_s32(R8, Address(Rublock, Deoptimization::UnrollBlock::number_of_frames_offset())); + __ ldr_s32(Rtemp, Address(Rublock, Deoptimization::UnrollBlock::caller_adjustment_offset())); + __ mov(Rsender, SP); + __ sub(SP, SP, Rtemp); + // __ ldr(FP, Address(FP)); + __ ldr(FP, Address(Rublock, Deoptimization::UnrollBlock::initial_info_offset())); + + // Push interpreter frames in a loop + Label loop; + __ bind(loop); + __ ldr(LR, Address(R2, wordSize, post_indexed)); // load frame pc + __ ldr(Rtemp, Address(R3, wordSize, post_indexed)); // load frame size + + __ raw_push(FP, LR); // create new frame + __ mov(FP, SP); + __ sub(Rtemp, Rtemp, 2*wordSize); + + __ sub(SP, SP, Rtemp); + + __ str(Rsender, Address(FP, frame::interpreter_frame_sender_sp_offset * wordSize)); + __ mov(LR, 0); + __ str(LR, Address(FP, frame::interpreter_frame_last_sp_offset * wordSize)); + __ subs(R8, R8, 1); // decrement counter + __ mov(Rsender, SP); + __ b(loop, ne); + + // Re-push self-frame + __ ldr(LR, Address(R2)); + __ raw_push(FP, LR); + __ mov(FP, SP); + + // Call unpack_frames with proper arguments + __ mov(R0, Rthread); + __ mov(R1, Deoptimization::Unpack_uncommon_trap); + __ set_last_Java_frame(SP, FP, true, Rtemp); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames)); + // oop_maps->add_gc_map(__ pc() - start, new OopMap(frame_size_in_words, 0)); + __ reset_last_Java_frame(Rtemp); + + __ mov(SP, FP); + __ pop(RegisterSet(FP) | RegisterSet(PC)); + + masm->flush(); + _uncommon_trap_blob = UncommonTrapBlob::create(&buffer, nullptr, 2 /* LR+FP */); +} + //------------------------------ generate_exception_blob --------------------------- // creates exception blob at the end // Using exception blob, this code is jumped from a compiled method. @@ -148,3 +284,6 @@ void OptoRuntime::generate_exception_blob() { _exception_blob = ExceptionBlob::create(&buffer, oop_maps, framesize_in_words); } + +#endif // COMPILER2 + diff --git a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp index 3792fab082ba6..1305283aeaeba 100644 --- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp +++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp @@ -1595,147 +1595,6 @@ void SharedRuntime::generate_deopt_blob() { _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset); } -#ifdef COMPILER2 - -//------------------------------generate_uncommon_trap_blob-------------------- -// Ought to generate an ideal graph & compile, but here's some ASM -// instead. -void SharedRuntime::generate_uncommon_trap_blob() { - // allocate space for the code - ResourceMark rm; - - // setup code generation tools -#ifdef _LP64 - CodeBuffer buffer("uncommon_trap_blob", 2700, 512); -#else - // Measured 8/7/03 at 660 in 32bit debug build - CodeBuffer buffer("uncommon_trap_blob", 2000, 512); -#endif - // bypassed when code generation useless - MacroAssembler* masm = new MacroAssembler(&buffer); - const Register Rublock = R6; - const Register Rsender = altFP_7_11; - assert_different_registers(Rublock, Rsender, Rexception_obj, R0, R1, R2, R3, R8, Rtemp); - - // - // This is the entry point for all traps the compiler takes when it thinks - // it cannot handle further execution of compilation code. The frame is - // deoptimized in these cases and converted into interpreter frames for - // execution - // The steps taken by this frame are as follows: - // - push a fake "unpack_frame" - // - call the C routine Deoptimization::uncommon_trap (this function - // packs the current compiled frame into vframe arrays and returns - // information about the number and size of interpreter frames which - // are equivalent to the frame which is being deoptimized) - // - deallocate the "unpack_frame" - // - deallocate the deoptimization frame - // - in a loop using the information returned in the previous step - // push interpreter frames; - // - create a dummy "unpack_frame" - // - call the C routine: Deoptimization::unpack_frames (this function - // lays out values on the interpreter frame which was just created) - // - deallocate the dummy unpack_frame - // - return to the interpreter entry point - // - // Refer to the following methods for more information: - // - Deoptimization::uncommon_trap - // - Deoptimization::unpack_frame - - // the unloaded class index is in R0 (first parameter to this blob) - - __ raw_push(FP, LR); - __ set_last_Java_frame(SP, FP, false, Rtemp); - __ mov(R2, Deoptimization::Unpack_uncommon_trap); - __ mov(R1, R0); - __ mov(R0, Rthread); - __ call(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)); - __ mov(Rublock, R0); - __ reset_last_Java_frame(Rtemp); - __ raw_pop(FP, LR); - -#ifdef ASSERT - { Label L; - __ ldr_s32(Rtemp, Address(Rublock, Deoptimization::UnrollBlock::unpack_kind_offset())); - __ cmp_32(Rtemp, Deoptimization::Unpack_uncommon_trap); - __ b(L, eq); - __ stop("SharedRuntime::generate_uncommon_trap_blob: expected Unpack_uncommon_trap"); - __ bind(L); - } -#endif - - - // Set initial stack state before pushing interpreter frames - __ ldr_s32(Rtemp, Address(Rublock, Deoptimization::UnrollBlock::size_of_deoptimized_frame_offset())); - __ ldr(R2, Address(Rublock, Deoptimization::UnrollBlock::frame_pcs_offset())); - __ ldr(R3, Address(Rublock, Deoptimization::UnrollBlock::frame_sizes_offset())); - - __ add(SP, SP, Rtemp); - - // See if it is enough stack to push deoptimized frames. -#ifdef ASSERT - // Compilers generate code that bang the stack by as much as the - // interpreter would need. So this stack banging should never - // trigger a fault. Verify that it does not on non product builds. - // - // The compiled method that we are deoptimizing was popped from the stack. - // If the stack bang results in a stack overflow, we don't return to the - // method that is being deoptimized. The stack overflow exception is - // propagated to the caller of the deoptimized method. Need to get the pc - // from the caller in LR and restore FP. - __ ldr(LR, Address(R2, 0)); - __ ldr(FP, Address(Rublock, Deoptimization::UnrollBlock::initial_info_offset())); - __ ldr_s32(R8, Address(Rublock, Deoptimization::UnrollBlock::total_frame_sizes_offset())); - __ arm_stack_overflow_check(R8, Rtemp); -#endif - __ ldr_s32(R8, Address(Rublock, Deoptimization::UnrollBlock::number_of_frames_offset())); - __ ldr_s32(Rtemp, Address(Rublock, Deoptimization::UnrollBlock::caller_adjustment_offset())); - __ mov(Rsender, SP); - __ sub(SP, SP, Rtemp); - // __ ldr(FP, Address(FP)); - __ ldr(FP, Address(Rublock, Deoptimization::UnrollBlock::initial_info_offset())); - - // Push interpreter frames in a loop - Label loop; - __ bind(loop); - __ ldr(LR, Address(R2, wordSize, post_indexed)); // load frame pc - __ ldr(Rtemp, Address(R3, wordSize, post_indexed)); // load frame size - - __ raw_push(FP, LR); // create new frame - __ mov(FP, SP); - __ sub(Rtemp, Rtemp, 2*wordSize); - - __ sub(SP, SP, Rtemp); - - __ str(Rsender, Address(FP, frame::interpreter_frame_sender_sp_offset * wordSize)); - __ mov(LR, 0); - __ str(LR, Address(FP, frame::interpreter_frame_last_sp_offset * wordSize)); - __ subs(R8, R8, 1); // decrement counter - __ mov(Rsender, SP); - __ b(loop, ne); - - // Re-push self-frame - __ ldr(LR, Address(R2)); - __ raw_push(FP, LR); - __ mov(FP, SP); - - // Call unpack_frames with proper arguments - __ mov(R0, Rthread); - __ mov(R1, Deoptimization::Unpack_uncommon_trap); - __ set_last_Java_frame(SP, FP, true, Rtemp); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames)); - // oop_maps->add_gc_map(__ pc() - start, new OopMap(frame_size_in_words, 0)); - __ reset_last_Java_frame(Rtemp); - - __ mov(SP, FP); - __ pop(RegisterSet(FP) | RegisterSet(PC)); - - masm->flush(); - _uncommon_trap_blob = UncommonTrapBlob::create(&buffer, nullptr, 2 /* LR+FP */); -} - -#endif // COMPILER2 - //------------------------------generate_handler_blob------ // // Generate a special Compile2Runtime blob that saves all registers, diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp index 9b5a86bc45bfd..505f67ab6f952 100644 --- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp +++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp @@ -3078,7 +3078,7 @@ void SharedRuntime::generate_deopt_blob() { } #ifdef COMPILER2 -void SharedRuntime::generate_uncommon_trap_blob() { +void OptoRuntime::generate_uncommon_trap_blob() { // Allocate space for the code. ResourceMark rm; // Setup code generation tools. @@ -3144,7 +3144,7 @@ void SharedRuntime::generate_uncommon_trap_blob() { #ifdef ASSERT __ lwz(R22_tmp2, in_bytes(Deoptimization::UnrollBlock::unpack_kind_offset()), unroll_block_reg); __ cmpdi(CCR0, R22_tmp2, (unsigned)Deoptimization::Unpack_uncommon_trap); - __ asm_assert_eq("SharedRuntime::generate_deopt_blob: expected Unpack_uncommon_trap"); + __ asm_assert_eq("OptoRuntime::generate_uncommon_trap_blob: expected Unpack_uncommon_trap"); #endif // Freezing continuation frames requires that the caller is trimmed to unextended sp if compiled. diff --git a/src/hotspot/cpu/riscv/runtime_riscv.cpp b/src/hotspot/cpu/riscv/runtime_riscv.cpp new file mode 100644 index 0000000000000..9e16278c3b547 --- /dev/null +++ b/src/hotspot/cpu/riscv/runtime_riscv.cpp @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, Red Hat Inc. 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. + * + * 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. + * + */ + +#include "precompiled.hpp" +#ifdef COMPILER2 +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "code/vmreg.hpp" +#include "interpreter/interpreter.hpp" +#include "opto/runtime.hpp" +#include "runtime/interfaceSupport.inline.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/vframeArray.hpp" +#include "utilities/globalDefinitions.hpp" +#include "vmreg_riscv.inline.hpp" + +class SimpleRuntimeFrame { +public: + + // Most of the runtime stubs have this simple frame layout. + // This class exists to make the layout shared in one place. + // Offsets are for compiler stack slots, which are jints. + enum layout { + // The frame sender code expects that fp will be in the "natural" place and + // will override any oopMap setting for it. We must therefore force the layout + // so that it agrees with the frame sender code. + // we don't expect any arg reg save area so riscv asserts that + // frame::arg_reg_save_area_bytes == 0 + fp_off = 0, fp_off2, + return_off, return_off2, + framesize + }; +}; + +#define __ masm-> + +//------------------------------generate_uncommon_trap_blob-------------------- +void OptoRuntime::generate_uncommon_trap_blob() { + // Allocate space for the code + ResourceMark rm; + // Setup code generation tools + CodeBuffer buffer("uncommon_trap_blob", 2048, 1024); + MacroAssembler* masm = new MacroAssembler(&buffer); + assert_cond(masm != nullptr); + + assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned"); + + address start = __ pc(); + + // Push self-frame. We get here with a return address in RA + // and sp should be 16 byte aligned + // push fp and retaddr by hand + __ addi(sp, sp, -2 * wordSize); + __ sd(ra, Address(sp, wordSize)); + __ sd(fp, Address(sp, 0)); + // we don't expect an arg reg save area +#ifndef PRODUCT + assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area"); +#endif + // compiler left unloaded_class_index in j_rarg0 move to where the + // runtime expects it. + __ sign_extend(c_rarg1, j_rarg0, 32); + + // we need to set the past SP to the stack pointer of the stub frame + // and the pc to the address where this runtime call will return + // although actually any pc in this code blob will do). + Label retaddr; + __ set_last_Java_frame(sp, noreg, retaddr, t0); + + // Call C code. Need thread but NOT official VM entry + // crud. We cannot block on this call, no GC can happen. Call should + // capture callee-saved registers as well as return values. + // + // UnrollBlock* uncommon_trap(JavaThread* thread, jint unloaded_class_index, jint exec_mode) + // + // n.b. 3 gp args, 0 fp args, integral return type + + __ mv(c_rarg0, xthread); + __ mv(c_rarg2, Deoptimization::Unpack_uncommon_trap); + __ rt_call(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)); + __ bind(retaddr); + + // Set an oopmap for the call site + OopMapSet* oop_maps = new OopMapSet(); + OopMap* map = new OopMap(SimpleRuntimeFrame::framesize, 0); + assert_cond(oop_maps != nullptr && map != nullptr); + + // location of fp is known implicitly by the frame sender code + + oop_maps->add_gc_map(__ pc() - start, map); + + __ reset_last_Java_frame(false); + + // move UnrollBlock* into x14 + __ mv(x14, x10); + +#ifdef ASSERT + { Label L; + __ lwu(t0, Address(x14, Deoptimization::UnrollBlock::unpack_kind_offset())); + __ mv(t1, Deoptimization::Unpack_uncommon_trap); + __ beq(t0, t1, L); + __ stop("OptoRuntime::generate_uncommon_trap_blob: expected Unpack_uncommon_trap"); + __ bind(L); + } +#endif + + // Pop all the frames we must move/replace. + // + // Frame picture (youngest to oldest) + // 1: self-frame (no frame link) + // 2: deopting frame (no frame link) + // 3: caller of deopting frame (could be compiled/interpreted). + + __ add(sp, sp, (SimpleRuntimeFrame::framesize) << LogBytesPerInt); // Epilog! + + // Pop deoptimized frame (int) + __ lwu(x12, Address(x14, + Deoptimization::UnrollBlock:: + size_of_deoptimized_frame_offset())); + __ sub(x12, x12, 2 * wordSize); + __ add(sp, sp, x12); + __ ld(fp, Address(sp, 0)); + __ ld(ra, Address(sp, wordSize)); + __ addi(sp, sp, 2 * wordSize); + // RA should now be the return address to the caller (3) frame + +#ifdef ASSERT + // Compilers generate code that bang the stack by as much as the + // interpreter would need. So this stack banging should never + // trigger a fault. Verify that it does not on non product builds. + __ lwu(x11, Address(x14, + Deoptimization::UnrollBlock:: + total_frame_sizes_offset())); + __ bang_stack_size(x11, x12); +#endif + + // Load address of array of frame pcs into x12 (address*) + __ ld(x12, Address(x14, + Deoptimization::UnrollBlock::frame_pcs_offset())); + + // Load address of array of frame sizes into x15 (intptr_t*) + __ ld(x15, Address(x14, + Deoptimization::UnrollBlock:: + frame_sizes_offset())); + + // Counter + __ lwu(x13, Address(x14, + Deoptimization::UnrollBlock:: + number_of_frames_offset())); // (int) + + // Now adjust the caller's stack to make up for the extra locals but + // record the original sp so that we can save it in the skeletal + // interpreter frame and the stack walking of interpreter_sender + // will get the unextended sp value and not the "real" sp value. + + const Register sender_sp = t1; // temporary register + + __ lwu(x11, Address(x14, + Deoptimization::UnrollBlock:: + caller_adjustment_offset())); // (int) + __ mv(sender_sp, sp); + __ sub(sp, sp, x11); + + // Push interpreter frames in a loop + Label loop; + __ bind(loop); + __ ld(x11, Address(x15, 0)); // Load frame size + __ sub(x11, x11, 2 * wordSize); // We'll push pc and fp by hand + __ ld(ra, Address(x12, 0)); // Save return address + __ enter(); // and old fp & set new fp + __ sub(sp, sp, x11); // Prolog + __ sd(sender_sp, Address(fp, frame::interpreter_frame_sender_sp_offset * wordSize)); // Make it walkable + // This value is corrected by layout_activation_impl + __ sd(zr, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize)); + __ mv(sender_sp, sp); // Pass sender_sp to next frame + __ add(x15, x15, wordSize); // Bump array pointer (sizes) + __ add(x12, x12, wordSize); // Bump array pointer (pcs) + __ subw(x13, x13, 1); // Decrement counter + __ bgtz(x13, loop); + __ ld(ra, Address(x12, 0)); // save final return address + // Re-push self-frame + __ enter(); // & old fp & set new fp + + // Use fp because the frames look interpreted now + // Save "the_pc" since it cannot easily be retrieved using the last_java_SP after we aligned SP. + // Don't need the precise return PC here, just precise enough to point into this code blob. + address the_pc = __ pc(); + __ set_last_Java_frame(sp, fp, the_pc, t0); + + // Call C code. Need thread but NOT official VM entry + // crud. We cannot block on this call, no GC can happen. Call should + // restore return values to their stack-slots with the new SP. + // + // BasicType unpack_frames(JavaThread* thread, int exec_mode) + // + + // n.b. 2 gp args, 0 fp args, integral return type + + // sp should already be aligned + __ mv(c_rarg0, xthread); + __ mv(c_rarg1, Deoptimization::Unpack_uncommon_trap); + __ rt_call(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames)); + + // Set an oopmap for the call site + // Use the same PC we used for the last java frame + oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0)); + + // Clear fp AND pc + __ reset_last_Java_frame(true); + + // Pop self-frame. + __ leave(); // Epilog + + // Jump to interpreter + __ ret(); + + // Make sure all code is generated + masm->flush(); + + _uncommon_trap_blob = UncommonTrapBlob::create(&buffer, oop_maps, + SimpleRuntimeFrame::framesize >> 1); +} + +//------------------------------generate_exception_blob--------------------------- +// creates exception blob at the end +// Using exception blob, this code is jumped from a compiled method. +// (see emit_exception_handler in riscv.ad file) +// +// Given an exception pc at a call we call into the runtime for the +// handler in this method. This handler might merely restore state +// (i.e. callee save registers) unwind the frame and jump to the +// exception handler for the nmethod if there is no Java level handler +// for the nmethod. +// +// This code is entered with a jmp. +// +// Arguments: +// x10: exception oop +// x13: exception pc +// +// Results: +// x10: exception oop +// x13: exception pc in caller +// destination: exception handler of caller +// +// Note: the exception pc MUST be at a call (precise debug information) +// Registers x10, x13, x12, x14, x15, t0 are not callee saved. +// + +void OptoRuntime::generate_exception_blob() { + assert(!OptoRuntime::is_callee_saved_register(R13_num), ""); + assert(!OptoRuntime::is_callee_saved_register(R10_num), ""); + assert(!OptoRuntime::is_callee_saved_register(R12_num), ""); + + assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned"); + + // Allocate space for the code + ResourceMark rm; + // Setup code generation tools + CodeBuffer buffer("exception_blob", 2048, 1024); + MacroAssembler* masm = new MacroAssembler(&buffer); + assert_cond(masm != nullptr); + + // TODO check various assumptions made here + // + // make sure we do so before running this + + address start = __ pc(); + + // push fp and retaddr by hand + // Exception pc is 'return address' for stack walker + __ addi(sp, sp, -2 * wordSize); + __ sd(ra, Address(sp, wordSize)); + __ sd(fp, Address(sp)); + // there are no callee save registers and we don't expect an + // arg reg save area +#ifndef PRODUCT + assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area"); +#endif + // Store exception in Thread object. We cannot pass any arguments to the + // handle_exception call, since we do not want to make any assumption + // about the size of the frame where the exception happened in. + __ sd(x10, Address(xthread, JavaThread::exception_oop_offset())); + __ sd(x13, Address(xthread, JavaThread::exception_pc_offset())); + + // This call does all the hard work. It checks if an exception handler + // exists in the method. + // If so, it returns the handler address. + // If not, it prepares for stack-unwinding, restoring the callee-save + // registers of the frame being removed. + // + // address OptoRuntime::handle_exception_C(JavaThread* thread) + // + // n.b. 1 gp arg, 0 fp args, integral return type + + // the stack should always be aligned + address the_pc = __ pc(); + __ set_last_Java_frame(sp, noreg, the_pc, t0); + __ mv(c_rarg0, xthread); + __ rt_call(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C)); + + // handle_exception_C is a special VM call which does not require an explicit + // instruction sync afterwards. + + // Set an oopmap for the call site. This oopmap will only be used if we + // are unwinding the stack. Hence, all locations will be dead. + // Callee-saved registers will be the same as the frame above (i.e., + // handle_exception_stub), since they were restored when we got the + // exception. + + OopMapSet* oop_maps = new OopMapSet(); + assert_cond(oop_maps != nullptr); + + oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0)); + + __ reset_last_Java_frame(false); + + // Restore callee-saved registers + + // fp is an implicitly saved callee saved register (i.e. the calling + // convention will save restore it in prolog/epilog) Other than that + // there are no callee save registers now that adapter frames are gone. + // and we dont' expect an arg reg save area + __ ld(fp, Address(sp)); + __ ld(x13, Address(sp, wordSize)); + __ addi(sp, sp , 2 * wordSize); + + // x10: exception handler + + // We have a handler in x10 (could be deopt blob). + __ mv(t0, x10); + + // Get the exception oop + __ ld(x10, Address(xthread, JavaThread::exception_oop_offset())); + // Get the exception pc in case we are deoptimized + __ ld(x14, Address(xthread, JavaThread::exception_pc_offset())); +#ifdef ASSERT + __ sd(zr, Address(xthread, JavaThread::exception_handler_pc_offset())); + __ sd(zr, Address(xthread, JavaThread::exception_pc_offset())); +#endif + // Clear the exception oop so GC no longer processes it as a root. + __ sd(zr, Address(xthread, JavaThread::exception_oop_offset())); + + // x10: exception oop + // t0: exception handler + // x14: exception pc + // Jump to handler + + __ jr(t0); + + // Make sure all code is generated + masm->flush(); + + // Set exception blob + _exception_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1); +} +#endif // COMPILER2 + + diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp index 01ab3d5c27403..ad06f688d6a36 100644 --- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp +++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp @@ -67,24 +67,6 @@ const int StackAlignmentInSlots = StackAlignmentInBytes / VMRegImpl::stack_slot_size; -class SimpleRuntimeFrame { -public: - - // Most of the runtime stubs have this simple frame layout. - // This class exists to make the layout shared in one place. - // Offsets are for compiler stack slots, which are jints. - enum layout { - // The frame sender code expects that fp will be in the "natural" place and - // will override any oopMap setting for it. We must therefore force the layout - // so that it agrees with the frame sender code. - // we don't expect any arg reg save area so riscv asserts that - // frame::arg_reg_save_area_bytes == 0 - fp_off = 0, fp_off2, - return_off, return_off2, - framesize - }; -}; - class RegisterSaver { const bool _save_vectors; public: @@ -2441,195 +2423,6 @@ uint SharedRuntime::out_preserve_stack_slots() { return 0; } -#ifdef COMPILER2 -//------------------------------generate_uncommon_trap_blob-------------------- -void SharedRuntime::generate_uncommon_trap_blob() { - // Allocate space for the code - ResourceMark rm; - // Setup code generation tools - CodeBuffer buffer("uncommon_trap_blob", 2048, 1024); - MacroAssembler* masm = new MacroAssembler(&buffer); - assert_cond(masm != nullptr); - - assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned"); - - address start = __ pc(); - - // Push self-frame. We get here with a return address in RA - // and sp should be 16 byte aligned - // push fp and retaddr by hand - __ addi(sp, sp, -2 * wordSize); - __ sd(ra, Address(sp, wordSize)); - __ sd(fp, Address(sp, 0)); - // we don't expect an arg reg save area -#ifndef PRODUCT - assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area"); -#endif - // compiler left unloaded_class_index in j_rarg0 move to where the - // runtime expects it. - __ sign_extend(c_rarg1, j_rarg0, 32); - - // we need to set the past SP to the stack pointer of the stub frame - // and the pc to the address where this runtime call will return - // although actually any pc in this code blob will do). - Label retaddr; - __ set_last_Java_frame(sp, noreg, retaddr, t0); - - // Call C code. Need thread but NOT official VM entry - // crud. We cannot block on this call, no GC can happen. Call should - // capture callee-saved registers as well as return values. - // - // UnrollBlock* uncommon_trap(JavaThread* thread, jint unloaded_class_index, jint exec_mode) - // - // n.b. 3 gp args, 0 fp args, integral return type - - __ mv(c_rarg0, xthread); - __ mv(c_rarg2, Deoptimization::Unpack_uncommon_trap); - __ rt_call(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)); - __ bind(retaddr); - - // Set an oopmap for the call site - OopMapSet* oop_maps = new OopMapSet(); - OopMap* map = new OopMap(SimpleRuntimeFrame::framesize, 0); - assert_cond(oop_maps != nullptr && map != nullptr); - - // location of fp is known implicitly by the frame sender code - - oop_maps->add_gc_map(__ pc() - start, map); - - __ reset_last_Java_frame(false); - - // move UnrollBlock* into x14 - __ mv(x14, x10); - -#ifdef ASSERT - { Label L; - __ lwu(t0, Address(x14, Deoptimization::UnrollBlock::unpack_kind_offset())); - __ mv(t1, Deoptimization::Unpack_uncommon_trap); - __ beq(t0, t1, L); - __ stop("SharedRuntime::generate_uncommon_trap_blob: expected Unpack_uncommon_trap"); - __ bind(L); - } -#endif - - // Pop all the frames we must move/replace. - // - // Frame picture (youngest to oldest) - // 1: self-frame (no frame link) - // 2: deopting frame (no frame link) - // 3: caller of deopting frame (could be compiled/interpreted). - - __ add(sp, sp, (SimpleRuntimeFrame::framesize) << LogBytesPerInt); // Epilog! - - // Pop deoptimized frame (int) - __ lwu(x12, Address(x14, - Deoptimization::UnrollBlock:: - size_of_deoptimized_frame_offset())); - __ sub(x12, x12, 2 * wordSize); - __ add(sp, sp, x12); - __ ld(fp, Address(sp, 0)); - __ ld(ra, Address(sp, wordSize)); - __ addi(sp, sp, 2 * wordSize); - // RA should now be the return address to the caller (3) frame - -#ifdef ASSERT - // Compilers generate code that bang the stack by as much as the - // interpreter would need. So this stack banging should never - // trigger a fault. Verify that it does not on non product builds. - __ lwu(x11, Address(x14, - Deoptimization::UnrollBlock:: - total_frame_sizes_offset())); - __ bang_stack_size(x11, x12); -#endif - - // Load address of array of frame pcs into x12 (address*) - __ ld(x12, Address(x14, - Deoptimization::UnrollBlock::frame_pcs_offset())); - - // Load address of array of frame sizes into x15 (intptr_t*) - __ ld(x15, Address(x14, - Deoptimization::UnrollBlock:: - frame_sizes_offset())); - - // Counter - __ lwu(x13, Address(x14, - Deoptimization::UnrollBlock:: - number_of_frames_offset())); // (int) - - // Now adjust the caller's stack to make up for the extra locals but - // record the original sp so that we can save it in the skeletal - // interpreter frame and the stack walking of interpreter_sender - // will get the unextended sp value and not the "real" sp value. - - const Register sender_sp = t1; // temporary register - - __ lwu(x11, Address(x14, - Deoptimization::UnrollBlock:: - caller_adjustment_offset())); // (int) - __ mv(sender_sp, sp); - __ sub(sp, sp, x11); - - // Push interpreter frames in a loop - Label loop; - __ bind(loop); - __ ld(x11, Address(x15, 0)); // Load frame size - __ sub(x11, x11, 2 * wordSize); // We'll push pc and fp by hand - __ ld(ra, Address(x12, 0)); // Save return address - __ enter(); // and old fp & set new fp - __ sub(sp, sp, x11); // Prolog - __ sd(sender_sp, Address(fp, frame::interpreter_frame_sender_sp_offset * wordSize)); // Make it walkable - // This value is corrected by layout_activation_impl - __ sd(zr, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize)); - __ mv(sender_sp, sp); // Pass sender_sp to next frame - __ add(x15, x15, wordSize); // Bump array pointer (sizes) - __ add(x12, x12, wordSize); // Bump array pointer (pcs) - __ subw(x13, x13, 1); // Decrement counter - __ bgtz(x13, loop); - __ ld(ra, Address(x12, 0)); // save final return address - // Re-push self-frame - __ enter(); // & old fp & set new fp - - // Use fp because the frames look interpreted now - // Save "the_pc" since it cannot easily be retrieved using the last_java_SP after we aligned SP. - // Don't need the precise return PC here, just precise enough to point into this code blob. - address the_pc = __ pc(); - __ set_last_Java_frame(sp, fp, the_pc, t0); - - // Call C code. Need thread but NOT official VM entry - // crud. We cannot block on this call, no GC can happen. Call should - // restore return values to their stack-slots with the new SP. - // - // BasicType unpack_frames(JavaThread* thread, int exec_mode) - // - - // n.b. 2 gp args, 0 fp args, integral return type - - // sp should already be aligned - __ mv(c_rarg0, xthread); - __ mv(c_rarg1, Deoptimization::Unpack_uncommon_trap); - __ rt_call(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames)); - - // Set an oopmap for the call site - // Use the same PC we used for the last java frame - oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0)); - - // Clear fp AND pc - __ reset_last_Java_frame(true); - - // Pop self-frame. - __ leave(); // Epilog - - // Jump to interpreter - __ ret(); - - // Make sure all code is generated - masm->flush(); - - _uncommon_trap_blob = UncommonTrapBlob::create(&buffer, oop_maps, - SimpleRuntimeFrame::framesize >> 1); -} -#endif // COMPILER2 - //------------------------------generate_handler_blob------ // // Generate a special Compile2Runtime blob that saves all registers, @@ -2835,139 +2628,3 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha // return the blob return RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_in_words, oop_maps, true); } - -#ifdef COMPILER2 -//------------------------------generate_exception_blob--------------------------- -// creates exception blob at the end -// Using exception blob, this code is jumped from a compiled method. -// (see emit_exception_handler in riscv.ad file) -// -// Given an exception pc at a call we call into the runtime for the -// handler in this method. This handler might merely restore state -// (i.e. callee save registers) unwind the frame and jump to the -// exception handler for the nmethod if there is no Java level handler -// for the nmethod. -// -// This code is entered with a jmp. -// -// Arguments: -// x10: exception oop -// x13: exception pc -// -// Results: -// x10: exception oop -// x13: exception pc in caller -// destination: exception handler of caller -// -// Note: the exception pc MUST be at a call (precise debug information) -// Registers x10, x13, x12, x14, x15, t0 are not callee saved. -// - -void OptoRuntime::generate_exception_blob() { - assert(!OptoRuntime::is_callee_saved_register(R13_num), ""); - assert(!OptoRuntime::is_callee_saved_register(R10_num), ""); - assert(!OptoRuntime::is_callee_saved_register(R12_num), ""); - - assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned"); - - // Allocate space for the code - ResourceMark rm; - // Setup code generation tools - CodeBuffer buffer("exception_blob", 2048, 1024); - MacroAssembler* masm = new MacroAssembler(&buffer); - assert_cond(masm != nullptr); - - // TODO check various assumptions made here - // - // make sure we do so before running this - - address start = __ pc(); - - // push fp and retaddr by hand - // Exception pc is 'return address' for stack walker - __ addi(sp, sp, -2 * wordSize); - __ sd(ra, Address(sp, wordSize)); - __ sd(fp, Address(sp)); - // there are no callee save registers and we don't expect an - // arg reg save area -#ifndef PRODUCT - assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area"); -#endif - // Store exception in Thread object. We cannot pass any arguments to the - // handle_exception call, since we do not want to make any assumption - // about the size of the frame where the exception happened in. - __ sd(x10, Address(xthread, JavaThread::exception_oop_offset())); - __ sd(x13, Address(xthread, JavaThread::exception_pc_offset())); - - // This call does all the hard work. It checks if an exception handler - // exists in the method. - // If so, it returns the handler address. - // If not, it prepares for stack-unwinding, restoring the callee-save - // registers of the frame being removed. - // - // address OptoRuntime::handle_exception_C(JavaThread* thread) - // - // n.b. 1 gp arg, 0 fp args, integral return type - - // the stack should always be aligned - address the_pc = __ pc(); - __ set_last_Java_frame(sp, noreg, the_pc, t0); - __ mv(c_rarg0, xthread); - __ rt_call(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C)); - - // handle_exception_C is a special VM call which does not require an explicit - // instruction sync afterwards. - - // Set an oopmap for the call site. This oopmap will only be used if we - // are unwinding the stack. Hence, all locations will be dead. - // Callee-saved registers will be the same as the frame above (i.e., - // handle_exception_stub), since they were restored when we got the - // exception. - - OopMapSet* oop_maps = new OopMapSet(); - assert_cond(oop_maps != nullptr); - - oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0)); - - __ reset_last_Java_frame(false); - - // Restore callee-saved registers - - // fp is an implicitly saved callee saved register (i.e. the calling - // convention will save restore it in prolog/epilog) Other than that - // there are no callee save registers now that adapter frames are gone. - // and we dont' expect an arg reg save area - __ ld(fp, Address(sp)); - __ ld(x13, Address(sp, wordSize)); - __ addi(sp, sp , 2 * wordSize); - - // x10: exception handler - - // We have a handler in x10 (could be deopt blob). - __ mv(t0, x10); - - // Get the exception oop - __ ld(x10, Address(xthread, JavaThread::exception_oop_offset())); - // Get the exception pc in case we are deoptimized - __ ld(x14, Address(xthread, JavaThread::exception_pc_offset())); -#ifdef ASSERT - __ sd(zr, Address(xthread, JavaThread::exception_handler_pc_offset())); - __ sd(zr, Address(xthread, JavaThread::exception_pc_offset())); -#endif - // Clear the exception oop so GC no longer processes it as a root. - __ sd(zr, Address(xthread, JavaThread::exception_oop_offset())); - - // x10: exception oop - // t0: exception handler - // x14: exception pc - // Jump to handler - - __ jr(t0); - - // Make sure all code is generated - masm->flush(); - - // Set exception blob - _exception_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1); -} -#endif // COMPILER2 diff --git a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp index 0ee88345282b7..641b3712a175b 100644 --- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp +++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp @@ -2706,7 +2706,7 @@ void SharedRuntime::generate_deopt_blob() { #ifdef COMPILER2 //------------------------------generate_uncommon_trap_blob-------------------- -void SharedRuntime::generate_uncommon_trap_blob() { +void OptoRuntime::generate_uncommon_trap_blob() { // Allocate space for the code ResourceMark rm; // Setup code generation tools @@ -2769,7 +2769,7 @@ void SharedRuntime::generate_uncommon_trap_blob() { } else { __ z_cliy(unpack_kind_byte_offset, unroll_block_reg, Deoptimization::Unpack_uncommon_trap); } - __ asm_assert(Assembler::bcondEqual, "SharedRuntime::generate_deopt_blob: expected Unpack_uncommon_trap", 0); + __ asm_assert(Assembler::bcondEqual, "OptoRuntime::generate_deopt_blob: expected Unpack_uncommon_trap", 0); #endif __ zap_from_to(Z_SP, Z_SP, Z_R0_scratch, Z_R1, 500, -1); diff --git a/src/hotspot/cpu/x86/runtime_x86_32.cpp b/src/hotspot/cpu/x86/runtime_x86_32.cpp index d38fa3c60bdd1..2a21c42a5e606 100644 --- a/src/hotspot/cpu/x86/runtime_x86_32.cpp +++ b/src/hotspot/cpu/x86/runtime_x86_32.cpp @@ -41,6 +41,180 @@ #define __ masm-> +//------------------------------generate_uncommon_trap_blob-------------------- +void OptoRuntime::generate_uncommon_trap_blob() { + // allocate space for the code + ResourceMark rm; + // setup code generation tools + CodeBuffer buffer("uncommon_trap_blob", 512, 512); + MacroAssembler* masm = new MacroAssembler(&buffer); + + enum frame_layout { + arg0_off, // thread sp + 0 // Arg location for + arg1_off, // unloaded_class_index sp + 1 // calling C + arg2_off, // exec_mode sp + 2 + // The frame sender code expects that rbp will be in the "natural" place and + // will override any oopMap setting for it. We must therefore force the layout + // so that it agrees with the frame sender code. + rbp_off, // callee saved register sp + 3 + return_off, // slot for return address sp + 4 + framesize + }; + + address start = __ pc(); + + // Push self-frame. + __ subptr(rsp, return_off*wordSize); // Epilog! + + // rbp, is an implicitly saved callee saved register (i.e. the calling + // convention will save restore it in prolog/epilog) Other than that + // there are no callee save registers no that adapter frames are gone. + __ movptr(Address(rsp, rbp_off*wordSize), rbp); + + // Clear the floating point exception stack + __ empty_FPU_stack(); + + // set last_Java_sp + __ get_thread(rdx); + __ set_last_Java_frame(rdx, noreg, noreg, nullptr, noreg); + + // Call C code. Need thread but NOT official VM entry + // crud. We cannot block on this call, no GC can happen. Call should + // capture callee-saved registers as well as return values. + __ movptr(Address(rsp, arg0_off*wordSize), rdx); + // argument already in ECX + __ movl(Address(rsp, arg1_off*wordSize),rcx); + __ movl(Address(rsp, arg2_off*wordSize), Deoptimization::Unpack_uncommon_trap); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap))); + + // Set an oopmap for the call site + OopMapSet *oop_maps = new OopMapSet(); + OopMap* map = new OopMap( framesize, 0 ); + // No oopMap for rbp, it is known implicitly + + oop_maps->add_gc_map( __ pc()-start, map); + + __ get_thread(rcx); + + __ reset_last_Java_frame(rcx, false); + + // Load UnrollBlock into EDI + __ movptr(rdi, rax); + +#ifdef ASSERT + { Label L; + __ cmpptr(Address(rdi, Deoptimization::UnrollBlock::unpack_kind_offset()), + (int32_t)Deoptimization::Unpack_uncommon_trap); + __ jcc(Assembler::equal, L); + __ stop("OptoRuntime::generate_uncommon_trap_blob: expected Unpack_uncommon_trap"); + __ bind(L); + } +#endif + + // Pop all the frames we must move/replace. + // + // Frame picture (youngest to oldest) + // 1: self-frame (no frame link) + // 2: deopting frame (no frame link) + // 3: caller of deopting frame (could be compiled/interpreted). + + // Pop self-frame. We have no frame, and must rely only on EAX and ESP. + __ addptr(rsp,(framesize-1)*wordSize); // Epilog! + + // Pop deoptimized frame + __ movl2ptr(rcx, Address(rdi,Deoptimization::UnrollBlock::size_of_deoptimized_frame_offset())); + __ addptr(rsp, rcx); + + // sp should be pointing at the return address to the caller (3) + + // Pick up the initial fp we should save + // restore rbp before stack bang because if stack overflow is thrown it needs to be pushed (and preserved) + __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_info_offset())); + +#ifdef ASSERT + // Compilers generate code that bang the stack by as much as the + // interpreter would need. So this stack banging should never + // trigger a fault. Verify that it does not on non product builds. + __ movl(rbx, Address(rdi ,Deoptimization::UnrollBlock::total_frame_sizes_offset())); + __ bang_stack_size(rbx, rcx); +#endif + + // Load array of frame pcs into ECX + __ movl(rcx,Address(rdi,Deoptimization::UnrollBlock::frame_pcs_offset())); + + __ pop(rsi); // trash the pc + + // Load array of frame sizes into ESI + __ movptr(rsi,Address(rdi,Deoptimization::UnrollBlock::frame_sizes_offset())); + + Address counter(rdi, Deoptimization::UnrollBlock::counter_temp_offset()); + + __ movl(rbx, Address(rdi, Deoptimization::UnrollBlock::number_of_frames_offset())); + __ movl(counter, rbx); + + // Now adjust the caller's stack to make up for the extra locals + // but record the original sp so that we can save it in the skeletal interpreter + // frame and the stack walking of interpreter_sender will get the unextended sp + // value and not the "real" sp value. + + Address sp_temp(rdi, Deoptimization::UnrollBlock::sender_sp_temp_offset()); + __ movptr(sp_temp, rsp); + __ movl(rbx, Address(rdi, Deoptimization::UnrollBlock::caller_adjustment_offset())); + __ subptr(rsp, rbx); + + // Push interpreter frames in a loop + Label loop; + __ bind(loop); + __ movptr(rbx, Address(rsi, 0)); // Load frame size + __ subptr(rbx, 2*wordSize); // we'll push pc and rbp, by hand + __ pushptr(Address(rcx, 0)); // save return address + __ enter(); // save old & set new rbp, + __ subptr(rsp, rbx); // Prolog! + __ movptr(rbx, sp_temp); // sender's sp + // This value is corrected by layout_activation_impl + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD ); + __ movptr(Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize), rbx); // Make it walkable + __ movptr(sp_temp, rsp); // pass to next frame + __ addptr(rsi, wordSize); // Bump array pointer (sizes) + __ addptr(rcx, wordSize); // Bump array pointer (pcs) + __ decrementl(counter); // decrement counter + __ jcc(Assembler::notZero, loop); + __ pushptr(Address(rcx, 0)); // save final return address + + // Re-push self-frame + __ enter(); // save old & set new rbp, + __ subptr(rsp, (framesize-2) * wordSize); // Prolog! + + + // set last_Java_sp, last_Java_fp + __ get_thread(rdi); + __ set_last_Java_frame(rdi, noreg, rbp, nullptr, noreg); + + // Call C code. Need thread but NOT official VM entry + // crud. We cannot block on this call, no GC can happen. Call should + // restore return values to their stack-slots with the new SP. + __ movptr(Address(rsp,arg0_off*wordSize),rdi); + __ movl(Address(rsp,arg1_off*wordSize), Deoptimization::Unpack_uncommon_trap); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames))); + // Set an oopmap for the call site + oop_maps->add_gc_map( __ pc()-start, new OopMap( framesize, 0 ) ); + + __ get_thread(rdi); + __ reset_last_Java_frame(rdi, true); + + // Pop self-frame. + __ leave(); // Epilog! + + // Jump to interpreter + __ ret(0); + + // ------------- + // make sure all code is generated + masm->flush(); + + _uncommon_trap_blob = UncommonTrapBlob::create(&buffer, oop_maps, framesize); +} + //------------------------------generate_exception_blob--------------------------- // creates exception blob at the end // Using exception blob, this code is jumped from a compiled method. diff --git a/src/hotspot/cpu/x86/runtime_x86_64.cpp b/src/hotspot/cpu/x86/runtime_x86_64.cpp index e08550715b495..eb3bab36b88cb 100644 --- a/src/hotspot/cpu/x86/runtime_x86_64.cpp +++ b/src/hotspot/cpu/x86/runtime_x86_64.cpp @@ -34,11 +34,328 @@ #include "runtime/vframeArray.hpp" #include "utilities/globalDefinitions.hpp" #include "vmreg_x86.inline.hpp" + +class SimpleRuntimeFrame { + + public: + + // Most of the runtime stubs have this simple frame layout. + // This class exists to make the layout shared in one place. + // Offsets are for compiler stack slots, which are jints. + enum layout { + // The frame sender code expects that rbp will be in the "natural" place and + // will override any oopMap setting for it. We must therefore force the layout + // so that it agrees with the frame sender code. + rbp_off = frame::arg_reg_save_area_bytes/BytesPerInt, + rbp_off2, + return_off, return_off2, + framesize + }; +}; + +#define __ masm-> + +//------------------------------generate_uncommon_trap_blob-------------------- +void OptoRuntime::generate_uncommon_trap_blob() { + // Allocate space for the code + ResourceMark rm; + // Setup code generation tools + CodeBuffer buffer("uncommon_trap_blob", 2048, 1024); + MacroAssembler* masm = new MacroAssembler(&buffer); + + assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned"); + + address start = __ pc(); + + // Push self-frame. We get here with a return address on the + // stack, so rsp is 8-byte aligned until we allocate our frame. + __ subptr(rsp, SimpleRuntimeFrame::return_off << LogBytesPerInt); // Epilog! + + // No callee saved registers. rbp is assumed implicitly saved + __ movptr(Address(rsp, SimpleRuntimeFrame::rbp_off << LogBytesPerInt), rbp); + + // compiler left unloaded_class_index in j_rarg0 move to where the + // runtime expects it. + __ movl(c_rarg1, j_rarg0); + + __ set_last_Java_frame(noreg, noreg, nullptr, rscratch1); + + // Call C code. Need thread but NOT official VM entry + // crud. We cannot block on this call, no GC can happen. Call should + // capture callee-saved registers as well as return values. + // Thread is in rdi already. + // + // UnrollBlock* uncommon_trap(JavaThread* thread, jint unloaded_class_index); + + __ mov(c_rarg0, r15_thread); + __ movl(c_rarg2, Deoptimization::Unpack_uncommon_trap); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap))); + + // Set an oopmap for the call site + OopMapSet* oop_maps = new OopMapSet(); + OopMap* map = new OopMap(SimpleRuntimeFrame::framesize, 0); + + // location of rbp is known implicitly by the frame sender code + + oop_maps->add_gc_map(__ pc() - start, map); + + __ reset_last_Java_frame(false); + + // Load UnrollBlock* into rdi + __ mov(rdi, rax); + +#ifdef ASSERT + { Label L; + __ cmpptr(Address(rdi, Deoptimization::UnrollBlock::unpack_kind_offset()), + Deoptimization::Unpack_uncommon_trap); + __ jcc(Assembler::equal, L); + __ stop("OptoRuntime::generate_uncommon_trap_blob: expected Unpack_uncommon_trap"); + __ bind(L); + } #endif + // Pop all the frames we must move/replace. + // + // Frame picture (youngest to oldest) + // 1: self-frame (no frame link) + // 2: deopting frame (no frame link) + // 3: caller of deopting frame (could be compiled/interpreted). + + // Pop self-frame. We have no frame, and must rely only on rax and rsp. + __ addptr(rsp, (SimpleRuntimeFrame::framesize - 2) << LogBytesPerInt); // Epilog! + + // Pop deoptimized frame (int) + __ movl(rcx, Address(rdi, + Deoptimization::UnrollBlock:: + size_of_deoptimized_frame_offset())); + __ addptr(rsp, rcx); + + // rsp should be pointing at the return address to the caller (3) + + // Pick up the initial fp we should save + // restore rbp before stack bang because if stack overflow is thrown it needs to be pushed (and preserved) + __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_info_offset())); + +#ifdef ASSERT + // Compilers generate code that bang the stack by as much as the + // interpreter would need. So this stack banging should never + // trigger a fault. Verify that it does not on non product builds. + __ movl(rbx, Address(rdi ,Deoptimization::UnrollBlock::total_frame_sizes_offset())); + __ bang_stack_size(rbx, rcx); +#endif + + // Load address of array of frame pcs into rcx (address*) + __ movptr(rcx, Address(rdi, Deoptimization::UnrollBlock::frame_pcs_offset())); + + // Trash the return pc + __ addptr(rsp, wordSize); + + // Load address of array of frame sizes into rsi (intptr_t*) + __ movptr(rsi, Address(rdi, Deoptimization::UnrollBlock:: frame_sizes_offset())); + + // Counter + __ movl(rdx, Address(rdi, Deoptimization::UnrollBlock:: number_of_frames_offset())); // (int) + + // Now adjust the caller's stack to make up for the extra locals but + // record the original sp so that we can save it in the skeletal + // interpreter frame and the stack walking of interpreter_sender + // will get the unextended sp value and not the "real" sp value. + + const Register sender_sp = r8; + + __ mov(sender_sp, rsp); + __ movl(rbx, Address(rdi, Deoptimization::UnrollBlock:: caller_adjustment_offset())); // (int) + __ subptr(rsp, rbx); + + // Push interpreter frames in a loop + Label loop; + __ bind(loop); + __ movptr(rbx, Address(rsi, 0)); // Load frame size + __ subptr(rbx, 2 * wordSize); // We'll push pc and rbp by hand + __ pushptr(Address(rcx, 0)); // Save return address + __ enter(); // Save old & set new rbp + __ subptr(rsp, rbx); // Prolog + __ movptr(Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize), + sender_sp); // Make it walkable + // This value is corrected by layout_activation_impl + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); + __ mov(sender_sp, rsp); // Pass sender_sp to next frame + __ addptr(rsi, wordSize); // Bump array pointer (sizes) + __ addptr(rcx, wordSize); // Bump array pointer (pcs) + __ decrementl(rdx); // Decrement counter + __ jcc(Assembler::notZero, loop); + __ pushptr(Address(rcx, 0)); // Save final return address + + // Re-push self-frame + __ enter(); // Save old & set new rbp + __ subptr(rsp, (SimpleRuntimeFrame::framesize - 4) << LogBytesPerInt); + // Prolog + + // Use rbp because the frames look interpreted now + // Save "the_pc" since it cannot easily be retrieved using the last_java_SP after we aligned SP. + // Don't need the precise return PC here, just precise enough to point into this code blob. + address the_pc = __ pc(); + __ set_last_Java_frame(noreg, rbp, the_pc, rscratch1); + + // Call C code. Need thread but NOT official VM entry + // crud. We cannot block on this call, no GC can happen. Call should + // restore return values to their stack-slots with the new SP. + // Thread is in rdi already. + // + // BasicType unpack_frames(JavaThread* thread, int exec_mode); + + __ andptr(rsp, -(StackAlignmentInBytes)); // Align SP as required by ABI + __ mov(c_rarg0, r15_thread); + __ movl(c_rarg1, Deoptimization::Unpack_uncommon_trap); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames))); + + // Set an oopmap for the call site + // Use the same PC we used for the last java frame + oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0)); + + // Clear fp AND pc + __ reset_last_Java_frame(true); + + // Pop self-frame. + __ leave(); // Epilog + + // Jump to interpreter + __ ret(0); + + // Make sure all code is generated + masm->flush(); + + _uncommon_trap_blob = UncommonTrapBlob::create(&buffer, oop_maps, + SimpleRuntimeFrame::framesize >> 1); +} + +//------------------------------generate_exception_blob--------------------------- +// creates exception blob at the end +// Using exception blob, this code is jumped from a compiled method. +// (see emit_exception_handler in x86_64.ad file) +// +// Given an exception pc at a call we call into the runtime for the +// handler in this method. This handler might merely restore state +// (i.e. callee save registers) unwind the frame and jump to the +// exception handler for the nmethod if there is no Java level handler +// for the nmethod. +// +// This code is entered with a jmp. +// +// Arguments: +// rax: exception oop +// rdx: exception pc +// +// Results: +// rax: exception oop +// rdx: exception pc in caller or ??? +// destination: exception handler of caller +// +// Note: the exception pc MUST be at a call (precise debug information) +// Registers rax, rdx, rcx, rsi, rdi, r8-r11 are not callee saved. +// + +void OptoRuntime::generate_exception_blob() { + assert(!OptoRuntime::is_callee_saved_register(RDX_num), ""); + assert(!OptoRuntime::is_callee_saved_register(RAX_num), ""); + assert(!OptoRuntime::is_callee_saved_register(RCX_num), ""); + + assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned"); + + // Allocate space for the code + ResourceMark rm; + // Setup code generation tools + CodeBuffer buffer("exception_blob", 2048, 1024); + MacroAssembler* masm = new MacroAssembler(&buffer); + + + address start = __ pc(); + + // Exception pc is 'return address' for stack walker + __ push(rdx); + __ subptr(rsp, SimpleRuntimeFrame::return_off << LogBytesPerInt); // Prolog + + // Save callee-saved registers. See x86_64.ad. + + // rbp is an implicitly saved callee saved register (i.e., the calling + // convention will save/restore it in the prolog/epilog). Other than that + // there are no callee save registers now that adapter frames are gone. + + __ movptr(Address(rsp, SimpleRuntimeFrame::rbp_off << LogBytesPerInt), rbp); + + // Store exception in Thread object. We cannot pass any arguments to the + // handle_exception call, since we do not want to make any assumption + // about the size of the frame where the exception happened in. + // c_rarg0 is either rdi (Linux) or rcx (Windows). + __ movptr(Address(r15_thread, JavaThread::exception_oop_offset()),rax); + __ movptr(Address(r15_thread, JavaThread::exception_pc_offset()), rdx); + + // This call does all the hard work. It checks if an exception handler + // exists in the method. + // If so, it returns the handler address. + // If not, it prepares for stack-unwinding, restoring the callee-save + // registers of the frame being removed. + // + // address OptoRuntime::handle_exception_C(JavaThread* thread) + + // At a method handle call, the stack may not be properly aligned + // when returning with an exception. + address the_pc = __ pc(); + __ set_last_Java_frame(noreg, noreg, the_pc, rscratch1); + __ mov(c_rarg0, r15_thread); + __ andptr(rsp, -(StackAlignmentInBytes)); // Align stack + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C))); + + // Set an oopmap for the call site. This oopmap will only be used if we + // are unwinding the stack. Hence, all locations will be dead. + // Callee-saved registers will be the same as the frame above (i.e., + // handle_exception_stub), since they were restored when we got the + // exception. + + OopMapSet* oop_maps = new OopMapSet(); + + oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0)); + + __ reset_last_Java_frame(false); + + // Restore callee-saved registers + + // rbp is an implicitly saved callee-saved register (i.e., the calling + // convention will save restore it in prolog/epilog) Other than that + // there are no callee save registers now that adapter frames are gone. + + __ movptr(rbp, Address(rsp, SimpleRuntimeFrame::rbp_off << LogBytesPerInt)); + + __ addptr(rsp, SimpleRuntimeFrame::return_off << LogBytesPerInt); // Epilog + __ pop(rdx); // No need for exception pc anymore + + // rax: exception handler + + // We have a handler in rax (could be deopt blob). + __ mov(r8, rax); + + // Get the exception oop + __ movptr(rax, Address(r15_thread, JavaThread::exception_oop_offset())); + // Get the exception pc in case we are deoptimized + __ movptr(rdx, Address(r15_thread, JavaThread::exception_pc_offset())); +#ifdef ASSERT + __ movptr(Address(r15_thread, JavaThread::exception_handler_pc_offset()), NULL_WORD); + __ movptr(Address(r15_thread, JavaThread::exception_pc_offset()), NULL_WORD); +#endif + // Clear the exception oop so GC no longer processes it as a root. + __ movptr(Address(r15_thread, JavaThread::exception_oop_offset()), NULL_WORD); + + // rax: exception oop + // r8: exception handler + // rdx: exception pc + // Jump to handler + + __ jmp(r8); + + // Make sure all code is generated + masm->flush(); -// This file should really contain the code for generating the OptoRuntime -// exception_blob. However that code uses SimpleRuntimeFrame which only -// exists in sharedRuntime_x86_64.cpp. When there is a sharedRuntime_.hpp -// file and SimpleRuntimeFrame is able to move there then the exception_blob -// code will move here where it belongs. + // Set exception blob + _exception_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1); +} +#endif // COMPILER2 diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp index 6303c279195ca..80be7c7d5b642 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp @@ -2389,183 +2389,6 @@ void SharedRuntime::generate_deopt_blob() { _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset); } - -#ifdef COMPILER2 -//------------------------------generate_uncommon_trap_blob-------------------- -void SharedRuntime::generate_uncommon_trap_blob() { - // allocate space for the code - ResourceMark rm; - // setup code generation tools - CodeBuffer buffer("uncommon_trap_blob", 512, 512); - MacroAssembler* masm = new MacroAssembler(&buffer); - - enum frame_layout { - arg0_off, // thread sp + 0 // Arg location for - arg1_off, // unloaded_class_index sp + 1 // calling C - arg2_off, // exec_mode sp + 2 - // The frame sender code expects that rbp will be in the "natural" place and - // will override any oopMap setting for it. We must therefore force the layout - // so that it agrees with the frame sender code. - rbp_off, // callee saved register sp + 3 - return_off, // slot for return address sp + 4 - framesize - }; - - address start = __ pc(); - - // Push self-frame. - __ subptr(rsp, return_off*wordSize); // Epilog! - - // rbp, is an implicitly saved callee saved register (i.e. the calling - // convention will save restore it in prolog/epilog) Other than that - // there are no callee save registers no that adapter frames are gone. - __ movptr(Address(rsp, rbp_off*wordSize), rbp); - - // Clear the floating point exception stack - __ empty_FPU_stack(); - - // set last_Java_sp - __ get_thread(rdx); - __ set_last_Java_frame(rdx, noreg, noreg, nullptr, noreg); - - // Call C code. Need thread but NOT official VM entry - // crud. We cannot block on this call, no GC can happen. Call should - // capture callee-saved registers as well as return values. - __ movptr(Address(rsp, arg0_off*wordSize), rdx); - // argument already in ECX - __ movl(Address(rsp, arg1_off*wordSize),rcx); - __ movl(Address(rsp, arg2_off*wordSize), Deoptimization::Unpack_uncommon_trap); - __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap))); - - // Set an oopmap for the call site - OopMapSet *oop_maps = new OopMapSet(); - OopMap* map = new OopMap( framesize, 0 ); - // No oopMap for rbp, it is known implicitly - - oop_maps->add_gc_map( __ pc()-start, map); - - __ get_thread(rcx); - - __ reset_last_Java_frame(rcx, false); - - // Load UnrollBlock into EDI - __ movptr(rdi, rax); - -#ifdef ASSERT - { Label L; - __ cmpptr(Address(rdi, Deoptimization::UnrollBlock::unpack_kind_offset()), - (int32_t)Deoptimization::Unpack_uncommon_trap); - __ jcc(Assembler::equal, L); - __ stop("SharedRuntime::generate_uncommon_trap_blob: expected Unpack_uncommon_trap"); - __ bind(L); - } -#endif - - // Pop all the frames we must move/replace. - // - // Frame picture (youngest to oldest) - // 1: self-frame (no frame link) - // 2: deopting frame (no frame link) - // 3: caller of deopting frame (could be compiled/interpreted). - - // Pop self-frame. We have no frame, and must rely only on EAX and ESP. - __ addptr(rsp,(framesize-1)*wordSize); // Epilog! - - // Pop deoptimized frame - __ movl2ptr(rcx, Address(rdi,Deoptimization::UnrollBlock::size_of_deoptimized_frame_offset())); - __ addptr(rsp, rcx); - - // sp should be pointing at the return address to the caller (3) - - // Pick up the initial fp we should save - // restore rbp before stack bang because if stack overflow is thrown it needs to be pushed (and preserved) - __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_info_offset())); - -#ifdef ASSERT - // Compilers generate code that bang the stack by as much as the - // interpreter would need. So this stack banging should never - // trigger a fault. Verify that it does not on non product builds. - __ movl(rbx, Address(rdi ,Deoptimization::UnrollBlock::total_frame_sizes_offset())); - __ bang_stack_size(rbx, rcx); -#endif - - // Load array of frame pcs into ECX - __ movl(rcx,Address(rdi,Deoptimization::UnrollBlock::frame_pcs_offset())); - - __ pop(rsi); // trash the pc - - // Load array of frame sizes into ESI - __ movptr(rsi,Address(rdi,Deoptimization::UnrollBlock::frame_sizes_offset())); - - Address counter(rdi, Deoptimization::UnrollBlock::counter_temp_offset()); - - __ movl(rbx, Address(rdi, Deoptimization::UnrollBlock::number_of_frames_offset())); - __ movl(counter, rbx); - - // Now adjust the caller's stack to make up for the extra locals - // but record the original sp so that we can save it in the skeletal interpreter - // frame and the stack walking of interpreter_sender will get the unextended sp - // value and not the "real" sp value. - - Address sp_temp(rdi, Deoptimization::UnrollBlock::sender_sp_temp_offset()); - __ movptr(sp_temp, rsp); - __ movl(rbx, Address(rdi, Deoptimization::UnrollBlock::caller_adjustment_offset())); - __ subptr(rsp, rbx); - - // Push interpreter frames in a loop - Label loop; - __ bind(loop); - __ movptr(rbx, Address(rsi, 0)); // Load frame size - __ subptr(rbx, 2*wordSize); // we'll push pc and rbp, by hand - __ pushptr(Address(rcx, 0)); // save return address - __ enter(); // save old & set new rbp, - __ subptr(rsp, rbx); // Prolog! - __ movptr(rbx, sp_temp); // sender's sp - // This value is corrected by layout_activation_impl - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD ); - __ movptr(Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize), rbx); // Make it walkable - __ movptr(sp_temp, rsp); // pass to next frame - __ addptr(rsi, wordSize); // Bump array pointer (sizes) - __ addptr(rcx, wordSize); // Bump array pointer (pcs) - __ decrementl(counter); // decrement counter - __ jcc(Assembler::notZero, loop); - __ pushptr(Address(rcx, 0)); // save final return address - - // Re-push self-frame - __ enter(); // save old & set new rbp, - __ subptr(rsp, (framesize-2) * wordSize); // Prolog! - - - // set last_Java_sp, last_Java_fp - __ get_thread(rdi); - __ set_last_Java_frame(rdi, noreg, rbp, nullptr, noreg); - - // Call C code. Need thread but NOT official VM entry - // crud. We cannot block on this call, no GC can happen. Call should - // restore return values to their stack-slots with the new SP. - __ movptr(Address(rsp,arg0_off*wordSize),rdi); - __ movl(Address(rsp,arg1_off*wordSize), Deoptimization::Unpack_uncommon_trap); - __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames))); - // Set an oopmap for the call site - oop_maps->add_gc_map( __ pc()-start, new OopMap( framesize, 0 ) ); - - __ get_thread(rdi); - __ reset_last_Java_frame(rdi, true); - - // Pop self-frame. - __ leave(); // Epilog! - - // Jump to interpreter - __ ret(0); - - // ------------- - // make sure all code is generated - masm->flush(); - - _uncommon_trap_blob = UncommonTrapBlob::create(&buffer, oop_maps, framesize); -} -#endif // COMPILER2 - //------------------------------generate_handler_blob------ // // Generate a special Compile2Runtime blob that saves all registers, diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index decaa9d1ee914..f2488ef4e7445 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -72,24 +72,6 @@ const int StackAlignmentInSlots = StackAlignmentInBytes / VMRegImpl::stack_slot_size; -class SimpleRuntimeFrame { - - public: - - // Most of the runtime stubs have this simple frame layout. - // This class exists to make the layout shared in one place. - // Offsets are for compiler stack slots, which are jints. - enum layout { - // The frame sender code expects that rbp will be in the "natural" place and - // will override any oopMap setting for it. We must therefore force the layout - // so that it agrees with the frame sender code. - rbp_off = frame::arg_reg_save_area_bytes/BytesPerInt, - rbp_off2, - return_off, return_off2, - framesize - }; -}; - class RegisterSaver { // Capture info about frame layout. Layout offsets are in jint // units because compiler frame slots are jints. @@ -2987,182 +2969,6 @@ void SharedRuntime::generate_deopt_blob() { #endif } -#ifdef COMPILER2 -//------------------------------generate_uncommon_trap_blob-------------------- -void SharedRuntime::generate_uncommon_trap_blob() { - // Allocate space for the code - ResourceMark rm; - // Setup code generation tools - CodeBuffer buffer("uncommon_trap_blob", 2048, 1024); - MacroAssembler* masm = new MacroAssembler(&buffer); - - assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned"); - - address start = __ pc(); - - // Push self-frame. We get here with a return address on the - // stack, so rsp is 8-byte aligned until we allocate our frame. - __ subptr(rsp, SimpleRuntimeFrame::return_off << LogBytesPerInt); // Epilog! - - // No callee saved registers. rbp is assumed implicitly saved - __ movptr(Address(rsp, SimpleRuntimeFrame::rbp_off << LogBytesPerInt), rbp); - - // compiler left unloaded_class_index in j_rarg0 move to where the - // runtime expects it. - __ movl(c_rarg1, j_rarg0); - - __ set_last_Java_frame(noreg, noreg, nullptr, rscratch1); - - // Call C code. Need thread but NOT official VM entry - // crud. We cannot block on this call, no GC can happen. Call should - // capture callee-saved registers as well as return values. - // Thread is in rdi already. - // - // UnrollBlock* uncommon_trap(JavaThread* thread, jint unloaded_class_index); - - __ mov(c_rarg0, r15_thread); - __ movl(c_rarg2, Deoptimization::Unpack_uncommon_trap); - __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap))); - - // Set an oopmap for the call site - OopMapSet* oop_maps = new OopMapSet(); - OopMap* map = new OopMap(SimpleRuntimeFrame::framesize, 0); - - // location of rbp is known implicitly by the frame sender code - - oop_maps->add_gc_map(__ pc() - start, map); - - __ reset_last_Java_frame(false); - - // Load UnrollBlock* into rdi - __ mov(rdi, rax); - -#ifdef ASSERT - { Label L; - __ cmpptr(Address(rdi, Deoptimization::UnrollBlock::unpack_kind_offset()), - Deoptimization::Unpack_uncommon_trap); - __ jcc(Assembler::equal, L); - __ stop("SharedRuntime::generate_uncommon_trap_blob: expected Unpack_uncommon_trap"); - __ bind(L); - } -#endif - - // Pop all the frames we must move/replace. - // - // Frame picture (youngest to oldest) - // 1: self-frame (no frame link) - // 2: deopting frame (no frame link) - // 3: caller of deopting frame (could be compiled/interpreted). - - // Pop self-frame. We have no frame, and must rely only on rax and rsp. - __ addptr(rsp, (SimpleRuntimeFrame::framesize - 2) << LogBytesPerInt); // Epilog! - - // Pop deoptimized frame (int) - __ movl(rcx, Address(rdi, - Deoptimization::UnrollBlock:: - size_of_deoptimized_frame_offset())); - __ addptr(rsp, rcx); - - // rsp should be pointing at the return address to the caller (3) - - // Pick up the initial fp we should save - // restore rbp before stack bang because if stack overflow is thrown it needs to be pushed (and preserved) - __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_info_offset())); - -#ifdef ASSERT - // Compilers generate code that bang the stack by as much as the - // interpreter would need. So this stack banging should never - // trigger a fault. Verify that it does not on non product builds. - __ movl(rbx, Address(rdi ,Deoptimization::UnrollBlock::total_frame_sizes_offset())); - __ bang_stack_size(rbx, rcx); -#endif - - // Load address of array of frame pcs into rcx (address*) - __ movptr(rcx, Address(rdi, Deoptimization::UnrollBlock::frame_pcs_offset())); - - // Trash the return pc - __ addptr(rsp, wordSize); - - // Load address of array of frame sizes into rsi (intptr_t*) - __ movptr(rsi, Address(rdi, Deoptimization::UnrollBlock:: frame_sizes_offset())); - - // Counter - __ movl(rdx, Address(rdi, Deoptimization::UnrollBlock:: number_of_frames_offset())); // (int) - - // Now adjust the caller's stack to make up for the extra locals but - // record the original sp so that we can save it in the skeletal - // interpreter frame and the stack walking of interpreter_sender - // will get the unextended sp value and not the "real" sp value. - - const Register sender_sp = r8; - - __ mov(sender_sp, rsp); - __ movl(rbx, Address(rdi, Deoptimization::UnrollBlock:: caller_adjustment_offset())); // (int) - __ subptr(rsp, rbx); - - // Push interpreter frames in a loop - Label loop; - __ bind(loop); - __ movptr(rbx, Address(rsi, 0)); // Load frame size - __ subptr(rbx, 2 * wordSize); // We'll push pc and rbp by hand - __ pushptr(Address(rcx, 0)); // Save return address - __ enter(); // Save old & set new rbp - __ subptr(rsp, rbx); // Prolog - __ movptr(Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize), - sender_sp); // Make it walkable - // This value is corrected by layout_activation_impl - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); - __ mov(sender_sp, rsp); // Pass sender_sp to next frame - __ addptr(rsi, wordSize); // Bump array pointer (sizes) - __ addptr(rcx, wordSize); // Bump array pointer (pcs) - __ decrementl(rdx); // Decrement counter - __ jcc(Assembler::notZero, loop); - __ pushptr(Address(rcx, 0)); // Save final return address - - // Re-push self-frame - __ enter(); // Save old & set new rbp - __ subptr(rsp, (SimpleRuntimeFrame::framesize - 4) << LogBytesPerInt); - // Prolog - - // Use rbp because the frames look interpreted now - // Save "the_pc" since it cannot easily be retrieved using the last_java_SP after we aligned SP. - // Don't need the precise return PC here, just precise enough to point into this code blob. - address the_pc = __ pc(); - __ set_last_Java_frame(noreg, rbp, the_pc, rscratch1); - - // Call C code. Need thread but NOT official VM entry - // crud. We cannot block on this call, no GC can happen. Call should - // restore return values to their stack-slots with the new SP. - // Thread is in rdi already. - // - // BasicType unpack_frames(JavaThread* thread, int exec_mode); - - __ andptr(rsp, -(StackAlignmentInBytes)); // Align SP as required by ABI - __ mov(c_rarg0, r15_thread); - __ movl(c_rarg1, Deoptimization::Unpack_uncommon_trap); - __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames))); - - // Set an oopmap for the call site - // Use the same PC we used for the last java frame - oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0)); - - // Clear fp AND pc - __ reset_last_Java_frame(true); - - // Pop self-frame. - __ leave(); // Epilog - - // Jump to interpreter - __ ret(0); - - // Make sure all code is generated - masm->flush(); - - _uncommon_trap_blob = UncommonTrapBlob::create(&buffer, oop_maps, - SimpleRuntimeFrame::framesize >> 1); -} -#endif // COMPILER2 - //------------------------------generate_handler_blob------ // // Generate a special Compile2Runtime blob that saves all registers, @@ -3669,136 +3475,3 @@ void SharedRuntime::montgomery_square(jint *a_ints, jint *n_ints, reverse_words(m, (julong *)m_ints, longwords); } -#ifdef COMPILER2 -// This is here instead of runtime_x86_64.cpp because it uses SimpleRuntimeFrame -// -//------------------------------generate_exception_blob--------------------------- -// creates exception blob at the end -// Using exception blob, this code is jumped from a compiled method. -// (see emit_exception_handler in x86_64.ad file) -// -// Given an exception pc at a call we call into the runtime for the -// handler in this method. This handler might merely restore state -// (i.e. callee save registers) unwind the frame and jump to the -// exception handler for the nmethod if there is no Java level handler -// for the nmethod. -// -// This code is entered with a jmp. -// -// Arguments: -// rax: exception oop -// rdx: exception pc -// -// Results: -// rax: exception oop -// rdx: exception pc in caller or ??? -// destination: exception handler of caller -// -// Note: the exception pc MUST be at a call (precise debug information) -// Registers rax, rdx, rcx, rsi, rdi, r8-r11 are not callee saved. -// - -void OptoRuntime::generate_exception_blob() { - assert(!OptoRuntime::is_callee_saved_register(RDX_num), ""); - assert(!OptoRuntime::is_callee_saved_register(RAX_num), ""); - assert(!OptoRuntime::is_callee_saved_register(RCX_num), ""); - - assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned"); - - // Allocate space for the code - ResourceMark rm; - // Setup code generation tools - CodeBuffer buffer("exception_blob", 2048, 1024); - MacroAssembler* masm = new MacroAssembler(&buffer); - - - address start = __ pc(); - - // Exception pc is 'return address' for stack walker - __ push(rdx); - __ subptr(rsp, SimpleRuntimeFrame::return_off << LogBytesPerInt); // Prolog - - // Save callee-saved registers. See x86_64.ad. - - // rbp is an implicitly saved callee saved register (i.e., the calling - // convention will save/restore it in the prolog/epilog). Other than that - // there are no callee save registers now that adapter frames are gone. - - __ movptr(Address(rsp, SimpleRuntimeFrame::rbp_off << LogBytesPerInt), rbp); - - // Store exception in Thread object. We cannot pass any arguments to the - // handle_exception call, since we do not want to make any assumption - // about the size of the frame where the exception happened in. - // c_rarg0 is either rdi (Linux) or rcx (Windows). - __ movptr(Address(r15_thread, JavaThread::exception_oop_offset()),rax); - __ movptr(Address(r15_thread, JavaThread::exception_pc_offset()), rdx); - - // This call does all the hard work. It checks if an exception handler - // exists in the method. - // If so, it returns the handler address. - // If not, it prepares for stack-unwinding, restoring the callee-save - // registers of the frame being removed. - // - // address OptoRuntime::handle_exception_C(JavaThread* thread) - - // At a method handle call, the stack may not be properly aligned - // when returning with an exception. - address the_pc = __ pc(); - __ set_last_Java_frame(noreg, noreg, the_pc, rscratch1); - __ mov(c_rarg0, r15_thread); - __ andptr(rsp, -(StackAlignmentInBytes)); // Align stack - __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C))); - - // Set an oopmap for the call site. This oopmap will only be used if we - // are unwinding the stack. Hence, all locations will be dead. - // Callee-saved registers will be the same as the frame above (i.e., - // handle_exception_stub), since they were restored when we got the - // exception. - - OopMapSet* oop_maps = new OopMapSet(); - - oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0)); - - __ reset_last_Java_frame(false); - - // Restore callee-saved registers - - // rbp is an implicitly saved callee-saved register (i.e., the calling - // convention will save restore it in prolog/epilog) Other than that - // there are no callee save registers now that adapter frames are gone. - - __ movptr(rbp, Address(rsp, SimpleRuntimeFrame::rbp_off << LogBytesPerInt)); - - __ addptr(rsp, SimpleRuntimeFrame::return_off << LogBytesPerInt); // Epilog - __ pop(rdx); // No need for exception pc anymore - - // rax: exception handler - - // We have a handler in rax (could be deopt blob). - __ mov(r8, rax); - - // Get the exception oop - __ movptr(rax, Address(r15_thread, JavaThread::exception_oop_offset())); - // Get the exception pc in case we are deoptimized - __ movptr(rdx, Address(r15_thread, JavaThread::exception_pc_offset())); -#ifdef ASSERT - __ movptr(Address(r15_thread, JavaThread::exception_handler_pc_offset()), NULL_WORD); - __ movptr(Address(r15_thread, JavaThread::exception_pc_offset()), NULL_WORD); -#endif - // Clear the exception oop so GC no longer processes it as a root. - __ movptr(Address(r15_thread, JavaThread::exception_oop_offset()), NULL_WORD); - - // rax: exception oop - // r8: exception handler - // rdx: exception pc - // Jump to handler - - __ jmp(r8); - - // Make sure all code is generated - masm->flush(); - - // Set exception blob - _exception_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1); -} -#endif // COMPILER2 diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 569d6bc35cd16..3bc5b9a8b2a7d 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -2151,7 +2151,7 @@ Node* GraphKit::uncommon_trap(int trap_request, kill_dead_locals(); // Now insert the uncommon trap subroutine call - address call_addr = SharedRuntime::uncommon_trap_blob()->entry_point(); + address call_addr = OptoRuntime::uncommon_trap_blob()->entry_point(); const TypePtr* no_memory_effects = nullptr; // Pass the index of the class to be loaded Node* call = make_runtime_call(RC_NO_LEAF | RC_UNCOMMON | diff --git a/src/hotspot/share/opto/lcm.cpp b/src/hotspot/share/opto/lcm.cpp index 549290397e3b7..9db94748ca27c 100644 --- a/src/hotspot/share/opto/lcm.cpp +++ b/src/hotspot/share/opto/lcm.cpp @@ -122,7 +122,7 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo for (uint i1 = 0; i1 < null_block->number_of_nodes(); i1++) { Node* nn = null_block->get_node(i1); if (nn->is_MachCall() && - nn->as_MachCall()->entry_point() == SharedRuntime::uncommon_trap_blob()->entry_point()) { + nn->as_MachCall()->entry_point() == OptoRuntime::uncommon_trap_blob()->entry_point()) { const Type* trtype = nn->in(TypeFunc::Parms)->bottom_type(); if (trtype->isa_int() && trtype->is_int()->is_con()) { jint tr_con = trtype->is_int()->get_con(); diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index f1c3e592fff53..9660413dd190f 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -5949,7 +5949,7 @@ CallStaticJavaNode* LibraryCallKit::get_uncommon_trap_from_success_proj(Node* no for (DUIterator_Fast jmax, j = other_proj->fast_outs(jmax); j < jmax; j++) { Node* obs = other_proj->fast_out(j); if (obs->in(0) == other_proj && obs->is_CallStaticJava() && - (obs->as_CallStaticJava()->entry_point() == SharedRuntime::uncommon_trap_blob()->entry_point())) { + (obs->as_CallStaticJava()->entry_point() == OptoRuntime::uncommon_trap_blob()->entry_point())) { return obs->as_CallStaticJava(); } } diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 45e59f4e21680..b4c134570e63f 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -567,7 +567,7 @@ void PhaseIdealLoop::add_parse_predicate(Deoptimization::DeoptReason reason, Nod register_control(if_true, loop, parse_predicate); int trap_request = Deoptimization::make_trap_request(reason, Deoptimization::Action_maybe_recompile); - address call_addr = SharedRuntime::uncommon_trap_blob()->entry_point(); + address call_addr = OptoRuntime::uncommon_trap_blob()->entry_point(); const TypePtr* no_memory_effects = nullptr; JVMState* jvms = sfpt->jvms(); CallNode* unc = new CallStaticJavaNode(OptoRuntime::uncommon_trap_Type(), call_addr, "uncommon_trap", diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp index 4c2f208e445c1..4e2306602e6f7 100644 --- a/src/hotspot/share/opto/matcher.cpp +++ b/src/hotspot/share/opto/matcher.cpp @@ -2960,7 +2960,7 @@ bool Matcher::branches_to_uncommon_trap(const Node *n) { } if (call && - call->entry_point() == SharedRuntime::uncommon_trap_blob()->entry_point()) { + call->entry_point() == OptoRuntime::uncommon_trap_blob()->entry_point()) { const Type* trtype = call->in(TypeFunc::Parms)->bottom_type(); if (trtype->isa_int() && trtype->is_int()->is_con()) { jint tr_con = trtype->is_int()->get_con(); diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp index 465404bb4693f..54408146d0c26 100644 --- a/src/hotspot/share/opto/runtime.cpp +++ b/src/hotspot/share/opto/runtime.cpp @@ -114,7 +114,8 @@ address OptoRuntime::_notify_jvmti_vthread_mount = nullptr; address OptoRuntime::_notify_jvmti_vthread_unmount = nullptr; #endif -ExceptionBlob* OptoRuntime::_exception_blob; +UncommonTrapBlob* OptoRuntime::_uncommon_trap_blob; +ExceptionBlob* OptoRuntime::_exception_blob; // This should be called in an assertion at the start of OptoRuntime routines // which are entered from compiled code (all of them) @@ -138,6 +139,7 @@ static bool check_compiled_frame(JavaThread* thread) { bool OptoRuntime::generate(ciEnv* env) { + generate_uncommon_trap_blob(); generate_exception_blob(); // Note: tls: Means fetching the return oop out of the thread-local storage diff --git a/src/hotspot/share/opto/runtime.hpp b/src/hotspot/share/opto/runtime.hpp index 6aadab9712243..34c2780a2f8d7 100644 --- a/src/hotspot/share/opto/runtime.hpp +++ b/src/hotspot/share/opto/runtime.hpp @@ -168,7 +168,10 @@ class OptoRuntime : public AllStatic { // CodeBlob support // =================================================================== + static UncommonTrapBlob* _uncommon_trap_blob; static ExceptionBlob* _exception_blob; + + static void generate_uncommon_trap_blob(void); static void generate_exception_blob(); static void register_finalizer(oopDesc* obj, JavaThread* current); @@ -208,6 +211,7 @@ class OptoRuntime : public AllStatic { static address notify_jvmti_vthread_unmount() { return _notify_jvmti_vthread_unmount; } #endif + static UncommonTrapBlob* uncommon_trap_blob() { return _uncommon_trap_blob; } static ExceptionBlob* exception_blob() { return _exception_blob; } // Implicit exception support diff --git a/src/hotspot/share/opto/stringopts.cpp b/src/hotspot/share/opto/stringopts.cpp index 2e227be765cfa..7bf75c93055a5 100644 --- a/src/hotspot/share/opto/stringopts.cpp +++ b/src/hotspot/share/opto/stringopts.cpp @@ -203,7 +203,7 @@ class StringConcat : public ResourceObj { Node* uct = _uncommon_traps.at(u); // Build a new call using the jvms state of the allocate - address call_addr = SharedRuntime::uncommon_trap_blob()->entry_point(); + address call_addr = OptoRuntime::uncommon_trap_blob()->entry_point(); const TypeFunc* call_type = OptoRuntime::uncommon_trap_Type(); const TypePtr* no_memory_effects = nullptr; Compile* C = _stringopts->C; diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index 0e6d367586b9d..0eec7e4c34cae 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -100,10 +100,6 @@ SafepointBlob* SharedRuntime::_polling_page_vectors_safepoint_handler_blob; SafepointBlob* SharedRuntime::_polling_page_safepoint_handler_blob; SafepointBlob* SharedRuntime::_polling_page_return_handler_blob; -#ifdef COMPILER2 -UncommonTrapBlob* SharedRuntime::_uncommon_trap_blob; -#endif // COMPILER2 - nmethod* SharedRuntime::_cont_doYield_stub; //----------------------------generate_stubs----------------------------------- @@ -129,10 +125,6 @@ void SharedRuntime::generate_stubs() { _polling_page_return_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_RETURN); generate_deopt_blob(); - -#ifdef COMPILER2 - generate_uncommon_trap_blob(); -#endif // COMPILER2 } #include diff --git a/src/hotspot/share/runtime/sharedRuntime.hpp b/src/hotspot/share/runtime/sharedRuntime.hpp index da61883b2fe64..9eec8e079ec34 100644 --- a/src/hotspot/share/runtime/sharedRuntime.hpp +++ b/src/hotspot/share/runtime/sharedRuntime.hpp @@ -62,10 +62,6 @@ class SharedRuntime: AllStatic { static SafepointBlob* _polling_page_safepoint_handler_blob; static SafepointBlob* _polling_page_return_handler_blob; -#ifdef COMPILER2 - static UncommonTrapBlob* _uncommon_trap_blob; -#endif // COMPILER2 - static nmethod* _cont_doYield_stub; #ifndef PRODUCT @@ -223,11 +219,6 @@ class SharedRuntime: AllStatic { return _wrong_method_abstract_blob->entry_point(); } -#ifdef COMPILER2 - static void generate_uncommon_trap_blob(void); - static UncommonTrapBlob* uncommon_trap_blob() { return _uncommon_trap_blob; } -#endif // COMPILER2 - static address get_resolve_opt_virtual_call_stub() { assert(_resolve_opt_virtual_call_blob != nullptr, "oops"); return _resolve_opt_virtual_call_blob->entry_point(); From 53db937dd0766695906dc20c1dbbd3228c02fe1e Mon Sep 17 00:00:00 2001 From: Feilong Jiang Date: Tue, 6 Aug 2024 14:01:23 +0000 Subject: [PATCH 30/77] 8337780: RISC-V: C2: Change C calling convention for sp to NS Reviewed-by: fyang, rehn --- src/hotspot/cpu/riscv/riscv.ad | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index b176c6e9cb7c2..1e26c2bf14202 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -84,8 +84,8 @@ reg_def R0 ( NS, NS, Op_RegI, 0, x0->as_VMReg() ); // zr reg_def R0_H ( NS, NS, Op_RegI, 0, x0->as_VMReg()->next() ); reg_def R1 ( NS, SOC, Op_RegI, 1, x1->as_VMReg() ); // ra reg_def R1_H ( NS, SOC, Op_RegI, 1, x1->as_VMReg()->next() ); -reg_def R2 ( NS, SOE, Op_RegI, 2, x2->as_VMReg() ); // sp -reg_def R2_H ( NS, SOE, Op_RegI, 2, x2->as_VMReg()->next() ); +reg_def R2 ( NS, NS, Op_RegI, 2, x2->as_VMReg() ); // sp +reg_def R2_H ( NS, NS, Op_RegI, 2, x2->as_VMReg()->next() ); reg_def R3 ( NS, NS, Op_RegI, 3, x3->as_VMReg() ); // gp reg_def R3_H ( NS, NS, Op_RegI, 3, x3->as_VMReg()->next() ); reg_def R4 ( NS, NS, Op_RegI, 4, x4->as_VMReg() ); // tp From 3f8b3e55276336cbb814d3b746d4337678389969 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Tue, 6 Aug 2024 16:37:59 +0000 Subject: [PATCH 31/77] 8337887: [JVMCI] Clarify jdk.vm.ci.code.Architecture.getName javadoc Reviewed-by: never --- .../share/classes/jdk/vm/ci/aarch64/AArch64.java | 2 ++ .../share/classes/jdk/vm/ci/amd64/AMD64.java | 2 ++ .../share/classes/jdk/vm/ci/code/Architecture.java | 13 +++++++++---- .../share/classes/jdk/vm/ci/riscv64/RISCV64.java | 2 ++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java index 609e01a8db154..c0d6c4cdb84ee 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java @@ -35,6 +35,8 @@ /** * Represents the AArch64 architecture. + * + * The value returned by {@code Architecture#getName} for an instance of this class is {@code "aarch64"}. */ public class AArch64 extends Architecture { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java index 83401fed62033..f0ca7a2fc2359 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java @@ -40,6 +40,8 @@ /** * Represents the AMD64 architecture. + * + * The value returned by {@code Architecture#getName} for an instance of this class is {@code "AMD64"}. */ public class AMD64 extends Architecture { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/Architecture.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/Architecture.java index f14855cd6b995..64b0600674fd6 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/Architecture.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/Architecture.java @@ -107,7 +107,7 @@ protected Architecture(String name, PlatformKind wordKind, ByteOrder byteOrder, /** * Converts this architecture to a string. * - * @return the string representation of this architecture + * @return a lowercase version of {@linkplain #getName name} */ @Override public final String toString() { @@ -126,9 +126,14 @@ public PlatformKind getWordKind() { return wordKind; } - /** - * Gets the name of this architecture. - */ + /// Gets the name of this architecture. The value returned for + /// each architecture is shown in the table below. + /// + /// | Name | Receiver type | + /// |-----------|-----------------------------| + /// | "aarch64" | [jdk.vm.ci.aarch64.AArch64] | + /// | "AMD64" | [jdk.vm.ci.amd64.AMD64] | + /// | "riscv64" | [jdk.vm.ci.riscv64.RISCV64] | public String getName() { return name; } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/riscv64/RISCV64.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/riscv64/RISCV64.java index c06ba315a149c..0a28703001503 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/riscv64/RISCV64.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/riscv64/RISCV64.java @@ -35,6 +35,8 @@ /** * Represents the RISCV64 architecture. + * + * The value returned by {@code Architecture#getName} for an instance of this class is {@code "riscv64"}. */ public class RISCV64 extends Architecture { From ff634a967027cfa56b666d31c45db9a4acc09ea4 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Tue, 6 Aug 2024 20:11:21 +0000 Subject: [PATCH 32/77] 8337506: Disable "best-fit" mapping on Windows command line Reviewed-by: alanb --- src/java.base/share/native/launcher/main.c | 22 ++++- .../launcher/DisableBestFitMappingTest.java | 83 +++++++++++++++++++ 2 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 test/jdk/tools/launcher/DisableBestFitMappingTest.java diff --git a/src/java.base/share/native/launcher/main.c b/src/java.base/share/native/launcher/main.c index d3898d7adc634..c504c13154f5b 100644 --- a/src/java.base/share/native/launcher/main.c +++ b/src/java.base/share/native/launcher/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2024, 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 @@ -110,7 +110,25 @@ main(int argc, char **argv) } } } - JLI_CmdToArgs(GetCommandLine()); + + // Obtain the command line in UTF-16, then convert it to ANSI code page + // without the "best-fit" option + LPWSTR wcCmdline = GetCommandLineW(); + int mbSize = WideCharToMultiByte(CP_ACP, + WC_NO_BEST_FIT_CHARS | WC_COMPOSITECHECK | WC_DEFAULTCHAR, + wcCmdline, -1, NULL, 0, NULL, NULL); + // If the call to WideCharToMultiByte() fails, it returns 0, which + // will then make the following JLI_MemAlloc() to issue exit(1) + LPSTR mbCmdline = JLI_MemAlloc(mbSize); + if (WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS | WC_COMPOSITECHECK | WC_DEFAULTCHAR, + wcCmdline, -1, mbCmdline, mbSize, NULL, NULL) == 0) { + perror("command line encoding conversion failure"); + exit(1); + } + + JLI_CmdToArgs(mbCmdline); + JLI_MemFree(mbCmdline); + margc = JLI_GetStdArgc(); // add one more to mark the end margv = (char **)JLI_MemAlloc((margc + 1) * (sizeof(char *))); diff --git a/test/jdk/tools/launcher/DisableBestFitMappingTest.java b/test/jdk/tools/launcher/DisableBestFitMappingTest.java new file mode 100644 index 0000000000000..6602aae60a9fe --- /dev/null +++ b/test/jdk/tools/launcher/DisableBestFitMappingTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2024, 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. + * + * 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. + */ + +/* + * @test + * @bug 8337506 + * @summary Verify Command Line arguments are not mapped with + * "best-fit" mappings on Windows + * @requires (os.family == "windows") + * @library /test/lib + * @run junit DisableBestFitMappingTest + */ +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; +import java.util.stream.Stream; +import jdk.test.lib.process.ProcessTools; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assumptions.*; + +public class DisableBestFitMappingTest { + private static final CharsetEncoder NATIVE_ENC = + Charset.forName(System.getProperty("native.encoding")).newEncoder(); + private static final String REPLACEMENT = + NATIVE_ENC.charset().decode(ByteBuffer.wrap(NATIVE_ENC.replacement())).toString(); + private static final int EXIT_SUCCESS = 0; + private static final int EXIT_FAILURE = -1; + + static Stream CMD_ARGS() { + return Stream.of( + Arguments.of("aa\uff02 \uff02bb", "aa" + REPLACEMENT + " " + REPLACEMENT + "bb"), + Arguments.of("aa\uff01bb", "aa" + REPLACEMENT + "bb"), + Arguments.of("aa\u221ebb", "aa" + REPLACEMENT + "bb") + ); + } + + @ParameterizedTest + @MethodSource("CMD_ARGS") + void testDisableBestFitMapping(String arg, String expected) throws Exception { + // Only execute if the arg cannot be encoded + assumeFalse(NATIVE_ENC.canEncode(arg), + "native.encoding (%s) can encode the argument '%s'. Test ignored." + .formatted(NATIVE_ENC.charset(), arg)); + + var result= ProcessTools.executeTestJava( + DisableBestFitMappingTest.class.getSimpleName(), arg, expected); + result.asLines().forEach(System.out::println); + assertEquals(EXIT_SUCCESS, result.getExitValue(), + "Disabling best-fit mapping failed"); + } + + public static void main(String... args) { + System.out.println(args[0]); + System.out.println(args[1]); + System.exit(args[0].equals(args[1]) ? EXIT_SUCCESS : EXIT_FAILURE); + } +} From 22a3421379162bb302fb8e5ccc315e53d95b6245 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 6 Aug 2024 20:15:47 +0000 Subject: [PATCH 33/77] 8337786: Fix simple -Wzero-as-null-pointer-constant warnings in aarch64 code Reviewed-by: shade, tschatzl --- src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp | 2 +- src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp | 4 ++-- src/hotspot/cpu/aarch64/frame_aarch64.cpp | 6 +++--- src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp | 2 +- src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp | 4 ++-- src/hotspot/cpu/aarch64/vm_version_aarch64.cpp | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp index 615c8e19ac863..91430be5835b5 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp @@ -647,7 +647,7 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi break; case T_OBJECT: case T_ARRAY: - assert(c->as_jobject() == 0, "should be"); + assert(c->as_jobject() == nullptr, "should be"); if (UseCompressedOops && !wide) { insn = &Assembler::strw; } else { diff --git a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp index 63a32e714e365..780055a611f3b 100644 --- a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1029,4 +1029,4 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { #undef __ -const char *Runtime1::pd_name_for_address(address entry) { Unimplemented(); return 0; } +const char *Runtime1::pd_name_for_address(address entry) { Unimplemented(); } diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.cpp b/src/hotspot/cpu/aarch64/frame_aarch64.cpp index 0387f763bbdd7..c2b127f31bb6d 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp @@ -293,7 +293,7 @@ void frame::patch_pc(Thread* thread, address pc) { // Either the return address is the original one or we are going to // patch in the same address that's already there. - assert(_pc == pc_old || pc == pc_old || pc_old == 0, ""); + assert(_pc == pc_old || pc == pc_old || pc_old == nullptr, ""); DEBUG_ONLY(address old_pc = _pc;) *pc_addr = signed_pc; _pc = pc; // must be set before call to get_deopt_original_pc @@ -497,10 +497,10 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const { bool frame::is_interpreted_frame_valid(JavaThread* thread) const { assert(is_interpreted_frame(), "Not an interpreted frame"); // These are reasonable sanity checks - if (fp() == 0 || (intptr_t(fp()) & (wordSize-1)) != 0) { + if (fp() == nullptr || (intptr_t(fp()) & (wordSize-1)) != 0) { return false; } - if (sp() == 0 || (intptr_t(sp()) & (wordSize-1)) != 0) { + if (sp() == nullptr || (intptr_t(sp()) & (wordSize-1)) != 0) { return false; } if (fp() + interpreter_frame_initial_sp_offset < sp()) { diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index e210c8b3de05a..25dfaca6dca20 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -215,7 +215,7 @@ class RelocActions { break; } else { // nothing to do - assert(target == 0, "did not expect to relocate target for polling page load"); + assert(target == nullptr, "did not expect to relocate target for polling page load"); } break; } diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp index 5a3f9d228ca89..770ed2f6c3868 100644 --- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp @@ -228,7 +228,7 @@ address NativeJump::jump_destination() const { // load // return -1 if jump to self or to 0 - if ((dest == (address)this) || dest == 0) { + if ((dest == (address)this) || dest == nullptr) { dest = (address) -1; } return dest; @@ -256,7 +256,7 @@ address NativeGeneralJump::jump_destination() const { // a general jump // return -1 if jump to self or to 0 - if ((dest == (address)this) || dest == 0) { + if ((dest == (address)this) || dest == nullptr) { dest = (address) -1; } return dest; diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index aa64f411dbfb9..c0f10adc85df9 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -606,12 +606,12 @@ static bool check_info_file(const char* fpath, return false; } while (fgets(line, sizeof(line), fp) != nullptr) { - if (strcasestr(line, virt1) != 0) { + if (strcasestr(line, virt1) != nullptr) { Abstract_VM_Version::_detected_virtualization = vt1; fclose(fp); return true; } - if (virt2 != nullptr && strcasestr(line, virt2) != 0) { + if (virt2 != nullptr && strcasestr(line, virt2) != nullptr) { Abstract_VM_Version::_detected_virtualization = vt2; fclose(fp); return true; From fc652d2a58bfd99b05011c051e5710d1dac049ab Mon Sep 17 00:00:00 2001 From: Alisen Chung Date: Tue, 6 Aug 2024 21:10:06 +0000 Subject: [PATCH 34/77] 8235404: [macos] JOptionPane blocks drawing string on another component Reviewed-by: honkar, dnguyen --- .../classes/javax/swing/JOptionPane.java | 7 +- .../swing/JOptionPane/OptionPaneInput.java | 80 +++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 test/jdk/javax/swing/JOptionPane/OptionPaneInput.java diff --git a/src/java.desktop/share/classes/javax/swing/JOptionPane.java b/src/java.desktop/share/classes/javax/swing/JOptionPane.java index 930acc90b35c3..1c1f3ee9ba355 100644 --- a/src/java.desktop/share/classes/javax/swing/JOptionPane.java +++ b/src/java.desktop/share/classes/javax/swing/JOptionPane.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -883,6 +883,11 @@ public static int showOptionDialog(Component parentComponent, Object selectedValue = pane.getValue(); + if (parentComponent != null) { + parentComponent.revalidate(); + parentComponent.repaint(); + } + if(selectedValue == null) return CLOSED_OPTION; if(options == null) { diff --git a/test/jdk/javax/swing/JOptionPane/OptionPaneInput.java b/test/jdk/javax/swing/JOptionPane/OptionPaneInput.java new file mode 100644 index 0000000000000..998efccf1f3ce --- /dev/null +++ b/test/jdk/javax/swing/JOptionPane/OptionPaneInput.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2024, 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. + * + * 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. + */ + +import java.awt.Canvas; +import java.awt.Color; +import java.awt.Graphics2D; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 8235404 + * @summary Checks that JOptionPane doesn't block drawing strings on another component + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual OptionPaneInput + */ +public class OptionPaneInput { + private static JFrame f; + private static Canvas c; + private static JTextField t; + private static final String instructions = """ + 1. Type "test" into the message dialog. + 2. Press enter key. + 3. Press OK button. + 4. If the OptionPaneInput frame has test drawn on it, pass. Otherwise fail. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame testFrame = new PassFailJFrame(instructions); + + SwingUtilities.invokeAndWait(() -> createGUI()); + testFrame.awaitAndCheck(); + } + + public static void createGUI() { + f = new JFrame("OptionPaneInput"); + c = new Canvas(); + t = new JTextField(); + f.add(c); + + t.addActionListener(e -> { + String text = t.getText(); + Graphics2D g2 = (Graphics2D)(c.getGraphics()); + g2.setColor(Color.BLACK); + g2.drawString(text, 10, 10); + System.out.println("drawing "+text); + g2.dispose(); + }); + + f.setSize(300, 100); + PassFailJFrame.addTestWindow(f); + PassFailJFrame.positionTestWindow(f, PassFailJFrame.Position.HORIZONTAL); + f.setVisible(true); + + JOptionPane.showMessageDialog(f, t); + } +} From 6733b89de1ed9ebcc1e8a8271970048ad0f0aac3 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Tue, 6 Aug 2024 21:44:30 +0000 Subject: [PATCH 35/77] 8337667: sun/tools/jcmd/TestJcmdPIDSubstitution.java is failing on mac and windows Reviewed-by: stuefe, kevinw --- test/jdk/sun/tools/jcmd/TestJcmdPIDSubstitution.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/jdk/sun/tools/jcmd/TestJcmdPIDSubstitution.java b/test/jdk/sun/tools/jcmd/TestJcmdPIDSubstitution.java index f462ea1a52b0d..4af5bf1ff6755 100644 --- a/test/jdk/sun/tools/jcmd/TestJcmdPIDSubstitution.java +++ b/test/jdk/sun/tools/jcmd/TestJcmdPIDSubstitution.java @@ -40,6 +40,8 @@ import java.nio.file.Path; import java.nio.file.Paths; +import jdk.test.lib.Platform; + public class TestJcmdPIDSubstitution { private static final String FILENAME = "myfile%p"; @@ -47,8 +49,10 @@ public class TestJcmdPIDSubstitution { public static void main(String[] args) throws Exception { verifyOutputFilenames("Thread.dump_to_file", FILENAME); verifyOutputFilenames("GC.heap_dump", FILENAME); - verifyOutputFilenames("Compiler.perfmap", FILENAME); - verifyOutputFilenames("System.dump_map", "-F=%s".formatted(FILENAME)); + if (Platform.isLinux()) { + verifyOutputFilenames("Compiler.perfmap", FILENAME); + verifyOutputFilenames("System.dump_map", "-F=%s".formatted(FILENAME)); + } } private static void verifyOutputFilenames(String... args) throws Exception { From 920751e5d5838dab90438117a77f43876902eb72 Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Tue, 6 Aug 2024 21:56:48 +0000 Subject: [PATCH 36/77] 8311990: Two JDI tests may interfere with each other Reviewed-by: dholmes, sspitsyn --- test/jdk/com/sun/jdi/JdwpListenTest.java | 5 +++-- test/jdk/com/sun/jdi/JdwpNetProps.java | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/test/jdk/com/sun/jdi/JdwpListenTest.java b/test/jdk/com/sun/jdi/JdwpListenTest.java index a55eefb58689c..53f5b404de5e4 100644 --- a/test/jdk/com/sun/jdi/JdwpListenTest.java +++ b/test/jdk/com/sun/jdi/JdwpListenTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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 @@ -50,7 +50,8 @@ public class JdwpListenTest { // Set to true to allow testing of attach from wrong address (expected to fail). // It's off by default as it causes test time increase and test interference (see JDK-8231915). - private static boolean allowNegativeTesting = false; + private static boolean allowNegativeTesting = + "true".equalsIgnoreCase(System.getProperty("jdk.jdi.allowNegativeTesting")); public static void main(String[] args) throws Exception { List addresses = Utils.getAddressesWithSymbolicAndNumericScopes(); diff --git a/test/jdk/com/sun/jdi/JdwpNetProps.java b/test/jdk/com/sun/jdi/JdwpNetProps.java index af69c9ca3adf2..0247e4551a3da 100644 --- a/test/jdk/com/sun/jdi/JdwpNetProps.java +++ b/test/jdk/com/sun/jdi/JdwpNetProps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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 @@ -49,6 +49,11 @@ */ public class JdwpNetProps { + // Set to true to allow testing of attach from wrong address (expected to fail). + // It's off by default as it causes test interference (see JDK-8311990). + private static boolean allowNegativeAttachTesting = + "true".equalsIgnoreCase(System.getProperty("jdk.jdi.allowNegativeTesting")); + public static void main(String[] args) throws Exception { InetAddress addrs[] = InetAddress.getAllByName("localhost"); InetAddress ipv4Address = null; @@ -171,6 +176,14 @@ public ListenTest preferIPv6Addresses(String value) { } public void run(TestResult expectedResult) throws Exception { + log("\nTest: listen at " + listenAddress + ", attaching to " + connectAddress + + ", preferIPv4Stack = " + preferIPv4Stack + + ", preferIPv6Addresses = " + preferIPv6Addresses + + ", expectedResult = " + expectedResult); + if (expectedResult == TestResult.AttachFailed && !allowNegativeAttachTesting) { + log("SKIPPED: negative attach testing is disabled"); + return; + } List options = new LinkedList<>(); if (preferIPv4Stack != null) { options.add("-Djava.net.preferIPv4Stack=" + preferIPv4Stack.toString()); From 66286b25a183de2ffd0689da9c2bd1978b881aa7 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Wed, 7 Aug 2024 05:32:28 +0000 Subject: [PATCH 37/77] 8337968: Problem list compiler/vectorapi/VectorRebracket128Test.java Reviewed-by: chagedorn --- test/hotspot/jtreg/ProblemList.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 7e7970a4c6caf..f5b14e87607e3 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -59,6 +59,8 @@ compiler/codecache/CheckLargePages.java 8332654 linux-x64 compiler/vectorapi/reshape/TestVectorReinterpret.java 8320897 aix-ppc64,linux-ppc64le compiler/vectorapi/VectorLogicalOpIdentityTest.java 8302459 linux-x64,windows-x64 +compiler/vectorapi/VectorRebracket128Test.java#ZSinglegen 8330538 generic-all +compiler/vectorapi/VectorRebracket128Test.java#ZGenerational 8330538 generic-all compiler/jvmci/TestUncaughtErrorInCompileMethod.java 8309073 generic-all From 41f784fe63f8e06a25e1fe00dc96e398874adf81 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 7 Aug 2024 07:48:05 +0000 Subject: [PATCH 38/77] 8335925: Serial: Move allocation API from Generation to subclasses Reviewed-by: gli, kbarrett, iwalulya --- src/hotspot/share/gc/serial/defNewGeneration.cpp | 10 ++-------- src/hotspot/share/gc/serial/defNewGeneration.hpp | 8 +++----- src/hotspot/share/gc/serial/generation.hpp | 14 -------------- src/hotspot/share/gc/serial/serialHeap.cpp | 13 +++++++------ src/hotspot/share/gc/serial/tenuredGeneration.cpp | 9 ++++----- src/hotspot/share/gc/serial/tenuredGeneration.hpp | 8 +++++--- .../share/gc/serial/tenuredGeneration.inline.hpp | 14 +------------- 7 files changed, 22 insertions(+), 54 deletions(-) diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index e93b97c85eb12..047171a5eb364 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -572,11 +572,6 @@ HeapWord* DefNewGeneration::block_start(const void* p) const { return block_start_const(to(), p); } -HeapWord* DefNewGeneration::expand_and_allocate(size_t size, bool is_tlab) { - // We don't attempt to expand the young generation (but perhaps we should.) - return allocate(size, is_tlab); -} - void DefNewGeneration::adjust_desired_tenuring_threshold() { // Set the desired survivor size to half the real survivor space size_t const survivor_capacity = to()->capacity() / HeapWordSize; @@ -865,7 +860,7 @@ const char* DefNewGeneration::name() const { return "def new generation"; } -HeapWord* DefNewGeneration::allocate(size_t word_size, bool is_tlab) { +HeapWord* DefNewGeneration::allocate(size_t word_size) { // This is the slow-path allocation for the DefNewGeneration. // Most allocations are fast-path in compiled code. // We try to allocate from the eden. If that works, we are happy. @@ -875,8 +870,7 @@ HeapWord* DefNewGeneration::allocate(size_t word_size, bool is_tlab) { return result; } -HeapWord* DefNewGeneration::par_allocate(size_t word_size, - bool is_tlab) { +HeapWord* DefNewGeneration::par_allocate(size_t word_size) { return eden()->par_allocate(word_size); } diff --git a/src/hotspot/share/gc/serial/defNewGeneration.hpp b/src/hotspot/share/gc/serial/defNewGeneration.hpp index 011b79fdabd6b..c5b7c095ac4e6 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.hpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.hpp @@ -209,9 +209,9 @@ class DefNewGeneration: public Generation { return result; } - HeapWord* allocate(size_t word_size, bool is_tlab); - - HeapWord* par_allocate(size_t word_size, bool is_tlab); + // Allocate requested size or return null; single-threaded and lock-free versions. + HeapWord* allocate(size_t word_size); + HeapWord* par_allocate(size_t word_size); void gc_epilogue(bool full); @@ -227,8 +227,6 @@ class DefNewGeneration: public Generation { bool collect(bool clear_all_soft_refs); - HeapWord* expand_and_allocate(size_t size, bool is_tlab); - oop copy_to_survivor_space(oop old); uint tenuring_threshold() { return _tenuring_threshold; } diff --git a/src/hotspot/share/gc/serial/generation.hpp b/src/hotspot/share/gc/serial/generation.hpp index a757c97c5cb15..beb29928f4826 100644 --- a/src/hotspot/share/gc/serial/generation.hpp +++ b/src/hotspot/share/gc/serial/generation.hpp @@ -103,20 +103,6 @@ class Generation: public CHeapObj { return _reserved.contains(p); } - // Allocate and returns a block of the requested size, or returns "null". - // Assumes the caller has done any necessary locking. - virtual HeapWord* allocate(size_t word_size, bool is_tlab) = 0; - - // Like "allocate", but performs any necessary locking internally. - virtual HeapWord* par_allocate(size_t word_size, bool is_tlab) = 0; - - // Perform a heap collection, attempting to create (at least) enough - // space to support an allocation of the given "word_size". If - // successful, perform the allocation and return the resulting - // "oop" (initializing the allocated block). If the allocation is - // still unsuccessful, return "null". - virtual HeapWord* expand_and_allocate(size_t word_size, bool is_tlab) = 0; - // Printing virtual const char* name() const = 0; virtual const char* short_name() const = 0; diff --git a/src/hotspot/share/gc/serial/serialHeap.cpp b/src/hotspot/share/gc/serial/serialHeap.cpp index c1fdc1eba1a32..3c48177554121 100644 --- a/src/hotspot/share/gc/serial/serialHeap.cpp +++ b/src/hotspot/share/gc/serial/serialHeap.cpp @@ -156,7 +156,7 @@ void SerialHeap::safepoint_synchronize_end() { HeapWord* SerialHeap::allocate_loaded_archive_space(size_t word_size) { MutexLocker ml(Heap_lock); - return old_gen()->allocate(word_size, false /* is_tlab */); + return old_gen()->allocate(word_size); } void SerialHeap::complete_loaded_archive_space(MemRegion archive_space) { @@ -292,11 +292,12 @@ bool SerialHeap::should_try_older_generation_allocation(size_t word_size) const HeapWord* SerialHeap::expand_heap_and_allocate(size_t size, bool is_tlab) { HeapWord* result = nullptr; if (_old_gen->should_allocate(size, is_tlab)) { - result = _old_gen->expand_and_allocate(size, is_tlab); + result = _old_gen->expand_and_allocate(size); } if (result == nullptr) { if (_young_gen->should_allocate(size, is_tlab)) { - result = _young_gen->expand_and_allocate(size, is_tlab); + // Young-gen is not expanded. + result = _young_gen->allocate(size); } } assert(result == nullptr || is_in_reserved(result), "result not in heap"); @@ -314,7 +315,7 @@ HeapWord* SerialHeap::mem_allocate_work(size_t size, // First allocation attempt is lock-free. DefNewGeneration *young = _young_gen; if (young->should_allocate(size, is_tlab)) { - result = young->par_allocate(size, is_tlab); + result = young->par_allocate(size); if (result != nullptr) { assert(is_in_reserved(result), "result not in heap"); return result; @@ -406,14 +407,14 @@ HeapWord* SerialHeap::attempt_allocation(size_t size, HeapWord* res = nullptr; if (_young_gen->should_allocate(size, is_tlab)) { - res = _young_gen->allocate(size, is_tlab); + res = _young_gen->allocate(size); if (res != nullptr || first_only) { return res; } } if (_old_gen->should_allocate(size, is_tlab)) { - res = _old_gen->allocate(size, is_tlab); + res = _old_gen->allocate(size); } return res; diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.cpp b/src/hotspot/share/gc/serial/tenuredGeneration.cpp index b1b7507094771..febc4713d0372 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.cpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.cpp @@ -397,20 +397,19 @@ oop TenuredGeneration::allocate_for_promotion(oop obj, size_t obj_size) { #endif // #ifndef PRODUCT // Allocate new object. - HeapWord* result = allocate(obj_size, false); + HeapWord* result = allocate(obj_size); if (result == nullptr) { // Promotion of obj into gen failed. Try to expand and allocate. - result = expand_and_allocate(obj_size, false); + result = expand_and_allocate(obj_size); } return cast_to_oop(result); } HeapWord* -TenuredGeneration::expand_and_allocate(size_t word_size, bool is_tlab) { - assert(!is_tlab, "TenuredGeneration does not support TLAB allocation"); +TenuredGeneration::expand_and_allocate(size_t word_size) { expand(word_size*HeapWordSize, _min_heap_delta_bytes); - return allocate(word_size, is_tlab); + return allocate(word_size); } void TenuredGeneration::assert_correct_size_change_locking() { diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.hpp b/src/hotspot/share/gc/serial/tenuredGeneration.hpp index dcec912d4887f..fc0578d4e4fe4 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.hpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.hpp @@ -130,10 +130,12 @@ class TenuredGeneration: public Generation { void complete_loaded_archive_space(MemRegion archive_space); inline void update_for_block(HeapWord* start, HeapWord* end); - virtual inline HeapWord* allocate(size_t word_size, bool is_tlab); - virtual inline HeapWord* par_allocate(size_t word_size, bool is_tlab); + // Allocate and returns a block of the requested size, or returns "null". + // Assumes the caller has done any necessary locking. + inline HeapWord* allocate(size_t word_size); - HeapWord* expand_and_allocate(size_t size, bool is_tlab); + // Expand the old-gen then invoke allocate above. + HeapWord* expand_and_allocate(size_t size); void gc_prologue(); void gc_epilogue(); diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.inline.hpp b/src/hotspot/share/gc/serial/tenuredGeneration.inline.hpp index ba0dbcdc02d57..c6a6a0ae71634 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.inline.hpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.inline.hpp @@ -48,9 +48,7 @@ inline void TenuredGeneration::update_for_block(HeapWord* start, HeapWord* end) _bts->update_for_block(start, end); } -HeapWord* TenuredGeneration::allocate(size_t word_size, - bool is_tlab) { - assert(!is_tlab, "TenuredGeneration does not support TLAB allocation"); +HeapWord* TenuredGeneration::allocate(size_t word_size) { HeapWord* res = _the_space->allocate(word_size); if (res != nullptr) { _bts->update_for_block(res, res + word_size); @@ -58,14 +56,4 @@ HeapWord* TenuredGeneration::allocate(size_t word_size, return res; } -HeapWord* TenuredGeneration::par_allocate(size_t word_size, - bool is_tlab) { - assert(!is_tlab, "TenuredGeneration does not support TLAB allocation"); - HeapWord* res = _the_space->par_allocate(word_size); - if (res != nullptr) { - _bts->update_for_block(res, res + word_size); - } - return res; -} - #endif // SHARE_GC_SERIAL_TENUREDGENERATION_INLINE_HPP From 88a05a853ed9e0425ba3315b751a5015bed62675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Wed, 7 Aug 2024 10:24:34 +0000 Subject: [PATCH 39/77] 8337975: [BACKOUT] Native memory leak when not recording any events Reviewed-by: jpai, egahlin --- .../share/jfr/recorder/service/jfrRecorderService.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp index 418b774996e4c..fc2043a4d921d 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp @@ -639,7 +639,11 @@ static void write_thread_local_buffer(JfrChunkWriter& chunkwriter, Thread* t) { size_t JfrRecorderService::flush() { size_t total_elements = flush_metadata(_chunkwriter); - total_elements += flush_storage(_storage, _chunkwriter); + const size_t storage_elements = flush_storage(_storage, _chunkwriter); + if (0 == storage_elements) { + return total_elements; + } + total_elements += storage_elements; if (_string_pool.is_modified()) { total_elements += flush_stringpool(_string_pool, _chunkwriter); } From 21f710e7f6698b12b06cc3685cefa31f5fcff2a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Sikstr=C3=B6m?= Date: Wed, 7 Aug 2024 14:16:01 +0000 Subject: [PATCH 40/77] 8310675: Fix -Wconversion warnings in ZGC code Reviewed-by: stefank, ayang --- src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp | 2 +- src/hotspot/share/gc/z/zArguments.cpp | 2 +- src/hotspot/share/gc/z/zArray.inline.hpp | 4 +- src/hotspot/share/gc/z/zBarrier.cpp | 4 +- src/hotspot/share/gc/z/zBarrierSetNMethod.cpp | 4 +- src/hotspot/share/gc/z/zCPU.inline.hpp | 4 +- src/hotspot/share/gc/z/zDirector.cpp | 10 ++--- .../gc/z/zForwardingAllocator.inline.hpp | 4 +- src/hotspot/share/gc/z/zGeneration.cpp | 6 +-- src/hotspot/share/gc/z/zGeneration.hpp | 4 +- src/hotspot/share/gc/z/zHeapIterator.cpp | 6 +-- src/hotspot/share/gc/z/zHeuristics.cpp | 14 +++---- .../share/gc/z/zIndexDistributor.inline.hpp | 6 +-- src/hotspot/share/gc/z/zLiveMap.cpp | 6 +-- src/hotspot/share/gc/z/zLiveMap.hpp | 4 +- src/hotspot/share/gc/z/zMarkCache.cpp | 4 +- src/hotspot/share/gc/z/zMarkStack.cpp | 4 +- src/hotspot/share/gc/z/zMetronome.cpp | 10 ++--- src/hotspot/share/gc/z/zNMethod.cpp | 6 +-- src/hotspot/share/gc/z/zNMethodTable.cpp | 8 ++-- src/hotspot/share/gc/z/zObjArrayAllocator.cpp | 4 +- src/hotspot/share/gc/z/zPage.inline.hpp | 12 +++--- src/hotspot/share/gc/z/zPageCache.cpp | 6 +-- src/hotspot/share/gc/z/zPageTable.inline.hpp | 4 +- src/hotspot/share/gc/z/zRelocationSet.cpp | 6 +-- .../share/gc/z/zRelocationSetSelector.cpp | 8 ++-- src/hotspot/share/gc/z/zStat.cpp | 38 ++++++++++--------- src/hotspot/share/gc/z/zStat.hpp | 3 +- .../share/gc/z/zStoreBarrierBuffer.cpp | 20 +++++----- .../share/gc/z/zStoreBarrierBuffer.hpp | 10 ++--- .../share/gc/z/zStoreBarrierBuffer.inline.hpp | 4 +- src/hotspot/share/gc/z/zUnmapper.cpp | 4 +- src/hotspot/share/gc/z/zVerify.cpp | 4 +- 33 files changed, 120 insertions(+), 115 deletions(-) diff --git a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp index dbec45fd96ea9..f72e84eaf5935 100644 --- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp +++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp @@ -327,7 +327,7 @@ int ZBarrierSetC2::estimate_stub_size() const { int size = 0; for (int i = 0; i < stubs->length(); i++) { - CodeBuffer cb(blob->content_begin(), (address)C->output()->scratch_locs_memory() - blob->content_begin()); + CodeBuffer cb(blob->content_begin(), checked_cast((address)C->output()->scratch_locs_memory() - blob->content_begin())); MacroAssembler masm(&cb); stubs->at(i)->emit_code(masm); size += cb.insts_size(); diff --git a/src/hotspot/share/gc/z/zArguments.cpp b/src/hotspot/share/gc/z/zArguments.cpp index c71e59944f095..f3ff568c64d14 100644 --- a/src/hotspot/share/gc/z/zArguments.cpp +++ b/src/hotspot/share/gc/z/zArguments.cpp @@ -146,7 +146,7 @@ void ZArguments::initialize() { ZHeuristics::set_medium_page_size(); if (!FLAG_IS_DEFAULT(ZTenuringThreshold) && ZTenuringThreshold != -1) { - FLAG_SET_ERGO_IF_DEFAULT(MaxTenuringThreshold, ZTenuringThreshold); + FLAG_SET_ERGO_IF_DEFAULT(MaxTenuringThreshold, (uint)ZTenuringThreshold); if (MaxTenuringThreshold == 0) { FLAG_SET_ERGO_IF_DEFAULT(AlwaysTenure, true); } diff --git a/src/hotspot/share/gc/z/zArray.inline.hpp b/src/hotspot/share/gc/z/zArray.inline.hpp index 2ec87a761564e..ec7feda8d6398 100644 --- a/src/hotspot/share/gc/z/zArray.inline.hpp +++ b/src/hotspot/share/gc/z/zArray.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -61,7 +61,7 @@ inline ZArrayIteratorImpl::ZArrayIteratorImpl(const T* array, size_ template inline ZArrayIteratorImpl::ZArrayIteratorImpl(const ZArray* array) - : ZArrayIteratorImpl(array->is_empty() ? nullptr : array->adr_at(0), array->length()) {} + : ZArrayIteratorImpl(array->is_empty() ? nullptr : array->adr_at(0), (size_t)array->length()) {} template inline bool ZArrayIteratorImpl::next(T* elem) { diff --git a/src/hotspot/share/gc/z/zBarrier.cpp b/src/hotspot/share/gc/z/zBarrier.cpp index c4b6e0f8239e1..7d7f1284bdfdc 100644 --- a/src/hotspot/share/gc/z/zBarrier.cpp +++ b/src/hotspot/share/gc/z/zBarrier.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -291,7 +291,7 @@ zaddress ZBarrier::keep_alive_slow_path(zaddress addr) { // ON_WEAK barriers should only ever be applied to j.l.r.Reference.referents. void ZBarrier::verify_on_weak(volatile zpointer* referent_addr) { if (referent_addr != nullptr) { - const uintptr_t base = (uintptr_t)referent_addr - java_lang_ref_Reference::referent_offset(); + const uintptr_t base = (uintptr_t)referent_addr - (size_t)java_lang_ref_Reference::referent_offset(); const oop obj = cast_to_oop(base); assert(oopDesc::is_oop(obj), "Verification failed for: ref " PTR_FORMAT " obj: " PTR_FORMAT, (uintptr_t)referent_addr, base); assert(java_lang_ref_Reference::is_referent_field(obj, java_lang_ref_Reference::referent_offset()), "Sanity"); diff --git a/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp b/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp index b8ecc3eddd3cd..33894f166a3e9 100644 --- a/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp +++ b/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, 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 @@ -79,7 +79,7 @@ bool ZBarrierSetNMethod::nmethod_entry_barrier(nmethod* nm) { ZNMethod::nmethod_oops_do_inner(nm, &cl); const uintptr_t prev_color = ZNMethod::color(nm); - const uintptr_t new_color = *(int*)ZPointerStoreGoodMaskLowOrderBitsAddr; + const uintptr_t new_color = *ZPointerStoreGoodMaskLowOrderBitsAddr; log_develop_trace(gc, nmethod)("nmethod: " PTR_FORMAT " visited by entry (complete) [" PTR_FORMAT " -> " PTR_FORMAT "]", p2i(nm), prev_color, new_color); // CodeCache unloading support diff --git a/src/hotspot/share/gc/z/zCPU.inline.hpp b/src/hotspot/share/gc/z/zCPU.inline.hpp index 67d26f4c2e17c..b3712dc5ac98b 100644 --- a/src/hotspot/share/gc/z/zCPU.inline.hpp +++ b/src/hotspot/share/gc/z/zCPU.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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 @@ -30,7 +30,7 @@ #include "utilities/debug.hpp" inline uint32_t ZCPU::count() { - return os::processor_count(); + return (uint32_t)os::processor_count(); } inline uint32_t ZCPU::id() { diff --git a/src/hotspot/share/gc/z/zDirector.cpp b/src/hotspot/share/gc/z/zDirector.cpp index 162e05f2c0763..3ba8698bd8e22 100644 --- a/src/hotspot/share/gc/z/zDirector.cpp +++ b/src/hotspot/share/gc/z/zDirector.cpp @@ -102,7 +102,7 @@ static double estimated_gc_workers(double serial_gc_time, double parallelizable_ } static uint discrete_young_gc_workers(double gc_workers) { - return clamp(ceil(gc_workers), 1, ZYoungGCThreads); + return clamp((uint)ceil(gc_workers), 1, ZYoungGCThreads); } static double select_young_gc_workers(const ZDirectorStats& stats, double serial_gc_time, double parallelizable_gc_time, double alloc_rate_sd_percent, double time_until_oom) { @@ -426,7 +426,7 @@ static bool rule_major_warmup(const ZDirectorStats& stats) { const size_t soft_max_capacity = stats._heap._soft_max_heap_size; const size_t used = stats._heap._used; const double used_threshold_percent = (stats._old_stats._cycle._nwarmup_cycles + 1) * 0.1; - const size_t used_threshold = soft_max_capacity * used_threshold_percent; + const size_t used_threshold = (size_t)(soft_max_capacity * used_threshold_percent); log_debug(gc, director)("Rule Major: Warmup %.0f%%, Used: " SIZE_FORMAT "MB, UsedThreshold: " SIZE_FORMAT "MB", used_threshold_percent * 100, used / M, used_threshold / M); @@ -497,13 +497,13 @@ static bool rule_major_allocation_rate(const ZDirectorStats& stats) { // Doing an old collection makes subsequent young collections more efficient. // Calculate the number of young collections ahead that we will try to amortize // the cost of doing an old collection for. - const int lookahead = stats._heap._total_collections - stats._old_stats._general._total_collections_at_start; + const uint lookahead = stats._heap._total_collections - stats._old_stats._general._total_collections_at_start; // Calculate extra young collection overhead predicted for a number of future // young collections, due to not freeing up memory in the old generation. const double extra_young_gc_time_for_lookahead = extra_young_gc_time * lookahead; - log_debug(gc, director)("Rule Major: Allocation Rate, ExtraYoungGCTime: %.3fs, OldGCTime: %.3fs, Lookahead: %d, ExtraYoungGCTimeForLookahead: %.3fs", + log_debug(gc, director)("Rule Major: Allocation Rate, ExtraYoungGCTime: %.3fs, OldGCTime: %.3fs, Lookahead: %u, ExtraYoungGCTimeForLookahead: %.3fs", extra_young_gc_time, old_gc_time, lookahead, extra_young_gc_time_for_lookahead); // If we continue doing as many minor collections as we already did since the @@ -565,7 +565,7 @@ static bool rule_major_proactive(const ZDirectorStats& stats) { // passed since the previous GC. This helps avoid superfluous GCs when running // applications with very low allocation rate. const size_t used_after_last_gc = stats._old_stats._stat_heap._used_at_relocate_end; - const size_t used_increase_threshold = stats._heap._soft_max_heap_size * 0.10; // 10% + const size_t used_increase_threshold = (size_t)(stats._heap._soft_max_heap_size * 0.10); // 10% const size_t used_threshold = used_after_last_gc + used_increase_threshold; const size_t used = stats._heap._used; const double time_since_last_gc = stats._old_stats._cycle._time_since_last; diff --git a/src/hotspot/share/gc/z/zForwardingAllocator.inline.hpp b/src/hotspot/share/gc/z/zForwardingAllocator.inline.hpp index 41d9106843450..42d006a5b3734 100644 --- a/src/hotspot/share/gc/z/zForwardingAllocator.inline.hpp +++ b/src/hotspot/share/gc/z/zForwardingAllocator.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -30,7 +30,7 @@ #include "utilities/debug.hpp" inline size_t ZForwardingAllocator::size() const { - return _end - _start; + return (size_t)(_end - _start); } inline bool ZForwardingAllocator::is_full() const { diff --git a/src/hotspot/share/gc/z/zGeneration.cpp b/src/hotspot/share/gc/z/zGeneration.cpp index be86550d32171..8a7d38e299166 100644 --- a/src/hotspot/share/gc/z/zGeneration.cpp +++ b/src/hotspot/share/gc/z/zGeneration.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, 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 @@ -299,7 +299,7 @@ void ZGeneration::reset_statistics() { _page_allocator->reset_statistics(_id); } -ssize_t ZGeneration::freed() const { +size_t ZGeneration::freed() const { return _freed; } @@ -448,7 +448,7 @@ class VM_ZOperation : public VM_Operation { _success = do_operation(); // Update statistics - ZStatSample(ZSamplerJavaThreads, Threads::number_of_threads()); + ZStatSample(ZSamplerJavaThreads, (uint64_t)Threads::number_of_threads()); } virtual void doit_epilogue() { diff --git a/src/hotspot/share/gc/z/zGeneration.hpp b/src/hotspot/share/gc/z/zGeneration.hpp index 32762a50b6278..aec48a0a07236 100644 --- a/src/hotspot/share/gc/z/zGeneration.hpp +++ b/src/hotspot/share/gc/z/zGeneration.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, 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 @@ -122,7 +122,7 @@ class ZGeneration { // Statistics void reset_statistics(); virtual bool should_record_stats() = 0; - ssize_t freed() const; + size_t freed() const; void increase_freed(size_t size); size_t promoted() const; void increase_promoted(size_t size); diff --git a/src/hotspot/share/gc/z/zHeapIterator.cpp b/src/hotspot/share/gc/z/zHeapIterator.cpp index cbcac39a11bbc..50fc921131fe7 100644 --- a/src/hotspot/share/gc/z/zHeapIterator.cpp +++ b/src/hotspot/share/gc/z/zHeapIterator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, 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. * * This code is free software; you can redistribute it and/or modify it @@ -204,7 +204,7 @@ class ZHeapIteratorOopClosure : public OopIterateClosure { assert(ZCollectedHeap::heap()->is_in(p), "Should be in heap"); if (VisitReferents) { - return HeapAccess::oop_load_at(_base, _base->field_offset(p)); + return HeapAccess::oop_load_at(_base, (ptrdiff_t)_base->field_offset(p)); } return HeapAccess::oop_load(p); @@ -447,7 +447,7 @@ void ZHeapIterator::follow_array_chunk(const ZHeapIteratorContext& context, cons const objArrayOop obj = objArrayOop(array.obj()); const int length = obj->length(); const int start = array.index(); - const int stride = MIN2(length - start, ObjArrayMarkingStride); + const int stride = MIN2(length - start, (int)ObjArrayMarkingStride); const int end = start + stride; // Push remaining array chunk first diff --git a/src/hotspot/share/gc/z/zHeuristics.cpp b/src/hotspot/share/gc/z/zHeuristics.cpp index c764227061e88..ebf979af79518 100644 --- a/src/hotspot/share/gc/z/zHeuristics.cpp +++ b/src/hotspot/share/gc/z/zHeuristics.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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 @@ -39,14 +39,14 @@ void ZHeuristics::set_medium_page_size() { // becomes larger than ZPageSizeSmall. const size_t min = ZGranuleSize; const size_t max = ZGranuleSize * 16; - const size_t unclamped = MaxHeapSize * 0.03125; + const size_t unclamped = (size_t)(MaxHeapSize * 0.03125); const size_t clamped = clamp(unclamped, min, max); const size_t size = round_down_power_of_2(clamped); if (size > ZPageSizeSmall) { // Enable medium pages ZPageSizeMedium = size; - ZPageSizeMediumShift = log2i_exact(ZPageSizeMedium); + ZPageSizeMediumShift = (size_t)log2i_exact(ZPageSizeMedium); ZObjectSizeLimitMedium = ZPageSizeMedium / 8; ZObjectAlignmentMediumShift = (int)ZPageSizeMediumShift - 13; ZObjectAlignmentMedium = 1 << ZObjectAlignmentMediumShift; @@ -68,11 +68,11 @@ bool ZHeuristics::use_per_cpu_shared_small_pages() { } static uint nworkers_based_on_ncpus(double cpu_share_in_percent) { - return ceil(os::initial_active_processor_count() * cpu_share_in_percent / 100.0); + return (uint)ceil(os::initial_active_processor_count() * cpu_share_in_percent / 100.0); } static uint nworkers_based_on_heap_size(double heap_share_in_percent) { - return (MaxHeapSize * (heap_share_in_percent / 100.0)) / ZPageSizeSmall; + return (uint)(MaxHeapSize * (heap_share_in_percent / 100.0) / ZPageSizeSmall); } static uint nworkers(double cpu_share_in_percent) { @@ -101,9 +101,9 @@ uint ZHeuristics::nconcurrent_workers() { } size_t ZHeuristics::significant_heap_overhead() { - return MaxHeapSize * (ZFragmentationLimit / 100); + return (size_t)(MaxHeapSize * (ZFragmentationLimit / 100)); } size_t ZHeuristics::significant_young_overhead() { - return MaxHeapSize * (ZYoungCompactionLimit / 100); + return (size_t)(MaxHeapSize * (ZYoungCompactionLimit / 100)); } diff --git a/src/hotspot/share/gc/z/zIndexDistributor.inline.hpp b/src/hotspot/share/gc/z/zIndexDistributor.inline.hpp index 172ba2505759d..26afdef9d052d 100644 --- a/src/hotspot/share/gc/z/zIndexDistributor.inline.hpp +++ b/src/hotspot/share/gc/z/zIndexDistributor.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, 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 @@ -47,7 +47,7 @@ class ZIndexDistributorStriped : public CHeapObj { } volatile int* claim_addr(int index) { - return (volatile int*)(align_up(_mem, ZCacheLineSize) + index * ZCacheLineSize); + return (volatile int*)(align_up(_mem, ZCacheLineSize) + (size_t)index * ZCacheLineSize); } public: @@ -136,7 +136,7 @@ class ZIndexDistributorClaimTree : public CHeapObj { // Total size used to hold all claim variables static size_t claim_variables_size() { - return sizeof(int) * claim_level_end_index(ClaimLevels); + return sizeof(int) * (size_t)claim_level_end_index(ClaimLevels); } // Returns the index of the start of the current segment of the current level diff --git a/src/hotspot/share/gc/z/zLiveMap.cpp b/src/hotspot/share/gc/z/zLiveMap.cpp index 2e4a8edd356cc..4123620f8b7e0 100644 --- a/src/hotspot/share/gc/z/zLiveMap.cpp +++ b/src/hotspot/share/gc/z/zLiveMap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -47,7 +47,7 @@ ZLiveMap::ZLiveMap(uint32_t size) _segment_live_bits(0), _segment_claim_bits(0), _bitmap(bitmap_size(size, nsegments)), - _segment_shift(exact_log2(segment_size())) {} + _segment_shift(log2i_exact(segment_size())) {} void ZLiveMap::reset(ZGenerationId id) { ZGeneration* const generation = ZGeneration::generation(id); @@ -130,6 +130,6 @@ void ZLiveMap::resize(uint32_t size) { const size_t new_bitmap_size = bitmap_size(size, nsegments); if (_bitmap.size() != new_bitmap_size) { _bitmap.reinitialize(new_bitmap_size, false /* clear */); - _segment_shift = exact_log2(segment_size()); + _segment_shift = log2i_exact(segment_size()); } } diff --git a/src/hotspot/share/gc/z/zLiveMap.hpp b/src/hotspot/share/gc/z/zLiveMap.hpp index e3bcd2e267ddb..f8b16d06dc52c 100644 --- a/src/hotspot/share/gc/z/zLiveMap.hpp +++ b/src/hotspot/share/gc/z/zLiveMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -43,7 +43,7 @@ class ZLiveMap { BitMap::bm_word_t _segment_live_bits; BitMap::bm_word_t _segment_claim_bits; ZBitMap _bitmap; - size_t _segment_shift; + int _segment_shift; const BitMapView segment_live_bits() const; const BitMapView segment_claim_bits() const; diff --git a/src/hotspot/share/gc/z/zMarkCache.cpp b/src/hotspot/share/gc/z/zMarkCache.cpp index 7fbb5a8be4e61..0eecfbfaa6773 100644 --- a/src/hotspot/share/gc/z/zMarkCache.cpp +++ b/src/hotspot/share/gc/z/zMarkCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, 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. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ #include "utilities/powerOfTwo.hpp" static size_t shift_for_stripes(size_t nstripes) { - return ZMarkStripeShift + exact_log2(nstripes); + return ZMarkStripeShift + (size_t)log2i_exact(nstripes); } ZMarkCacheEntry::ZMarkCacheEntry() diff --git a/src/hotspot/share/gc/z/zMarkStack.cpp b/src/hotspot/share/gc/z/zMarkStack.cpp index 1e10c41eb41dd..c4938af0a5f6d 100644 --- a/src/hotspot/share/gc/z/zMarkStack.cpp +++ b/src/hotspot/share/gc/z/zMarkStack.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, 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. * * This code is free software; you can redistribute it and/or modify it @@ -86,7 +86,7 @@ ZMarkStripe* ZMarkStripeSet::stripe_for_worker(uint nworkers, uint worker_id) { const size_t spillover_nworkers = nworkers - spillover_limit; const size_t spillover_worker_id = worker_id - spillover_limit; const double spillover_chunk = (double)nstripes / (double)spillover_nworkers; - index = spillover_worker_id * spillover_chunk; + index = (size_t)(spillover_worker_id * spillover_chunk); } assert(index < nstripes, "Invalid index"); diff --git a/src/hotspot/share/gc/z/zMetronome.cpp b/src/hotspot/share/gc/z/zMetronome.cpp index 0cc209cd7c843..876b1f6922799 100644 --- a/src/hotspot/share/gc/z/zMetronome.cpp +++ b/src/hotspot/share/gc/z/zMetronome.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -38,7 +38,7 @@ bool ZMetronome::wait_for_tick() { if (_nticks++ == 0) { // First tick, set start time const Ticks now = Ticks::now(); - _start_ms = TimeHelper::counter_to_millis(now.value()); + _start_ms = (uint64_t)TimeHelper::counter_to_millis(now.value()); } MonitorLocker ml(&_monitor, Monitor::_no_safepoint_check_flag); @@ -47,9 +47,9 @@ bool ZMetronome::wait_for_tick() { // We might wake up spuriously from wait, so always recalculate // the timeout after a wakeup to see if we need to wait again. const Ticks now = Ticks::now(); - const uint64_t now_ms = TimeHelper::counter_to_millis(now.value()); + const uint64_t now_ms = (uint64_t)TimeHelper::counter_to_millis(now.value()); const uint64_t next_ms = _start_ms + (_interval_ms * _nticks); - const int64_t timeout_ms = next_ms - now_ms; + const int64_t timeout_ms = (int64_t)(next_ms - now_ms); if (timeout_ms > 0) { // Wait @@ -57,7 +57,7 @@ bool ZMetronome::wait_for_tick() { } else { // Tick if (timeout_ms < 0) { - const uint64_t overslept = -timeout_ms; + const uint64_t overslept = (uint64_t)-timeout_ms; if (overslept > _interval_ms) { // Missed one or more ticks. Bump _nticks accordingly to // avoid firing a string of immediate ticks to make up diff --git a/src/hotspot/share/gc/z/zNMethod.cpp b/src/hotspot/share/gc/z/zNMethod.cpp index 7ae7b204d08c9..7c5b1e06edbb0 100644 --- a/src/hotspot/share/gc/z/zNMethod.cpp +++ b/src/hotspot/share/gc/z/zNMethod.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, 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. * * This code is free software; you can redistribute it and/or modify it @@ -302,8 +302,8 @@ void ZNMethod::nmethods_do(bool secondary, NMethodClosure* cl) { uintptr_t ZNMethod::color(nmethod* nm) { BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); - // color is stored at low order bits of int; implicit conversion to uintptr_t is fine - return bs_nm->guard_value(nm); + // color is stored at low order bits of int; conversion to uintptr_t is fine + return (uintptr_t)bs_nm->guard_value(nm); } oop ZNMethod::load_oop(oop* p, DecoratorSet decorators) { diff --git a/src/hotspot/share/gc/z/zNMethodTable.cpp b/src/hotspot/share/gc/z/zNMethodTable.cpp index a4b56292c522b..9714bee4bd88f 100644 --- a/src/hotspot/share/gc/z/zNMethodTable.cpp +++ b/src/hotspot/share/gc/z/zNMethodTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, 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. * * This code is free software; you can redistribute it and/or modify it @@ -144,9 +144,9 @@ void ZNMethodTable::rebuild_if_needed() { // grows/shrinks by doubling/halving its size. Pruning of unregistered // entries is done by rebuilding the table with or without resizing it. const size_t min_size = 1024; - const size_t shrink_threshold = _size * 0.30; - const size_t prune_threshold = _size * 0.65; - const size_t grow_threshold = _size * 0.70; + const size_t shrink_threshold = (size_t)(_size * 0.30); + const size_t prune_threshold = (size_t)(_size * 0.65); + const size_t grow_threshold = (size_t)(_size * 0.70); if (_size == 0) { // Initialize table diff --git a/src/hotspot/share/gc/z/zObjArrayAllocator.cpp b/src/hotspot/share/gc/z/zObjArrayAllocator.cpp index ad19f273dcf0f..ada8351a9f65f 100644 --- a/src/hotspot/share/gc/z/zObjArrayAllocator.cpp +++ b/src/hotspot/share/gc/z/zObjArrayAllocator.cpp @@ -76,8 +76,8 @@ oop ZObjArrayAllocator::initialize(HeapWord* mem) const { ZThreadLocalData::set_invisible_root(_thread, (zaddress_unsafe*)&mem); const BasicType element_type = ArrayKlass::cast(_klass)->element_type(); - const size_t base_offset_in_bytes = arrayOopDesc::base_offset_in_bytes(element_type); - const size_t process_start_offset_in_bytes = align_up(base_offset_in_bytes, BytesPerWord); + const size_t base_offset_in_bytes = (size_t)arrayOopDesc::base_offset_in_bytes(element_type); + const size_t process_start_offset_in_bytes = align_up(base_offset_in_bytes, (size_t)BytesPerWord); if (process_start_offset_in_bytes != base_offset_in_bytes) { // initialize_memory can only fill word aligned memory, diff --git a/src/hotspot/share/gc/z/zPage.inline.hpp b/src/hotspot/share/gc/z/zPage.inline.hpp index 0b4ee28ba7d0a..fcf69c685f7b6 100644 --- a/src/hotspot/share/gc/z/zPage.inline.hpp +++ b/src/hotspot/share/gc/z/zPage.inline.hpp @@ -83,13 +83,13 @@ inline uint32_t ZPage::object_max_count() const { inline size_t ZPage::object_alignment_shift() const { switch (type()) { case ZPageType::small: - return ZObjectAlignmentSmallShift; + return (size_t)ZObjectAlignmentSmallShift; case ZPageType::medium: - return ZObjectAlignmentMediumShift; + return (size_t)ZObjectAlignmentMediumShift; case ZPageType::large: - return ZObjectAlignmentLargeShift; + return (size_t)ZObjectAlignmentLargeShift; default: fatal("Unexpected page type"); @@ -100,13 +100,13 @@ inline size_t ZPage::object_alignment_shift() const { inline size_t ZPage::object_alignment() const { switch (type()) { case ZPageType::small: - return ZObjectAlignmentSmall; + return (size_t)ZObjectAlignmentSmall; case ZPageType::medium: - return ZObjectAlignmentMedium; + return (size_t)ZObjectAlignmentMedium; case ZPageType::large: - return ZObjectAlignmentLarge; + return (size_t)ZObjectAlignmentLarge; default: fatal("Unexpected page type"); diff --git a/src/hotspot/share/gc/z/zPageCache.cpp b/src/hotspot/share/gc/z/zPageCache.cpp index 96fd2eafe0f66..163bb395560de 100644 --- a/src/hotspot/share/gc/z/zPageCache.cpp +++ b/src/hotspot/share/gc/z/zPageCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -308,7 +308,7 @@ class ZPageCacheFlushForUncommitClosure : public ZPageCacheFlushClosure { }; size_t ZPageCache::flush_for_uncommit(size_t requested, ZList* to, uint64_t* timeout) { - const uint64_t now = os::elapsedTime(); + const uint64_t now = (uint64_t)os::elapsedTime(); const uint64_t expires = _last_commit + ZUncommitDelay; if (expires > now) { // Delay uncommit, set next timeout @@ -329,5 +329,5 @@ size_t ZPageCache::flush_for_uncommit(size_t requested, ZList* to, uint64 } void ZPageCache::set_last_commit() { - _last_commit = ceil(os::elapsedTime()); + _last_commit = (uint64_t)ceil(os::elapsedTime()); } diff --git a/src/hotspot/share/gc/z/zPageTable.inline.hpp b/src/hotspot/share/gc/z/zPageTable.inline.hpp index 3b4cbe9220cfb..79a2d297df889 100644 --- a/src/hotspot/share/gc/z/zPageTable.inline.hpp +++ b/src/hotspot/share/gc/z/zPageTable.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -69,7 +69,7 @@ inline ZPageTableParallelIterator::ZPageTableParallelIterator(const ZPageTable* template inline void ZPageTableParallelIterator::do_pages(Function function) { _index_distributor.do_indices([&](int index) { - ZPage* const page = _table->at(index); + ZPage* const page = _table->at(size_t(index)); if (page != nullptr) { const size_t start_index = untype(page->start()) >> ZGranuleSizeShift; if (size_t(index) == start_index) { diff --git a/src/hotspot/share/gc/z/zRelocationSet.cpp b/src/hotspot/share/gc/z/zRelocationSet.cpp index 92f245777b4e9..5c82f55bbbfe7 100644 --- a/src/hotspot/share/gc/z/zRelocationSet.cpp +++ b/src/hotspot/share/gc/z/zRelocationSet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, 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. * * This code is free software; you can redistribute it and/or modify it @@ -84,7 +84,7 @@ class ZRelocationSetInstallTask : public ZTask { : ZTask("ZRelocationSetInstallTask"), _allocator(allocator), _forwardings(nullptr), - _nforwardings(selector->selected_small()->length() + selector->selected_medium()->length()), + _nforwardings((size_t)selector->selected_small()->length() + (size_t)selector->selected_medium()->length()), _small(selector->selected_small()), _medium(selector->selected_medium()), _small_iter(selector->selected_small()), @@ -113,7 +113,7 @@ class ZRelocationSetInstallTask : public ZTask { for (size_t page_index; _small_iter.next_index(&page_index);) { ZPage* page = _small->at(int(page_index)); ZForwarding* const forwarding = ZForwarding::alloc(_allocator, page, to_age(page)); - install_small(forwarding, _medium->length() + page_index); + install_small(forwarding, (size_t)_medium->length() + page_index); SuspendibleThreadSet::yield(); } diff --git a/src/hotspot/share/gc/z/zRelocationSetSelector.cpp b/src/hotspot/share/gc/z/zRelocationSetSelector.cpp index ab1df68fe5110..ec904b914fb0b 100644 --- a/src/hotspot/share/gc/z/zRelocationSetSelector.cpp +++ b/src/hotspot/share/gc/z/zRelocationSetSelector.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, 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. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ ZRelocationSetSelectorGroup::ZRelocationSetSelectorGroup(const char* name, _page_size(page_size), _object_size_limit(object_size_limit), _fragmentation_limit(fragmentation_limit), - _page_fragmentation_limit(page_size * (fragmentation_limit / 100)), + _page_fragmentation_limit((size_t)(page_size * (fragmentation_limit / 100))), _live_pages(), _not_selected_pages(), _forwarding_entries(0), @@ -72,7 +72,7 @@ void ZRelocationSetSelectorGroup::semi_sort() { const size_t npartitions_shift = 11; const size_t npartitions = (size_t)1 << npartitions_shift; const size_t partition_size = _page_size >> npartitions_shift; - const size_t partition_size_shift = exact_log2(partition_size); + const int partition_size_shift = log2i_exact(partition_size); // Partition slots/fingers int partitions[npartitions] = { /* zero initialize */ }; @@ -135,7 +135,7 @@ void ZRelocationSetSelectorGroup::select_inner() { // By subtracting the object size limit from the pages size we get the maximum // number of pages that the relocation set is guaranteed to fit in, regardless // of in which order the objects are relocated. - const int to = ceil((double)(from_live_bytes) / (double)(_page_size - _object_size_limit)); + const int to = (int)ceil(from_live_bytes / (double)(_page_size - _object_size_limit)); // Calculate the relative difference in reclaimable space compared to our // currently selected final relocation set. If this number is larger than the diff --git a/src/hotspot/share/gc/z/zStat.cpp b/src/hotspot/share/gc/z/zStat.cpp index d838cb0b8138a..613f7b2740b43 100644 --- a/src/hotspot/share/gc/z/zStat.cpp +++ b/src/hotspot/share/gc/z/zStat.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -250,14 +250,14 @@ void ZStatUnitTime(LogTargetHandle log, const ZStatSampler& sampler, const ZStat "%9.3f / %-9.3f ms", sampler.group(), sampler.name(), - TimeHelper::counter_to_millis(history.avg_10_seconds()), - TimeHelper::counter_to_millis(history.max_10_seconds()), - TimeHelper::counter_to_millis(history.avg_10_minutes()), - TimeHelper::counter_to_millis(history.max_10_minutes()), - TimeHelper::counter_to_millis(history.avg_10_hours()), - TimeHelper::counter_to_millis(history.max_10_hours()), - TimeHelper::counter_to_millis(history.avg_total()), - TimeHelper::counter_to_millis(history.max_total())); + TimeHelper::counter_to_millis((jlong)history.avg_10_seconds()), + TimeHelper::counter_to_millis((jlong)history.max_10_seconds()), + TimeHelper::counter_to_millis((jlong)history.avg_10_minutes()), + TimeHelper::counter_to_millis((jlong)history.max_10_minutes()), + TimeHelper::counter_to_millis((jlong)history.avg_10_hours()), + TimeHelper::counter_to_millis((jlong)history.max_10_hours()), + TimeHelper::counter_to_millis((jlong)history.avg_total()), + TimeHelper::counter_to_millis((jlong)history.max_total())); } void ZStatUnitBytes(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history) { @@ -677,7 +677,7 @@ void ZStatPhaseCollection::register_end(ConcurrentGCTimer* timer, const Ticks& s ZCollectedHeap::heap()->trace_heap_after_gc(jfr_tracer()); const Tickspan duration = end - start; - ZStatSample(_sampler, duration.value()); + ZStatDurationSample(_sampler, duration); const size_t used_at_end = ZHeap::heap()->used(); @@ -718,7 +718,7 @@ void ZStatPhaseGeneration::register_end(ConcurrentGCTimer* timer, const Ticks& s ZCollectedHeap::heap()->print_heap_after_gc(); const Tickspan duration = end - start; - ZStatSample(_sampler, duration.value()); + ZStatDurationSample(_sampler, duration); ZGeneration* const generation = ZGeneration::generation(_id); @@ -766,7 +766,7 @@ void ZStatPhasePause::register_end(ConcurrentGCTimer* timer, const Ticks& start, timer->register_gc_pause_end(end); const Tickspan duration = end - start; - ZStatSample(_sampler, duration.value()); + ZStatDurationSample(_sampler, duration); // Track max pause time if (_max < duration) { @@ -798,7 +798,7 @@ void ZStatPhaseConcurrent::register_end(ConcurrentGCTimer* timer, const Ticks& s timer->register_gc_concurrent_end(end); const Tickspan duration = end - start; - ZStatSample(_sampler, duration.value()); + ZStatDurationSample(_sampler, duration); LogTarget(Info, gc, phases) log; log_end(log, duration); @@ -835,7 +835,7 @@ void ZStatSubPhase::register_end(ConcurrentGCTimer* timer, const Ticks& start, c ZTracer::report_thread_phase(name(), start, end); const Tickspan duration = end - start; - ZStatSample(_sampler, duration.value()); + ZStatDurationSample(_sampler, duration); if (Thread::current()->is_Worker_thread()) { LogTarget(Trace, gc, phases) log; @@ -862,7 +862,7 @@ void ZStatCriticalPhase::register_end(ConcurrentGCTimer* timer, const Ticks& sta ZTracer::report_thread_phase(name(), start, end); const Tickspan duration = end - start; - ZStatSample(_sampler, duration.value()); + ZStatDurationSample(_sampler, duration); ZStatInc(_counter); if (_verbose) { @@ -914,6 +914,10 @@ void ZStatSample(const ZStatSampler& sampler, uint64_t value) { ZTracer::report_stat_sampler(sampler, value); } +void ZStatDurationSample(const ZStatSampler& sampler, const Tickspan& duration) { + ZStatSample(sampler, (uint64_t)duration.value()); +} + void ZStatInc(const ZStatCounter& counter, uint64_t increment) { ZStatCounterData* const cpu_data = counter.get(); const uint64_t value = Atomic::add(&cpu_data->_counter, increment); @@ -1036,7 +1040,7 @@ void ZStat::sample_and_collect(ZStatSamplerHistory* history) const { bool ZStat::should_print(LogTargetHandle log) const { static uint64_t print_at = ZStatisticsInterval; - const uint64_t now = os::elapsedTime(); + const uint64_t now = (uint64_t)os::elapsedTime(); if (now < print_at) { return false; @@ -1846,7 +1850,7 @@ void ZStatHeap::at_relocate_end(const ZPageAllocatorStats& stats, bool record_st } size_t ZStatHeap::reclaimed_avg() { - return _reclaimed_bytes.davg(); + return (size_t)_reclaimed_bytes.davg(); } size_t ZStatHeap::max_capacity() { diff --git a/src/hotspot/share/gc/z/zStat.hpp b/src/hotspot/share/gc/z/zStat.hpp index 346773c3b7e2a..d7482dbe6aaaf 100644 --- a/src/hotspot/share/gc/z/zStat.hpp +++ b/src/hotspot/share/gc/z/zStat.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -345,6 +345,7 @@ class ZStatTimerWorker : public ZStatTimer { // Stat sample/increment // void ZStatSample(const ZStatSampler& sampler, uint64_t value); +void ZStatDurationSample(const ZStatSampler& sampler, const Tickspan& duration); void ZStatInc(const ZStatCounter& counter, uint64_t increment = 1); void ZStatInc(const ZStatUnsampledCounter& counter, uint64_t increment = 1); diff --git a/src/hotspot/share/gc/z/zStoreBarrierBuffer.cpp b/src/hotspot/share/gc/z/zStoreBarrierBuffer.cpp index 537609e723bbb..c94551dc62d20 100644 --- a/src/hotspot/share/gc/z/zStoreBarrierBuffer.cpp +++ b/src/hotspot/share/gc/z/zStoreBarrierBuffer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, 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 @@ -79,7 +79,7 @@ void ZStoreBarrierBuffer::install_base_pointers_inner() { (ZPointer::remap_bits(_last_processed_color) & ZPointerRemappedOldMask) == 0, "Should not have double bit errors"); - for (int i = current(); i < (int)_buffer_length; ++i) { + for (size_t i = current(); i < _buffer_length; ++i) { const ZStoreBarrierEntry& entry = _buffer[i]; volatile zpointer* const p = entry._p; const zaddress_unsafe p_unsafe = to_zaddress_unsafe((uintptr_t)p); @@ -141,7 +141,7 @@ static volatile zpointer* make_load_good(volatile zpointer* p, zaddress_unsafe p return (volatile zpointer*)p_remapped; } -void ZStoreBarrierBuffer::on_new_phase_relocate(int i) { +void ZStoreBarrierBuffer::on_new_phase_relocate(size_t i) { const uintptr_t last_remap_bits = ZPointer::remap_bits(_last_processed_color); if (last_remap_bits == ZPointerRemapped) { // All pointers are already remapped @@ -160,7 +160,7 @@ void ZStoreBarrierBuffer::on_new_phase_relocate(int i) { entry._p = make_load_good(entry._p, p_base, _last_processed_color); } -void ZStoreBarrierBuffer::on_new_phase_remember(int i) { +void ZStoreBarrierBuffer::on_new_phase_remember(size_t i) { volatile zpointer* const p = _buffer[i]._p; if (ZHeap::heap()->is_young(p)) { @@ -197,7 +197,7 @@ bool ZStoreBarrierBuffer::stored_during_old_mark() const { return last_mark_old_bits == ZPointerMarkedOld; } -void ZStoreBarrierBuffer::on_new_phase_mark(int i) { +void ZStoreBarrierBuffer::on_new_phase_mark(size_t i) { const ZStoreBarrierEntry& entry = _buffer[i]; const zpointer prev = entry._prev; @@ -229,7 +229,7 @@ void ZStoreBarrierBuffer::on_new_phase() { // Install all base pointers for relocation install_base_pointers(); - for (int i = current(); i < (int)_buffer_length; ++i) { + for (size_t i = current(); i < _buffer_length; ++i) { on_new_phase_relocate(i); on_new_phase_remember(i); on_new_phase_mark(i); @@ -259,8 +259,8 @@ void ZStoreBarrierBuffer::on_error(outputStream* st) { st->print_cr(" _last_processed_color: " PTR_FORMAT, _last_processed_color); st->print_cr(" _last_installed_color: " PTR_FORMAT, _last_installed_color); - for (int i = current(); i < (int)_buffer_length; ++i) { - st->print_cr(" [%2d]: base: " PTR_FORMAT " p: " PTR_FORMAT " prev: " PTR_FORMAT, + for (size_t i = current(); i < _buffer_length; ++i) { + st->print_cr(" [%2zu]: base: " PTR_FORMAT " p: " PTR_FORMAT " prev: " PTR_FORMAT, i, untype(_base_pointers[i]), p2i(_buffer[i]._p), @@ -276,7 +276,7 @@ void ZStoreBarrierBuffer::flush() { OnError on_error(this); VMErrorCallbackMark mark(&on_error); - for (int i = current(); i < (int)_buffer_length; ++i) { + for (size_t i = current(); i < _buffer_length; ++i) { const ZStoreBarrierEntry& entry = _buffer[i]; const zaddress addr = ZBarrier::make_load_good(entry._prev); ZBarrier::mark_and_remember(entry._p, addr); @@ -296,7 +296,7 @@ bool ZStoreBarrierBuffer::is_in(volatile zpointer* p) { const uintptr_t last_remap_bits = ZPointer::remap_bits(buffer->_last_processed_color) & ZPointerRemappedMask; const bool needs_remap = last_remap_bits != ZPointerRemapped; - for (int i = buffer->current(); i < (int)_buffer_length; ++i) { + for (size_t i = buffer->current(); i < _buffer_length; ++i) { const ZStoreBarrierEntry& entry = buffer->_buffer[i]; volatile zpointer* entry_p = entry._p; diff --git a/src/hotspot/share/gc/z/zStoreBarrierBuffer.hpp b/src/hotspot/share/gc/z/zStoreBarrierBuffer.hpp index f917a6c3e7b58..5903edb6ad409 100644 --- a/src/hotspot/share/gc/z/zStoreBarrierBuffer.hpp +++ b/src/hotspot/share/gc/z/zStoreBarrierBuffer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, 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 @@ -59,16 +59,16 @@ class ZStoreBarrierBuffer : public CHeapObj { // sizeof(ZStoreBarrierEntry) scaled index growing downwards size_t _current; - void on_new_phase_relocate(int i); - void on_new_phase_remember(int i); - void on_new_phase_mark(int i); + void on_new_phase_relocate(size_t i); + void on_new_phase_remember(size_t i); + void on_new_phase_mark(size_t i); void clear(); bool is_old_mark() const; bool stored_during_old_mark() const; bool is_empty() const; - intptr_t current() const; + size_t current() const; void install_base_pointers_inner(); diff --git a/src/hotspot/share/gc/z/zStoreBarrierBuffer.inline.hpp b/src/hotspot/share/gc/z/zStoreBarrierBuffer.inline.hpp index 762aac3ccd5bf..72327fe83466b 100644 --- a/src/hotspot/share/gc/z/zStoreBarrierBuffer.inline.hpp +++ b/src/hotspot/share/gc/z/zStoreBarrierBuffer.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, 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 @@ -30,7 +30,7 @@ #include "gc/z/zThreadLocalData.hpp" #include "runtime/thread.hpp" -inline intptr_t ZStoreBarrierBuffer::current() const { +inline size_t ZStoreBarrierBuffer::current() const { return _current / sizeof(ZStoreBarrierEntry); } diff --git a/src/hotspot/share/gc/z/zUnmapper.cpp b/src/hotspot/share/gc/z/zUnmapper.cpp index 3b2bac7eb00a7..b6ef40b6b059f 100644 --- a/src/hotspot/share/gc/z/zUnmapper.cpp +++ b/src/hotspot/share/gc/z/zUnmapper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -85,7 +85,7 @@ bool ZUnmapper::try_enqueue(ZPage* page) { } size_t ZUnmapper::queue_capacity() const { - return align_up(_page_allocator->max_capacity() * ZAsyncUnmappingLimit / 100.0, ZGranuleSize); + return align_up((size_t)(_page_allocator->max_capacity() * ZAsyncUnmappingLimit / 100.0), ZGranuleSize); } bool ZUnmapper::is_saturated() const { diff --git a/src/hotspot/share/gc/z/zVerify.cpp b/src/hotspot/share/gc/z/zVerify.cpp index fba8adfb3c16f..d47886ec7c2fc 100644 --- a/src/hotspot/share/gc/z/zVerify.cpp +++ b/src/hotspot/share/gc/z/zVerify.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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 @@ -583,7 +583,7 @@ void ZVerify::on_color_flip() { for (JavaThreadIteratorWithHandle jtiwh; JavaThread* const jt = jtiwh.next(); ) { const ZStoreBarrierBuffer* const buffer = ZThreadLocalData::store_barrier_buffer(jt); - for (int i = buffer->current(); i < (int)ZStoreBarrierBuffer::_buffer_length; ++i) { + for (size_t i = buffer->current(); i < ZStoreBarrierBuffer::_buffer_length; ++i) { volatile zpointer* const p = buffer->_buffer[i]._p; bool created = false; z_verify_store_barrier_buffer_table->put_if_absent(p, true, &created); From d19ba81ce12a99de1114c1bfe67392f5aee2104e Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Wed, 7 Aug 2024 15:58:03 +0000 Subject: [PATCH 41/77] 8337603: Change in behavior with -Djava.locale.useOldISOCodes=true Reviewed-by: iris, bpb --- .../util/locale/provider/LocaleResources.java | 13 ++++++- test/jdk/java/util/Locale/LocaleTest.java | 35 +++++++++++++++++-- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java b/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java index e83f2896304af..ee6ec0f72baa8 100644 --- a/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java +++ b/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, 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 @@ -62,6 +62,7 @@ import java.util.regex.Pattern; import java.util.stream.Stream; +import jdk.internal.util.StaticProperty; import sun.security.action.GetPropertyAction; import sun.util.resources.LocaleData; import sun.util.resources.OpenListResourceBundle; @@ -289,6 +290,16 @@ public String getCurrencyName(String key) { } public String getLocaleName(String key) { + // Get names for old ISO codes with new ISO code resources + if (StaticProperty.javaLocaleUseOldISOCodes().equalsIgnoreCase("true")) { + key = switch (key) { + case "iw" -> "he"; + case "in" -> "id"; + case "ji" -> "yi"; + default -> key; + }; + } + Object localeName = null; String cacheKey = LOCALE_NAMES + key; diff --git a/test/jdk/java/util/Locale/LocaleTest.java b/test/jdk/java/util/Locale/LocaleTest.java index c6afbc099ae75..0cf272f20a0d2 100644 --- a/test/jdk/java/util/Locale/LocaleTest.java +++ b/test/jdk/java/util/Locale/LocaleTest.java @@ -20,12 +20,13 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -/** +/* * @test * @bug 4052404 4052440 4084688 4092475 4101316 4105828 4107014 4107953 4110613 * 4118587 4118595 4122371 4126371 4126880 4135316 4135752 4139504 4139940 4143951 * 4147315 4147317 4147552 4335196 4778440 4940539 5010672 6475525 6544471 6627549 * 6786276 7066203 7085757 8008577 8030696 8170840 8174269 8255086 8263202 8287868 + * 8337603 * @summary test Locales * @modules jdk.localedata * @run junit LocaleTest @@ -84,9 +85,13 @@ import java.util.List; import java.util.Locale; import java.util.MissingResourceException; +import java.util.stream.Stream; import org.junit.jupiter.api.Test; - +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; public class LocaleTest { @@ -734,6 +739,32 @@ public void TestChangedISO639Codes() { } + /** + * @bug 8337603 + */ + static Stream changedISOCodes() { + var hebrew = "\u05e2\u05d1\u05e8\u05d9\u05ea"; + var yiddish = "\u05d9\u05d9\u05b4\u05d3\u05d9\u05e9"; + var indonesian = "Indonesia"; + + return Stream.of( + Arguments.of("he", hebrew), + Arguments.of("iw", hebrew), + Arguments.of("yi", yiddish), + Arguments.of("ji", yiddish), + Arguments.of("id", indonesian), + Arguments.of("in", indonesian) + ); + } + @ParameterizedTest + @MethodSource("changedISOCodes") + public void TestOldISOCodeLanguageName(String code, String expected) { + var loc = Locale.of(code); + assertEquals(expected, + loc.getDisplayName(loc), + "java.locale.useOldISOCodes=" + System.getProperty("java.locale.useOldISOCodes")); + } + /** * @bug 4092475 * I could not reproduce this bug. I'm pretty convinced it was fixed with the From 36d08c213d03deddf69ecb9770a3afef73a15444 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Wed, 7 Aug 2024 17:41:23 +0000 Subject: [PATCH 42/77] 8336846: assert(state->get_thread() == jt) failed: handshake unsafe conditions Reviewed-by: amenkov, dholmes, cjplummer, pchilanomate, lmesnik --- src/hotspot/share/prims/jvmtiEventController.cpp | 4 +++- src/hotspot/share/runtime/mutexLocker.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/prims/jvmtiEventController.cpp b/src/hotspot/share/prims/jvmtiEventController.cpp index d5c5d53ba8104..c9867ff164350 100644 --- a/src/hotspot/share/prims/jvmtiEventController.cpp +++ b/src/hotspot/share/prims/jvmtiEventController.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -982,6 +982,8 @@ JvmtiEventControllerPrivate::change_field_watch(jvmtiEvent event_type, bool adde added? "add" : "remove", *count_addr)); + JvmtiVTMSTransitionDisabler disabler; + if (added) { (*count_addr)++; if (*count_addr == 1) { diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index a63014d78a171..8c1dff38051d9 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -269,7 +269,6 @@ void mutex_init() { MUTEX_DEFN(JvmtiThreadState_lock , PaddedMutex , safepoint); // Used by JvmtiThreadState/JvmtiEventController MUTEX_DEFN(EscapeBarrier_lock , PaddedMonitor, nosafepoint); // Used to synchronize object reallocation/relocking triggered by JVMTI - MUTEX_DEFN(JvmtiVTMSTransition_lock , PaddedMonitor, safepoint); // used for Virtual Thread Mount State transition management MUTEX_DEFN(Management_lock , PaddedMutex , safepoint); // used for JVM management MUTEX_DEFN(ConcurrentGCBreakpoints_lock , PaddedMonitor, safepoint, true); @@ -355,6 +354,7 @@ void mutex_init() { // JVMCIRuntime_lock must be acquired before JVMCI_lock to avoid deadlock MUTEX_DEFL(JVMCI_lock , PaddedMonitor, JVMCIRuntime_lock); #endif + MUTEX_DEFL(JvmtiVTMSTransition_lock , PaddedMonitor, JvmtiThreadState_lock); // used for Virtual Thread Mount State transition management // Allocate RecursiveMutex MultiArray_lock = new RecursiveMutex(); From a5c2d7b305407974b3f67c48b8dcb1f8e77abde3 Mon Sep 17 00:00:00 2001 From: Fernando Guallini Date: Wed, 7 Aug 2024 18:24:08 +0000 Subject: [PATCH 43/77] 8335172: Add manual steps to run security/auth/callback/TextCallbackHandler/Password.java test Reviewed-by: rhalade --- test/jdk/ProblemList.txt | 1 - test/jdk/TEST.groups | 2 +- .../callback/TextCallbackHandler/Password.java | 16 ++++++++++++++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 3211f27b5c1e4..84c7a7d855f73 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -606,7 +606,6 @@ sun/security/smartcardio/TestExclusive.java 8039280 generic- sun/security/smartcardio/TestMultiplePresent.java 8039280 generic-all sun/security/smartcardio/TestPresent.java 8039280 generic-all sun/security/smartcardio/TestTransmit.java 8039280 generic-all -com/sun/security/auth/callback/TextCallbackHandler/Password.java 8039280 generic-all com/sun/security/sasl/gsskerb/AuthOnly.java 8039280 generic-all com/sun/security/sasl/gsskerb/ConfSecurityLayer.java 8039280 generic-all com/sun/security/sasl/gsskerb/NoSecurityLayer.java 8039280 generic-all diff --git a/test/jdk/TEST.groups b/test/jdk/TEST.groups index 55ae0e9c67b14..97b355fbea6c5 100644 --- a/test/jdk/TEST.groups +++ b/test/jdk/TEST.groups @@ -623,7 +623,6 @@ jdk_security_manual_no_input = \ :jdk_security_infra \ com/sun/crypto/provider/Cipher/AEAD/GCMIncrementByte4.java \ com/sun/crypto/provider/Cipher/AEAD/GCMIncrementDirect4.java \ - com/sun/security/auth/callback/TextCallbackHandler/Password.java \ com/sun/security/sasl/gsskerb/AuthOnly.java \ com/sun/security/sasl/gsskerb/ConfSecurityLayer.java \ com/sun/security/sasl/gsskerb/NoSecurityLayer.java \ @@ -652,6 +651,7 @@ jdk_core_manual_interactive = \ jdk_security_manual_interactive = \ sun/security/tools/keytool/i18n.java \ java/security/Policy/Root/Root.java \ + com/sun/security/auth/callback/TextCallbackHandler/Password.java \ sun/security/krb5/config/native/TestDynamicStore.java # Test sets for running inside container environment diff --git a/test/jdk/com/sun/security/auth/callback/TextCallbackHandler/Password.java b/test/jdk/com/sun/security/auth/callback/TextCallbackHandler/Password.java index b34ef04355867..f9231a0b36edc 100644 --- a/test/jdk/com/sun/security/auth/callback/TextCallbackHandler/Password.java +++ b/test/jdk/com/sun/security/auth/callback/TextCallbackHandler/Password.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, 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 @@ -23,11 +23,23 @@ /* * @test - * @bug 6825240 + * @bug 6825240 6829785 * @summary Password.readPassword() echos the input when System.Console is null * @run main/manual Password */ +/* + * This scenario cannot be automated because util/Password.java verifies the given input stream is + * equal to the initialSystemIn. This prevents the test from providing a custom input stream. + * + * Steps to run the test: + * 1) Compile the class using the JDK version being tested: '/javac Password.java' + * 2) Run the test using the JDK version being tested: '/java -cp . Password' + * 3) Type in the first password, it should not be visible in the console + * 4) Type in the second password, it should be visible in the console + * 5) The final output line displays the entered passwords, both should be visible + */ + import com.sun.security.auth.callback.TextCallbackHandler; import javax.security.auth.callback.*; From 5e021cbcc7a6cb30a27380950e115ff12846239c Mon Sep 17 00:00:00 2001 From: Leonid Mesnik Date: Wed, 7 Aug 2024 20:25:51 +0000 Subject: [PATCH 44/77] 8337410: The makefiles should set problemlist and adjust timeout basing on the given VM flags Reviewed-by: ihse --- make/RunTests.gmk | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/make/RunTests.gmk b/make/RunTests.gmk index b0291e4eff4e7..8cfee45892339 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2016, 2023, 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. # # This code is free software; you can redistribute it and/or modify it @@ -748,8 +748,6 @@ define SetupRunJtregTestBody # we may end up with a lot of JVM's $1_JTREG_MAX_RAM_PERCENTAGE := $$(shell $(AWK) 'BEGIN { print 25 / $$($1_JTREG_JOBS); }') - JTREG_TIMEOUT_FACTOR ?= 4 - JTREG_VERBOSE ?= fail,error,summary JTREG_RETAIN ?= fail,error JTREG_TEST_THREAD_FACTORY ?= @@ -837,6 +835,24 @@ define SetupRunJtregTestBody $1_JTREG_BASIC_OPTIONS += $$(addprefix $$(JTREG_PROBLEM_LIST_PREFIX), $$($1_JTREG_PROBLEM_LIST)) endif + JTREG_ALL_OPTIONS := $$(JTREG_JAVA_OPTIONS) $$(JTREG_VM_OPTIONS) + + JTREG_AUTO_PROBLEM_LISTS := + JTREG_AUTO_TIMEOUT_FACTOR := 4 + + ifneq ($$(findstring -Xcomp, $$(JTREG_ALL_OPTIONS)), ) + JTREG_AUTO_PROBLEM_LISTS += ProblemList-Xcomp.txt + JTREG_AUTO_TIMEOUT_FACTOR := 10 + endif + + ifneq ($$(findstring -XX:+UseZGC, $$(JTREG_ALL_OPTIONS)), ) + ifneq ($$(findstring -XX:-ZGenerational, $$(JTREG_ALL_OPTIONS)), ) + JTREG_AUTO_PROBLEM_LISTS += ProblemList-zgc.txt + else + JTREG_AUTO_PROBLEM_LISTS += ProblemList-generational-zgc.txt + endif + endif + ifneq ($$(JTREG_EXTRA_PROBLEM_LISTS), ) # Accept both absolute paths as well as relative to the current test root. $1_JTREG_BASIC_OPTIONS += $$(addprefix $$(JTREG_PROBLEM_LIST_PREFIX), $$(wildcard \ @@ -868,6 +884,18 @@ define SetupRunJtregTestBody $$(eval $$(call SetupRunJtregTestCustom, $1)) + # SetupRunJtregTestCustom might also adjust JTREG_AUTO_ variables + # so set the final results after setting values from custom setup + ifneq ($$(JTREG_AUTO_PROBLEM_LISTS), ) + # Accept both absolute paths as well as relative to the current test root. + $1_JTREG_BASIC_OPTIONS += $$(addprefix $$(JTREG_PROBLEM_LIST_PREFIX), $$(wildcard \ + $$(JTREG_AUTO_PROBLEM_LISTS) \ + $$(addprefix $$($1_TEST_ROOT)/, $$(JTREG_AUTO_PROBLEM_LISTS)) \ + )) + endif + + JTREG_TIMEOUT_FACTOR ?= $$(JTREG_AUTO_TIMEOUT_FACTOR) + clean-outputdirs-$1: $$(RM) -r $$($1_TEST_SUPPORT_DIR) $$(RM) -r $$($1_TEST_RESULTS_DIR) From 9b11bd7f4a511ddadf9f02e82aab6ba78beb6763 Mon Sep 17 00:00:00 2001 From: Jamil Nimeh Date: Wed, 7 Aug 2024 21:06:47 +0000 Subject: [PATCH 45/77] 8337826: Improve logging in OCSPTimeout and SimpleOCSPResponder to help diagnose JDK-8309754 Reviewed-by: mullan --- .../CertPathValidator/OCSP/OCSPTimeout.java | 124 ++++++++++-------- .../testlibrary/SimpleOCSPServer.java | 16 ++- 2 files changed, 81 insertions(+), 59 deletions(-) diff --git a/test/jdk/java/security/cert/CertPathValidator/OCSP/OCSPTimeout.java b/test/jdk/java/security/cert/CertPathValidator/OCSP/OCSPTimeout.java index 3e2648af7cb5f..dfd7dcdc81efe 100644 --- a/test/jdk/java/security/cert/CertPathValidator/OCSP/OCSPTimeout.java +++ b/test/jdk/java/security/cert/CertPathValidator/OCSP/OCSPTimeout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -36,17 +36,17 @@ * java.base/sun.security.util * @library ../../../../../java/security/testlibrary * @build CertificateBuilder SimpleOCSPServer - * @run main/othervm OCSPTimeout 1000 true - * @run main/othervm -Dcom.sun.security.ocsp.readtimeout=5 - * OCSPTimeout 1000 true - * @run main/othervm -Dcom.sun.security.ocsp.readtimeout=1 - * OCSPTimeout 5000 false - * @run main/othervm -Dcom.sun.security.ocsp.readtimeout=1s - * OCSPTimeout 5000 false - * @run main/othervm -Dcom.sun.security.ocsp.readtimeout=1500ms - * OCSPTimeout 5000 false - * @run main/othervm -Dcom.sun.security.ocsp.readtimeout=4500ms - * OCSPTimeout 1000 true + * @run main/othervm -Djava.security.debug=certpath OCSPTimeout 1000 true + * @run main/othervm -Djava.security.debug=certpath + * -Dcom.sun.security.ocsp.readtimeout=5 OCSPTimeout 1000 true + * @run main/othervm -Djava.security.debug=certpath + * -Dcom.sun.security.ocsp.readtimeout=1 OCSPTimeout 5000 false + * @run main/othervm -Djava.security.debug=certpath + * -Dcom.sun.security.ocsp.readtimeout=1s OCSPTimeout 5000 false + * @run main/othervm -Djava.security.debug=certpath + * -Dcom.sun.security.ocsp.readtimeout=1500ms OCSPTimeout 5000 false + * @run main/othervm -Djava.security.debug=certpath + * -Dcom.sun.security.ocsp.readtimeout=4500ms OCSPTimeout 1000 true */ import java.io.*; @@ -82,62 +82,72 @@ public class OCSPTimeout { static SimpleOCSPServer rootOcsp; // Root CA OCSP Responder static int rootOcspPort; // Port number for root OCSP - public static void main(String args[]) throws Exception { + public static void main(String[] args) throws Exception { int ocspTimeout = 15000; boolean expected = false; createPKI(); - if (args[0] != null) { - ocspTimeout = Integer.parseInt(args[0]); - } - rootOcsp.setDelay(ocspTimeout); - - expected = (args[1] != null && Boolean.parseBoolean(args[1])); - log("Test case expects to " + (expected ? "pass" : "fail")); - - // validate chain - CertPathValidator cpv = CertPathValidator.getInstance("PKIX"); - PKIXRevocationChecker prc = - (PKIXRevocationChecker) cpv.getRevocationChecker(); - prc.setOptions(EnumSet.of(NO_FALLBACK, SOFT_FAIL)); - PKIXParameters params = - new PKIXParameters(Set.of(new TrustAnchor(rootCert, null))); - params.addCertPathChecker(prc); - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - CertPath cp = cf.generateCertPath(List.of(eeCert)); - cpv.validate(cp, params); - - // unwrap soft fail exceptions and check for SocketTimeoutException - List softExc = prc.getSoftFailExceptions(); - if (expected) { - if (softExc.size() > 0) { - throw new RuntimeException("Expected to pass, found " + - softExc.size() + " soft fail exceptions"); + try { + if (args[0] != null) { + ocspTimeout = Integer.parseInt(args[0]); } - } else { - // If we expect to fail the validation then there should be a - // SocketTimeoutException - boolean found = false; - for (CertPathValidatorException softFail : softExc) { - log("CPVE: " + softFail); - Throwable cause = softFail.getCause(); - log("Cause: " + cause); - while (cause != null) { - if (cause instanceof SocketTimeoutException) { - found = true; - break; + rootOcsp.setDelay(ocspTimeout); + + expected = (args[1] != null && Boolean.parseBoolean(args[1])); + log("Test case expects to " + (expected ? "pass" : "fail")); + + // validate chain + CertPathValidator cpv = CertPathValidator.getInstance("PKIX"); + PKIXRevocationChecker prc = + (PKIXRevocationChecker) cpv.getRevocationChecker(); + prc.setOptions(EnumSet.of(NO_FALLBACK, SOFT_FAIL)); + PKIXParameters params = + new PKIXParameters(Set.of(new TrustAnchor(rootCert, null))); + params.addCertPathChecker(prc); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + CertPath cp = cf.generateCertPath(List.of(eeCert)); + cpv.validate(cp, params); + + // unwrap soft fail exceptions and check for SocketTimeoutException + List softExc = prc.getSoftFailExceptions(); + if (expected) { + if (!softExc.isEmpty()) { + log("Expected to pass, found " + softExc.size() + + " soft fail exceptions"); + for (CertPathValidatorException cpve : softExc) { + log("Exception: " + cpve); } - cause = cause.getCause(); + throw new RuntimeException("Expected to pass, found " + + softExc.size() + " soft fail exceptions"); } - if (found) { - break; + } else { + // If we expect to fail the validation then there should be a + // SocketTimeoutException + boolean found = false; + for (CertPathValidatorException softFail : softExc) { + log("CPVE: " + softFail); + Throwable cause = softFail.getCause(); + log("Cause: " + cause); + while (cause != null) { + if (cause instanceof SocketTimeoutException) { + found = true; + break; + } + cause = cause.getCause(); + } + if (found) { + break; + } } - } - if (!found) { - throw new RuntimeException("SocketTimeoutException not thrown"); + if (!found) { + throw new RuntimeException("SocketTimeoutException not thrown"); + } } + } finally { + rootOcsp.stop(); + rootOcsp.shutdownNow(); } } diff --git a/test/jdk/java/security/testlibrary/SimpleOCSPServer.java b/test/jdk/java/security/testlibrary/SimpleOCSPServer.java index e1883edeec51f..5b9fb23c4ef90 100644 --- a/test/jdk/java/security/testlibrary/SimpleOCSPServer.java +++ b/test/jdk/java/security/testlibrary/SimpleOCSPServer.java @@ -572,8 +572,8 @@ public void setDisableContentLength(boolean isDisabled) { */ private synchronized void log(String message) { if (logEnabled || debug != null) { - System.out.println("[" + Thread.currentThread().getName() + "]: " + - message); + System.out.println("[" + Thread.currentThread().getName() + "][" + + System.currentTimeMillis() + "]: " + message); } } @@ -727,6 +727,7 @@ public void run() { // wait out the delay here before any other processing. try { if (delayMsec > 0) { + log("Delaying response for " + delayMsec + " milliseconds."); Thread.sleep(delayMsec); } } catch (InterruptedException ie) { @@ -908,6 +909,13 @@ private LocalOcspRequest parseHttpOcspPost(InputStream inStream) */ private LocalOcspRequest parseHttpOcspGet(String[] headerTokens, InputStream inStream) throws IOException, CertificateException { + // Display the whole request + StringBuilder sb = new StringBuilder("OCSP GET REQUEST\n"); + for (String hTok : headerTokens) { + sb.append(hTok).append("\n"); + } + log(sb.toString()); + // Before we process the remainder of the GET URL, we should drain // the InputStream of any other header data. We (for now) won't // use it, but will display the contents if logging is enabled. @@ -1000,6 +1008,10 @@ private LocalOcspRequest(byte[] requestBytes) throws IOException, CertificateException { Objects.requireNonNull(requestBytes, "Received null input"); + // Display the DER encoding before parsing + log("Local OCSP Request Constructor, parsing bytes:\n" + + dumpHexBytes(requestBytes)); + DerInputStream dis = new DerInputStream(requestBytes); // Parse the top-level structure, it should have no more than From 16df9c33e9bbc9329ae60ba14332c09aadaba3f0 Mon Sep 17 00:00:00 2001 From: Gui Cao Date: Thu, 8 Aug 2024 05:22:20 +0000 Subject: [PATCH 46/77] 8337971: Problem list several jvmci tests on linux-riscv64 until JDK-8331704 is fixed Reviewed-by: fyang, shade --- test/hotspot/jtreg/ProblemList.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index f5b14e87607e3..d40a8c2d5f431 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -63,6 +63,12 @@ compiler/vectorapi/VectorRebracket128Test.java#ZSinglegen 8330538 generic-all compiler/vectorapi/VectorRebracket128Test.java#ZGenerational 8330538 generic-all compiler/jvmci/TestUncaughtErrorInCompileMethod.java 8309073 generic-all +compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DataPatchTest.java 8331704 linux-riscv64 +compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MaxOopMapStackOffsetTest.java 8331704 linux-riscv64 +compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java 8331704 linux-riscv64 +compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java 8331704 linux-riscv64 +compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java 8331704 linux-riscv64 +compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java 8331704 linux-riscv64 compiler/floatingpoint/TestSubnormalFloat.java 8317810 generic-i586 compiler/floatingpoint/TestSubnormalDouble.java 8317810 generic-i586 From 1846a65e32624f6da691c1072f44fcb762b43233 Mon Sep 17 00:00:00 2001 From: Turkhan Badalov Date: Thu, 8 Aug 2024 05:34:32 +0000 Subject: [PATCH 47/77] 8337205: Typo in Stack vs Deque Method table in Deque specification Reviewed-by: liach --- src/java.base/share/classes/java/util/Deque.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/util/Deque.java b/src/java.base/share/classes/java/util/Deque.java index ce40687989434..79e4187a586d8 100644 --- a/src/java.base/share/classes/java/util/Deque.java +++ b/src/java.base/share/classes/java/util/Deque.java @@ -163,7 +163,7 @@ * * * {@link #peek() peek()} - * {@link #getFirst() getFirst()} + * {@link #peekFirst() peekFirst()} * * * From fa18359007bd80d2e74c07a5a1ea6170e1bd474d Mon Sep 17 00:00:00 2001 From: Afshin Zafari Date: Thu, 8 Aug 2024 08:55:05 +0000 Subject: [PATCH 48/77] 8335981: ProblemList runtime/Thread/TestAlwaysPreTouchStacks.java for MacOS Reviewed-by: tschatzl --- test/hotspot/jtreg/ProblemList.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index d40a8c2d5f431..2414f3d090a18 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -117,8 +117,10 @@ runtime/ErrorHandling/CreateCoredumpOnCrash.java 8267433 macosx-x64 runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all runtime/ErrorHandling/TestDwarf.java#checkDecoder 8305489 linux-all runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le +runtime/Thread/TestAlwaysPreTouchStacks.java 8335167 macosx-aarch64 runtime/cds/appcds/customLoader/HelloCustom_JFR.java 8241075 linux-all,windows-x64 + applications/jcstress/copy.java 8229852 linux-all containers/docker/TestJcmd.java 8278102 linux-all From a9460a69e74f876274ec64394ac6504580041b21 Mon Sep 17 00:00:00 2001 From: Casper Norrbin Date: Thu, 8 Aug 2024 10:38:02 +0000 Subject: [PATCH 49/77] 8337982: Remove dead undef assrt0n Reviewed-by: stefank, dholmes --- src/hotspot/share/memory/metaspace/blockTree.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/hotspot/share/memory/metaspace/blockTree.cpp b/src/hotspot/share/memory/metaspace/blockTree.cpp index 934f25d84ccb3..1f1e54f4a4612 100644 --- a/src/hotspot/share/memory/metaspace/blockTree.cpp +++ b/src/hotspot/share/memory/metaspace/blockTree.cpp @@ -178,8 +178,6 @@ void BlockTree::verify() const { // (which also verifies that we visited every node, or at least // as many nodes as are in this tree) _counter.check(counter); - - #undef assrt0n } void BlockTree::zap_range(MetaWord* p, size_t word_size) { From 3bc4a1acc4bb1885ddba69283b99bbe02f8e43b7 Mon Sep 17 00:00:00 2001 From: Tejesh R Date: Thu, 8 Aug 2024 10:40:56 +0000 Subject: [PATCH 50/77] 8233068: HIDPI: Linux: AWT Checkbox check mark is unscaled Reviewed-by: jdv, abhiscxk, honkar --- .../classes/sun/awt/X11/XCheckboxPeer.java | 9 +- .../Checkbox/CheckboxCheckerScalingTest.java | 92 +++++++++++++++++++ 2 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 test/jdk/java/awt/Checkbox/CheckboxCheckerScalingTest.java diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XCheckboxPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XCheckboxPeer.java index 88f1784889e73..c66cda1644372 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XCheckboxPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XCheckboxPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 @@ -362,12 +362,15 @@ public void paintCheckbox(Graphics g, if (armed | selected) { //Paint the check + AffineTransform af = g2.getTransform(); + double scaleX = af.getScaleX(); + double scaleY = af.getScaleY(); // FIXME: is this the right color? g2.setColor(getPeerForeground()); - AffineTransform af = g2.getTransform(); - g2.setTransform(AffineTransform.getTranslateInstance(rx,ry)); + g2.setTransform(AffineTransform.getTranslateInstance(rx * scaleX, ry * scaleY)); + g2.scale(scaleX, scaleY); g2.fill(myCheckMark); g2.setTransform(af); } diff --git a/test/jdk/java/awt/Checkbox/CheckboxCheckerScalingTest.java b/test/jdk/java/awt/Checkbox/CheckboxCheckerScalingTest.java new file mode 100644 index 0000000000000..5e531e84801cd --- /dev/null +++ b/test/jdk/java/awt/Checkbox/CheckboxCheckerScalingTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2024, 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. + * + * 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. + */ + +import java.awt.Checkbox; +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; + +/* + * @test + * @key headful + * @bug 8233068 + * @summary Tests checkbox checker on scaling + * @requires (os.family == "linux") + * @run main CheckboxCheckerScalingTest + */ + +public class CheckboxCheckerScalingTest { + private static Frame frame; + private static Checkbox checkbox; + private static BufferedImage imageAfterChecked; + private static volatile boolean checkmarkFound = false; + + public static void main(String[] args) throws Exception { + System.setProperty("sun.java2d.uiScale", "2"); + Robot robot = new Robot(); + try { + EventQueue.invokeAndWait(() -> { + frame = new Frame("ComboBox checker scaling test"); + checkbox = new Checkbox("one"); + checkbox.setState(true); + frame.add(checkbox); + frame.pack(); + frame.setVisible(true); + }); + + robot.waitForIdle(); + robot.delay(100); + EventQueue.invokeAndWait(() -> { + Point point = checkbox.getLocationOnScreen(); + Rectangle rect = new Rectangle(point.x + 5, point.y + 7, 8, 8); + imageAfterChecked = robot.createScreenCapture(rect); + + check: { + for (int i = 0; i < imageAfterChecked.getHeight(); i++) { + for (int j = 0; j < imageAfterChecked.getWidth(); j++) { + if (Color.black.getRGB() == imageAfterChecked.getRGB(i, j)) { + checkmarkFound = true; + break check; + } + } + } + } + }); + + if (!checkmarkFound) { + throw new RuntimeException("Checkmark not scaled"); + } + System.out.println("Test Passed"); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} From 088871ce36f85fb30b24c49146f547bc8e2b0dcb Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Thu, 8 Aug 2024 10:51:47 +0000 Subject: [PATCH 51/77] 8335267: [XWayland] move screencast tokens from .awt to .java folder Reviewed-by: prr, avu --- .../sun/awt/screencast/TokenStorage.java | 91 +++++++++++-------- 1 file changed, 53 insertions(+), 38 deletions(-) diff --git a/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java b/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java index 3daf9b2a8b8e8..b05ff7f8c4add 100644 --- a/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java +++ b/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java @@ -60,35 +60,33 @@ * The restore token allows the ScreenCast session to be restored * with previously granted screen access permissions. */ -@SuppressWarnings("removal") final class TokenStorage { private TokenStorage() {} private static final String REL_NAME = + ".java/robot/screencast-tokens.properties"; + private static final String REL_NAME_SECONDARY = ".awt/robot/screencast-tokens.properties"; private static final Properties PROPS = new Properties(); private static final Path PROPS_PATH; private static final Path PROP_FILENAME; + @SuppressWarnings("removal") private static void doPrivilegedRunnable(Runnable runnable) { - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - runnable.run(); - return null; - } + AccessController.doPrivileged((PrivilegedAction) () -> { + runnable.run(); + return null; }); } static { - PROPS_PATH = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Path run() { - return setupPath(); - } - }); + @SuppressWarnings("removal") + Path propsPath = AccessController + .doPrivileged((PrivilegedAction) () -> setupPath()); + + PROPS_PATH = propsPath; if (PROPS_PATH != null) { PROP_FILENAME = PROPS_PATH.getFileName(); @@ -110,25 +108,32 @@ private static Path setupPath() { } Path path = Path.of(userHome, REL_NAME); + Path secondaryPath = Path.of(userHome, REL_NAME_SECONDARY); + + boolean copyFromSecondary = !Files.isWritable(path) + && Files.isWritable(secondaryPath); + Path workdir = path.getParent(); - if (!Files.exists(workdir)) { - try { - Files.createDirectories(workdir); - } catch (Exception e) { - if (SCREENCAST_DEBUG) { - System.err.printf("Token storage: cannot create" + - " directory %s %s\n", workdir, e); + if (!Files.isWritable(path)) { + if (!Files.exists(workdir)) { + try { + Files.createDirectories(workdir); + } catch (Exception e) { + if (SCREENCAST_DEBUG) { + System.err.printf("Token storage: cannot create" + + " directory %s %s\n", workdir, e); + } + return null; } - return null; } - } - if (!Files.isWritable(workdir)) { - if (SCREENCAST_DEBUG) { - System.err.printf("Token storage: %s is not writable\n", workdir); + if (!Files.isWritable(workdir)) { + if (SCREENCAST_DEBUG) { + System.err.printf("Token storage: %s is not writable\n", workdir); + } + return null; } - return null; } try { @@ -145,7 +150,17 @@ private static Path setupPath() { } } - if (Files.exists(path)) { + if (copyFromSecondary) { + if (SCREENCAST_DEBUG) { + System.out.println("Token storage: copying from the secondary location " + + secondaryPath); + } + synchronized (PROPS) { + if (readTokens(secondaryPath)) { + store(path, "copy from the secondary location"); + } + } + } else if (Files.exists(path)) { if (!setFilePermission(path)) { return null; } @@ -302,7 +317,7 @@ private static void storeTokenFromNative(String oldToken, } if (changed) { - doPrivilegedRunnable(() -> store("save tokens")); + doPrivilegedRunnable(() -> store(PROPS_PATH, "save tokens")); } } } @@ -315,7 +330,7 @@ private static boolean readTokens(Path path) { PROPS.clear(); PROPS.load(reader); } - } catch (IOException e) { + } catch (IOException | IllegalArgumentException e) { if (SCREENCAST_DEBUG) { System.err.printf(""" Token storage: failed to load property file %s @@ -410,7 +425,7 @@ static Set getTokens(List affectedScreenBounds) { } private static void removeMalformedRecords(Set malformedRecords) { - if (!isWritable() + if (!isWritable(PROPS_PATH) || malformedRecords == null || malformedRecords.isEmpty()) { return; @@ -424,17 +439,17 @@ private static void removeMalformedRecords(Set malformedRecords) { } } - store("remove malformed records"); + store(PROPS_PATH, "remove malformed records"); } } - private static void store(String failMsg) { - if (!isWritable()) { + private static void store(Path path, String failMsg) { + if (!isWritable(path)) { return; } synchronized (PROPS) { - try (BufferedWriter writer = Files.newBufferedWriter(PROPS_PATH)) { + try (BufferedWriter writer = Files.newBufferedWriter(path)) { PROPS.store(writer, null); } catch (IOException e) { if (SCREENCAST_DEBUG) { @@ -445,13 +460,13 @@ private static void store(String failMsg) { } } - private static boolean isWritable() { - if (PROPS_PATH == null - || (Files.exists(PROPS_PATH) && !Files.isWritable(PROPS_PATH))) { + private static boolean isWritable(Path path) { + if (path == null + || (Files.exists(path) && !Files.isWritable(path))) { if (SCREENCAST_DEBUG) { System.err.printf( - "Token storage: %s is not writable\n", PROPS_PATH); + "Token storage: %s is not writable\n", path); } return false; } else { From 12c553f12876b4095685676f800119c0e275bf44 Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Thu, 8 Aug 2024 10:51:58 +0000 Subject: [PATCH 52/77] 8329471: Remove GTK2 Reviewed-by: abhiscxk, prr, ihse --- .../modules/java.desktop/lib/AwtLibraries.gmk | 4 - .../sun/java/swing/plaf/gtk/GTKEngine.java | 16 +- .../java/swing/plaf/gtk/GTKIconFactory.java | 6 +- .../java/swing/plaf/gtk/GTKLookAndFeel.java | 24 +- .../sun/java/swing/plaf/gtk/GTKPainter.java | 98 +- .../com/sun/java/swing/plaf/gtk/GTKStyle.java | 11 +- .../unix/classes/sun/awt/UNIXToolkit.java | 19 +- .../native/libawt_xawt/awt/gtk2_interface.c | 2603 ----------------- .../native/libawt_xawt/awt/gtk2_interface.h | 448 --- .../native/libawt_xawt/awt/gtk_interface.c | 11 +- .../libawt_xawt/awt/screencast_pipewire.c | 3 +- .../Gtk/GtkVersionTest/GtkVersionTest.java | 7 +- .../ScreenCaptureGtkTest.java | 11 +- .../swing/LookAndFeel/8145547/DemandGTK.java | 3 +- .../swing/LookAndFeel/8145547/DemandGTK2.sh | 91 - .../swing/LookAndFeel/8145547/DemandGTK2.txt | 36 - .../swing/LookAndFeel/8145547/DemandGTK3.sh | 11 +- 17 files changed, 54 insertions(+), 3348 deletions(-) delete mode 100644 src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c delete mode 100644 src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h delete mode 100644 test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK2.sh delete mode 100644 test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK2.txt diff --git a/make/modules/java.desktop/lib/AwtLibraries.gmk b/make/modules/java.desktop/lib/AwtLibraries.gmk index 11f92585bd919..be29805f35271 100644 --- a/make/modules/java.desktop/lib/AwtLibraries.gmk +++ b/make/modules/java.desktop/lib/AwtLibraries.gmk @@ -237,7 +237,6 @@ ifeq ($(call isTargetOs, windows macosx)+$(ENABLE_HEADLESS_ONLY), false+false) DISABLED_WARNINGS_gcc := int-to-pointer-cast, \ DISABLED_WARNINGS_gcc_awt_Taskbar.c := parentheses, \ DISABLED_WARNINGS_gcc_GLXSurfaceData.c := unused-function, \ - DISABLED_WARNINGS_gcc_gtk2_interface.c := parentheses type-limits, \ DISABLED_WARNINGS_gcc_gtk3_interface.c := parentheses type-limits \ unused-function, \ DISABLED_WARNINGS_gcc_OGLBufImgOps.c := format-nonliteral, \ @@ -252,7 +251,6 @@ ifeq ($(call isTargetOs, windows macosx)+$(ENABLE_HEADLESS_ONLY), false+false) DISABLED_WARNINGS_gcc_XToolkit.c := unused-result, \ DISABLED_WARNINGS_gcc_XWindow.c := unused-function, \ DISABLED_WARNINGS_clang_awt_Taskbar.c := parentheses, \ - DISABLED_WARNINGS_clang_gtk2_interface.c := parentheses, \ DISABLED_WARNINGS_clang_gtk3_interface.c := parentheses, \ DISABLED_WARNINGS_clang_OGLBufImgOps.c := format-nonliteral, \ DISABLED_WARNINGS_clang_OGLPaints.c := format-nonliteral, \ @@ -262,8 +260,6 @@ ifeq ($(call isTargetOs, windows macosx)+$(ENABLE_HEADLESS_ONLY), false+false) DISABLED_WARNINGS_clang_aix_awt_Taskbar.c := parentheses, \ DISABLED_WARNINGS_clang_aix_OGLPaints.c := format-nonliteral, \ DISABLED_WARNINGS_clang_aix_OGLBufImgOps.c := format-nonliteral, \ - DISABLED_WARNINGS_clang_aix_gtk2_interface.c := parentheses \ - logical-op-parentheses, \ DISABLED_WARNINGS_clang_aix_gtk3_interface.c := parentheses \ logical-op-parentheses, \ DISABLED_WARNINGS_clang_aix_sun_awt_X11_GtkFileDialogPeer.c := \ diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java index 1326cee140371..f9f6307678108 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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 @@ -61,7 +61,7 @@ class GTKEngine { /** Size of the image cache */ private static final int CACHE_SIZE = 50; - /** This enum mirrors that in gtk2_interface.h */ + /** This enum mirrors that in gtk_interface.h */ static enum WidgetType { BUTTON, CHECK_BOX, CHECK_BOX_MENU_ITEM, COLOR_CHOOSER, COMBO_BOX, COMBO_BOX_ARROW_BUTTON, COMBO_BOX_TEXT_FIELD, @@ -493,13 +493,13 @@ public void paintShadow(Graphics g, SynthContext context, GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); int synthState = context.getComponentState(); Container parent = context.getComponent().getParent(); - if(GTKLookAndFeel.is3()) { - if (parent != null && parent.getParent() instanceof JComboBox) { - if (parent.getParent().hasFocus()) { - synthState |= SynthConstants.FOCUSED; - } + + if (parent != null && parent.getParent() instanceof JComboBox) { + if (parent.getParent().hasFocus()) { + synthState |= SynthConstants.FOCUSED; } } + int dir = getTextDirection(context); int widget = getWidgetType(context.getComponent(), id).ordinal(); native_paint_shadow(widget, gtkState, shadowType.ordinal(), detail, @@ -628,7 +628,7 @@ public void themeChanged() { cache.flush(); } - /* GtkSettings enum mirrors that in gtk2_interface.h */ + /* GtkSettings enum mirrors that in gtk_interface.h */ public Object getSetting(Settings property) { synchronized(sun.awt.UNIXToolkit.GTK_LOCK) { return native_get_gtk_setting(property.ordinal()); diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java index 46f8d3ff189c0..4f04d729099f7 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 @@ -44,7 +44,7 @@ class GTKIconFactory { static final int CHECK_ICON_EXTRA_INSET = 1; static final int DEFAULT_ICON_SPACING = 2; static final int DEFAULT_ICON_SIZE = 13; - static final int DEFAULT_TOGGLE_MENU_ITEM_SIZE = 12; // For pre-gtk2.4 + static final int DEFAULT_TOGGLE_MENU_ITEM_SIZE = 12; private static final String RADIO_BUTTON_ICON = "paintRadioButtonIcon"; private static final String CHECK_BOX_ICON = "paintCheckBoxIcon"; @@ -214,7 +214,7 @@ int getIconDimension(SynthContext context) { Region region = context.getRegion(); GTKStyle style = (GTKStyle) context.getStyle(); - if (GTKLookAndFeel.is3() && region == Region.MENU) { + if (region == Region.MENU) { Object value = style.getClassSpecificValue("arrow-scaling"); if (value instanceof Number) { iconDimension = (int)(((Number) value).floatValue() * diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java index 93ba22d8dd3da..681c0e5195838 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java @@ -77,7 +77,6 @@ */ @SuppressWarnings("serial") // Superclass not serializable public class GTKLookAndFeel extends SynthLookAndFeel { - private static boolean IS_22; private static boolean IS_3; /** @@ -124,17 +123,6 @@ public class GTKLookAndFeel extends SynthLookAndFeel { */ private static String gtkThemeName = "Default"; - /** - * Returns true if running on system containing at least 2.2. - */ - static boolean is2_2() { - // NOTE: We're currently hard coding to use 2.2. - // If we want to support both GTK 2.0 and 2.2, we'll - // need to get the major/minor/micro version from the .so. - // Refer to bug 4912613 for details. - return IS_22; - } - static boolean is3() { return IS_3; } @@ -1454,17 +1442,7 @@ public void initialize() { throw new InternalError("Unable to load native GTK libraries"); } - if (UNIXToolkit.getGtkVersion() == UNIXToolkit.GtkVersions.GTK2) { - @SuppressWarnings("removal") - String version = AccessController.doPrivileged( - new GetPropertyAction("jdk.gtk.version")); - if (version != null) { - IS_22 = version.equals("2.2"); - } else { - IS_22 = true; - } - } else if (UNIXToolkit.getGtkVersion() == - UNIXToolkit.GtkVersions.GTK3) { + if (UNIXToolkit.getGtkVersion() == UNIXToolkit.GtkVersions.GTK3) { IS_3 = true; } diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java index 5d77800f88e5f..4787696a367eb 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java @@ -211,20 +211,7 @@ public void paintRadioButtonMenuItemBackground(SynthContext context, int gtkState = GTKLookAndFeel.synthStateToGTKState( id, context.getComponentState()); if (gtkState == SynthConstants.MOUSE_OVER) { - if (GTKLookAndFeel.is3()) { - paintComponentBackground(context, g, x, y, w, h); - return; - } - synchronized (UNIXToolkit.GTK_LOCK) { - if (! ENGINE.paintCachedImage(g, x, y, w, h, id)) { - ShadowType shadow = (GTKLookAndFeel.is2_2() ? - ShadowType.NONE : ShadowType.OUT); - ENGINE.startPainting(g, x, y, w, h, id); - ENGINE.paintBox(g, context, id, gtkState, - shadow, "menuitem", x, y, w, h); - ENGINE.finishPainting(); - } - } + paintComponentBackground(context, g, x, y, w, h); } } @@ -570,21 +557,7 @@ public void paintMenuItemBackground(SynthContext context, int gtkState = GTKLookAndFeel.synthStateToGTKState( context.getRegion(), context.getComponentState()); if (gtkState == SynthConstants.MOUSE_OVER) { - if (GTKLookAndFeel.is3()) { - paintComponentBackground(context, g, x, y, w, h); - return; - } - Region id = Region.MENU_ITEM; - synchronized (UNIXToolkit.GTK_LOCK) { - if (! ENGINE.paintCachedImage(g, x, y, w, h, id)) { - ShadowType shadow = (GTKLookAndFeel.is2_2() ? - ShadowType.NONE : ShadowType.OUT); - ENGINE.startPainting(g, x, y, w, h, id); - ENGINE.paintBox(g, context, id, gtkState, shadow, - "menuitem", x, y, w, h); - ENGINE.finishPainting(); - } - } + paintComponentBackground(context, g, x, y, w, h); } } @@ -698,17 +671,14 @@ public void paintSeparatorBackground(SynthContext context, } else { h -= (insets.top + insets.bottom); } - if (GTKLookAndFeel.is3()) { - if (id == Region.POPUP_MENU_SEPARATOR) { - detail = "menuitem"; - h -= (insets.top + insets.bottom); - } else { - detail = "separator"; - } + + if (id == Region.POPUP_MENU_SEPARATOR) { + detail = "menuitem"; + h -= (insets.top + insets.bottom); } else { - detail = orientation == JSeparator.HORIZONTAL ? - "hseparator" : "vseparator"; + detail = "separator"; } + synchronized (UNIXToolkit.GTK_LOCK) { if (! ENGINE.paintCachedImage(g, x, y, w, h, id, state, detail, orientation)) { @@ -823,15 +793,15 @@ public void paintSliderTrackBackground(SynthContext context, // The ubuntulooks engine paints slider troughs differently depending // on the current slider value and its component orientation. JSlider slider = (JSlider)context.getComponent(); - if (GTKLookAndFeel.is3()) { - if (slider.getOrientation() == JSlider.VERTICAL) { - y += 1; - h -= 2; - } else { - x += 1; - w -= 2; - } + + if (slider.getOrientation() == JSlider.VERTICAL) { + y += 1; + h -= 2; + } else { + x += 1; + w -= 2; } + double value = slider.getValue(); double min = slider.getMinimum(); double max = slider.getMaximum(); @@ -865,7 +835,7 @@ public void paintSliderThumbBackground(SynthContext context, Region id = context.getRegion(); int gtkState = GTKLookAndFeel.synthStateToGTKState( id, context.getComponentState()); - boolean hasFocus = GTKLookAndFeel.is3() && + boolean hasFocus = ((context.getComponentState() & SynthConstants.FOCUSED) != 0); synchronized (UNIXToolkit.GTK_LOCK) { if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState, dir, @@ -1059,21 +1029,10 @@ private void paintTextBackground(SynthContext context, Graphics g, int yThickness = style.getYThickness(); ENGINE.startPainting(g, x, y, w, h, id, state); - if (GTKLookAndFeel.is3()) { - ENGINE.paintBackground(g, context, id, gtkState, null, - x, y, w, h); - } + ENGINE.paintBackground(g, context, id, gtkState, null, + x, y, w, h); ENGINE.paintShadow(g, context, id, gtkState, ShadowType.IN, "entry", x, y, w, h); - if (!GTKLookAndFeel.is3()) { - ENGINE.paintFlatBox(g, context, id, - gtkState, ShadowType.NONE, "entry_bg", - x + xThickness, - y + yThickness, - w - (2 * xThickness), - h - (2 * yThickness), - ColorType.TEXT_BACKGROUND); - } if (focusSize > 0 && (state & SynthConstants.FOCUSED) != 0) { if (!interiorFocus) { @@ -1084,14 +1043,14 @@ private void paintTextBackground(SynthContext context, Graphics g, } else { if (containerParent instanceof JComboBox) { x += (focusSize + 2); - y += focusSize + (GTKLookAndFeel.is3() ? 3 : 1); - w -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 1); - h -= 2 * focusSize + (GTKLookAndFeel.is3() ? 6 : 2); + y += focusSize + 3; + w -= 2 * focusSize + 4; + h -= 2 * focusSize + 6; } else { - x += focusSize + (GTKLookAndFeel.is3() ? 2 : 0); - y += focusSize + (GTKLookAndFeel.is3() ? 2 :0 ); - w -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 0); - h -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 0); + x += focusSize + 2; + y += focusSize + 2; + w -= 2 * focusSize + 4; + h -= 2 * focusSize + 4; } } ENGINE.paintFocus(g, context, id, gtkState, @@ -1437,11 +1396,6 @@ public void paintMenuArrowIcon(SynthContext context, Graphics g, if (gtkState == SynthConstants.MOUSE_OVER) { shadow = ShadowType.IN; } - if (!GTKLookAndFeel.is3()) { - x += 3; - y += 3; - w = h = 7; - } ENGINE.paintArrow(g, context, Region.MENU_ITEM, gtkState, shadow, dir, "menuitem", x, y, w, h); } diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java index 3ba534ea2a723..90c051353686e 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java @@ -751,14 +751,7 @@ public boolean isOpaque(SynthContext context) { region == Region.EDITOR_PANE) { return true; } - if (!GTKLookAndFeel.is3()) { - if (region == Region.FORMATTED_TEXT_FIELD || - region == Region.PASSWORD_FIELD || - region == Region.SPINNER || - region == Region.TEXT_FIELD) { - return true; - } - } + Component c = context.getComponent(); String name = c.getName(); if (name == "ComboBox.renderer" || name == "ComboBox.listRenderer") { @@ -884,7 +877,7 @@ else if ("CheckBox.iconTextGap".equals(key) || int focusPad = getClassSpecificIntValue(context, "focus-padding", 1); return indicatorSpacing + focusSize + focusPad; - } else if (GTKLookAndFeel.is3() && "ComboBox.forceOpaque".equals(key)) { + } else if ("ComboBox.forceOpaque".equals(key)) { return true; } else if ("Tree.expanderSize".equals(key)) { Object value = getClassSpecificValue("expander-size"); diff --git a/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java b/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java index 191a12092a1ff..d509fe802b028 100644 --- a/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java +++ b/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java @@ -70,19 +70,12 @@ public abstract class UNIXToolkit extends SunToolkit private static final int[] BAND_OFFSETS_ALPHA = { 0, 1, 2, 3 }; private static final int DEFAULT_DATATRANSFER_TIMEOUT = 10000; - private static final String GTK2_DEPRECATION_MESSAGE = - "WARNING: the GTK 2 library is deprecated and " + - "its support will be removed in a future release"; - private static volatile boolean gtk2WarningIssued = false; - // Allowed GTK versions public enum GtkVersions { ANY(0), - GTK2(Constants.GTK2_MAJOR_NUMBER), GTK3(Constants.GTK3_MAJOR_NUMBER); static class Constants { - static final int GTK2_MAJOR_NUMBER = 2; static final int GTK3_MAJOR_NUMBER = 3; } @@ -94,8 +87,6 @@ static class Constants { public static GtkVersions getVersion(int number) { switch (number) { - case Constants.GTK2_MAJOR_NUMBER: - return GTK2; case Constants.GTK3_MAJOR_NUMBER: return GTK3; default: @@ -498,15 +489,7 @@ public static GtkVersions getEnabledGtkVersion() { @SuppressWarnings("removal") String version = AccessController.doPrivileged( new GetPropertyAction("jdk.gtk.version")); - if (version == null) { - return GtkVersions.ANY; - } else if (version.startsWith("2")) { - if (!gtk2WarningIssued) { - System.err.println(GTK2_DEPRECATION_MESSAGE); - gtk2WarningIssued = true; - } - return GtkVersions.GTK2; - } else if("3".equals(version) ){ + if ("3".equals(version)) { return GtkVersions.GTK3; } return GtkVersions.ANY; diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c b/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c deleted file mode 100644 index 7dba83e9024d2..0000000000000 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c +++ /dev/null @@ -1,2603 +0,0 @@ -/* - * Copyright (c) 2005, 2023, 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. - */ - -#ifdef HEADLESS - #error This file should not be included in headless library -#endif - -#include -#include -#include -#include -#include -#include -#include "gtk2_interface.h" -#include "java_awt_Transparency.h" -#include "jvm_md.h" -#include "sizecalc.h" -#include -#include "awt.h" - -#define GTK_TYPE_BORDER ((*fp_gtk_border_get_type)()) - -#define G_TYPE_FUNDAMENTAL_SHIFT (2) -#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT)) - -#define CONV_BUFFER_SIZE 128 - -#define NO_SYMBOL_EXCEPTION 1 - -static void *gtk2_libhandle = NULL; -static void *gthread_libhandle = NULL; - -static jmp_buf j; - -/* Widgets */ -static GtkWidget *gtk2_widget = NULL; -static GtkWidget *gtk2_window = NULL; -static GtkFixed *gtk2_fixed = NULL; - -/* Paint system */ -static GdkPixmap *gtk2_white_pixmap = NULL; -static GdkPixmap *gtk2_black_pixmap = NULL; -static GdkPixbuf *gtk2_white_pixbuf = NULL; -static GdkPixbuf *gtk2_black_pixbuf = NULL; -static int gtk2_pixbuf_width = 0; -static int gtk2_pixbuf_height = 0; - -/* Static buffer for conversion from java.lang.String to UTF-8 */ -static char convertionBuffer[CONV_BUFFER_SIZE]; - -static gboolean new_combo = TRUE; -const char ENV_PREFIX[] = "GTK_MODULES="; - - -static GtkWidget *gtk2_widgets[_GTK_WIDGET_TYPE_SIZE]; - -/************************* - * Glib function pointers - *************************/ - -static gboolean (*fp_g_main_context_iteration)(GMainContext *context, - gboolean may_block); - -static GValue* (*fp_g_value_init)(GValue *value, GType g_type); -static gboolean (*fp_g_type_is_a)(GType type, GType is_a_type); -static gboolean (*fp_g_value_get_boolean)(const GValue *value); -static gchar (*fp_g_value_get_char)(const GValue *value); -static guchar (*fp_g_value_get_uchar)(const GValue *value); -static gint (*fp_g_value_get_int)(const GValue *value); -static guint (*fp_g_value_get_uint)(const GValue *value); -static glong (*fp_g_value_get_long)(const GValue *value); -static gulong (*fp_g_value_get_ulong)(const GValue *value); -static gint64 (*fp_g_value_get_int64)(const GValue *value); -static guint64 (*fp_g_value_get_uint64)(const GValue *value); -static gfloat (*fp_g_value_get_float)(const GValue *value); -static gdouble (*fp_g_value_get_double)(const GValue *value); -static const gchar* (*fp_g_value_get_string)(const GValue *value); -static gint (*fp_g_value_get_enum)(const GValue *value); -static guint (*fp_g_value_get_flags)(const GValue *value); -static GParamSpec* (*fp_g_value_get_param)(const GValue *value); -static gpointer* (*fp_g_value_get_boxed)(const GValue *value); -static gpointer* (*fp_g_value_get_pointer)(const GValue *value); -static GObject* (*fp_g_value_get_object)(const GValue *value); -static GParamSpec* (*fp_g_param_spec_int)(const gchar *name, - const gchar *nick, const gchar *blurb, - gint minimum, gint maximum, gint default_value, - GParamFlags flags); -static void (*fp_g_object_get)(gpointer object, - const gchar* fpn, ...); -static void (*fp_g_object_set)(gpointer object, - const gchar *first_property_name, - ...); -/************************ - * GDK function pointers - ************************/ -static GdkPixmap *(*fp_gdk_pixmap_new)(GdkDrawable *drawable, - gint width, gint height, gint depth); -static GdkGC *(*fp_gdk_gc_new)(GdkDrawable*); -static void (*fp_gdk_rgb_gc_set_foreground)(GdkGC*, guint32); -static void (*fp_gdk_draw_rectangle)(GdkDrawable*, GdkGC*, gboolean, - gint, gint, gint, gint); -static GdkPixbuf *(*fp_gdk_pixbuf_new)(GdkColorspace colorspace, - gboolean has_alpha, int bits_per_sample, int width, int height); -static void (*fp_gdk_drawable_get_size)(GdkDrawable *drawable, - gint* width, gint* height); - -/************************ - * Gtk function pointers - ************************/ -static gboolean (*fp_gtk_init_check)(int* argc, char** argv); - -/* Painting */ -static void (*fp_gtk_paint_hline)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GdkRectangle* area, GtkWidget* widget, - const gchar* detail, gint x1, gint x2, gint y); -static void (*fp_gtk_paint_vline)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GdkRectangle* area, GtkWidget* widget, - const gchar* detail, gint y1, gint y2, gint x); -static void (*fp_gtk_paint_shadow)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - gint x, gint y, gint width, gint height); -static void (*fp_gtk_paint_arrow)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - GtkArrowType arrow_type, gboolean fill, gint x, gint y, - gint width, gint height); -static void (*fp_gtk_paint_box)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - gint x, gint y, gint width, gint height); -static void (*fp_gtk_paint_flat_box)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - gint x, gint y, gint width, gint height); -static void (*fp_gtk_paint_check)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - gint x, gint y, gint width, gint height); -static void (*fp_gtk_paint_option)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - gint x, gint y, gint width, gint height); -static void (*fp_gtk_paint_box_gap)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - gint x, gint y, gint width, gint height, - GtkPositionType gap_side, gint gap_x, gint gap_width); -static void (*fp_gtk_paint_extension)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - gint x, gint y, gint width, gint height, GtkPositionType gap_side); -static void (*fp_gtk_paint_focus)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GdkRectangle* area, GtkWidget* widget, - const gchar* detail, gint x, gint y, gint width, gint height); -static void (*fp_gtk_paint_slider)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - gint x, gint y, gint width, gint height, GtkOrientation orientation); -static void (*fp_gtk_paint_handle)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - gint x, gint y, gint width, gint height, GtkOrientation orientation); -static void (*fp_gtk_paint_expander)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GdkRectangle* area, GtkWidget* widget, - const gchar* detail, gint x, gint y, GtkExpanderStyle expander_style); -static void (*fp_gtk_style_apply_default_background)(GtkStyle* style, - GdkWindow* window, gboolean set_bg, GtkStateType state_type, - GdkRectangle* area, gint x, gint y, gint width, gint height); - -/* Widget creation */ -static GtkWidget* (*fp_gtk_arrow_new)(GtkArrowType arrow_type, - GtkShadowType shadow_type); -static GtkWidget* (*fp_gtk_button_new)(); -static GtkWidget* (*fp_gtk_check_button_new)(); -static GtkWidget* (*fp_gtk_check_menu_item_new)(); -static GtkWidget* (*fp_gtk_color_selection_dialog_new)(const gchar* title); -static GtkWidget* (*fp_gtk_combo_box_new)(); -static GtkWidget* (*fp_gtk_combo_box_entry_new)(); -static GtkWidget* (*fp_gtk_entry_new)(); -static GtkWidget* (*fp_gtk_fixed_new)(); -static GtkWidget* (*fp_gtk_handle_box_new)(); -static GtkWidget* (*fp_gtk_hpaned_new)(); -static GtkWidget* (*fp_gtk_vpaned_new)(); -static GtkWidget* (*fp_gtk_hscale_new)(GtkAdjustment* adjustment); -static GtkWidget* (*fp_gtk_vscale_new)(GtkAdjustment* adjustment); -static GtkWidget* (*fp_gtk_hscrollbar_new)(GtkAdjustment* adjustment); -static GtkWidget* (*fp_gtk_vscrollbar_new)(GtkAdjustment* adjustment); -static GtkWidget* (*fp_gtk_hseparator_new)(); -static GtkWidget* (*fp_gtk_vseparator_new)(); -static GtkWidget* (*fp_gtk_image_new)(); -static GtkWidget* (*fp_gtk_label_new)(const gchar* str); -static GtkWidget* (*fp_gtk_menu_new)(); -static GtkWidget* (*fp_gtk_menu_bar_new)(); -static GtkWidget* (*fp_gtk_menu_item_new)(); -static GtkWidget* (*fp_gtk_notebook_new)(); -static GtkWidget* (*fp_gtk_progress_bar_new)(); -static GtkWidget* (*fp_gtk_progress_bar_set_orientation)( - GtkProgressBar *pbar, - GtkProgressBarOrientation orientation); -static GtkWidget* (*fp_gtk_radio_button_new)(GSList *group); -static GtkWidget* (*fp_gtk_radio_menu_item_new)(GSList *group); -static GtkWidget* (*fp_gtk_scrolled_window_new)(GtkAdjustment *hadjustment, - GtkAdjustment *vadjustment); -static GtkWidget* (*fp_gtk_separator_menu_item_new)(); -static GtkWidget* (*fp_gtk_separator_tool_item_new)(); -static GtkWidget* (*fp_gtk_text_view_new)(); -static GtkWidget* (*fp_gtk_toggle_button_new)(); -static GtkWidget* (*fp_gtk_toolbar_new)(); -static GtkWidget* (*fp_gtk_tree_view_new)(); -static GtkWidget* (*fp_gtk_viewport_new)(GtkAdjustment *hadjustment, - GtkAdjustment *vadjustment); -static GtkWidget* (*fp_gtk_window_new)(GtkWindowType type); -static GtkWidget* (*fp_gtk_dialog_new)(); -static GtkWidget* (*fp_gtk_spin_button_new)(GtkAdjustment *adjustment, - gdouble climb_rate, guint digits); -static GtkWidget* (*fp_gtk_frame_new)(const gchar *label); - -/* Other widget operations */ -static GtkObject* (*fp_gtk_adjustment_new)(gdouble value, - gdouble lower, gdouble upper, gdouble step_increment, - gdouble page_increment, gdouble page_size); -static void (*fp_gtk_container_add)(GtkContainer *window, GtkWidget *widget); -static void (*fp_gtk_menu_shell_append)(GtkMenuShell *menu_shell, - GtkWidget *child); -static void (*fp_gtk_menu_item_set_submenu)(GtkMenuItem *menu_item, - GtkWidget *submenu); -static void (*fp_gtk_widget_realize)(GtkWidget *widget); -static GdkPixbuf* (*fp_gtk_widget_render_icon)(GtkWidget *widget, - const gchar *stock_id, GtkIconSize size, const gchar *detail); -static void (*fp_gtk_widget_set_name)(GtkWidget *widget, const gchar *name); -static void (*fp_gtk_widget_set_parent)(GtkWidget *widget, GtkWidget *parent); -static void (*fp_gtk_widget_set_direction)(GtkWidget *widget, - GtkTextDirection direction); -static void (*fp_gtk_widget_style_get)(GtkWidget *widget, - const gchar *first_property_name, ...); -static void (*fp_gtk_widget_class_install_style_property)( - GtkWidgetClass* class, GParamSpec *pspec); -static GParamSpec* (*fp_gtk_widget_class_find_style_property)( - GtkWidgetClass* class, const gchar* property_name); -static void (*fp_gtk_widget_style_get_property)(GtkWidget* widget, - const gchar* property_name, GValue* value); -static char* (*fp_pango_font_description_to_string)( - const PangoFontDescription* fd); -static GtkSettings* (*fp_gtk_settings_get_default)(); -static GtkSettings* (*fp_gtk_widget_get_settings)(GtkWidget *widget); -static GType (*fp_gtk_border_get_type)(); -static void (*fp_gtk_arrow_set)(GtkWidget* arrow, - GtkArrowType arrow_type, - GtkShadowType shadow_type); -static void (*fp_gtk_widget_size_request)(GtkWidget *widget, - GtkRequisition *requisition); -static GtkAdjustment* (*fp_gtk_range_get_adjustment)(GtkRange* range); - -/* Method bodies */ - -static void throw_exception(JNIEnv *env, const char* name, const char* message) -{ - jclass class = (*env)->FindClass(env, name); - - if (class != NULL) - (*env)->ThrowNew(env, class, message); - - (*env)->DeleteLocalRef(env, class); -} - -/* This is a workaround for the bug: - * http://sourceware.org/bugzilla/show_bug.cgi?id=1814 - * (dlsym/dlopen clears dlerror state) - * This bug is specific to Linux, but there is no harm in - * applying this workaround on Solaris as well. - */ -static void* dl_symbol(const char* name) -{ - void* result = dlsym(gtk2_libhandle, name); - if (!result) - longjmp(j, NO_SYMBOL_EXCEPTION); - - return result; -} - -static void* dl_symbol_gthread(const char* name) -{ - void* result = dlsym(gthread_libhandle, name); - if (!result) - longjmp(j, NO_SYMBOL_EXCEPTION); - - return result; -} - -gboolean gtk2_check(const char* lib_name, gboolean load) -{ - if (gtk2_libhandle != NULL) { - /* We've already successfully opened the GTK libs, so return true. */ - return TRUE; - } else { - void *lib = NULL; - -#ifdef RTLD_NOLOAD - /* Just check if gtk libs are already in the process space */ - lib = dlopen(lib_name, RTLD_LAZY | RTLD_NOLOAD); - if (!load || lib != NULL) { - return lib != NULL; - } -#else -#ifdef _AIX - /* On AIX we could implement this with the help of loadquery(L_GETINFO, ..) */ - /* (see reload_table() in hotspot/src/os/aix/vm/loadlib_aix.cpp) but it is */ - /* probably not worth it because most AIX servers don't have GTK libs anyway */ -#endif -#endif - - lib = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL); - if (lib == NULL) { - return FALSE; - } - - fp_gtk_check_version = dlsym(lib, "gtk_check_version"); - /* Check for GTK 2.2+ */ - if (!fp_gtk_check_version(2, 2, 0)) { - return TRUE; - } - - // 8048289: workaround for https://bugzilla.gnome.org/show_bug.cgi?id=733065 - // dlclose(lib); - - return FALSE; - } -} - -#define ADD_SUPPORTED_ACTION(actionStr) \ -do { \ - jfieldID fld_action = (*env)->GetStaticFieldID(env, cls_action, actionStr, "Ljava/awt/Desktop$Action;"); \ - if (!(*env)->ExceptionCheck(env)) { \ - jobject action = (*env)->GetStaticObjectField(env, cls_action, fld_action); \ - (*env)->CallBooleanMethod(env, supportedActions, mid_arrayListAdd, action); \ - } else { \ - (*env)->ExceptionClear(env); \ - } \ -} while(0); - - -static void update_supported_actions(JNIEnv *env) { - GVfs * (*fp_g_vfs_get_default) (void); - const gchar * const * (*fp_g_vfs_get_supported_uri_schemes) (GVfs * vfs); - const gchar * const * schemes = NULL; - - jclass cls_action = (*env)->FindClass(env, "java/awt/Desktop$Action"); - CHECK_NULL(cls_action); - jclass cls_xDesktopPeer = (*env)->FindClass(env, "sun/awt/X11/XDesktopPeer"); - CHECK_NULL(cls_xDesktopPeer); - jfieldID fld_supportedActions = (*env)->GetStaticFieldID(env, cls_xDesktopPeer, "supportedActions", "Ljava/util/List;"); - CHECK_NULL(fld_supportedActions); - jobject supportedActions = (*env)->GetStaticObjectField(env, cls_xDesktopPeer, fld_supportedActions); - - jclass cls_arrayList = (*env)->FindClass(env, "java/util/ArrayList"); - CHECK_NULL(cls_arrayList); - jmethodID mid_arrayListAdd = (*env)->GetMethodID(env, cls_arrayList, "add", "(Ljava/lang/Object;)Z"); - CHECK_NULL(mid_arrayListAdd); - jmethodID mid_arrayListClear = (*env)->GetMethodID(env, cls_arrayList, "clear", "()V"); - CHECK_NULL(mid_arrayListClear); - - (*env)->CallVoidMethod(env, supportedActions, mid_arrayListClear); - - ADD_SUPPORTED_ACTION("OPEN"); - - /** - * gtk_show_uri() documentation says: - * - * > you need to install gvfs to get support for uri schemes such as http:// - * > or ftp://, as only local files are handled by GIO itself. - * - * So OPEN action was safely added here. - * However, it looks like Solaris 11 have gvfs support only for 32-bit - * applications only by default. - */ - - fp_g_vfs_get_default = dl_symbol("g_vfs_get_default"); - fp_g_vfs_get_supported_uri_schemes = dl_symbol("g_vfs_get_supported_uri_schemes"); - dlerror(); - - if (fp_g_vfs_get_default && fp_g_vfs_get_supported_uri_schemes) { - GVfs * vfs = fp_g_vfs_get_default(); - schemes = vfs ? fp_g_vfs_get_supported_uri_schemes(vfs) : NULL; - if (schemes) { - int i = 0; - while (schemes[i]) { - if (strcmp(schemes[i], "http") == 0) { - ADD_SUPPORTED_ACTION("BROWSE"); - ADD_SUPPORTED_ACTION("MAIL"); - break; - } - i++; - } - } - } else { -#ifdef DEBUG - fprintf(stderr, "Cannot load g_vfs_get_supported_uri_schemes\n"); -#endif /* DEBUG */ - } - -} -/** - * Functions for awt_Desktop.c - */ -static gboolean gtk2_show_uri_load(JNIEnv *env) { - gboolean success = FALSE; - dlerror(); - const char *gtk_version = fp_gtk_check_version(2, 14, 0); - if (gtk_version != NULL) { - // The gtk_show_uri is available from GTK+ 2.14 -#ifdef DEBUG - fprintf (stderr, "The version of GTK is %s. " - "The gtk_show_uri function is supported " - "since GTK+ 2.14.\n", gtk_version); -#endif /* DEBUG */ - } else { - // Loading symbols only if the GTK version is 2.14 and higher - fp_gtk_show_uri = dl_symbol("gtk_show_uri"); - const char *dlsym_error = dlerror(); - if (dlsym_error) { -#ifdef DEBUG - fprintf (stderr, "Cannot load symbol: %s \n", dlsym_error); -#endif /* DEBUG */ - } else if (fp_gtk_show_uri == NULL) { -#ifdef DEBUG - fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n"); -#endif /* DEBUG */ - } else { - gtk->gtk_show_uri = fp_gtk_show_uri; - update_supported_actions(env); - success = TRUE; - } - } - return success; -} - -/** - * Functions for sun_awt_X11_GtkFileDialogPeer.c - */ -static void gtk2_file_chooser_load() -{ - fp_gtk_file_chooser_get_filename = dl_symbol( - "gtk_file_chooser_get_filename"); - fp_gtk_file_chooser_dialog_new = dl_symbol("gtk_file_chooser_dialog_new"); - fp_gtk_file_chooser_set_current_folder = dl_symbol( - "gtk_file_chooser_set_current_folder"); - fp_gtk_file_chooser_set_filename = dl_symbol( - "gtk_file_chooser_set_filename"); - fp_gtk_file_chooser_set_current_name = dl_symbol( - "gtk_file_chooser_set_current_name"); - fp_gtk_file_filter_add_custom = dl_symbol("gtk_file_filter_add_custom"); - fp_gtk_file_chooser_set_filter = dl_symbol("gtk_file_chooser_set_filter"); - fp_gtk_file_chooser_get_type = dl_symbol("gtk_file_chooser_get_type"); - fp_gtk_file_filter_new = dl_symbol("gtk_file_filter_new"); - if (fp_gtk_check_version(2, 8, 0) == NULL) { - fp_gtk_file_chooser_set_do_overwrite_confirmation = dl_symbol( - "gtk_file_chooser_set_do_overwrite_confirmation"); - } - fp_gtk_file_chooser_set_select_multiple = dl_symbol( - "gtk_file_chooser_set_select_multiple"); - fp_gtk_file_chooser_get_current_folder = dl_symbol( - "gtk_file_chooser_get_current_folder"); - fp_gtk_file_chooser_get_filenames = dl_symbol( - "gtk_file_chooser_get_filenames"); - fp_gtk_g_slist_length = dl_symbol("g_slist_length"); - fp_gdk_x11_drawable_get_xid = dl_symbol("gdk_x11_drawable_get_xid"); -} - -GtkApi* gtk2_load(JNIEnv *env, const char* lib_name) -{ - gboolean result; - int i; - int (*handler)(); - int (*io_handler)(); - char *gtk_modules_env; - - gtk2_libhandle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL); - if (gtk2_libhandle == NULL) { - return FALSE; - } - - gthread_libhandle = dlopen(GTHREAD_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL); - if (gthread_libhandle == NULL) { - gthread_libhandle = dlopen(GTHREAD_LIB, RTLD_LAZY | RTLD_LOCAL); - if (gthread_libhandle == NULL) - return FALSE; - } - - if (setjmp(j) == 0) - { - fp_gtk_check_version = dl_symbol("gtk_check_version"); - /* Check for GTK 2.2+ */ - if (fp_gtk_check_version(2, 2, 0)) { - longjmp(j, NO_SYMBOL_EXCEPTION); - } - - /* GLib */ - fp_glib_check_version = dlsym(gtk2_libhandle, "glib_check_version"); - if (!fp_glib_check_version) { - dlerror(); - } - fp_g_free = dl_symbol("g_free"); - fp_g_object_unref = dl_symbol("g_object_unref"); - - fp_g_main_context_iteration = - dl_symbol("g_main_context_iteration"); - - fp_g_value_init = dl_symbol("g_value_init"); - fp_g_type_is_a = dl_symbol("g_type_is_a"); - - fp_g_value_get_boolean = dl_symbol("g_value_get_boolean"); - fp_g_value_get_char = dl_symbol("g_value_get_char"); - fp_g_value_get_uchar = dl_symbol("g_value_get_uchar"); - fp_g_value_get_int = dl_symbol("g_value_get_int"); - fp_g_value_get_uint = dl_symbol("g_value_get_uint"); - fp_g_value_get_long = dl_symbol("g_value_get_long"); - fp_g_value_get_ulong = dl_symbol("g_value_get_ulong"); - fp_g_value_get_int64 = dl_symbol("g_value_get_int64"); - fp_g_value_get_uint64 = dl_symbol("g_value_get_uint64"); - fp_g_value_get_float = dl_symbol("g_value_get_float"); - fp_g_value_get_double = dl_symbol("g_value_get_double"); - fp_g_value_get_string = dl_symbol("g_value_get_string"); - fp_g_value_get_enum = dl_symbol("g_value_get_enum"); - fp_g_value_get_flags = dl_symbol("g_value_get_flags"); - fp_g_value_get_param = dl_symbol("g_value_get_param"); - fp_g_value_get_boxed = dl_symbol("g_value_get_boxed"); - fp_g_value_get_pointer = dl_symbol("g_value_get_pointer"); - fp_g_value_get_object = dl_symbol("g_value_get_object"); - fp_g_param_spec_int = dl_symbol("g_param_spec_int"); - fp_g_object_get = dl_symbol("g_object_get"); - fp_g_object_set = dl_symbol("g_object_set"); - - /* GDK */ - fp_gdk_get_default_root_window = - dl_symbol("gdk_get_default_root_window"); - fp_gdk_pixmap_new = dl_symbol("gdk_pixmap_new"); - fp_gdk_pixbuf_get_from_drawable = - dl_symbol("gdk_pixbuf_get_from_drawable"); - fp_gdk_pixbuf_scale_simple = - dl_symbol("gdk_pixbuf_scale_simple"); - fp_gdk_gc_new = dl_symbol("gdk_gc_new"); - fp_gdk_rgb_gc_set_foreground = - dl_symbol("gdk_rgb_gc_set_foreground"); - fp_gdk_draw_rectangle = dl_symbol("gdk_draw_rectangle"); - fp_gdk_drawable_get_size = dl_symbol("gdk_drawable_get_size"); - - /* Pixbuf */ - fp_gdk_pixbuf_new = dl_symbol("gdk_pixbuf_new"); - fp_gdk_pixbuf_new_from_file = - dl_symbol("gdk_pixbuf_new_from_file"); - fp_gdk_pixbuf_get_width = dl_symbol("gdk_pixbuf_get_width"); - fp_gdk_pixbuf_get_height = dl_symbol("gdk_pixbuf_get_height"); - fp_gdk_pixbuf_get_pixels = dl_symbol("gdk_pixbuf_get_pixels"); - fp_gdk_pixbuf_get_rowstride = - dl_symbol("gdk_pixbuf_get_rowstride"); - fp_gdk_pixbuf_get_has_alpha = - dl_symbol("gdk_pixbuf_get_has_alpha"); - fp_gdk_pixbuf_get_bits_per_sample = - dl_symbol("gdk_pixbuf_get_bits_per_sample"); - fp_gdk_pixbuf_get_n_channels = - dl_symbol("gdk_pixbuf_get_n_channels"); - fp_gdk_pixbuf_get_colorspace = - dl_symbol("gdk_pixbuf_get_colorspace"); - - /* GTK painting */ - fp_gtk_init_check = dl_symbol("gtk_init_check"); - fp_gtk_paint_hline = dl_symbol("gtk_paint_hline"); - fp_gtk_paint_vline = dl_symbol("gtk_paint_vline"); - fp_gtk_paint_shadow = dl_symbol("gtk_paint_shadow"); - fp_gtk_paint_arrow = dl_symbol("gtk_paint_arrow"); - fp_gtk_paint_box = dl_symbol("gtk_paint_box"); - fp_gtk_paint_flat_box = dl_symbol("gtk_paint_flat_box"); - fp_gtk_paint_check = dl_symbol("gtk_paint_check"); - fp_gtk_paint_option = dl_symbol("gtk_paint_option"); - fp_gtk_paint_box_gap = dl_symbol("gtk_paint_box_gap"); - fp_gtk_paint_extension = dl_symbol("gtk_paint_extension"); - fp_gtk_paint_focus = dl_symbol("gtk_paint_focus"); - fp_gtk_paint_slider = dl_symbol("gtk_paint_slider"); - fp_gtk_paint_handle = dl_symbol("gtk_paint_handle"); - fp_gtk_paint_expander = dl_symbol("gtk_paint_expander"); - fp_gtk_style_apply_default_background = - dl_symbol("gtk_style_apply_default_background"); - - /* GTK widgets */ - fp_gtk_arrow_new = dl_symbol("gtk_arrow_new"); - fp_gtk_button_new = dl_symbol("gtk_button_new"); - fp_gtk_spin_button_new = dl_symbol("gtk_spin_button_new"); - fp_gtk_check_button_new = dl_symbol("gtk_check_button_new"); - fp_gtk_check_menu_item_new = - dl_symbol("gtk_check_menu_item_new"); - fp_gtk_color_selection_dialog_new = - dl_symbol("gtk_color_selection_dialog_new"); - fp_gtk_entry_new = dl_symbol("gtk_entry_new"); - fp_gtk_fixed_new = dl_symbol("gtk_fixed_new"); - fp_gtk_handle_box_new = dl_symbol("gtk_handle_box_new"); - fp_gtk_image_new = dl_symbol("gtk_image_new"); - fp_gtk_hpaned_new = dl_symbol("gtk_hpaned_new"); - fp_gtk_vpaned_new = dl_symbol("gtk_vpaned_new"); - fp_gtk_hscale_new = dl_symbol("gtk_hscale_new"); - fp_gtk_vscale_new = dl_symbol("gtk_vscale_new"); - fp_gtk_hscrollbar_new = dl_symbol("gtk_hscrollbar_new"); - fp_gtk_vscrollbar_new = dl_symbol("gtk_vscrollbar_new"); - fp_gtk_hseparator_new = dl_symbol("gtk_hseparator_new"); - fp_gtk_vseparator_new = dl_symbol("gtk_vseparator_new"); - fp_gtk_label_new = dl_symbol("gtk_label_new"); - fp_gtk_menu_new = dl_symbol("gtk_menu_new"); - fp_gtk_menu_bar_new = dl_symbol("gtk_menu_bar_new"); - fp_gtk_menu_item_new = dl_symbol("gtk_menu_item_new"); - fp_gtk_menu_item_set_submenu = - dl_symbol("gtk_menu_item_set_submenu"); - fp_gtk_notebook_new = dl_symbol("gtk_notebook_new"); - fp_gtk_progress_bar_new = - dl_symbol("gtk_progress_bar_new"); - fp_gtk_progress_bar_set_orientation = - dl_symbol("gtk_progress_bar_set_orientation"); - fp_gtk_radio_button_new = - dl_symbol("gtk_radio_button_new"); - fp_gtk_radio_menu_item_new = - dl_symbol("gtk_radio_menu_item_new"); - fp_gtk_scrolled_window_new = - dl_symbol("gtk_scrolled_window_new"); - fp_gtk_separator_menu_item_new = - dl_symbol("gtk_separator_menu_item_new"); - fp_gtk_text_view_new = dl_symbol("gtk_text_view_new"); - fp_gtk_toggle_button_new = - dl_symbol("gtk_toggle_button_new"); - fp_gtk_toolbar_new = dl_symbol("gtk_toolbar_new"); - fp_gtk_tree_view_new = dl_symbol("gtk_tree_view_new"); - fp_gtk_viewport_new = dl_symbol("gtk_viewport_new"); - fp_gtk_window_new = dl_symbol("gtk_window_new"); - fp_gtk_window_present = dl_symbol("gtk_window_present"); - fp_gtk_window_move = dl_symbol("gtk_window_move"); - fp_gtk_window_resize = dl_symbol("gtk_window_resize"); - - fp_gtk_dialog_new = dl_symbol("gtk_dialog_new"); - fp_gtk_frame_new = dl_symbol("gtk_frame_new"); - - fp_gtk_adjustment_new = dl_symbol("gtk_adjustment_new"); - fp_gtk_container_add = dl_symbol("gtk_container_add"); - fp_gtk_menu_shell_append = - dl_symbol("gtk_menu_shell_append"); - fp_gtk_widget_realize = dl_symbol("gtk_widget_realize"); - fp_gtk_widget_destroy = dl_symbol("gtk_widget_destroy"); - fp_gtk_widget_render_icon = - dl_symbol("gtk_widget_render_icon"); - fp_gtk_widget_set_name = - dl_symbol("gtk_widget_set_name"); - fp_gtk_widget_set_parent = - dl_symbol("gtk_widget_set_parent"); - fp_gtk_widget_set_direction = - dl_symbol("gtk_widget_set_direction"); - fp_gtk_widget_style_get = - dl_symbol("gtk_widget_style_get"); - fp_gtk_widget_class_install_style_property = - dl_symbol("gtk_widget_class_install_style_property"); - fp_gtk_widget_class_find_style_property = - dl_symbol("gtk_widget_class_find_style_property"); - fp_gtk_widget_style_get_property = - dl_symbol("gtk_widget_style_get_property"); - fp_pango_font_description_to_string = - dl_symbol("pango_font_description_to_string"); - fp_gtk_settings_get_default = - dl_symbol("gtk_settings_get_default"); - fp_gtk_widget_get_settings = - dl_symbol("gtk_widget_get_settings"); - fp_gtk_border_get_type = dl_symbol("gtk_border_get_type"); - fp_gtk_arrow_set = dl_symbol("gtk_arrow_set"); - fp_gtk_widget_size_request = - dl_symbol("gtk_widget_size_request"); - fp_gtk_range_get_adjustment = - dl_symbol("gtk_range_get_adjustment"); - - fp_gtk_widget_hide = dl_symbol("gtk_widget_hide"); - fp_gtk_main_quit = dl_symbol("gtk_main_quit"); - fp_g_signal_connect_data = dl_symbol("g_signal_connect_data"); - fp_gtk_widget_show = dl_symbol("gtk_widget_show"); - fp_gtk_main = dl_symbol("gtk_main"); - - fp_g_path_get_dirname = dl_symbol("g_path_get_dirname"); - - /** - * GLib thread system - */ - if (GLIB_CHECK_VERSION(2, 20, 0)) { - fp_g_thread_get_initialized = dl_symbol_gthread("g_thread_get_initialized"); - } - fp_g_thread_init = dl_symbol_gthread("g_thread_init"); - fp_gdk_threads_init = dl_symbol("gdk_threads_init"); - fp_gdk_threads_enter = dl_symbol("gdk_threads_enter"); - fp_gdk_threads_leave = dl_symbol("gdk_threads_leave"); - - /** - * Functions for sun_awt_X11_GtkFileDialogPeer.c - */ - if (fp_gtk_check_version(2, 4, 0) == NULL) { - // The current GtkFileChooser is available from GTK+ 2.4 - gtk2_file_chooser_load(); - } - - /* Some functions may be missing in pre-2.4 GTK. - We handle them specially here. - */ - fp_gtk_combo_box_new = dlsym(gtk2_libhandle, "gtk_combo_box_new"); - if (fp_gtk_combo_box_new == NULL) { - fp_gtk_combo_box_new = dl_symbol("gtk_combo_new"); - } - - fp_gtk_combo_box_entry_new = - dlsym(gtk2_libhandle, "gtk_combo_box_entry_new"); - if (fp_gtk_combo_box_entry_new == NULL) { - fp_gtk_combo_box_entry_new = dl_symbol("gtk_combo_new"); - new_combo = FALSE; - } - - fp_gtk_separator_tool_item_new = - dlsym(gtk2_libhandle, "gtk_separator_tool_item_new"); - if (fp_gtk_separator_tool_item_new == NULL) { - fp_gtk_separator_tool_item_new = - dl_symbol("gtk_vseparator_new"); - } - - fp_g_list_append = dl_symbol("g_list_append"); - fp_g_list_free = dl_symbol("g_list_free"); - fp_g_list_free_full = dl_symbol("g_list_free_full"); - } - /* Now we have only one kind of exceptions: NO_SYMBOL_EXCEPTION - * Otherwise we can check the return value of setjmp method. - */ - else - { - dlclose(gtk2_libhandle); - gtk2_libhandle = NULL; - - dlclose(gthread_libhandle); - gthread_libhandle = NULL; - - return FALSE; - } - - /* - * Strip the AT-SPI GTK_MODULES if present - */ - gtk_modules_env = getenv ("GTK_MODULES"); - if ((gtk_modules_env && strstr(gtk_modules_env, "atk-bridge")) || - (gtk_modules_env && strstr(gtk_modules_env, "gail"))) { - /* careful, strtok modifies its args */ - gchar *tmp_env = strdup(gtk_modules_env); - if (tmp_env) { - /* the new env will be smaller than the old one */ - gchar *s, *new_env = SAFE_SIZE_STRUCT_ALLOC(malloc, - sizeof(ENV_PREFIX), 1, strlen (gtk_modules_env)); - - if (new_env) { - strcpy(new_env, ENV_PREFIX); - - /* strip out 'atk-bridge' and 'gail' */ - size_t PREFIX_LENGTH = strlen(ENV_PREFIX); - gchar *tmp_ptr = NULL; - for (s = strtok_r(tmp_env, ":", &tmp_ptr); s; - s = strtok_r(NULL, ":", &tmp_ptr)) { - if ((!strstr(s, "atk-bridge")) && (!strstr(s, "gail"))) { - if (strlen(new_env) > PREFIX_LENGTH) { - new_env = strcat(new_env, ":"); - } - new_env = strcat(new_env, s); - } - } - if (putenv(new_env) != 0) { - /* no free() on success, putenv() doesn't copy string */ - free(new_env); - } - } - free(tmp_env); - } - } - /* - * GTK should be initialized with gtk_init_check() before use. - * - * gtk_init_check installs its own error handlers. It is critical that - * we preserve error handler set from AWT. Otherwise we'll crash on - * BadMatch errors which we would normally ignore. The IO error handler - * is preserved here, too, just for consistency. - */ - AWT_LOCK(); - handler = XSetErrorHandler(NULL); - io_handler = XSetIOErrorHandler(NULL); - - if (fp_gtk_check_version(2, 2, 0) == NULL) { - - // Calling g_thread_init() multiple times leads to crash on GLib < 2.24 - // We can use g_thread_get_initialized () but it is available only for - // GLib >= 2.20. - gboolean is_g_thread_get_initialized = FALSE; - if (GLIB_CHECK_VERSION(2, 20, 0)) { - is_g_thread_get_initialized = fp_g_thread_get_initialized(); - } - - if (!is_g_thread_get_initialized) { - fp_g_thread_init(NULL); - } - - //According the GTK documentation, gdk_threads_init() should be - //called before gtk_init() or gtk_init_check() - fp_gdk_threads_init(); - } - result = (*fp_gtk_init_check)(NULL, NULL); - - XSetErrorHandler(handler); - XSetIOErrorHandler(io_handler); - AWT_UNLOCK(); - - /* Initialize widget array. */ - for (i = 0; i < _GTK_WIDGET_TYPE_SIZE; i++) - { - gtk2_widgets[i] = NULL; - } - if (result) { - GtkApi* gtk = (GtkApi*)malloc(sizeof(GtkApi)); - gtk2_init(gtk); - return gtk; - } - return NULL; -} - -int gtk2_unload() -{ - int i; - char *gtk2_error; - - if (!gtk2_libhandle) - return TRUE; - - /* Release painting objects */ - if (gtk2_white_pixmap != NULL) { - (*fp_g_object_unref)(gtk2_white_pixmap); - (*fp_g_object_unref)(gtk2_black_pixmap); - (*fp_g_object_unref)(gtk2_white_pixbuf); - (*fp_g_object_unref)(gtk2_black_pixbuf); - gtk2_white_pixmap = gtk2_black_pixmap = - gtk2_white_pixbuf = gtk2_black_pixbuf = NULL; - } - gtk2_pixbuf_width = 0; - gtk2_pixbuf_height = 0; - - if (gtk2_window != NULL) { - /* Destroying toplevel widget will destroy all contained widgets */ - (*fp_gtk_widget_destroy)(gtk2_window); - - /* Unset some static data so they get reinitialized on next load */ - gtk2_window = NULL; - } - - dlerror(); - dlclose(gtk2_libhandle); - dlclose(gthread_libhandle); - if ((gtk2_error = dlerror()) != NULL) - { - return FALSE; - } - return TRUE; -} - -/* Dispatch all pending events from the GTK event loop. - * This is needed to catch theme change and update widgets' style. - */ -static void flush_gtk_event_loop() -{ - while( (*fp_g_main_context_iteration)(NULL, FALSE)); -} - -/* - * Initialize components of containment hierarchy. This creates a GtkFixed - * inside a GtkWindow. All widgets get realized. - */ -static void init_containers() -{ - if (gtk2_window == NULL) - { - gtk2_window = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL); - gtk2_fixed = (GtkFixed *)(*fp_gtk_fixed_new)(); - (*fp_gtk_container_add)((GtkContainer*)gtk2_window, - (GtkWidget *)gtk2_fixed); - (*fp_gtk_widget_realize)(gtk2_window); - (*fp_gtk_widget_realize)((GtkWidget *)gtk2_fixed); - } -} - -/* - * Ensure everything is ready for drawing an element of the specified width - * and height. - * - * We should somehow handle translucent images. GTK can draw to X Drawables - * only, which don't support alpha. When we retrieve the image back from - * the server, translucency information is lost. There're several ways to - * work around this: - * 1) Subclass GdkPixmap and cache translucent objects on client side. This - * requires us to implement parts of X server drawing logic on client side. - * Many X requests can potentially be "translucent"; e.g. XDrawLine with - * fill=tile and a translucent tile is a "translucent" operation, whereas - * XDrawLine with fill=solid is an "opaque" one. Moreover themes can (and some - * do) intermix transparent and opaque operations which makes caching even - * more problematic. - * 2) Use Xorg 32bit ARGB visual when available. GDK has no native support - * for it (as of version 2.6). Also even in JDS 3 Xorg does not support - * these visuals by default, which makes optimizing for them pointless. - * We can consider doing this at a later point when ARGB visuals become more - * popular. - * 3') GTK has plans to use Cairo as its graphical backend (presumably in - * 2.8), and Cairo supports alpha. With it we could also get rid of the - * unnecessary round trip to server and do all the drawing on client side. - * 4) For now we draw to two different pixmaps and restore alpha channel by - * comparing results. This can be optimized by using subclassed pixmap and - * doing the second drawing only if necessary. -*/ -static void gtk2_init_painting(JNIEnv *env, gint width, gint height) -{ - GdkGC *gc; - GdkPixbuf *white, *black; - - init_containers(); - - if (gtk2_pixbuf_width < width || gtk2_pixbuf_height < height) - { - white = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8, width, height); - black = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8, width, height); - - if (white == NULL || black == NULL) - { - snprintf(convertionBuffer, CONV_BUFFER_SIZE, "Couldn't create pixbuf of size %dx%d", width, height); - throw_exception(env, "java/lang/RuntimeException", convertionBuffer); - fp_gdk_threads_leave(); - return; - } - - if (gtk2_white_pixmap != NULL) { - /* free old stuff */ - (*fp_g_object_unref)(gtk2_white_pixmap); - (*fp_g_object_unref)(gtk2_black_pixmap); - (*fp_g_object_unref)(gtk2_white_pixbuf); - (*fp_g_object_unref)(gtk2_black_pixbuf); - } - - gtk2_white_pixmap = (*fp_gdk_pixmap_new)(gtk2_window->window, width, height, -1); - gtk2_black_pixmap = (*fp_gdk_pixmap_new)(gtk2_window->window, width, height, -1); - - gtk2_white_pixbuf = white; - gtk2_black_pixbuf = black; - - gtk2_pixbuf_width = width; - gtk2_pixbuf_height = height; - } - - /* clear the pixmaps */ - gc = (*fp_gdk_gc_new)(gtk2_white_pixmap); - (*fp_gdk_rgb_gc_set_foreground)(gc, 0xffffff); - (*fp_gdk_draw_rectangle)(gtk2_white_pixmap, gc, TRUE, 0, 0, width, height); - (*fp_g_object_unref)(gc); - - gc = (*fp_gdk_gc_new)(gtk2_black_pixmap); - (*fp_gdk_rgb_gc_set_foreground)(gc, 0x000000); - (*fp_gdk_draw_rectangle)(gtk2_black_pixmap, gc, TRUE, 0, 0, width, height); - (*fp_g_object_unref)(gc); -} - -/* - * Restore image from white and black pixmaps and copy it into destination - * buffer. This method compares two pixbufs taken from white and black - * pixmaps and decodes color and alpha components. Pixbufs are RGB without - * alpha, destination buffer is ABGR. - * - * The return value is the transparency type of the resulting image, either - * one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and - * java_awt_Transparency_TRANSLUCENT. - */ -static gint gtk2_copy_image(gint *dst, gint width, gint height) -{ - gint i, j, r, g, b; - guchar *white, *black; - gint stride, padding; - gboolean is_opaque = TRUE; - gboolean is_bitmask = TRUE; - - (*fp_gdk_pixbuf_get_from_drawable)(gtk2_white_pixbuf, gtk2_white_pixmap, - NULL, 0, 0, 0, 0, width, height); - (*fp_gdk_pixbuf_get_from_drawable)(gtk2_black_pixbuf, gtk2_black_pixmap, - NULL, 0, 0, 0, 0, width, height); - - white = (*fp_gdk_pixbuf_get_pixels)(gtk2_white_pixbuf); - black = (*fp_gdk_pixbuf_get_pixels)(gtk2_black_pixbuf); - stride = (*fp_gdk_pixbuf_get_rowstride)(gtk2_black_pixbuf); - padding = stride - width * 4; - if (padding >= 0 && stride > 0) { - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - int r1 = *white++; - int r2 = *black++; - int alpha = 0xff + r2 - r1; - - switch (alpha) { - case 0: /* transparent pixel */ - r = g = b = 0; - black += 3; - white += 3; - is_opaque = FALSE; - break; - - case 0xff: /* opaque pixel */ - r = r2; - g = *black++; - b = *black++; - black++; - white += 3; - break; - - default: /* translucent pixel */ - r = 0xff * r2 / alpha; - g = 0xff * *black++ / alpha; - b = 0xff * *black++ / alpha; - black++; - white += 3; - is_opaque = FALSE; - is_bitmask = FALSE; - break; - } - - *dst++ = (alpha << 24 | r << 16 | g << 8 | b); - } - - white += padding; - black += padding; - } - } - return is_opaque ? java_awt_Transparency_OPAQUE : - (is_bitmask ? java_awt_Transparency_BITMASK : - java_awt_Transparency_TRANSLUCENT); -} - -static void -gtk2_set_direction(GtkWidget *widget, GtkTextDirection dir) -{ - /* - * Some engines (inexplicably) look at the direction of the widget's - * parent, so we need to set the direction of both the widget and its - * parent. - */ - (*fp_gtk_widget_set_direction)(widget, dir); - if (widget->parent != NULL) { - (*fp_gtk_widget_set_direction)(widget->parent, dir); - } -} - -/* - * Initializes the widget to correct state for some engines. - * This is a pure empirical method. - */ -static void init_toggle_widget(WidgetType widget_type, gint synth_state) -{ - gboolean is_active = ((synth_state & SELECTED) != 0); - - if (widget_type == RADIO_BUTTON || - widget_type == CHECK_BOX || - widget_type == TOGGLE_BUTTON) { - ((GtkToggleButton*)gtk2_widget)->active = is_active; - } - - if ((synth_state & FOCUSED) != 0) { - ((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS; - } else { - ((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS; - } - - if ((((synth_state & MOUSE_OVER) != 0) && ((synth_state & PRESSED) == 0)) || - (((synth_state & FOCUSED) != 0) && ((synth_state & PRESSED) != 0))) { - gtk2_widget->state = GTK_STATE_PRELIGHT; - } else if ((synth_state & DISABLED) != 0) { - gtk2_widget->state = GTK_STATE_INSENSITIVE; - } else { - gtk2_widget->state = is_active ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL; - } -} - -/* GTK state_type filter */ -static GtkStateType get_gtk_state_type(WidgetType widget_type, gint synth_state) -{ - GtkStateType result = GTK_STATE_NORMAL; - - if ((synth_state & DISABLED) != 0) { - result = GTK_STATE_INSENSITIVE; - } else if ((synth_state & PRESSED) != 0) { - result = GTK_STATE_ACTIVE; - } else if ((synth_state & MOUSE_OVER) != 0) { - result = GTK_STATE_PRELIGHT; - } - return result; -} - -/* GTK shadow_type filter */ -static GtkShadowType get_gtk_shadow_type(WidgetType widget_type, gint synth_state) -{ - GtkShadowType result = GTK_SHADOW_OUT; - - if ((synth_state & SELECTED) != 0) { - result = GTK_SHADOW_IN; - } - return result; -} - - -static GtkWidget* gtk2_get_arrow(GtkArrowType arrow_type, GtkShadowType shadow_type) -{ - GtkWidget *arrow = NULL; - if (NULL == gtk2_widgets[_GTK_ARROW_TYPE]) - { - gtk2_widgets[_GTK_ARROW_TYPE] = (*fp_gtk_arrow_new)(arrow_type, shadow_type); - (*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, gtk2_widgets[_GTK_ARROW_TYPE]); - (*fp_gtk_widget_realize)(gtk2_widgets[_GTK_ARROW_TYPE]); - } - arrow = gtk2_widgets[_GTK_ARROW_TYPE]; - - (*fp_gtk_arrow_set)(arrow, arrow_type, shadow_type); - return arrow; -} - -static GtkAdjustment* create_adjustment() -{ - return (GtkAdjustment *) - (*fp_gtk_adjustment_new)(50.0, 0.0, 100.0, 10.0, 20.0, 20.0); -} - -/** - * Returns a pointer to the cached native widget for the specified widget - * type. - */ -static GtkWidget *gtk2_get_widget(WidgetType widget_type) -{ - gboolean init_result = FALSE; - GtkWidget *result = NULL; - switch (widget_type) - { - case BUTTON: - case TABLE_HEADER: - if (init_result = (NULL == gtk2_widgets[_GTK_BUTTON_TYPE])) - { - gtk2_widgets[_GTK_BUTTON_TYPE] = (*fp_gtk_button_new)(); - } - result = gtk2_widgets[_GTK_BUTTON_TYPE]; - break; - case CHECK_BOX: - if (init_result = (NULL == gtk2_widgets[_GTK_CHECK_BUTTON_TYPE])) - { - gtk2_widgets[_GTK_CHECK_BUTTON_TYPE] = - (*fp_gtk_check_button_new)(); - } - result = gtk2_widgets[_GTK_CHECK_BUTTON_TYPE]; - break; - case CHECK_BOX_MENU_ITEM: - if (init_result = (NULL == gtk2_widgets[_GTK_CHECK_MENU_ITEM_TYPE])) - { - gtk2_widgets[_GTK_CHECK_MENU_ITEM_TYPE] = - (*fp_gtk_check_menu_item_new)(); - } - result = gtk2_widgets[_GTK_CHECK_MENU_ITEM_TYPE]; - break; - /************************************************************ - * Creation a dedicated color chooser is dangerous because - * it deadlocks the EDT - ************************************************************/ -/* case COLOR_CHOOSER: - if (init_result = - (NULL == gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE])) - { - gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE] = - (*fp_gtk_color_selection_dialog_new)(NULL); - } - result = gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE]; - break;*/ - case COMBO_BOX: - if (init_result = (NULL == gtk2_widgets[_GTK_COMBO_BOX_TYPE])) - { - gtk2_widgets[_GTK_COMBO_BOX_TYPE] = - (*fp_gtk_combo_box_new)(); - } - result = gtk2_widgets[_GTK_COMBO_BOX_TYPE]; - break; - case COMBO_BOX_ARROW_BUTTON: - if (init_result = - (NULL == gtk2_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE])) - { - gtk2_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE] = - (*fp_gtk_toggle_button_new)(); - } - result = gtk2_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE]; - break; - case COMBO_BOX_TEXT_FIELD: - if (init_result = - (NULL == gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE])) - { - result = gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE] = - (*fp_gtk_entry_new)(); - } - result = gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE]; - break; - case DESKTOP_ICON: - case INTERNAL_FRAME_TITLE_PANE: - case LABEL: - if (init_result = (NULL == gtk2_widgets[_GTK_LABEL_TYPE])) - { - gtk2_widgets[_GTK_LABEL_TYPE] = - (*fp_gtk_label_new)(NULL); - } - result = gtk2_widgets[_GTK_LABEL_TYPE]; - break; - case DESKTOP_PANE: - case PANEL: - case ROOT_PANE: - if (init_result = (NULL == gtk2_widgets[_GTK_CONTAINER_TYPE])) - { - /* There is no constructor for a container type. I've - * chosen GtkFixed container since it has a default - * constructor. - */ - gtk2_widgets[_GTK_CONTAINER_TYPE] = - (*fp_gtk_fixed_new)(); - } - result = gtk2_widgets[_GTK_CONTAINER_TYPE]; - break; - case EDITOR_PANE: - case TEXT_AREA: - case TEXT_PANE: - if (init_result = (NULL == gtk2_widgets[_GTK_TEXT_VIEW_TYPE])) - { - gtk2_widgets[_GTK_TEXT_VIEW_TYPE] = - (*fp_gtk_text_view_new)(); - } - result = gtk2_widgets[_GTK_TEXT_VIEW_TYPE]; - break; - case FORMATTED_TEXT_FIELD: - case PASSWORD_FIELD: - case TEXT_FIELD: - if (init_result = (NULL == gtk2_widgets[_GTK_ENTRY_TYPE])) - { - gtk2_widgets[_GTK_ENTRY_TYPE] = - (*fp_gtk_entry_new)(); - } - result = gtk2_widgets[_GTK_ENTRY_TYPE]; - break; - case HANDLE_BOX: - if (init_result = (NULL == gtk2_widgets[_GTK_HANDLE_BOX_TYPE])) - { - gtk2_widgets[_GTK_HANDLE_BOX_TYPE] = - (*fp_gtk_handle_box_new)(); - } - result = gtk2_widgets[_GTK_HANDLE_BOX_TYPE]; - break; - case HSCROLL_BAR: - case HSCROLL_BAR_BUTTON_LEFT: - case HSCROLL_BAR_BUTTON_RIGHT: - case HSCROLL_BAR_TRACK: - case HSCROLL_BAR_THUMB: - if (init_result = (NULL == gtk2_widgets[_GTK_HSCROLLBAR_TYPE])) - { - gtk2_widgets[_GTK_HSCROLLBAR_TYPE] = - (*fp_gtk_hscrollbar_new)(create_adjustment()); - } - result = gtk2_widgets[_GTK_HSCROLLBAR_TYPE]; - break; - case HSEPARATOR: - if (init_result = (NULL == gtk2_widgets[_GTK_HSEPARATOR_TYPE])) - { - gtk2_widgets[_GTK_HSEPARATOR_TYPE] = - (*fp_gtk_hseparator_new)(); - } - result = gtk2_widgets[_GTK_HSEPARATOR_TYPE]; - break; - case HSLIDER: - case HSLIDER_THUMB: - case HSLIDER_TRACK: - if (init_result = (NULL == gtk2_widgets[_GTK_HSCALE_TYPE])) - { - gtk2_widgets[_GTK_HSCALE_TYPE] = - (*fp_gtk_hscale_new)(NULL); - } - result = gtk2_widgets[_GTK_HSCALE_TYPE]; - break; - case HSPLIT_PANE_DIVIDER: - case SPLIT_PANE: - if (init_result = (NULL == gtk2_widgets[_GTK_HPANED_TYPE])) - { - gtk2_widgets[_GTK_HPANED_TYPE] = (*fp_gtk_hpaned_new)(); - } - result = gtk2_widgets[_GTK_HPANED_TYPE]; - break; - case IMAGE: - if (init_result = (NULL == gtk2_widgets[_GTK_IMAGE_TYPE])) - { - gtk2_widgets[_GTK_IMAGE_TYPE] = (*fp_gtk_image_new)(); - } - result = gtk2_widgets[_GTK_IMAGE_TYPE]; - break; - case INTERNAL_FRAME: - if (init_result = (NULL == gtk2_widgets[_GTK_WINDOW_TYPE])) - { - gtk2_widgets[_GTK_WINDOW_TYPE] = - (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL); - } - result = gtk2_widgets[_GTK_WINDOW_TYPE]; - break; - case TOOL_TIP: - if (init_result = (NULL == gtk2_widgets[_GTK_TOOLTIP_TYPE])) - { - result = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL); - (*fp_gtk_widget_set_name)(result, "gtk-tooltips"); - gtk2_widgets[_GTK_TOOLTIP_TYPE] = result; - } - result = gtk2_widgets[_GTK_TOOLTIP_TYPE]; - break; - case LIST: - case TABLE: - case TREE: - case TREE_CELL: - if (init_result = (NULL == gtk2_widgets[_GTK_TREE_VIEW_TYPE])) - { - gtk2_widgets[_GTK_TREE_VIEW_TYPE] = - (*fp_gtk_tree_view_new)(); - } - result = gtk2_widgets[_GTK_TREE_VIEW_TYPE]; - break; - case TITLED_BORDER: - if (init_result = (NULL == gtk2_widgets[_GTK_FRAME_TYPE])) - { - gtk2_widgets[_GTK_FRAME_TYPE] = fp_gtk_frame_new(NULL); - } - result = gtk2_widgets[_GTK_FRAME_TYPE]; - break; - case POPUP_MENU: - if (init_result = (NULL == gtk2_widgets[_GTK_MENU_TYPE])) - { - gtk2_widgets[_GTK_MENU_TYPE] = - (*fp_gtk_menu_new)(); - } - result = gtk2_widgets[_GTK_MENU_TYPE]; - break; - case MENU: - case MENU_ITEM: - case MENU_ITEM_ACCELERATOR: - if (init_result = (NULL == gtk2_widgets[_GTK_MENU_ITEM_TYPE])) - { - gtk2_widgets[_GTK_MENU_ITEM_TYPE] = - (*fp_gtk_menu_item_new)(); - } - result = gtk2_widgets[_GTK_MENU_ITEM_TYPE]; - break; - case MENU_BAR: - if (init_result = (NULL == gtk2_widgets[_GTK_MENU_BAR_TYPE])) - { - gtk2_widgets[_GTK_MENU_BAR_TYPE] = - (*fp_gtk_menu_bar_new)(); - } - result = gtk2_widgets[_GTK_MENU_BAR_TYPE]; - break; - case COLOR_CHOOSER: - case OPTION_PANE: - if (init_result = (NULL == gtk2_widgets[_GTK_DIALOG_TYPE])) - { - gtk2_widgets[_GTK_DIALOG_TYPE] = - (*fp_gtk_dialog_new)(); - } - result = gtk2_widgets[_GTK_DIALOG_TYPE]; - break; - case POPUP_MENU_SEPARATOR: - if (init_result = - (NULL == gtk2_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE])) - { - gtk2_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE] = - (*fp_gtk_separator_menu_item_new)(); - } - result = gtk2_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE]; - break; - case HPROGRESS_BAR: - if (init_result = (NULL == gtk2_widgets[_GTK_HPROGRESS_BAR_TYPE])) - { - gtk2_widgets[_GTK_HPROGRESS_BAR_TYPE] = - (*fp_gtk_progress_bar_new)(); - } - result = gtk2_widgets[_GTK_HPROGRESS_BAR_TYPE]; - break; - case VPROGRESS_BAR: - if (init_result = (NULL == gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE])) - { - gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE] = - (*fp_gtk_progress_bar_new)(); - /* - * Vertical JProgressBars always go bottom-to-top, - * regardless of the ComponentOrientation. - */ - (*fp_gtk_progress_bar_set_orientation)( - (GtkProgressBar *)gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE], - GTK_PROGRESS_BOTTOM_TO_TOP); - } - result = gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE]; - break; - case RADIO_BUTTON: - if (init_result = (NULL == gtk2_widgets[_GTK_RADIO_BUTTON_TYPE])) - { - gtk2_widgets[_GTK_RADIO_BUTTON_TYPE] = - (*fp_gtk_radio_button_new)(NULL); - } - result = gtk2_widgets[_GTK_RADIO_BUTTON_TYPE]; - break; - case RADIO_BUTTON_MENU_ITEM: - if (init_result = - (NULL == gtk2_widgets[_GTK_RADIO_MENU_ITEM_TYPE])) - { - gtk2_widgets[_GTK_RADIO_MENU_ITEM_TYPE] = - (*fp_gtk_radio_menu_item_new)(NULL); - } - result = gtk2_widgets[_GTK_RADIO_MENU_ITEM_TYPE]; - break; - case SCROLL_PANE: - if (init_result = - (NULL == gtk2_widgets[_GTK_SCROLLED_WINDOW_TYPE])) - { - gtk2_widgets[_GTK_SCROLLED_WINDOW_TYPE] = - (*fp_gtk_scrolled_window_new)(NULL, NULL); - } - result = gtk2_widgets[_GTK_SCROLLED_WINDOW_TYPE]; - break; - case SPINNER: - case SPINNER_ARROW_BUTTON: - case SPINNER_TEXT_FIELD: - if (init_result = (NULL == gtk2_widgets[_GTK_SPIN_BUTTON_TYPE])) - { - result = gtk2_widgets[_GTK_SPIN_BUTTON_TYPE] = - (*fp_gtk_spin_button_new)(NULL, 0, 0); - } - result = gtk2_widgets[_GTK_SPIN_BUTTON_TYPE]; - break; - case TABBED_PANE: - case TABBED_PANE_TAB_AREA: - case TABBED_PANE_CONTENT: - case TABBED_PANE_TAB: - if (init_result = (NULL == gtk2_widgets[_GTK_NOTEBOOK_TYPE])) - { - gtk2_widgets[_GTK_NOTEBOOK_TYPE] = - (*fp_gtk_notebook_new)(); - } - result = gtk2_widgets[_GTK_NOTEBOOK_TYPE]; - break; - case TOGGLE_BUTTON: - if (init_result = (NULL == gtk2_widgets[_GTK_TOGGLE_BUTTON_TYPE])) - { - gtk2_widgets[_GTK_TOGGLE_BUTTON_TYPE] = - (*fp_gtk_toggle_button_new)(); - } - result = gtk2_widgets[_GTK_TOGGLE_BUTTON_TYPE]; - break; - case TOOL_BAR: - case TOOL_BAR_DRAG_WINDOW: - if (init_result = (NULL == gtk2_widgets[_GTK_TOOLBAR_TYPE])) - { - gtk2_widgets[_GTK_TOOLBAR_TYPE] = - (*fp_gtk_toolbar_new)(); - } - result = gtk2_widgets[_GTK_TOOLBAR_TYPE]; - break; - case TOOL_BAR_SEPARATOR: - if (init_result = - (NULL == gtk2_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE])) - { - gtk2_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE] = - (*fp_gtk_separator_tool_item_new)(); - } - result = gtk2_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE]; - break; - case VIEWPORT: - if (init_result = (NULL == gtk2_widgets[_GTK_VIEWPORT_TYPE])) - { - GtkAdjustment *adjustment = create_adjustment(); - gtk2_widgets[_GTK_VIEWPORT_TYPE] = - (*fp_gtk_viewport_new)(adjustment, adjustment); - } - result = gtk2_widgets[_GTK_VIEWPORT_TYPE]; - break; - case VSCROLL_BAR: - case VSCROLL_BAR_BUTTON_UP: - case VSCROLL_BAR_BUTTON_DOWN: - case VSCROLL_BAR_TRACK: - case VSCROLL_BAR_THUMB: - if (init_result = (NULL == gtk2_widgets[_GTK_VSCROLLBAR_TYPE])) - { - gtk2_widgets[_GTK_VSCROLLBAR_TYPE] = - (*fp_gtk_vscrollbar_new)(create_adjustment()); - } - result = gtk2_widgets[_GTK_VSCROLLBAR_TYPE]; - break; - case VSEPARATOR: - if (init_result = (NULL == gtk2_widgets[_GTK_VSEPARATOR_TYPE])) - { - gtk2_widgets[_GTK_VSEPARATOR_TYPE] = - (*fp_gtk_vseparator_new)(); - } - result = gtk2_widgets[_GTK_VSEPARATOR_TYPE]; - break; - case VSLIDER: - case VSLIDER_THUMB: - case VSLIDER_TRACK: - if (init_result = (NULL == gtk2_widgets[_GTK_VSCALE_TYPE])) - { - gtk2_widgets[_GTK_VSCALE_TYPE] = - (*fp_gtk_vscale_new)(NULL); - } - result = gtk2_widgets[_GTK_VSCALE_TYPE]; - /* - * Vertical JSliders start at the bottom, while vertical - * GtkVScale widgets start at the top (by default), so to fix - * this we set the "inverted" flag to get the Swing behavior. - */ - ((GtkRange*)result)->inverted = 1; - break; - case VSPLIT_PANE_DIVIDER: - if (init_result = (NULL == gtk2_widgets[_GTK_VPANED_TYPE])) - { - gtk2_widgets[_GTK_VPANED_TYPE] = (*fp_gtk_vpaned_new)(); - } - result = gtk2_widgets[_GTK_VPANED_TYPE]; - break; - default: - result = NULL; - break; - } - - if (result != NULL && init_result) - { - if (widget_type == RADIO_BUTTON_MENU_ITEM || - widget_type == CHECK_BOX_MENU_ITEM || - widget_type == MENU_ITEM || - widget_type == MENU || - widget_type == POPUP_MENU_SEPARATOR) - { - GtkWidget *menu = gtk2_get_widget(POPUP_MENU); - (*fp_gtk_menu_shell_append)((GtkMenuShell *)menu, result); - } - else if (widget_type == POPUP_MENU) - { - GtkWidget *menu_bar = gtk2_get_widget(MENU_BAR); - GtkWidget *root_menu = (*fp_gtk_menu_item_new)(); - (*fp_gtk_menu_item_set_submenu)((GtkMenuItem*)root_menu, result); - (*fp_gtk_menu_shell_append)((GtkMenuShell *)menu_bar, root_menu); - } - else if (widget_type == COMBO_BOX_ARROW_BUTTON || - widget_type == COMBO_BOX_TEXT_FIELD) - { - /* - * We add a regular GtkButton/GtkEntry to a GtkComboBoxEntry - * in order to trick engines into thinking it's a real combobox - * arrow button/text field. - */ - GtkWidget *combo = (*fp_gtk_combo_box_entry_new)(); - - if (new_combo && widget_type == COMBO_BOX_ARROW_BUTTON) { - (*fp_gtk_widget_set_parent)(result, combo); - ((GtkBin*)combo)->child = result; - } else { - (*fp_gtk_container_add)((GtkContainer *)combo, result); - } - (*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, combo); - } - else if (widget_type != TOOL_TIP && - widget_type != INTERNAL_FRAME && - widget_type != OPTION_PANE) - { - (*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, result); - } - (*fp_gtk_widget_realize)(result); - } - return result; -} - -void gtk2_paint_arrow(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, - GtkArrowType arrow_type, gboolean fill) -{ - static int w, h; - static GtkRequisition size; - - if (widget_type == COMBO_BOX_ARROW_BUTTON || widget_type == TABLE) - gtk2_widget = gtk2_get_arrow(arrow_type, shadow_type); - else - gtk2_widget = gtk2_get_widget(widget_type); - - switch (widget_type) - { - case SPINNER_ARROW_BUTTON: - x = 1; - y = ((arrow_type == GTK_ARROW_UP) ? 2 : 0); - height -= 2; - width -= 3; - - w = width / 2; - w -= w % 2 - 1; - h = (w + 1) / 2; - break; - - case HSCROLL_BAR_BUTTON_LEFT: - case HSCROLL_BAR_BUTTON_RIGHT: - case VSCROLL_BAR_BUTTON_UP: - case VSCROLL_BAR_BUTTON_DOWN: - w = width / 2; - h = height / 2; - break; - - case COMBO_BOX_ARROW_BUTTON: - case TABLE: - x = 1; - (*fp_gtk_widget_size_request)(gtk2_widget, &size); - w = size.width - ((GtkMisc*)gtk2_widget)->xpad * 2; - h = size.height - ((GtkMisc*)gtk2_widget)->ypad * 2; - w = h = MIN(MIN(w, h), MIN(width,height)) * 0.7; - break; - - default: - w = width; - h = height; - break; - } - x += (width - w) / 2; - y += (height - h) / 2; - - (*fp_gtk_paint_arrow)(gtk2_widget->style, gtk2_white_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, arrow_type, fill, - x, y, w, h); - (*fp_gtk_paint_arrow)(gtk2_widget->style, gtk2_black_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, arrow_type, fill, - x, y, w, h); -} - -static void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, - gint synth_state, GtkTextDirection dir) -{ - gtk2_widget = gtk2_get_widget(widget_type); - - /* - * The clearlooks engine sometimes looks at the widget's state field - * instead of just the state_type variable that we pass in, so to account - * for those cases we set the widget's state field accordingly. The - * flags field is similarly important for things like focus/default state. - */ - gtk2_widget->state = state_type; - - if (widget_type == HSLIDER_TRACK) { - /* - * For horizontal JSliders with right-to-left orientation, we need - * to set the "inverted" flag to match the native GTK behavior where - * the foreground highlight is on the right side of the slider thumb. - * This is needed especially for the ubuntulooks engine, which looks - * exclusively at the "inverted" flag to determine on which side of - * the thumb to paint the highlight... - */ - ((GtkRange*)gtk2_widget)->inverted = (dir == GTK_TEXT_DIR_RTL); - - /* - * Note however that other engines like clearlooks will look at both - * the "inverted" field and the text direction to determine how - * the foreground highlight is painted: - * !inverted && ltr --> paint highlight on left side - * !inverted && rtl --> paint highlight on right side - * inverted && ltr --> paint highlight on right side - * inverted && rtl --> paint highlight on left side - * So the only way to reliably get the desired results for horizontal - * JSlider (i.e., highlight on left side for LTR ComponentOrientation - * and highlight on right side for RTL ComponentOrientation) is to - * always override text direction as LTR, and then set the "inverted" - * flag accordingly (as we have done above). - */ - dir = GTK_TEXT_DIR_LTR; - } - - /* - * Some engines (e.g. clearlooks) will paint the shadow of certain - * widgets (e.g. COMBO_BOX_ARROW_BUTTON) differently depending on the - * the text direction. - */ - gtk2_set_direction(gtk2_widget, dir); - - switch (widget_type) { - case BUTTON: - if (synth_state & DEFAULT) { - ((GtkObject*)gtk2_widget)->flags |= GTK_HAS_DEFAULT; - } else { - ((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_DEFAULT; - } - break; - case TOGGLE_BUTTON: - init_toggle_widget(widget_type, synth_state); - break; - case HSCROLL_BAR_BUTTON_LEFT: - /* - * The clearlooks engine will draw a "left" button when: - * x == w->allocation.x - * - * The ubuntulooks engine will draw a "left" button when: - * [x,y,width,height] - * intersects - * [w->alloc.x,w->alloc.y,width,height] - * - * The values that are set below should ensure that a "left" - * button is rendered for both of these (and other) engines. - */ - gtk2_widget->allocation.x = x; - gtk2_widget->allocation.y = y; - gtk2_widget->allocation.width = width; - gtk2_widget->allocation.height = height; - break; - case HSCROLL_BAR_BUTTON_RIGHT: - /* - * The clearlooks engine will draw a "right" button when: - * x + width == w->allocation.x + w->allocation.width - * - * The ubuntulooks engine will draw a "right" button when: - * [x,y,width,height] - * does not intersect - * [w->alloc.x,w->alloc.y,width,height] - * but does intersect - * [w->alloc.x+width,w->alloc.y,width,height] - * - * The values that are set below should ensure that a "right" - * button is rendered for both of these (and other) engines. - */ - gtk2_widget->allocation.x = x+width; - gtk2_widget->allocation.y = 0; - gtk2_widget->allocation.width = 0; - gtk2_widget->allocation.height = height; - break; - case VSCROLL_BAR_BUTTON_UP: - /* - * The clearlooks engine will draw an "up" button when: - * y == w->allocation.y - * - * The ubuntulooks engine will draw an "up" button when: - * [x,y,width,height] - * intersects - * [w->alloc.x,w->alloc.y,width,height] - * - * The values that are set below should ensure that an "up" - * button is rendered for both of these (and other) engines. - */ - gtk2_widget->allocation.x = x; - gtk2_widget->allocation.y = y; - gtk2_widget->allocation.width = width; - gtk2_widget->allocation.height = height; - break; - case VSCROLL_BAR_BUTTON_DOWN: - /* - * The clearlooks engine will draw a "down" button when: - * y + height == w->allocation.y + w->allocation.height - * - * The ubuntulooks engine will draw a "down" button when: - * [x,y,width,height] - * does not intersect - * [w->alloc.x,w->alloc.y,width,height] - * but does intersect - * [w->alloc.x,w->alloc.y+height,width,height] - * - * The values that are set below should ensure that a "down" - * button is rendered for both of these (and other) engines. - */ - gtk2_widget->allocation.x = x; - gtk2_widget->allocation.y = y+height; - gtk2_widget->allocation.width = width; - gtk2_widget->allocation.height = 0; - break; - default: - break; - } - - (*fp_gtk_paint_box)(gtk2_widget->style, gtk2_white_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, x, y, width, height); - (*fp_gtk_paint_box)(gtk2_widget->style, gtk2_black_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, x, y, width, height); - - /* - * Reset the text direction to the default value so that we don't - * accidentally affect other operations and widgets. - */ - gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR); -} - -void gtk2_paint_box_gap(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, - GtkPositionType gap_side, gint gap_x, gint gap_width) -{ - /* Clearlooks needs a real clip area to paint the gap properly */ - GdkRectangle area = { x, y, width, height }; - - gtk2_widget = gtk2_get_widget(widget_type); - (*fp_gtk_paint_box_gap)(gtk2_widget->style, gtk2_white_pixmap, state_type, - shadow_type, &area, gtk2_widget, detail, - x, y, width, height, gap_side, gap_x, gap_width); - (*fp_gtk_paint_box_gap)(gtk2_widget->style, gtk2_black_pixmap, state_type, - shadow_type, &area, gtk2_widget, detail, - x, y, width, height, gap_side, gap_x, gap_width); -} - -static void gtk2_paint_check(WidgetType widget_type, gint synth_state, - const gchar *detail, gint x, gint y, gint width, gint height) -{ - GtkStateType state_type = get_gtk_state_type(widget_type, synth_state); - GtkShadowType shadow_type = get_gtk_shadow_type(widget_type, synth_state); - - gtk2_widget = gtk2_get_widget(widget_type); - init_toggle_widget(widget_type, synth_state); - - (*fp_gtk_paint_check)(gtk2_widget->style, gtk2_white_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, - x, y, width, height); - (*fp_gtk_paint_check)(gtk2_widget->style, gtk2_black_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, - x, y, width, height); -} - -static void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type, - const gchar *detail, gint x, gint y, gint width, gint height, - GtkExpanderStyle expander_style) -{ - gtk2_widget = gtk2_get_widget(widget_type); - (*fp_gtk_paint_expander)(gtk2_widget->style, gtk2_white_pixmap, - state_type, NULL, gtk2_widget, detail, - x + width / 2, y + height / 2, expander_style); - (*fp_gtk_paint_expander)(gtk2_widget->style, gtk2_black_pixmap, - state_type, NULL, gtk2_widget, detail, - x + width / 2, y + height / 2, expander_style); -} - -static void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, GtkPositionType gap_side) -{ - gtk2_widget = gtk2_get_widget(widget_type); - (*fp_gtk_paint_extension)(gtk2_widget->style, gtk2_white_pixmap, - state_type, shadow_type, NULL, gtk2_widget, detail, - x, y, width, height, gap_side); - (*fp_gtk_paint_extension)(gtk2_widget->style, gtk2_black_pixmap, - state_type, shadow_type, NULL, gtk2_widget, detail, - x, y, width, height, gap_side); -} - -static void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, gboolean has_focus) -{ - gtk2_widget = gtk2_get_widget(widget_type); - - if (has_focus) - ((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS; - else - ((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS; - - (*fp_gtk_paint_flat_box)(gtk2_widget->style, gtk2_white_pixmap, - state_type, shadow_type, NULL, gtk2_widget, detail, - x, y, width, height); - (*fp_gtk_paint_flat_box)(gtk2_widget->style, gtk2_black_pixmap, - state_type, shadow_type, NULL, gtk2_widget, detail, - x, y, width, height); -} - -static void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type, - const char *detail, gint x, gint y, gint width, gint height) -{ - gtk2_widget = gtk2_get_widget(widget_type); - (*fp_gtk_paint_focus)(gtk2_widget->style, gtk2_white_pixmap, state_type, - NULL, gtk2_widget, detail, x, y, width, height); - (*fp_gtk_paint_focus)(gtk2_widget->style, gtk2_black_pixmap, state_type, - NULL, gtk2_widget, detail, x, y, width, height); -} - -static void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, GtkOrientation orientation) -{ - gtk2_widget = gtk2_get_widget(widget_type); - (*fp_gtk_paint_handle)(gtk2_widget->style, gtk2_white_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, - x, y, width, height, orientation); - (*fp_gtk_paint_handle)(gtk2_widget->style, gtk2_black_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, - x, y, width, height, orientation); -} - -static void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type, - const gchar *detail, gint x, gint y, gint width, gint height) -{ - gtk2_widget = gtk2_get_widget(widget_type); - (*fp_gtk_paint_hline)(gtk2_widget->style, gtk2_white_pixmap, state_type, - NULL, gtk2_widget, detail, x, x + width, y); - (*fp_gtk_paint_hline)(gtk2_widget->style, gtk2_black_pixmap, state_type, - NULL, gtk2_widget, detail, x, x + width, y); -} - -static void gtk2_paint_option(WidgetType widget_type, gint synth_state, - const gchar *detail, gint x, gint y, gint width, gint height) -{ - GtkStateType state_type = get_gtk_state_type(widget_type, synth_state); - GtkShadowType shadow_type = get_gtk_shadow_type(widget_type, synth_state); - - gtk2_widget = gtk2_get_widget(widget_type); - init_toggle_widget(widget_type, synth_state); - - (*fp_gtk_paint_option)(gtk2_widget->style, gtk2_white_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, - x, y, width, height); - (*fp_gtk_paint_option)(gtk2_widget->style, gtk2_black_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, - x, y, width, height); -} - -static void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, - gint synth_state, GtkTextDirection dir) -{ - gtk2_widget = gtk2_get_widget(widget_type); - - /* - * The clearlooks engine sometimes looks at the widget's state field - * instead of just the state_type variable that we pass in, so to account - * for those cases we set the widget's state field accordingly. The - * flags field is similarly important for things like focus state. - */ - gtk2_widget->state = state_type; - - /* - * Some engines (e.g. clearlooks) will paint the shadow of certain - * widgets (e.g. COMBO_BOX_TEXT_FIELD) differently depending on the - * the text direction. - */ - gtk2_set_direction(gtk2_widget, dir); - - switch (widget_type) { - case COMBO_BOX_TEXT_FIELD: - case FORMATTED_TEXT_FIELD: - case PASSWORD_FIELD: - case SPINNER_TEXT_FIELD: - case TEXT_FIELD: - if (synth_state & FOCUSED) { - ((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS; - } else { - ((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS; - } - break; - default: - break; - } - - (*fp_gtk_paint_shadow)(gtk2_widget->style, gtk2_white_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, x, y, width, height); - (*fp_gtk_paint_shadow)(gtk2_widget->style, gtk2_black_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, x, y, width, height); - - /* - * Reset the text direction to the default value so that we don't - * accidentally affect other operations and widgets. - */ - gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR); -} - -static void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, GtkOrientation orientation, - gboolean has_focus) -{ - gtk2_widget = gtk2_get_widget(widget_type); - (*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_white_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, - x, y, width, height, orientation); - (*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_black_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, - x, y, width, height, orientation); -} - -static void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type, - const gchar *detail, gint x, gint y, gint width, gint height) -{ - gtk2_widget = gtk2_get_widget(widget_type); - (*fp_gtk_paint_vline)(gtk2_widget->style, gtk2_white_pixmap, state_type, - NULL, gtk2_widget, detail, y, y + height, x); - (*fp_gtk_paint_vline)(gtk2_widget->style, gtk2_black_pixmap, state_type, - NULL, gtk2_widget, detail, y, y + height, x); -} - -static void gtk_paint_background(WidgetType widget_type, GtkStateType state_type, - gint x, gint y, gint width, gint height) -{ - gtk2_widget = gtk2_get_widget(widget_type); - (*fp_gtk_style_apply_default_background)(gtk2_widget->style, - gtk2_white_pixmap, TRUE, state_type, NULL, x, y, width, height); - (*fp_gtk_style_apply_default_background)(gtk2_widget->style, - gtk2_black_pixmap, TRUE, state_type, NULL, x, y, width, height); -} - -static GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id, - GtkIconSize size, GtkTextDirection direction, const char *detail) -{ - init_containers(); - gtk2_widget = gtk2_get_widget((widget_type < 0) ? IMAGE : widget_type); - gtk2_widget->state = GTK_STATE_NORMAL; - (*fp_gtk_widget_set_direction)(gtk2_widget, direction); - return (*fp_gtk_widget_render_icon)(gtk2_widget, stock_id, size, detail); -} - -static jboolean gtk2_get_pixbuf_data(JNIEnv *env, GdkPixbuf* pixbuf, - jmethodID icon_upcall_method, jobject this) { - if (!pixbuf) { - return JNI_FALSE; - } - guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf); - if (pixbuf_data) { - int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf); - int width = (*fp_gdk_pixbuf_get_width)(pixbuf); - int height = (*fp_gdk_pixbuf_get_height)(pixbuf); - int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf); - int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf); - gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf); - - jbyteArray data = (*env)->NewByteArray(env, (row_stride * height)); - JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); - - (*env)->SetByteArrayRegion(env, data, 0, (row_stride * height), - (jbyte *)pixbuf_data); - (*fp_g_object_unref)(pixbuf); - - /* Call the callback method to create the image on the Java side. */ - (*env)->CallVoidMethod(env, this, icon_upcall_method, data, - width, height, row_stride, bps, channels, alpha); - return JNI_TRUE; - } - return JNI_FALSE; -} - -static jboolean gtk2_get_file_icon_data(JNIEnv *env, const char *filename, - GError **error, jmethodID icon_upcall_method, jobject this) { - GdkPixbuf* pixbuf = fp_gdk_pixbuf_new_from_file(filename, error); - return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this); -} - -static jboolean gtk2_get_icon_data(JNIEnv *env, gint widget_type, - const gchar *stock_id, GtkIconSize size, - GtkTextDirection direction, const char *detail, - jmethodID icon_upcall_method, jobject this) { - GdkPixbuf* pixbuf = gtk2_get_stock_icon(widget_type, stock_id, size, - direction, detail); - return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this); -} - -/*************************************************/ -static gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type) -{ - init_containers(); - - gtk2_widget = gtk2_get_widget(widget_type); - GtkStyle* style = gtk2_widget->style; - return style->xthickness; -} - -static gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type) -{ - init_containers(); - - gtk2_widget = gtk2_get_widget(widget_type); - GtkStyle* style = gtk2_widget->style; - return style->ythickness; -} - -/*************************************************/ -static guint8 recode_color(guint16 channel) -{ - return (guint8)(channel>>8); -} - -static gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type, - GtkStateType state_type, ColorType color_type) -{ - gint result = 0; - GdkColor *color = NULL; - - init_containers(); - - gtk2_widget = gtk2_get_widget(widget_type); - GtkStyle* style = gtk2_widget->style; - - switch (color_type) - { - case FOREGROUND: - color = &(style->fg[state_type]); - break; - case BACKGROUND: - color = &(style->bg[state_type]); - break; - case TEXT_FOREGROUND: - color = &(style->text[state_type]); - break; - case TEXT_BACKGROUND: - color = &(style->base[state_type]); - break; - case LIGHT: - color = &(style->light[state_type]); - break; - case DARK: - color = &(style->dark[state_type]); - break; - case MID: - color = &(style->mid[state_type]); - break; - case FOCUS: - case BLACK: - color = &(style->black); - break; - case WHITE: - color = &(style->white); - break; - } - - if (color) - result = recode_color(color->red) << 16 | - recode_color(color->green) << 8 | - recode_color(color->blue); - - return result; -} - -/*************************************************/ -static jobject create_Boolean(JNIEnv *env, jboolean boolean_value); -static jobject create_Integer(JNIEnv *env, jint int_value); -static jobject create_Long(JNIEnv *env, jlong long_value); -static jobject create_Float(JNIEnv *env, jfloat float_value); -static jobject create_Double(JNIEnv *env, jdouble double_value); -static jobject create_Character(JNIEnv *env, jchar char_value); -static jobject create_Insets(JNIEnv *env, GtkBorder *border); - -static jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type, - const char* key) -{ - init_containers(); - - gtk2_widget = gtk2_get_widget(widget_type); - - GValue value; - value.g_type = 0; - - GParamSpec* param = (*fp_gtk_widget_class_find_style_property)( - ((GTypeInstance*)gtk2_widget)->g_class, key); - if( param ) - { - (*fp_g_value_init)( &value, param->value_type ); - (*fp_gtk_widget_style_get_property)(gtk2_widget, key, &value); - - if( (*fp_g_type_is_a)( param->value_type, G_TYPE_BOOLEAN )) - { - gboolean val = (*fp_g_value_get_boolean)(&value); - return create_Boolean(env, (jboolean)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_CHAR )) - { - gchar val = (*fp_g_value_get_char)(&value); - return create_Character(env, (jchar)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_UCHAR )) - { - guchar val = (*fp_g_value_get_uchar)(&value); - return create_Character(env, (jchar)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_INT )) - { - gint val = (*fp_g_value_get_int)(&value); - return create_Integer(env, (jint)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_UINT )) - { - guint val = (*fp_g_value_get_uint)(&value); - return create_Integer(env, (jint)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_LONG )) - { - glong val = (*fp_g_value_get_long)(&value); - return create_Long(env, (jlong)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_ULONG )) - { - gulong val = (*fp_g_value_get_ulong)(&value); - return create_Long(env, (jlong)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_INT64 )) - { - gint64 val = (*fp_g_value_get_int64)(&value); - return create_Long(env, (jlong)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_UINT64 )) - { - guint64 val = (*fp_g_value_get_uint64)(&value); - return create_Long(env, (jlong)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_FLOAT )) - { - gfloat val = (*fp_g_value_get_float)(&value); - return create_Float(env, (jfloat)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_DOUBLE )) - { - gdouble val = (*fp_g_value_get_double)(&value); - return create_Double(env, (jdouble)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_ENUM )) - { - gint val = (*fp_g_value_get_enum)(&value); - return create_Integer(env, (jint)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_FLAGS )) - { - guint val = (*fp_g_value_get_flags)(&value); - return create_Integer(env, (jint)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_STRING )) - { - const gchar* val = (*fp_g_value_get_string)(&value); - - /* We suppose that all values come in C locale and - * utf-8 representation of a string is the same as - * the string itself. If this isn't so we should - * use g_convert. - */ - return (*env)->NewStringUTF(env, val); - } - else if( (*fp_g_type_is_a)( param->value_type, GTK_TYPE_BORDER )) - { - GtkBorder *border = (GtkBorder*)(*fp_g_value_get_boxed)(&value); - return border ? create_Insets(env, border) : NULL; - } - - /* TODO: Other types are not supported yet.*/ -/* else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_PARAM )) - { - GParamSpec* val = (*fp_g_value_get_param)(&value); - printf( "Param: %p\n", val ); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_BOXED )) - { - gpointer* val = (*fp_g_value_get_boxed)(&value); - printf( "Boxed: %p\n", val ); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_POINTER )) - { - gpointer* val = (*fp_g_value_get_pointer)(&value); - printf( "Pointer: %p\n", val ); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_OBJECT )) - { - GObject* val = (GObject*)(*fp_g_value_get_object)(&value); - printf( "Object: %p\n", val ); - }*/ - } - - return NULL; -} - -static void gtk2_set_range_value(WidgetType widget_type, jdouble value, - jdouble min, jdouble max, jdouble visible) -{ - GtkAdjustment *adj; - - gtk2_widget = gtk2_get_widget(widget_type); - - adj = (*fp_gtk_range_get_adjustment)((GtkRange *)gtk2_widget); - adj->value = (gdouble)value; - adj->lower = (gdouble)min; - adj->upper = (gdouble)max; - adj->page_size = (gdouble)visible; -} - -/*************************************************/ -static jobject create_Object(JNIEnv *env, jmethodID *cid, - const char* class_name, - const char* signature, - jvalue* value) -{ - jclass class; - jobject result; - - class = (*env)->FindClass(env, class_name); - if( class == NULL ) - return NULL; /* can't find/load the class, exception thrown */ - - if( *cid == NULL) - { - *cid = (*env)->GetMethodID(env, class, "", signature); - if( *cid == NULL ) - { - (*env)->DeleteLocalRef(env, class); - return NULL; /* can't find/get the method, exception thrown */ - } - } - - result = (*env)->NewObjectA(env, class, *cid, value); - - (*env)->DeleteLocalRef(env, class); - return result; -} - -jobject create_Boolean(JNIEnv *env, jboolean boolean_value) -{ - static jmethodID cid = NULL; - jvalue value; - - value.z = boolean_value; - - return create_Object(env, &cid, "java/lang/Boolean", "(Z)V", &value); -} - -jobject create_Integer(JNIEnv *env, jint int_value) -{ - static jmethodID cid = NULL; - jvalue value; - - value.i = int_value; - - return create_Object(env, &cid, "java/lang/Integer", "(I)V", &value); -} - -jobject create_Long(JNIEnv *env, jlong long_value) -{ - static jmethodID cid = NULL; - jvalue value; - - value.j = long_value; - - return create_Object(env, &cid, "java/lang/Long", "(J)V", &value); -} - -jobject create_Float(JNIEnv *env, jfloat float_value) -{ - static jmethodID cid = NULL; - jvalue value; - - value.f = float_value; - - return create_Object(env, &cid, "java/lang/Float", "(F)V", &value); -} - -jobject create_Double(JNIEnv *env, jdouble double_value) -{ - static jmethodID cid = NULL; - jvalue value; - - value.d = double_value; - - return create_Object(env, &cid, "java/lang/Double", "(D)V", &value); -} - -jobject create_Character(JNIEnv *env, jchar char_value) -{ - static jmethodID cid = NULL; - jvalue value; - - value.c = char_value; - - return create_Object(env, &cid, "java/lang/Character", "(C)V", &value); -} - - -jobject create_Insets(JNIEnv *env, GtkBorder *border) -{ - static jmethodID cid = NULL; - jvalue values[4]; - - values[0].i = border->top; - values[1].i = border->left; - values[2].i = border->bottom; - values[3].i = border->right; - - return create_Object(env, &cid, "java/awt/Insets", "(IIII)V", values); -} - -/*********************************************/ -static jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type) -{ - init_containers(); - - gtk2_widget = gtk2_get_widget(widget_type); - jstring result = NULL; - GtkStyle* style = gtk2_widget->style; - - if (style && style->font_desc) - { - gchar* val = (*fp_pango_font_description_to_string)(style->font_desc); - result = (*env)->NewStringUTF(env, val); - (*fp_g_free)( val ); - } - - return result; -} - -/***********************************************/ -static jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gchar* key) -{ - jobject result = NULL; - gchar* strval = NULL; - - (*fp_g_object_get)(settings, key, &strval, NULL); - result = (*env)->NewStringUTF(env, strval); - (*fp_g_free)(strval); - - return result; -} - -static jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key) -{ - gint intval = 0; - (*fp_g_object_get)(settings, key, &intval, NULL); - return create_Integer(env, intval); -} - -static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key) -{ - gint intval = 0; - (*fp_g_object_get)(settings, key, &intval, NULL); - return create_Boolean(env, intval); -} - -static jobject gtk2_get_setting(JNIEnv *env, Setting property) -{ - GtkSettings* settings = (*fp_gtk_settings_get_default)(); - - switch (property) - { - case GTK_FONT_NAME: - return get_string_property(env, settings, "gtk-font-name"); - case GTK_ICON_SIZES: - return get_string_property(env, settings, "gtk-icon-sizes"); - case GTK_CURSOR_BLINK: - return get_boolean_property(env, settings, "gtk-cursor-blink"); - case GTK_CURSOR_BLINK_TIME: - return get_integer_property(env, settings, "gtk-cursor-blink-time"); - } - - return NULL; -} - -static gboolean gtk2_get_drawable_data(JNIEnv *env, jintArray pixelArray, jint x, - jint y, jint width, jint height, jint jwidth, int dx, int dy) { - GdkPixbuf *pixbuf; - jint *ary; - - GdkWindow *root = (*fp_gdk_get_default_root_window)(); - - pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(NULL, root, NULL, x, y, - 0, 0, width, height); - - if (pixbuf) { - int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf); - int stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf); - - if ((*fp_gdk_pixbuf_get_width)(pixbuf) == width - && (*fp_gdk_pixbuf_get_height)(pixbuf) == height - && (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf) == 8 - && (*fp_gdk_pixbuf_get_colorspace)(pixbuf) == GDK_COLORSPACE_RGB - && nchan >= 3 - ) { - guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf); - - ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL); - if (ary) { - jint _x, _y; - int index; - for (_y = 0; _y < height; _y++) { - for (_x = 0; _x < width; _x++) { - p = pix + (intptr_t) _y * stride + _x * nchan; - - index = (_y + dy) * jwidth + (_x + dx); - ary[index] = 0xff000000 - | (p[0] << 16) - | (p[1] << 8) - | (p[2]); - - } - } - (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0); - } - } - (*fp_g_object_unref)(pixbuf); - } - return JNI_FALSE; -} - -static GdkWindow* gtk2_get_window(void *widget) { - return ((GtkWidget*)widget)->window; -} - -void gtk2_init(GtkApi* gtk) { - gtk->version = GTK_2; - - gtk->show_uri_load = >k2_show_uri_load; - gtk->unload = >k2_unload; - gtk->flush_event_loop = &flush_gtk_event_loop; - gtk->gtk_check_version = fp_gtk_check_version; - gtk->get_setting = >k2_get_setting; - - gtk->paint_arrow = >k2_paint_arrow; - gtk->paint_box = >k2_paint_box; - gtk->paint_box_gap = >k2_paint_box_gap; - gtk->paint_expander = >k2_paint_expander; - gtk->paint_extension = >k2_paint_extension; - gtk->paint_flat_box = >k2_paint_flat_box; - gtk->paint_focus = >k2_paint_focus; - gtk->paint_handle = >k2_paint_handle; - gtk->paint_hline = >k2_paint_hline; - gtk->paint_vline = >k2_paint_vline; - gtk->paint_option = >k2_paint_option; - gtk->paint_shadow = >k2_paint_shadow; - gtk->paint_slider = >k2_paint_slider; - gtk->paint_background = >k_paint_background; - gtk->paint_check = >k2_paint_check; - gtk->set_range_value = >k2_set_range_value; - - gtk->init_painting = >k2_init_painting; - gtk->copy_image = >k2_copy_image; - - gtk->get_xthickness = >k2_get_xthickness; - gtk->get_ythickness = >k2_get_ythickness; - gtk->get_color_for_state = >k2_get_color_for_state; - gtk->get_class_value = >k2_get_class_value; - - gtk->get_pango_font_name = >k2_get_pango_font_name; - gtk->get_icon_data = >k2_get_icon_data; - gtk->get_file_icon_data = >k2_get_file_icon_data; - gtk->gdk_threads_enter = fp_gdk_threads_enter; - gtk->gdk_threads_leave = fp_gdk_threads_leave; - gtk->gtk_show_uri = fp_gtk_show_uri; - gtk->get_drawable_data = >k2_get_drawable_data; - gtk->g_free = fp_g_free; - - gtk->gtk_file_chooser_get_filename = fp_gtk_file_chooser_get_filename; - gtk->gtk_widget_hide = fp_gtk_widget_hide; - gtk->gtk_main_quit = fp_gtk_main_quit; - gtk->gtk_file_chooser_dialog_new = fp_gtk_file_chooser_dialog_new; - gtk->gtk_file_chooser_set_current_folder = - fp_gtk_file_chooser_set_current_folder; - gtk->gtk_file_chooser_set_filename = fp_gtk_file_chooser_set_filename; - gtk->gtk_file_chooser_set_current_name = - fp_gtk_file_chooser_set_current_name; - gtk->gtk_file_filter_add_custom = fp_gtk_file_filter_add_custom; - gtk->gtk_file_chooser_set_filter = fp_gtk_file_chooser_set_filter; - gtk->gtk_file_chooser_get_type = fp_gtk_file_chooser_get_type; - gtk->gtk_file_filter_new = fp_gtk_file_filter_new; - gtk->gtk_file_chooser_set_do_overwrite_confirmation = - fp_gtk_file_chooser_set_do_overwrite_confirmation; - gtk->gtk_file_chooser_set_select_multiple = - fp_gtk_file_chooser_set_select_multiple; - gtk->gtk_file_chooser_get_current_folder = - fp_gtk_file_chooser_get_current_folder; - gtk->gtk_file_chooser_get_filenames = fp_gtk_file_chooser_get_filenames; - gtk->gtk_g_slist_length = fp_gtk_g_slist_length; - gtk->g_signal_connect_data = fp_g_signal_connect_data; - gtk->gtk_widget_show = fp_gtk_widget_show; - gtk->gtk_main = fp_gtk_main; - gtk->gtk_main_level = fp_gtk_main_level; - gtk->g_path_get_dirname = fp_g_path_get_dirname; - gtk->gdk_x11_drawable_get_xid = fp_gdk_x11_drawable_get_xid; - gtk->gtk_widget_destroy = fp_gtk_widget_destroy; - gtk->gtk_window_present = fp_gtk_window_present; - gtk->gtk_window_move = fp_gtk_window_move; - gtk->gtk_window_resize = fp_gtk_window_resize; - gtk->get_window = >k2_get_window; - - gtk->g_object_unref = fp_g_object_unref; - gtk->g_list_append = fp_g_list_append; - gtk->g_list_free = fp_g_list_free; - gtk->g_list_free_full = fp_g_list_free_full; -} diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h b/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h deleted file mode 100644 index 8075d4f419fad..0000000000000 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright (c) 2005, 2024, 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. - */ - -#ifdef HEADLESS - #error This file should not be included in headless library -#endif - -#ifndef _GTK2_INTERFACE_H -#define _GTK2_INTERFACE_H - -#include -#include -#include -#include "gtk_interface.h" - -#define GTK_HAS_FOCUS (1 << 12) -#define GTK_HAS_DEFAULT (1 << 14) - -typedef enum -{ - GTK_WINDOW_TOPLEVEL, - GTK_WINDOW_POPUP -} GtkWindowType; - -typedef enum -{ - G_PARAM_READABLE = 1 << 0, - G_PARAM_WRITABLE = 1 << 1, - G_PARAM_CONSTRUCT = 1 << 2, - G_PARAM_CONSTRUCT_ONLY = 1 << 3, - G_PARAM_LAX_VALIDATION = 1 << 4, - G_PARAM_PRIVATE = 1 << 5 -} GParamFlags; - -/* We define all structure pointers to be void* */ -typedef void GVfs; - -typedef void GdkColormap; -typedef void GdkDrawable; -typedef void GdkGC; -typedef void GdkPixmap; - -typedef void GtkFixed; -typedef void GtkMenuItem; -typedef void GtkMenuShell; -typedef void GtkWidgetClass; -typedef void PangoFontDescription; -typedef void GtkSettings; - -/* Some real structures */ -typedef struct -{ - guint32 pixel; - guint16 red; - guint16 green; - guint16 blue; -} GdkColor; - -typedef struct { - gint fd; - gushort events; - gushort revents; -} GPollFD; - -typedef struct { - gint x; - gint y; - gint width; - gint height; -} GtkAllocation; - -typedef struct { - gint width; - gint height; -} GtkRequisition; - -typedef struct { - GtkWidgetClass *g_class; -} GTypeInstance; - -typedef struct { - gint left; - gint right; - gint top; - gint bottom; -} GtkBorder; - -/****************************************************** - * FIXME: it is more safe to include gtk headers for - * the precise type definition of GType and other - * structures. This is a place where getting rid of gtk - * headers may be dangerous. - ******************************************************/ - -typedef struct -{ - GType g_type; - - union { - gint v_int; - guint v_uint; - glong v_long; - gulong v_ulong; - gint64 v_int64; - guint64 v_uint64; - gfloat v_float; - gdouble v_double; - gpointer v_pointer; - } data[2]; -} GValue; - -typedef struct -{ - GTypeInstance g_type_instance; - - gchar *name; - GParamFlags flags; - GType value_type; - GType owner_type; -} GParamSpec; - -typedef struct { - GTypeInstance g_type_instance; - guint ref_count; - void *qdata; -} GObject; - -typedef struct { - GObject parent_instance; - guint32 flags; -} GtkObject; - -typedef struct -{ - GObject parent_instance; - - GdkColor fg[5]; - GdkColor bg[5]; - GdkColor light[5]; - GdkColor dark[5]; - GdkColor mid[5]; - GdkColor text[5]; - GdkColor base[5]; - GdkColor text_aa[5]; /* Halfway between text/base */ - - GdkColor black; - GdkColor white; - PangoFontDescription *font_desc; - - gint xthickness; - gint ythickness; - - GdkGC *fg_gc[5]; - GdkGC *bg_gc[5]; - GdkGC *light_gc[5]; - GdkGC *dark_gc[5]; - GdkGC *mid_gc[5]; - GdkGC *text_gc[5]; - GdkGC *base_gc[5]; - GdkGC *text_aa_gc[5]; - GdkGC *black_gc; - GdkGC *white_gc; - - GdkPixmap *bg_pixmap[5]; -} GtkStyle; - -typedef struct _GtkWidget GtkWidget; -struct _GtkWidget -{ - GtkObject object; - guint16 private_flags; - guint8 state; - guint8 saved_state; - gchar *name; - GtkStyle *style; - GtkRequisition requisition; - GtkAllocation allocation; - GdkWindow *window; - GtkWidget *parent; -}; - -typedef struct -{ - GtkWidget widget; - - gfloat xalign; - gfloat yalign; - - guint16 xpad; - guint16 ypad; -} GtkMisc; - -typedef struct { - GtkWidget widget; - GtkWidget *focus_child; - guint border_width : 16; - guint need_resize : 1; - guint resize_mode : 2; - guint reallocate_redraws : 1; - guint has_focus_chain : 1; -} GtkContainer; - -typedef struct { - GtkContainer container; - GtkWidget *child; -} GtkBin; - -typedef struct { - GtkBin bin; - GdkWindow *event_window; - gchar *label_text; - guint activate_timeout; - guint constructed : 1; - guint in_button : 1; - guint button_down : 1; - guint relief : 2; - guint use_underline : 1; - guint use_stock : 1; - guint depressed : 1; - guint depress_on_activate : 1; - guint focus_on_click : 1; -} GtkButton; - -typedef struct { - GtkButton button; - guint active : 1; - guint draw_indicator : 1; - guint inconsistent : 1; -} GtkToggleButton; - -typedef struct _GtkAdjustment GtkAdjustment; -struct _GtkAdjustment -{ - GtkObject parent_instance; - - gdouble lower; - gdouble upper; - gdouble value; - gdouble step_increment; - gdouble page_increment; - gdouble page_size; -}; - -typedef enum -{ - GTK_UPDATE_CONTINUOUS, - GTK_UPDATE_DISCONTINUOUS, - GTK_UPDATE_DELAYED -} GtkUpdateType; - -typedef struct _GtkRange GtkRange; -struct _GtkRange -{ - GtkWidget widget; - GtkAdjustment *adjustment; - GtkUpdateType update_policy; - guint inverted : 1; - /*< protected >*/ - guint flippable : 1; - guint has_stepper_a : 1; - guint has_stepper_b : 1; - guint has_stepper_c : 1; - guint has_stepper_d : 1; - guint need_recalc : 1; - guint slider_size_fixed : 1; - gint min_slider_size; - GtkOrientation orientation; - GdkRectangle range_rect; - gint slider_start, slider_end; - gint round_digits; - /*< private >*/ - guint trough_click_forward : 1; - guint update_pending : 1; - /*GtkRangeLayout * */ void *layout; - /*GtkRangeStepTimer * */ void* timer; - gint slide_initial_slider_position; - gint slide_initial_coordinate; - guint update_timeout_id; - GdkWindow *event_window; -}; - -typedef struct _GtkProgressBar GtkProgressBar; - -typedef enum -{ - GTK_PROGRESS_CONTINUOUS, - GTK_PROGRESS_DISCRETE -} GtkProgressBarStyle; - -typedef enum -{ - GTK_PROGRESS_LEFT_TO_RIGHT, - GTK_PROGRESS_RIGHT_TO_LEFT, - GTK_PROGRESS_BOTTOM_TO_TOP, - GTK_PROGRESS_TOP_TO_BOTTOM -} GtkProgressBarOrientation; - -typedef struct _GtkProgress GtkProgress; - -struct _GtkProgress -{ - GtkWidget widget; - GtkAdjustment *adjustment; - GdkPixmap *offscreen_pixmap; - gchar *format; - gfloat x_align; - gfloat y_align; - guint show_text : 1; - guint activity_mode : 1; - guint use_text_format : 1; -}; - -struct _GtkProgressBar -{ - GtkProgress progress; - GtkProgressBarStyle bar_style; - GtkProgressBarOrientation orientation; - guint blocks; - gint in_block; - gint activity_pos; - guint activity_step; - guint activity_blocks; - gdouble pulse_fraction; - guint activity_dir : 1; - guint ellipsize : 3; -}; - -/** - * Returns : - * NULL if the GLib library is compatible with the given version, or a string - * describing the version mismatch. - * Please note that the glib_check_version() is available since 2.6, - * so you should use GLIB_CHECK_VERSION macro instead. - */ -static gchar* (*fp_glib_check_version)(guint required_major, guint required_minor, - guint required_micro); - -/** - * Returns : - * TRUE if the GLib library is compatible with the given version - */ -#define GLIB_CHECK_VERSION(major, minor, micro) \ - (fp_glib_check_version && fp_glib_check_version(major, minor, micro) == NULL) - -/** - * Returns : - * NULL if the GTK+ library is compatible with the given version, or a string - * describing the version mismatch. - */ -static gchar* (*fp_gtk_check_version)(guint required_major, guint required_minor, - guint required_micro); - -static void gtk2_init(GtkApi* gtk); - -static void (*fp_g_free)(gpointer mem); -static void (*fp_g_object_unref)(gpointer object); -static GdkWindow *(*fp_gdk_get_default_root_window) (void); - -static int (*fp_gdk_pixbuf_get_bits_per_sample)(const GdkPixbuf *pixbuf); -static guchar *(*fp_gdk_pixbuf_get_pixels)(const GdkPixbuf *pixbuf); -static gboolean (*fp_gdk_pixbuf_get_has_alpha)(const GdkPixbuf *pixbuf); -static int (*fp_gdk_pixbuf_get_height)(const GdkPixbuf *pixbuf); -static int (*fp_gdk_pixbuf_get_n_channels)(const GdkPixbuf *pixbuf); -static int (*fp_gdk_pixbuf_get_rowstride)(const GdkPixbuf *pixbuf); -static int (*fp_gdk_pixbuf_get_width)(const GdkPixbuf *pixbuf); -static GdkPixbuf *(*fp_gdk_pixbuf_new_from_file)(const char *filename, GError **error); -static GdkColorspace (*fp_gdk_pixbuf_get_colorspace)(const GdkPixbuf *pixbuf); - -static GdkPixbuf *(*fp_gdk_pixbuf_get_from_drawable)(GdkPixbuf *dest, - GdkDrawable *src, GdkColormap *cmap, int src_x, int src_y, - int dest_x, int dest_y, int width, int height); -static GdkPixbuf *(*fp_gdk_pixbuf_scale_simple)(GdkPixbuf *src, - int dest_width, int dest_heigh, GdkInterpType interp_type); - - -static void (*fp_gtk_widget_destroy)(void *widget); -static void (*fp_gtk_window_present)(GtkWindow *window); -static void (*fp_gtk_window_move)(GtkWindow *window, gint x, gint y); -static void (*fp_gtk_window_resize)(GtkWindow *window, gint width, gint height); - -/** - * Function Pointers for GtkFileChooser - */ -static gchar* (*fp_gtk_file_chooser_get_filename)(GtkFileChooser *chooser); -static void (*fp_gtk_widget_hide)(void *widget); -static void (*fp_gtk_main_quit)(void); -static void* (*fp_gtk_file_chooser_dialog_new)(const gchar *title, - GtkWindow *parent, GtkFileChooserAction action, - const gchar *first_button_text, ...); -static gboolean (*fp_gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser, - const gchar *filename); -static gboolean (*fp_gtk_file_chooser_set_filename)(GtkFileChooser *chooser, - const char *filename); -static void (*fp_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser, - const gchar *name); -static void (*fp_gtk_file_filter_add_custom)(GtkFileFilter *filter, - GtkFileFilterFlags needed, GtkFileFilterFunc func, gpointer data, - GDestroyNotify notify); -static void (*fp_gtk_file_chooser_set_filter)(GtkFileChooser *chooser, - GtkFileFilter *filter); -static GType (*fp_gtk_file_chooser_get_type)(void); -static GtkFileFilter* (*fp_gtk_file_filter_new)(void); -static void (*fp_gtk_file_chooser_set_do_overwrite_confirmation)( - GtkFileChooser *chooser, gboolean do_overwrite_confirmation); -static void (*fp_gtk_file_chooser_set_select_multiple)( - GtkFileChooser *chooser, gboolean select_multiple); -static gchar* (*fp_gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser); -static GSList* (*fp_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); -static guint (*fp_gtk_g_slist_length)(GSList *list); -static gulong (*fp_g_signal_connect_data)(gpointer instance, - const gchar *detailed_signal, GCallback c_handler, gpointer data, - GClosureNotify destroy_data, GConnectFlags connect_flags); -static void (*fp_gtk_widget_show)(void *widget); -static void (*fp_gtk_main)(void); -static guint (*fp_gtk_main_level)(void); -static gchar* (*fp_g_path_get_dirname) (const gchar *file_name); -static XID (*fp_gdk_x11_drawable_get_xid) (GdkWindow *drawable); - -static GList* (*fp_g_list_append) (GList *list, gpointer data); -static void (*fp_g_list_free) (GList *list); -static void (*fp_g_list_free_full) (GList *list, GDestroyNotify free_func); - -static gboolean (*fp_gtk_show_uri)(GdkScreen *screen, const gchar *uri, - guint32 timestamp, GError **error); - -#endif /* !_GTK2_INTERFACE_H */ diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c b/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c index c8573ed3fbfb9..fcf84948c66ee 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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 @@ -32,10 +32,8 @@ #include "jvm_md.h" #include "gtk_interface.h" -GtkApi* gtk2_load(JNIEnv *env, const char* lib_name); GtkApi* gtk3_load(JNIEnv *env, const char* lib_name); -gboolean gtk2_check(const char* lib_name, gboolean load); gboolean gtk3_check(const char* lib_name, gboolean load); GtkApi *gtk; @@ -56,13 +54,6 @@ static GtkLib gtk_libs[] = { >k3_load, >k3_check }, - { - GTK_2, - JNI_LIB_NAME("gtk-x11-2.0"), - VERSIONED_JNI_LIB_NAME("gtk-x11-2.0", "0"), - >k2_load, - >k2_check - } }; static GtkLib** get_libs_order(GtkVersion version) { diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c b/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c index e2f4ea31d2edb..6884b939ae727 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -675,7 +675,6 @@ static gboolean isAllDataReady() { static void *pipewire_libhandle = NULL; -//glib_version_2_68 false for gtk2, as it comes from gtk3_interface.c extern gboolean glib_version_2_68; diff --git a/test/jdk/java/awt/Gtk/GtkVersionTest/GtkVersionTest.java b/test/jdk/java/awt/Gtk/GtkVersionTest/GtkVersionTest.java index d2e460d4a1637..3d530178a8afc 100644 --- a/test/jdk/java/awt/Gtk/GtkVersionTest/GtkVersionTest.java +++ b/test/jdk/java/awt/Gtk/GtkVersionTest/GtkVersionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 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. * * This code is free software; you can redistribute it and/or modify it @@ -45,8 +45,9 @@ public static void main(String[] args) { public static void main(String[] args) throws Exception { test(null, "3"); - test("2", "2"); - test("2.2", "2"); +// GTK 2 is removed, but the test can still be useful. +// test("2", "2"); +// test("2.2", "2"); test("3", "3"); } diff --git a/test/jdk/java/awt/Robot/HiDPIScreenCapture/ScreenCaptureGtkTest.java b/test/jdk/java/awt/Robot/HiDPIScreenCapture/ScreenCaptureGtkTest.java index 1f6298a2a612f..155933404e8c5 100644 --- a/test/jdk/java/awt/Robot/HiDPIScreenCapture/ScreenCaptureGtkTest.java +++ b/test/jdk/java/awt/Robot/HiDPIScreenCapture/ScreenCaptureGtkTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2022, JetBrains s.r.o.. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -41,10 +41,9 @@ * @test * @key headful * @bug 8280861 - * @summary Verifies Robot screen capture capabilities with different + * @summary Verifies Robot screen capture capabilities with available * Gtk backends and presence of UI scaling * @requires os.family == "linux" - * @run main/othervm -Djdk.gtk.version=2 -Dsun.java2d.uiScale=1 ScreenCaptureGtkTest * @run main/othervm -Djdk.gtk.version=3 -Dsun.java2d.uiScale=1 ScreenCaptureGtkTest */ @@ -53,12 +52,6 @@ public class ScreenCaptureGtkTest { Color.GREEN, Color.BLUE, Color.ORANGE, Color.RED}; public static void main(String[] args) throws Exception { - if ("2".equals(System.getProperty("jdk.gtk.version")) - && System.getenv("WAYLAND_DISPLAY") != null) { - // screen capture is not supported with gtk2 on Wayland - return; - } - final int topOffset = 50; final int leftOffset = 50; diff --git a/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK.java b/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK.java index a8d460bc48e0b..906126071ff1d 100644 --- a/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK.java +++ b/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK.java @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ @bug 8156121 @key headful @requires os.family == "linux" - @run main/othervm -Djdk.gtk.version=2 DemandGTK @run main/othervm -Djdk.gtk.version=3 DemandGTK */ diff --git a/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK2.sh b/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK2.sh deleted file mode 100644 index eddae8748a7d1..0000000000000 --- a/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK2.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/ksh -p - -# -# Copyright (c) 2016, 2018, 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. -# -# 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. -# - -# @test -# @summary Try to force GTK2. We must bail out to GTK3 (if any) if no 2 available. -# -# @key headful -# @bug 8156128 8212903 -# @compile ProvokeGTK.java -# @requires os.family == "linux" -# @run shell/timeout=400 DemandGTK2.sh - -# -# Note that we depend on -# strace in the PATH -# /sbin/ldconfig (which may be not in PATH) -# It is true for OEL 7 and Ubuntu 14, 16 -# but may fail in future. Save tomorrow for tomorrow. -# -# Read DemandGTK2.txt how to prepare GTK2-less machine. -# - -which strace -if [ $? -ne 0 ] -then - echo "Please provide strace: \"which strace\" failed." - exit 1 -fi - -HAVE_2=`/sbin/ldconfig -v 2>/dev/null | grep libgtk-x11-2 | wc -l` -HAVE_3=`/sbin/ldconfig -v 2>/dev/null | grep libgtk-3.so | wc -l` - - -if [ "${HAVE_2}" = "0" ] -then - - if [ "${HAVE_3}" = "0" ] - then - echo "Neither GTK2 nor GTK3 found: system misconfiguration. Exit." - exit 1 - fi - echo "No GTK 2 library found: we should bail out to 3" - strace -o strace.log -fe open,openat ${TESTJAVA}/bin/java -cp ${TESTCLASSPATH} -Djdk.gtk.version=2 ProvokeGTK - EXECRES=$? - grep 'libgtk-3.*=\ *[0-9]*$' strace.log > logg -else - echo "There is GTK 2 library: we should use it" - strace -o strace.log -fe open,openat ${TESTJAVA}/bin/java -cp ${TESTCLASSPATH} -Djdk.gtk.version=2 ProvokeGTK - EXECRES=$? - grep 'libgtk-x11.*=\ *[0-9]*$' strace.log > logg -fi - -if [ ${EXECRES} -ne 0 ] -then - echo "java execution failed for unknown reason, see logs" - exit 2 -fi - -cat logg -if [ -s logg ] -then - echo "Success." - exit 0 -else - echo "Failed. Examine logs." - exit 3 -fi - - diff --git a/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK2.txt b/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK2.txt deleted file mode 100644 index 7313e3ee4a754..0000000000000 --- a/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK2.txt +++ /dev/null @@ -1,36 +0,0 @@ -How to prepare an Ubuntu machine for GTK-2-less test run. - -The test DemandGTK2.sh should work well without GTK-2 switching to version 3 -if there's no GTK-2 library available. -At the moment, it's not easy to find a system with GTK-3 and without GTK-2: -many programs still depend on version 2. -We can, however, rename GTK-2 library for a single test run and then restore -it back. - -(1) Find GTK2 library: run - /sbin/ldconfig -v 2>/dev/null | grep libgtk-x11-2 - -It will output one or two lines like -libgtk-x11-2.0.so.0 -> libgtk-x11-2.0.so.0.2400.23 -Search for the target of that symlink for instance with locate: -locate libgtk-x11-2.0.so.0.2400.23 -Finally, you'll find the libraries. On my current machine they are -/usr/lib/i386-linux-gnu/libgtk-x11-2.0.so.0.2400.23 -/usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.23 - -I'm running 64-bit JDK and need to tamper with x86_64 copy only. - -(2) Find running programs depending on this library. They probably would crash -if you rename it. Stop them for this test run. -That said, I'm afraid it would be impossible to do on a system older than Ubuntu 16.04. -On my Ubuntu 16.04 I have only hud-service using this library, and that's OK, it will restart -after a crash, if any. -To find these programs, run -lsof /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.23 - -(3) Now, -sudo mv /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.23 /usr/lib/x86_64-linux-gnu/bak.libgtk-x11-2.0.so.0.2400.23 -jtreg DemandGTK2.sh -sudo mv /usr/lib/x86_64-linux-gnu/bak.libgtk-x11-2.0.so.0.2400.23 /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.23 - -Needless to say, you should substitute your own library path and however you run jtreg. diff --git a/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK3.sh b/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK3.sh index bb00493c8622f..2383cc828519b 100644 --- a/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK3.sh +++ b/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK3.sh @@ -1,7 +1,7 @@ #!/bin/ksh -p # -# Copyright (c) 2016, 2018, 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. # # This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ # @test -# @summary Try to force GTK3. We must bail out to GTK2 if no 3 available. +# @summary Try to force GTK3. # # @key headful # @bug 8156128 8212903 @@ -53,11 +53,8 @@ HAVE_3=`/sbin/ldconfig -v 2>/dev/null | grep libgtk-3.so | wc -l` if [ "${HAVE_3}" = "0" ] then - - echo "No GTK 3 library found: we should bail out to 2" - strace -o strace.log -fe open,openat ${TESTJAVA}/bin/java -cp ${TESTCLASSPATH} -Djdk.gtk.version=3 ProvokeGTK - EXECRES=$? - grep 'libgtk-x11.*=\ *[0-9]*$' strace.log > logg + echo "No GTK 3 library found, do nothing" + exit 0 else echo "There is GTK 3 library: we should use it" strace -o strace.log -fe open,openat ${TESTJAVA}/bin/java -cp ${TESTCLASSPATH} -Djdk.gtk.version=3 ProvokeGTK From ddbd7a78f191462695ecbeeef7fd6312e322b15a Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Thu, 8 Aug 2024 10:53:23 +0000 Subject: [PATCH 53/77] 8337320: Update ProblemList.txt with tests known to fail on XWayland Reviewed-by: prr --- test/jdk/ProblemList.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 84c7a7d855f73..3b8421eb9cc77 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -473,6 +473,12 @@ java/awt/image/multiresolution/MultiResolutionJOptionPaneIconTest.java 8274106 m # This test fails on macOS 14 java/awt/Choice/SelectNewItemTest/SelectNewItemTest.java 8324782 macosx-all +# Wayland related + +java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java 8332158 linux-x64 +java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java 8280991 linux-x64 +java/awt/FullScreen/SetFullScreenTest.java 8332155 linux-x64 + ############################################################################ # jdk_beans From 4b740d87ee50ba49305add4aae6490bebb6963ba Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Thu, 8 Aug 2024 10:57:43 +0000 Subject: [PATCH 54/77] 8225209: jdk/jfr/event/compiler/TestCodeSweeper.java fails Reviewed-by: mgronlun --- test/jdk/ProblemList.txt | 1 - .../jfr/event/compiler/TestCodeSweeper.java | 56 +++++++++++++------ 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 3b8421eb9cc77..8aedbc7793116 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -744,7 +744,6 @@ jdk/incubator/vector/LoadJsvmlTest.java 8305390 windows- # jdk_jfr -jdk/jfr/event/compiler/TestCodeSweeper.java 8225209 generic-all jdk/jfr/event/runtime/TestResidentSetSizeEvent.java 8309846 aix-ppc64 jdk/jfr/startupargs/TestStartName.java 8214685 windows-x64 jdk/jfr/startupargs/TestStartDuration.java 8214685 windows-x64 diff --git a/test/jdk/jdk/jfr/event/compiler/TestCodeSweeper.java b/test/jdk/jdk/jfr/event/compiler/TestCodeSweeper.java index cb2a3f41b5582..df95af5b9be0a 100644 --- a/test/jdk/jdk/jfr/event/compiler/TestCodeSweeper.java +++ b/test/jdk/jdk/jfr/event/compiler/TestCodeSweeper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, 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 @@ -27,9 +27,11 @@ import java.lang.reflect.Method; import java.time.Instant; import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import jdk.jfr.Recording; +import jdk.jfr.Event; +import jdk.jfr.consumer.RecordingStream; import jdk.jfr.consumer.RecordedEvent; import jdk.test.lib.Asserts; import jdk.test.lib.jfr.EventNames; @@ -39,7 +41,7 @@ import jdk.test.whitebox.code.CodeBlob; /** - * Test for events: vm/code_cache/full vm/compiler/failure + * Test for events: jdk.CodeCacheFull jdk.CompilationFailure * * We verify that we should get at least one of each of the events listed above. * @@ -58,13 +60,15 @@ */ public class TestCodeSweeper { + static class ProvocationEvent extends Event { + } private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); private static final int COMP_LEVEL_SIMPLE = 1; private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4; private static final int SIZE = 1; private static final String METHOD_NAME = "verifyFullEvent"; - private static final String pathFull = EventNames.CodeCacheFull; - private static final String pathFailure = EventNames.CompilationFailure; + private static final String EVENT_CODE_CACHE_FULL = EventNames.CodeCacheFull; + private static final String EVENT_COMPILATION_FAILURE = EventNames.CompilationFailure; public static final long SEGMENT_SIZE = WhiteBox.getWhiteBox().getUintxVMFlag("CodeCacheSegmentSize"); public static final long MIN_BLOCK_LENGTH = WhiteBox.getWhiteBox().getUintxVMFlag("CodeCacheMinBlockLength"); public static final long MIN_ALLOCATION = SEGMENT_SIZE * MIN_BLOCK_LENGTH; @@ -77,26 +81,41 @@ public static void main(String[] args) throws Throwable { System.out.println("This test will warn that the code cache is full."); System.out.println("That is expected and is the purpose of the test."); System.out.println("************************************************"); - - Recording r = new Recording(); - r.enable(pathFull); - r.enable(pathFailure); - r.start(); - provokeEvents(); - r.stop(); + List events = Collections.synchronizedList(new ArrayList<>()); + try (RecordingStream rs = new RecordingStream()) { + rs.setReuse(false); + rs.enable(EVENT_CODE_CACHE_FULL); + rs.enable(EVENT_COMPILATION_FAILURE); + rs.onEvent(EVENT_CODE_CACHE_FULL, events::add); + rs.onEvent(EVENT_COMPILATION_FAILURE, events::add); + rs.onEvent(ProvocationEvent.class.getName(), e -> { + if (!events.isEmpty()) { + rs.close(); + return; + } + // Retry if CodeCacheFull or CompilationFailure events weren't provoked + try { + provokeEvents(); + } catch (Exception ex) { + ex.printStackTrace(); + rs.close(); + } + }); + rs.startAsync(); + provokeEvents(); + rs.awaitTermination(); + } int countEventFull = 0; int countEventFailure = 0; - - List events = Events.fromRecording(r); Events.hasEvents(events); - for (RecordedEvent event : events) { + for (RecordedEvent event : new ArrayList<>(events)) { switch (event.getEventType().getName()) { - case pathFull: + case EVENT_CODE_CACHE_FULL: countEventFull++; verifyFullEvent(event); break; - case pathFailure: + case EVENT_COMPILATION_FAILURE: countEventFailure++; verifyFailureEvent(event); break; @@ -115,6 +134,8 @@ private static boolean canAllocate(double size, long maxSize, MemoryPoolMXBean b } private static void provokeEvents() throws NoSuchMethodException, InterruptedException { + System.out.println("provokeEvents()"); + ProvocationEvent provocationEvent = new ProvocationEvent(); // Prepare for later, since we don't want to trigger any compilation // setting this up. Method method = TestCodeSweeper.class.getDeclaredMethod(METHOD_NAME, new Class[] { RecordedEvent.class }); @@ -159,6 +180,7 @@ private static void provokeEvents() throws NoSuchMethodException, InterruptedExc for (Long blob : blobs) { WHITE_BOX.freeCodeBlob(blob); } + provocationEvent.commit(); } private static void verifyFullEvent(RecordedEvent event) throws Throwable { From 6a9a867d645b8fe86f4ca2b04a43bf5aa8f9d487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Thu, 8 Aug 2024 14:38:46 +0000 Subject: [PATCH 55/77] 8337994: [REDO] Native memory leak when not recording any events Reviewed-by: egahlin --- .../share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp | 9 +++++++++ .../share/jfr/recorder/service/jfrRecorderService.cpp | 6 +----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp index 203ec3a3ec494..279b871d8181a 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp @@ -883,6 +883,15 @@ static void do_clds(CldWriter& cldw) { ModuleCldWriter mcw(&cldw); KlassAndModuleCldWriter kmcw(&kcw, &mcw); _artifacts->iterate_klasses(kmcw); + if (is_initial_typeset_for_chunk()) { + CldPtr bootloader = get_cld(Universe::boolArrayKlass()); + assert(bootloader != nullptr, "invariant"); + if (IS_NOT_SERIALIZED(bootloader)) { + write__cld(_writer, bootloader); + assert(IS_SERIALIZED(bootloader), "invariant"); + cldw.add(1); + } + } _artifacts->tally(cldw); } diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp index fc2043a4d921d..0395b711c6521 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp @@ -639,11 +639,7 @@ static void write_thread_local_buffer(JfrChunkWriter& chunkwriter, Thread* t) { size_t JfrRecorderService::flush() { size_t total_elements = flush_metadata(_chunkwriter); - const size_t storage_elements = flush_storage(_storage, _chunkwriter); - if (0 == storage_elements) { - return total_elements; - } - total_elements += storage_elements; + total_elements = flush_storage(_storage, _chunkwriter); if (_string_pool.is_modified()) { total_elements += flush_stringpool(_string_pool, _chunkwriter); } From 78773b1769922611318243b6680d59518ed4e015 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 8 Aug 2024 15:52:17 +0000 Subject: [PATCH 56/77] 8338015: Fix "Java Java" typo in package info file of java.lang.classfile Reviewed-by: jiefu, jpai, liach --- .../share/classes/java/lang/classfile/package-info.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/lang/classfile/package-info.java b/src/java.base/share/classes/java/lang/classfile/package-info.java index b5991b0e951b9..921cf9e1a3443 100644 --- a/src/java.base/share/classes/java/lang/classfile/package-info.java +++ b/src/java.base/share/classes/java/lang/classfile/package-info.java @@ -26,8 +26,8 @@ /** *

    Provides classfile parsing, generation, and transformation library.

    * The {@code java.lang.classfile} package contains classes for reading, writing, and - * modifying Java class files, as specified in Chapter {@jvms 4} of the Java - * Java Virtual Machine Specification. + * modifying Java class files, as specified in Chapter {@jvms 4} of the + * Java Virtual Machine Specification. * *

    Reading classfiles

    * The main class for reading classfiles is {@link java.lang.classfile.ClassModel}; we From 9695f09581bac856ad97943cca15c65dc21d2adf Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Thu, 8 Aug 2024 16:11:08 +0000 Subject: [PATCH 57/77] 8337683: Fix -Wconversion problem with arrayOop.hpp Reviewed-by: stefank, dholmes --- src/hotspot/share/oops/arrayOop.hpp | 18 +++++++++--------- src/hotspot/share/runtime/atomic.hpp | 5 +++-- src/hotspot/share/utilities/byteswap.hpp | 3 ++- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/hotspot/share/oops/arrayOop.hpp b/src/hotspot/share/oops/arrayOop.hpp index 0aa26500bd8d2..1ca8a9530a48c 100644 --- a/src/hotspot/share/oops/arrayOop.hpp +++ b/src/hotspot/share/oops/arrayOop.hpp @@ -68,10 +68,10 @@ class arrayOopDesc : public oopDesc { // The header is considered the oop part of this type plus the length. // This is not equivalent to sizeof(arrayOopDesc) which should not appear in the code. static int header_size_in_bytes() { - size_t hs = length_offset_in_bytes() + sizeof(int); + int hs = length_offset_in_bytes() + (int)sizeof(int); #ifdef ASSERT // make sure it isn't called before UseCompressedOops is initialized. - static size_t arrayoopdesc_hs = 0; + static int arrayoopdesc_hs = 0; if (arrayoopdesc_hs == 0) arrayoopdesc_hs = hs; assert(arrayoopdesc_hs == hs, "header size can't change"); #endif // ASSERT @@ -83,13 +83,13 @@ class arrayOopDesc : public oopDesc { // it occupies the second half of the _klass field in oopDesc. static int length_offset_in_bytes() { return UseCompressedClassPointers ? klass_gap_offset_in_bytes() : - sizeof(arrayOopDesc); + (int)sizeof(arrayOopDesc); } // Returns the offset of the first element. static int base_offset_in_bytes(BasicType type) { - size_t hs = header_size_in_bytes(); - return (int)(element_type_should_be_aligned(type) ? align_up(hs, BytesPerLong) : hs); + int hs = header_size_in_bytes(); + return element_type_should_be_aligned(type) ? align_up(hs, BytesPerLong) : hs; } // Returns the address of the first element. The elements in the array will not @@ -134,14 +134,14 @@ class arrayOopDesc : public oopDesc { assert(type < T_CONFLICT, "wrong type"); assert(type2aelembytes(type) != 0, "wrong type"); - size_t hdr_size_in_bytes = base_offset_in_bytes(type); + int hdr_size_in_bytes = base_offset_in_bytes(type); // This is rounded-up and may overlap with the first array elements. - size_t hdr_size_in_words = align_up(hdr_size_in_bytes, HeapWordSize) / HeapWordSize; + int hdr_size_in_words = align_up(hdr_size_in_bytes, HeapWordSize) / HeapWordSize; const size_t max_element_words_per_size_t = - align_down((SIZE_MAX/HeapWordSize - hdr_size_in_words), MinObjAlignment); + align_down((SIZE_MAX/HeapWordSize - (size_t)hdr_size_in_words), MinObjAlignment); const size_t max_elements_per_size_t = - HeapWordSize * max_element_words_per_size_t / type2aelembytes(type); + HeapWordSize * max_element_words_per_size_t / (size_t)type2aelembytes(type); if ((size_t)max_jint < max_elements_per_size_t) { // It should be ok to return max_jint here, but parts of the code // (CollectedHeap, Klass::oop_oop_iterate(), and more) uses an int for diff --git a/src/hotspot/share/runtime/atomic.hpp b/src/hotspot/share/runtime/atomic.hpp index 399a78fd3fce1..bf198b5f5621f 100644 --- a/src/hotspot/share/runtime/atomic.hpp +++ b/src/hotspot/share/runtime/atomic.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, 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 @@ -31,6 +31,7 @@ #include "runtime/orderAccess.hpp" #include "utilities/align.hpp" #include "utilities/bytes.hpp" +#include "utilities/checkedCast.hpp" #include "utilities/macros.hpp" #include @@ -1118,7 +1119,7 @@ inline T Atomic::CmpxchgByteUsingInt::operator()(T volatile* dest, uint8_t canon_compare_value = compare_value; volatile uint32_t* aligned_dest = reinterpret_cast(align_down(dest, sizeof(uint32_t))); - size_t offset = pointer_delta(dest, aligned_dest, 1); + uint32_t offset = checked_cast(pointer_delta(dest, aligned_dest, 1)); uint32_t idx = (Endian::NATIVE == Endian::BIG) ? (sizeof(uint32_t) - 1 - offset) diff --git a/src/hotspot/share/utilities/byteswap.hpp b/src/hotspot/share/utilities/byteswap.hpp index fba0775cf4992..9c3b53630b39b 100644 --- a/src/hotspot/share/utilities/byteswap.hpp +++ b/src/hotspot/share/utilities/byteswap.hpp @@ -26,6 +26,7 @@ #define SHARE_UTILITIES_BYTESWAP_HPP #include "metaprogramming/enableIf.hpp" +#include "utilities/checkedCast.hpp" #include "utilities/globalDefinitions.hpp" #include @@ -63,7 +64,7 @@ struct ByteswapFallbackImpl; template struct ByteswapFallbackImpl { inline constexpr uint16_t operator()(uint16_t x) const { - return (((x & UINT16_C(0x00ff)) << 8) | ((x & UINT16_C(0xff00)) >> 8)); + return checked_cast(((x & UINT16_C(0x00ff)) << 8) | ((x & UINT16_C(0xff00)) >> 8)); } }; From 53c9f037fb2805aab5ab9729166ce7d5bc7a77f9 Mon Sep 17 00:00:00 2001 From: Jiangli Zhou Date: Thu, 8 Aug 2024 16:31:02 +0000 Subject: [PATCH 58/77] 8336849: Remove .llvm_addrsig section from JDK/VM static libraries (.a files) Reviewed-by: ihse --- make/common/native/Link.gmk | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/make/common/native/Link.gmk b/make/common/native/Link.gmk index 2090218ffbb34..ca03c6ee6b12f 100644 --- a/make/common/native/Link.gmk +++ b/make/common/native/Link.gmk @@ -109,6 +109,11 @@ define CreateStaticLibrary $(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \ $$($1_LD) $(LDFLAGS_CXX_PARTIAL_LINKING) $$($1_SYSROOT_LDFLAGS) \ -o $$($1_TARGET_RELOCATABLE) $$($1_LD_OBJ_ARG)) + # 'ld -r' might invalidate the .llvm_addrsig section, and this will cause subsequent + # calls to lld (with '-Wl,--icf=safe') to fail when linking with this library, so + # remove that section. + $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_objcopy_remove_llvm_addrsig_section, \ + $$($1_OBJCOPY) --remove-section=.llvm_addrsig $$($1_TARGET_RELOCATABLE)) endif $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_run_ar, \ $(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \ From bfb75b96266f4c5840e2edea13f9aa2c801518cf Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Thu, 8 Aug 2024 16:53:38 +0000 Subject: [PATCH 59/77] 8336926: jdk/internal/util/ReferencedKeyTest.java can fail with ConcurrentModificationException Reviewed-by: bpb, shade, dfuchs --- .../jdk/internal/util/ReferencedKeyMap.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/util/ReferencedKeyMap.java b/src/java.base/share/classes/jdk/internal/util/ReferencedKeyMap.java index 9c364cd781350..810d43ae38a3a 100644 --- a/src/java.base/share/classes/jdk/internal/util/ReferencedKeyMap.java +++ b/src/java.base/share/classes/jdk/internal/util/ReferencedKeyMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -219,8 +219,14 @@ public boolean containsValue(Object value) { @Override public V get(Object key) { - Objects.requireNonNull(key, "key must not be null"); removeStaleReferences(); + return getNoCheckStale(key); + } + + // Internal get(key) without removing stale references that would modify the keyset. + // Use when iterating or streaming over the keys to avoid ConcurrentModificationException. + private V getNoCheckStale(Object key) { + Objects.requireNonNull(key, "key must not be null"); return map.get(lookupKey(key)); } @@ -291,7 +297,7 @@ public Collection values() { public Set> entrySet() { removeStaleReferences(); return filterKeySet() - .map(k -> new AbstractMap.SimpleEntry<>(k, get(k))) + .map(k -> new AbstractMap.SimpleEntry<>(k, getNoCheckStale(k))) .collect(Collectors.toSet()); } @@ -335,7 +341,7 @@ public V replace(K key, V value) { public String toString() { removeStaleReferences(); return filterKeySet() - .map(k -> k + "=" + get(k)) + .map(k -> k + "=" + getNoCheckStale(k)) .collect(Collectors.joining(", ", "{", "}")); } From e7a0b5b09bcfcd8b09667e51ec588e206f0652ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Thu, 8 Aug 2024 18:45:11 +0000 Subject: [PATCH 60/77] 8334780: Crash: assert(h_array_list.not_null()) failed: invariant Reviewed-by: egahlin, shade --- src/hotspot/share/jfr/support/jfrJdkJfrEvent.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/jfr/support/jfrJdkJfrEvent.cpp b/src/hotspot/share/jfr/support/jfrJdkJfrEvent.cpp index cd47630228931..0c2fb0206ecee 100644 --- a/src/hotspot/share/jfr/support/jfrJdkJfrEvent.cpp +++ b/src/hotspot/share/jfr/support/jfrJdkJfrEvent.cpp @@ -136,7 +136,9 @@ jobject JdkJfrEvent::get_all_klasses(TRAPS) { transform_klasses_to_local_jni_handles(event_subklasses, THREAD); Handle h_array_list(THREAD, new_java_util_arraylist(THREAD)); - assert(h_array_list.not_null(), "invariant"); + if (h_array_list.is_null()) { + return empty_java_util_arraylist; + } static const char add_method_name[] = "add"; static const char add_method_signature[] = "(Ljava/lang/Object;)Z"; From 9f08a01cb6ebb08f67749aabdff4efaedfaf3228 Mon Sep 17 00:00:00 2001 From: Leonid Mesnik Date: Thu, 8 Aug 2024 19:47:50 +0000 Subject: [PATCH 61/77] 8338010: WB_IsFrameDeoptimized miss ResourceMark Reviewed-by: dholmes, shade --- src/hotspot/share/prims/whitebox.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 6ee33a6107998..544eeabb5c212 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -799,6 +799,7 @@ WB_END WB_ENTRY(jboolean, WB_IsFrameDeoptimized(JNIEnv* env, jobject o, jint depth)) bool result = false; if (thread->has_last_Java_frame()) { + ResourceMark rm(THREAD); RegisterMap reg_map(thread, RegisterMap::UpdateMap::include, RegisterMap::ProcessFrames::include, From 55c509708e9b89a7609fd41b6e5a271f250bbacd Mon Sep 17 00:00:00 2001 From: Jiawei Tang Date: Fri, 9 Aug 2024 02:29:15 +0000 Subject: [PATCH 62/77] 8337331: crash: pinned virtual thread will lead to jvm crash when running with the javaagent option Reviewed-by: dholmes, sspitsyn --- src/hotspot/share/prims/jvmtiExport.cpp | 10 +-- .../TestPinCaseWithCFLH.java | 77 +++++++++++++++++++ 2 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 test/hotspot/jtreg/serviceability/jvmti/vthread/TestPinCaseWithCFLH/TestPinCaseWithCFLH.java diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp index f79116f5ebeb0..95cc54d93134f 100644 --- a/src/hotspot/share/prims/jvmtiExport.cpp +++ b/src/hotspot/share/prims/jvmtiExport.cpp @@ -929,9 +929,8 @@ class JvmtiClassFileLoadHookPoster : public StackObj { _cached_class_file_ptr = cache_ptr; _has_been_modified = false; - if (_thread->is_in_any_VTMS_transition()) { - return; // no events should be posted if thread is in any VTMS transition - } + assert(!_thread->is_in_any_VTMS_transition(), "CFLH events are not allowed in any VTMS transition"); + _state = JvmtiExport::get_jvmti_thread_state(_thread); if (_state != nullptr) { _class_being_redefined = _state->get_class_being_redefined(); @@ -1091,8 +1090,9 @@ bool JvmtiExport::post_class_file_load_hook(Symbol* h_name, if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) { return false; } - if (JavaThread::current()->is_in_tmp_VTMS_transition()) { - return false; // skip CFLH events in tmp VTMS transition + + if (JavaThread::current()->is_in_any_VTMS_transition()) { + return false; // no events should be posted if thread is in any VTMS transition } JvmtiClassFileLoadHookPoster poster(h_name, class_loader, diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/TestPinCaseWithCFLH/TestPinCaseWithCFLH.java b/test/hotspot/jtreg/serviceability/jvmti/vthread/TestPinCaseWithCFLH/TestPinCaseWithCFLH.java new file mode 100644 index 0000000000000..02755a0289fc1 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/TestPinCaseWithCFLH/TestPinCaseWithCFLH.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024, 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. + * + * 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. + */ +import java.lang.instrument.ClassFileTransformer; +import java.lang.instrument.IllegalClassFormatException; +import java.lang.instrument.Instrumentation; +import java.security.ProtectionDomain; +import jdk.test.lib.thread.VThreadPinner; + +/* + * @test + * @summary javaagent + tracePinnedThreads will cause jvm crash/ run into deadlock when the virtual thread is pinned + * @library /test/lib + * @requires vm.continuations + * @requires vm.jvmti + * @modules java.base/java.lang:+open + * @compile TestPinCaseWithCFLH.java + * @build jdk.test.lib.Utils + * @run driver jdk.test.lib.util.JavaAgentBuilder + * TestPinCaseWithCFLH TestPinCaseWithCFLH.jar + * @run main/othervm/timeout=100 -Djdk.virtualThreadScheduler.maxPoolSize=1 + * -Djdk.tracePinnedThreads=full --enable-native-access=ALL-UNNAMED + * -javaagent:TestPinCaseWithCFLH.jar TestPinCaseWithCFLH + */ +public class TestPinCaseWithCFLH { + + public static class TestClassFileTransformer implements ClassFileTransformer { + public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, + ProtectionDomain protectionDomain, byte[] classfileBuffer) + throws IllegalClassFormatException { + return classfileBuffer; + } + } + + // Called when agent is loaded at startup + public static void premain(String agentArgs, Instrumentation instrumentation) throws Exception { + instrumentation.addTransformer(new TestClassFileTransformer()); + } + + private static int result = 0; + + public static void main(String[] args) throws Exception{ + Thread t1 = Thread.ofVirtual().name("vthread-1").start(() -> { + VThreadPinner.runPinned(() -> { + try { + // try yield, will pin, + // javaagent + tracePinnedThreads should not lead to crash + // (because of the class `PinnedThreadPrinter`) + Thread.sleep(500); + } catch (Exception e) { + e.printStackTrace(); + } + }); + }); + t1.join(); + } + +} \ No newline at end of file From 0c1e9111d226b601236b9826e27ecc67a8b625fb Mon Sep 17 00:00:00 2001 From: Gui Cao Date: Fri, 9 Aug 2024 02:59:37 +0000 Subject: [PATCH 63/77] 8338019: Fix simple -Wzero-as-null-pointer-constant warnings in riscv code Reviewed-by: fyang, mli, luhenry --- src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp | 2 +- src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp | 2 +- src/hotspot/cpu/riscv/frame_riscv.cpp | 2 +- src/hotspot/cpu/riscv/nativeInst_riscv.cpp | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp index 798679185d3a2..3d146b87707aa 100644 --- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp @@ -542,7 +542,7 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi insn = &MacroAssembler::sw; break; case T_OBJECT: // fall through case T_ARRAY: - assert(c->as_jobject() == 0, "should be"); + assert(c->as_jobject() == nullptr, "should be"); if (UseCompressedOops && !wide) { insn = &MacroAssembler::sw; } else { diff --git a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp index 9fa8939837a85..e999b703b3e7b 100644 --- a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp @@ -1066,4 +1066,4 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { #undef __ -const char *Runtime1::pd_name_for_address(address entry) { Unimplemented(); return 0; } +const char *Runtime1::pd_name_for_address(address entry) { Unimplemented(); } diff --git a/src/hotspot/cpu/riscv/frame_riscv.cpp b/src/hotspot/cpu/riscv/frame_riscv.cpp index 32825a02c5eac..96dca4704ad95 100644 --- a/src/hotspot/cpu/riscv/frame_riscv.cpp +++ b/src/hotspot/cpu/riscv/frame_riscv.cpp @@ -269,7 +269,7 @@ void frame::patch_pc(Thread* thread, address pc) { // Either the return address is the original one or we are going to // patch in the same address that's already there. - assert(_pc == pc_old || pc == pc_old || pc_old == 0, "must be"); + assert(_pc == pc_old || pc == pc_old || pc_old == nullptr, "must be"); DEBUG_ONLY(address old_pc = _pc;) *pc_addr = pc; _pc = pc; // must be set before call to get_deopt_original_pc diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp index f0357f1cd3029..6c9e0986869b6 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp @@ -685,7 +685,7 @@ address NativeJump::jump_destination() const { // load // return -1 if jump to self or to 0 - if ((dest == (address) this) || dest == 0) { + if ((dest == (address) this) || dest == nullptr) { dest = (address) -1; } @@ -714,7 +714,7 @@ address NativeGeneralJump::jump_destination() const { // a general jump // return -1 if jump to self or to 0 - if ((dest == (address) this) || dest == 0) { + if ((dest == (address) this) || dest == nullptr) { dest = (address) -1; } From 9ab8c6b9ba90ffd12600a250c8704571e9feb78d Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 9 Aug 2024 05:09:27 +0000 Subject: [PATCH 64/77] 8335130: The test "javax/swing/plaf/synth/ComponentsOrientationSupport/5033822/bug5033822.java" fails because the background color of the tabs is displayed incorrectly. Reviewed-by: achung, psadhukhan --- .../sun/java/swing/plaf/gtk/GTKPainter.java | 34 ++++++++-------- .../swing/plaf/nimbus/SynthPainterImpl.java | 39 ++++++++++--------- .../swing/plaf/synth/SynthTabbedPaneUI.java | 8 +--- 3 files changed, 41 insertions(+), 40 deletions(-) diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java index 4787696a367eb..ea27a2a6e0d9b 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java @@ -935,25 +935,27 @@ public void paintTabbedPaneTabBackground(SynthContext context, Graphics g, int x, int y, int w, int h, int tabIndex) { - Region id = context.getRegion(); - int state = context.getComponentState(); - int gtkState = ((state & SynthConstants.SELECTED) != 0 ? - SynthConstants.ENABLED : SynthConstants.PRESSED); JTabbedPane pane = (JTabbedPane)context.getComponent(); - int placement = pane.getTabPlacement(); + if (UIManager.getBoolean("TabbedPane.tabsOpaque") || pane.isOpaque()) { + Region id = context.getRegion(); + int state = context.getComponentState(); + int gtkState = ((state & SynthConstants.SELECTED) != 0 ? + SynthConstants.ENABLED : SynthConstants.PRESSED); + int placement = pane.getTabPlacement(); - // Fill the tab rect area - g.fillRect(x, y, w, h); + // Fill the tab rect area + g.fillRect(x, y, w, h); - synchronized (UNIXToolkit.GTK_LOCK) { - if (! ENGINE.paintCachedImage(g, x, y, w, h, - id, gtkState, placement, tabIndex)) { - PositionType side = POSITIONS[placement - 1]; - ENGINE.startPainting(g, x, y, w, h, - id, gtkState, placement, tabIndex); - ENGINE.paintExtension(g, context, id, gtkState, - ShadowType.OUT, "tab", x, y, w, h, side, tabIndex); - ENGINE.finishPainting(); + synchronized (UNIXToolkit.GTK_LOCK) { + if (!ENGINE.paintCachedImage(g, x, y, w, h, + id, gtkState, placement, tabIndex)) { + PositionType side = POSITIONS[placement - 1]; + ENGINE.startPainting(g, x, y, w, h, + id, gtkState, placement, tabIndex); + ENGINE.paintExtension(g, context, id, gtkState, + ShadowType.OUT, "tab", x, y, w, h, side, tabIndex); + ENGINE.finishPainting(); + } } } } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java index c990c968ff6fa..9dfd422f6dddb 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java @@ -2098,24 +2098,27 @@ public void paintTabbedPaneTabBackground(SynthContext context, Graphics g, public void paintTabbedPaneTabBackground(SynthContext context, Graphics g, int x, int y, int w, int h, int tabIndex, int orientation) { - if (orientation == JTabbedPane.LEFT) { - AffineTransform transform = new AffineTransform(); - transform.scale(-1, 1); - transform.rotate(Math.toRadians(90)); - paintBackground(context, g, y, x, h, w, transform); - } else if (orientation == JTabbedPane.RIGHT) { - AffineTransform transform = new AffineTransform(); - transform.rotate(Math.toRadians(90)); - transform.translate(0, -(x + w)); - paintBackground(context, g, y, 0, h, w, transform); - } else if (orientation == JTabbedPane.BOTTOM) { - AffineTransform transform = new AffineTransform(); - transform.translate(x,y); - transform.scale(1, -1); - transform.translate(0,-h); - paintBackground(context, g, 0, 0, w, h, transform); - } else { - paintBackground(context, g, x, y, w, h, null); + JTabbedPane pane = (JTabbedPane)context.getComponent(); + if (UIManager.getBoolean("TabbedPane.tabsOpaque") || pane.isOpaque()) { + if (orientation == JTabbedPane.LEFT) { + AffineTransform transform = new AffineTransform(); + transform.scale(-1, 1); + transform.rotate(Math.toRadians(90)); + paintBackground(context, g, y, x, h, w, transform); + } else if (orientation == JTabbedPane.RIGHT) { + AffineTransform transform = new AffineTransform(); + transform.rotate(Math.toRadians(90)); + transform.translate(0, -(x + w)); + paintBackground(context, g, y, 0, h, w, transform); + } else if (orientation == JTabbedPane.BOTTOM) { + AffineTransform transform = new AffineTransform(); + transform.translate(x, y); + transform.scale(1, -1); + transform.translate(0, -h); + paintBackground(context, g, 0, 0, w, h, transform); + } else { + paintBackground(context, g, x, y, w, h, null); + } } } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java index 837c4d8298f9e..3378ef9e8b3de 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java @@ -127,7 +127,6 @@ public class SynthTabbedPaneUI extends BasicTabbedPaneUI // Background color for unselected tabs private Color unselectedBackground; private boolean contentOpaque = true; - private boolean tabsOpaque = true; /** * @@ -156,7 +155,6 @@ private boolean scrollableTabLayoutEnabled() { protected void installDefaults() { selectColor = UIManager.getColor("TabbedPane.selected"); contentOpaque = UIManager.getBoolean("TabbedPane.contentOpaque"); - tabsOpaque = UIManager.getBoolean("TabbedPane.tabsOpaque"); unselectedBackground = UIManager.getColor("TabbedPane.unselectedBackground"); updateStyle(tabPane); } @@ -655,10 +653,8 @@ private void paintTab(SynthContext ss, Graphics g, g.setColor(getUnselectedBackgroundAt(tabIndex)); } - if (tabsOpaque || tabPane.isOpaque()) { - tabContext.getPainter().paintTabbedPaneTabBackground(tabContext, g, - x, y, width, height, tabIndex, placement); - } + tabContext.getPainter().paintTabbedPaneTabBackground(tabContext, g, + x, y, width, height, tabIndex, placement); tabContext.getPainter().paintTabbedPaneTabBorder(tabContext, g, x, y, width, height, tabIndex, placement); From 00aac4097abd3c5e6144734cfd44228bc31892fb Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Fri, 9 Aug 2024 06:26:22 +0000 Subject: [PATCH 65/77] 8338058: map_or_reserve_memory_aligned Windows enhance remap assertion Reviewed-by: mdoerr, clanger --- src/hotspot/os/windows/os_windows.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 1cc7d9aa33adf..65ba13b0d9e81 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -3463,6 +3463,7 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi } assert(aligned_base != nullptr, "Did not manage to re-map after %d attempts?", max_attempts); + assert(aligned_base != nullptr, "Did not manage to re-map after %d attempts (size %zu, alignment %zu, file descriptor %d)", max_attempts, size, alignment, file_desc); return aligned_base; } From c01f53ac2dab1d4d2cd1e4d45a67f9373d4a9c7e Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Fri, 9 Aug 2024 07:17:59 +0000 Subject: [PATCH 66/77] 8337876: [IR Framework] Add support for IR tests with @Stable Reviewed-by: shade, kvn --- .../jtreg/compiler/lib/ir_framework/README.md | 11 ++- .../lib/ir_framework/TestFramework.java | 13 +++- .../ir_framework/driver/TestVMProcess.java | 15 ++-- .../tests/TestPhaseIRMatching.java | 2 +- .../tests/TestPrivilegedMode.java | 69 +++++++++++++++++++ 5 files changed, 103 insertions(+), 7 deletions(-) create mode 100644 test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPrivilegedMode.java diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/README.md b/test/hotspot/jtreg/compiler/lib/ir_framework/README.md index 3f6e0d4163faa..55d9fcbaecead 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/README.md +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/README.md @@ -157,7 +157,16 @@ The framework allows the use of additional compiler control annotations for help - [@ForceCompile](./ForceCompile.java) - [@ForceCompileClassInitializer](./ForceCompileClassInitializer.java) -### 2.5 Framework Debug and Stress Flags +### 2.5 IR Tests with Privileged Classes +To run tests in a privileged mode (e.g. when using `@Stable`, `@Contended`, `@ReservedStackAccess` etc.), one need to add the test classes to the boot classpath. This can easily be achieved by calling `TestFramework.addTestClassesToBootClassPath()` on the test framework object: +``` +TestFramework testFramework = new TestFramework(); +testFramework + .addTestClassesToBootClassPath() + .start(); +``` + +### 2.6 Framework Debug and Stress Flags The framework provides various stress and debug flags. They should mainly be used as JTreg VM and/or Javaoptions (apart from `VerifyIR`). The following (property) flags are supported: - `-DVerifyIR=false`: Explicitly disable IR verification. This is useful, for example, if some scenarios use VM flags that let `@IR` annotation rules fail and the user does not want to provide separate IR rules or add flag preconditions to the already existing IR rules. diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java index 67fadbc4eac31..d477aa44763fa 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java @@ -172,6 +172,7 @@ public class TestFramework { private Set scenarioIndices; private List flags; private int defaultWarmup = -1; + private boolean testClassesOnBootClassPath; /* * Public interface methods @@ -323,6 +324,15 @@ public TestFramework addScenarios(Scenario... scenarios) { return this; } + /** + * Add test classes to boot classpath. This adds all classes found on path {@link jdk.test.lib.Utils#TEST_CLASSES} + * to the boot classpath with "-Xbootclasspath/a". This is useful when trying to run tests in a privileged mode. + */ + public TestFramework addTestClassesToBootClassPath() { + this.testClassesOnBootClassPath = true; + return this; + } + /** * Start the testing of the implicitly (by {@link #TestFramework()}) or explicitly (by {@link #TestFramework(Class)}) * set test class. @@ -744,7 +754,8 @@ private boolean onlyWhitelistedJTregVMAndJavaOptsFlags() { } private void runTestVM(List additionalFlags) { - TestVMProcess testVMProcess = new TestVMProcess(additionalFlags, testClass, helperClasses, defaultWarmup); + TestVMProcess testVMProcess = new TestVMProcess(additionalFlags, testClass, helperClasses, defaultWarmup, + testClassesOnBootClassPath); if (shouldVerifyIR) { try { TestClassParser testClassParser = new TestClassParser(testClass); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java index 04f8096d96917..8c168b73260cf 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java @@ -34,6 +34,7 @@ import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; +import java.io.File; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -63,11 +64,12 @@ public class TestVMProcess { private OutputAnalyzer oa; private String irEncoding; - public TestVMProcess(List additionalFlags, Class testClass, Set> helperClasses, int defaultWarmup) { + public TestVMProcess(List additionalFlags, Class testClass, Set> helperClasses, int defaultWarmup, + boolean testClassesOnBootClassPath) { this.cmds = new ArrayList<>(); TestFrameworkSocket socket = new TestFrameworkSocket(); try (socket) { - prepareTestVMFlags(additionalFlags, socket, testClass, helperClasses, defaultWarmup); + prepareTestVMFlags(additionalFlags, socket, testClass, helperClasses, defaultWarmup, testClassesOnBootClassPath); start(); } processSocketOutput(socket); @@ -91,11 +93,16 @@ public static String getLastTestVMOutput() { } private void prepareTestVMFlags(List additionalFlags, TestFrameworkSocket socket, Class testClass, - Set> helperClasses, int defaultWarmup) { + Set> helperClasses, int defaultWarmup, boolean testClassesOnBootClassPath) { // Set java.library.path so JNI tests which rely on jtreg nativepath setting work cmds.add("-Djava.library.path=" + Utils.TEST_NATIVE_PATH); // Need White Box access in test VM. - cmds.add("-Xbootclasspath/a:."); + String bootClassPath = "-Xbootclasspath/a:."; + if (testClassesOnBootClassPath) { + // Add test classes themselves to boot classpath to make them privileged. + bootClassPath += File.pathSeparator + Utils.TEST_CLASSES; + } + cmds.add(bootClassPath); cmds.add("-XX:+UnlockDiagnosticVMOptions"); cmds.add("-XX:+WhiteBoxAPI"); // Ignore CompileCommand flags which have an impact on the profiling information. diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java index 9a39fb5310f35..f0056ebc79da9 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java @@ -66,7 +66,7 @@ private static void run(Class testClass) { List noAdditionalFlags = new ArrayList<>(); FlagVMProcess flagVMProcess = new FlagVMProcess(testClass, noAdditionalFlags); List testVMFlags = flagVMProcess.getTestVMFlags(); - TestVMProcess testVMProcess = new TestVMProcess(testVMFlags, testClass, null, -1); + TestVMProcess testVMProcess = new TestVMProcess(testVMFlags, testClass, null, -1, false); TestClassParser testClassParser = new TestClassParser(testClass); Matchable testClassMatchable = testClassParser.parse(testVMProcess.getHotspotPidFileName(), testVMProcess.getIrEncoding()); diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPrivilegedMode.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPrivilegedMode.java new file mode 100644 index 0000000000000..347b2eb39fbfc --- /dev/null +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPrivilegedMode.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2024, 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. + * + * 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 ir_framework.tests; + +import compiler.lib.ir_framework.*; +import compiler.lib.ir_framework.driver.irmatching.IRViolationException; + +import jdk.internal.vm.annotation.Stable; +import jdk.test.lib.Asserts; + +/* + * @test + * @requires vm.flagless + * @summary Test that IR framework successfully adds test class to boot classpath in order to run in privileged mode. + * @modules java.base/jdk.internal.vm.annotation + * @library /test/lib / + * @run driver ir_framework.tests.TestPrivilegedMode + */ + +public class TestPrivilegedMode { + static @Stable int iFld; // Treated as constant after first being set. + + public static void main(String[] args) { + try { + TestFramework.run(); + Asserts.fail("should not reach"); + } catch (IRViolationException e) { + // Without adding test class to boot classpath, we fail to replace the field load by a constant. + Asserts.assertTrue(e.getExceptionInfo().contains("Matched forbidden node")); + Asserts.assertTrue(e.getExceptionInfo().contains("LoadI")); + } + + // When adding the test class to the boot classpath, we can replace the field load by a constant. + new TestFramework().addTestClassesToBootClassPath().start(); + } + + @Test + @Arguments(setup = "setup") + @IR(failOn = IRNode.LOAD_I) + public int test() { + return iFld; + } + + @Setup + public void setup() { + iFld = 34; + } +} From 82d5768c1bdccfaf97a41f32a8bfcfd03a0fb378 Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Fri, 9 Aug 2024 07:20:01 +0000 Subject: [PATCH 67/77] 8337840: Remove redundant null check in ObjectOutputStream.writeProxyDesc Reviewed-by: rriggs --- src/java.base/share/classes/java/io/ObjectOutputStream.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/io/ObjectOutputStream.java b/src/java.base/share/classes/java/io/ObjectOutputStream.java index 2dcf174cf5399..3650b10135356 100644 --- a/src/java.base/share/classes/java/io/ObjectOutputStream.java +++ b/src/java.base/share/classes/java/io/ObjectOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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 @@ -1272,7 +1272,7 @@ private void writeProxyDesc(ObjectStreamClass desc, boolean unshared) } bout.setBlockDataMode(true); - if (cl != null && isCustomSubclass()) { + if (isCustomSubclass()) { ReflectUtil.checkPackageAccess(cl); } annotateProxyClass(cl); From f74109bd178c92a9dff1ca6fce03b25f51a0384f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Sikstr=C3=B6m?= Date: Fri, 9 Aug 2024 07:29:56 +0000 Subject: [PATCH 68/77] 8337939: ZGC: Make assertions and checks less convoluted and explicit Reviewed-by: stefank, ayang, eosterlund --- src/hotspot/share/gc/z/zAddress.cpp | 6 ++-- src/hotspot/share/gc/z/zAddress.inline.hpp | 30 +++++++++++++++---- src/hotspot/share/gc/z/zBarrier.inline.hpp | 6 ++-- src/hotspot/share/gc/z/zBarrierSet.inline.hpp | 4 +-- src/hotspot/share/gc/z/zHeapIterator.cpp | 2 +- src/hotspot/share/gc/z/zMark.cpp | 4 +-- src/hotspot/share/gc/z/zMark.inline.hpp | 4 +-- src/hotspot/share/gc/z/zPage.inline.hpp | 2 +- .../share/gc/z/zReferenceProcessor.cpp | 4 +-- src/hotspot/share/gc/z/zVerify.cpp | 24 +++++++++------ 10 files changed, 55 insertions(+), 31 deletions(-) diff --git a/src/hotspot/share/gc/z/zAddress.cpp b/src/hotspot/share/gc/z/zAddress.cpp index d1c199fad070c..1cd33e44a05d1 100644 --- a/src/hotspot/share/gc/z/zAddress.cpp +++ b/src/hotspot/share/gc/z/zAddress.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -93,9 +93,7 @@ static void initialize_check_oop_function() { #ifdef CHECK_UNHANDLED_OOPS if (ZVerifyOops) { // Enable extra verification of usages of oops in oopsHierarchy.hpp - check_oop_function = [](oopDesc* obj) { - (void)to_zaddress(obj); - }; + check_oop_function = &check_is_valid_zaddress; } #endif } diff --git a/src/hotspot/share/gc/z/zAddress.inline.hpp b/src/hotspot/share/gc/z/zAddress.inline.hpp index 4adbf50bc86c6..bbc92a7e2aaf3 100644 --- a/src/hotspot/share/gc/z/zAddress.inline.hpp +++ b/src/hotspot/share/gc/z/zAddress.inline.hpp @@ -333,10 +333,22 @@ inline void dereferenceable_test(zaddress addr) { } #endif -inline zaddress to_zaddress(uintptr_t value) { - const zaddress addr = zaddress(value); +inline void check_is_valid_zaddress(zaddress addr) { assert_is_valid(addr); DEBUG_ONLY(dereferenceable_test(addr)); +} + +inline void check_is_valid_zaddress(uintptr_t value) { + check_is_valid_zaddress(zaddress(value)); +} + +inline void check_is_valid_zaddress(oopDesc* o) { + check_is_valid_zaddress(uintptr_t(o)); +} + +inline zaddress to_zaddress(uintptr_t value) { + const zaddress addr = zaddress(value); + check_is_valid_zaddress(addr); return addr; } @@ -344,7 +356,7 @@ inline zaddress to_zaddress(oopDesc* o) { return to_zaddress(uintptr_t(o)); } -inline oop to_oop(zaddress addr) { +inline void assert_is_oop_or_null(zaddress addr) { const oop obj = cast_to_oop(addr); assert(!ZVerifyOops || oopDesc::is_oop_or_null(obj), "Broken oop: " PTR_FORMAT " [" PTR_FORMAT " " PTR_FORMAT " " PTR_FORMAT " " PTR_FORMAT "]", p2i(obj), @@ -352,7 +364,16 @@ inline oop to_oop(zaddress addr) { *(uintptr_t*)(untype(addr) + 0x08), *(uintptr_t*)(untype(addr) + 0x10), *(uintptr_t*)(untype(addr) + 0x18)); - return obj; +} + +inline void assert_is_oop(zaddress addr) { + assert(!is_null(addr), "Should not be null"); + assert_is_oop_or_null(addr); +} + +inline oop to_oop(zaddress addr) { + assert_is_oop_or_null(addr); + return cast_to_oop(addr); } inline zaddress operator+(zaddress addr, size_t size) { @@ -378,7 +399,6 @@ inline void assert_is_valid(zaddress_unsafe addr) { DEBUG_ONLY(is_valid(addr, true /* assert_on_failure */);) } - inline uintptr_t untype(zaddress_unsafe addr) { return static_cast(addr); } diff --git a/src/hotspot/share/gc/z/zBarrier.inline.hpp b/src/hotspot/share/gc/z/zBarrier.inline.hpp index b3191e9ae3f7a..a3eb7a9ca67d6 100644 --- a/src/hotspot/share/gc/z/zBarrier.inline.hpp +++ b/src/hotspot/share/gc/z/zBarrier.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -745,7 +745,7 @@ inline void ZBarrier::mark_and_remember(volatile zpointer* p, zaddress addr) { template inline void ZBarrier::mark(zaddress addr) { - assert(!ZVerifyOops || oopDesc::is_oop(to_oop(addr), false), "must be oop"); + assert_is_oop(addr); if (ZHeap::heap()->is_old(addr)) { ZGeneration::old()->mark_object_if_active(addr); @@ -757,7 +757,7 @@ inline void ZBarrier::mark(zaddress addr) { template inline void ZBarrier::mark_young(zaddress addr) { assert(ZGeneration::young()->is_phase_mark(), "Should only be called during marking"); - assert(!ZVerifyOops || oopDesc::is_oop(to_oop(addr), false), "must be oop"); + assert_is_oop(addr); assert(ZHeap::heap()->is_young(addr), "Must be young"); ZGeneration::young()->mark_object(addr); diff --git a/src/hotspot/share/gc/z/zBarrierSet.inline.hpp b/src/hotspot/share/gc/z/zBarrierSet.inline.hpp index d53b69345dd98..174cdfd9e909d 100644 --- a/src/hotspot/share/gc/z/zBarrierSet.inline.hpp +++ b/src/hotspot/share/gc/z/zBarrierSet.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, 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. * * This code is free software; you can redistribute it and/or modify it @@ -430,7 +430,7 @@ class ZLoadBarrierOopClosure : public BasicOopIterateClosure { template inline void ZBarrierSet::AccessBarrier::clone_in_heap(oop src, oop dst, size_t size) { - assert_is_valid(to_zaddress(src)); + check_is_valid_zaddress(src); if (dst->is_objArray()) { // Cloning an object array is similar to performing array copy. diff --git a/src/hotspot/share/gc/z/zHeapIterator.cpp b/src/hotspot/share/gc/z/zHeapIterator.cpp index 50fc921131fe7..e149a976add92 100644 --- a/src/hotspot/share/gc/z/zHeapIterator.cpp +++ b/src/hotspot/share/gc/z/zHeapIterator.cpp @@ -146,7 +146,7 @@ class ZHeapIteratorUncoloredRootOopClosure : public OopClosure { oop load_oop(oop* p) { const oop o = Atomic::load(p); - assert_is_valid(to_zaddress(o)); + check_is_valid_zaddress(o); return RawAccess<>::oop_load(p); } diff --git a/src/hotspot/share/gc/z/zMark.cpp b/src/hotspot/share/gc/z/zMark.cpp index eb342495f5799..d33b86c83e57c 100644 --- a/src/hotspot/share/gc/z/zMark.cpp +++ b/src/hotspot/share/gc/z/zMark.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -365,7 +365,7 @@ void ZMark::follow_array_object(objArrayOop obj, bool finalizable) { } // Should be convertible to colorless oop - assert_is_valid(to_zaddress(obj)); + check_is_valid_zaddress(obj); zpointer* const addr = (zpointer*)obj->base(); const size_t length = (size_t)obj->length(); diff --git a/src/hotspot/share/gc/z/zMark.inline.hpp b/src/hotspot/share/gc/z/zMark.inline.hpp index b530259361027..9edc57a60002e 100644 --- a/src/hotspot/share/gc/z/zMark.inline.hpp +++ b/src/hotspot/share/gc/z/zMark.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -47,7 +47,7 @@ template inline void ZMark::mark_object(zaddress addr) { - assert(!ZVerifyOops || oopDesc::is_oop(to_oop(addr)), "Should be oop"); + assert_is_oop(addr); ZPage* const page = _page_table->get(addr); if (page->is_allocating()) { diff --git a/src/hotspot/share/gc/z/zPage.inline.hpp b/src/hotspot/share/gc/z/zPage.inline.hpp index fcf69c685f7b6..d8ecad571907c 100644 --- a/src/hotspot/share/gc/z/zPage.inline.hpp +++ b/src/hotspot/share/gc/z/zPage.inline.hpp @@ -311,7 +311,7 @@ inline bool ZPage::mark_object(zaddress addr, bool finalizable, bool& inc_live) assert(is_in(addr), "Invalid address"); // Verify oop - (void)to_oop(addr); + assert_is_oop(addr); // Set mark bit const BitMap::idx_t index = bit_index(addr); diff --git a/src/hotspot/share/gc/z/zReferenceProcessor.cpp b/src/hotspot/share/gc/z/zReferenceProcessor.cpp index df8cb2b0e959f..1252de2ac2723 100644 --- a/src/hotspot/share/gc/z/zReferenceProcessor.cpp +++ b/src/hotspot/share/gc/z/zReferenceProcessor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -143,7 +143,7 @@ bool ZReferenceProcessor::is_inactive(zaddress reference, oop referent, Referenc return !is_null(reference_next(reference)); } else { // Verification - (void)to_zaddress(referent); + check_is_valid_zaddress(referent); // A non-FinalReference is inactive if the referent is null. The referent can only // be null if the application called Reference.enqueue() or Reference.clear(). diff --git a/src/hotspot/share/gc/z/zVerify.cpp b/src/hotspot/share/gc/z/zVerify.cpp index d47886ec7c2fc..b735965e9d49b 100644 --- a/src/hotspot/share/gc/z/zVerify.cpp +++ b/src/hotspot/share/gc/z/zVerify.cpp @@ -111,6 +111,16 @@ static bool z_is_null_relaxed(zpointer o) { return (untype(o) & ~color_mask) == 0; } +static void z_verify_oop_object(zaddress addr, zpointer o, void* p) { + const oop obj = cast_to_oop(addr); + guarantee(oopDesc::is_oop(obj), BAD_OOP_ARG(o, p)); +} + +static void z_verify_root_oop_object(zaddress addr, void* p) { + const oop obj = cast_to_oop(addr); + guarantee(oopDesc::is_oop(obj), BAD_OOP_ARG(addr, p)); +} + static void z_verify_old_oop(zpointer* p) { const zpointer o = *p; assert(o != zpointer::null, "Old should not contain raw null"); @@ -121,7 +131,7 @@ static void z_verify_old_oop(zpointer* p) { // safepoint after reference processing, where we hold the driver lock and // know there is no concurrent remembered set processing in the young generation. const zaddress addr = ZPointer::uncolor(o); - guarantee(oopDesc::is_oop(to_oop(addr)), BAD_OOP_ARG(o, p)); + z_verify_oop_object(addr, o, p); } else { const zaddress addr = ZBarrier::load_barrier_on_oop_field_preloaded(nullptr, o); // Old to young pointers might not be mark good if the young @@ -143,15 +153,11 @@ static void z_verify_young_oop(zpointer* p) { guarantee(ZPointer::is_marked_young(o), BAD_OOP_ARG(o, p)); if (ZPointer::is_load_good(o)) { - guarantee(oopDesc::is_oop(to_oop(ZPointer::uncolor(o))), BAD_OOP_ARG(o, p)); + z_verify_oop_object(ZPointer::uncolor(o), o, p); } } } -static void z_verify_root_oop_object(zaddress o, void* p) { - guarantee(oopDesc::is_oop(to_oop(o)), BAD_OOP_ARG(o, p)); -} - static void z_verify_uncolored_root_oop(zaddress* p) { assert(!ZHeap::heap()->is_in((uintptr_t)p), "Roots shouldn't be in heap"); const zaddress o = *p; @@ -168,7 +174,7 @@ static void z_verify_possibly_weak_oop(zpointer* p) { const zaddress addr = ZBarrier::load_barrier_on_oop_field_preloaded(nullptr, o); guarantee(ZHeap::heap()->is_old(addr) || ZPointer::is_marked_young(o), BAD_OOP_ARG(o, p)); guarantee(ZHeap::heap()->is_young(addr) || ZHeap::heap()->is_object_live(addr), BAD_OOP_ARG(o, p)); - guarantee(oopDesc::is_oop(to_oop(addr)), BAD_OOP_ARG(o, p)); + z_verify_oop_object(addr, o, p); // Verify no missing remset entries. We are holding the driver lock here and that // allows us to more precisely verify the remembered set, as there is no concurrent @@ -211,14 +217,14 @@ class ZVerifyColoredRootClosure : public OopClosure { // Minor collections could have relocated the object; // use load barrier to find correct object. const zaddress addr = ZBarrier::load_barrier_on_oop_field_preloaded(nullptr, o); - z_verify_root_oop_object(addr, p); + z_verify_oop_object(addr, o, p); } else { // Don't know the state of the oop if (is_valid(o)) { // it looks like a valid colored oop; // use load barrier to find correct object. const zaddress addr = ZBarrier::load_barrier_on_oop_field_preloaded(nullptr, o); - z_verify_root_oop_object(addr, p); + z_verify_oop_object(addr, o, p); } } } From 53fce38a3ff8700fef640fffc066efc21ff9c25f Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Fri, 9 Aug 2024 07:53:15 +0000 Subject: [PATCH 69/77] 8338062: JFR: Remove TestStartDuration.java and TestStartName.java from ProblemList.txt Reviewed-by: mgronlun --- test/jdk/ProblemList.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 8aedbc7793116..293d9d108d32c 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -745,8 +745,6 @@ jdk/incubator/vector/LoadJsvmlTest.java 8305390 windows- # jdk_jfr jdk/jfr/event/runtime/TestResidentSetSizeEvent.java 8309846 aix-ppc64 -jdk/jfr/startupargs/TestStartName.java 8214685 windows-x64 -jdk/jfr/startupargs/TestStartDuration.java 8214685 windows-x64 jdk/jfr/jvm/TestWaste.java 8282427 generic-all ############################################################################ From 6ebd5d74d57b334e7cf0b1282d7bb469a56fb3d6 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Fri, 9 Aug 2024 08:23:44 +0000 Subject: [PATCH 70/77] 8338036: Serial: Remove Generation::update_counters Reviewed-by: kbarrett --- src/hotspot/share/gc/serial/generation.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hotspot/share/gc/serial/generation.hpp b/src/hotspot/share/gc/serial/generation.hpp index beb29928f4826..c6a9f94a8703a 100644 --- a/src/hotspot/share/gc/serial/generation.hpp +++ b/src/hotspot/share/gc/serial/generation.hpp @@ -114,8 +114,7 @@ class Generation: public CHeapObj { public: // Performance Counter support - virtual void update_counters() = 0; - virtual CollectorCounters* counters() { return _gc_counters; } + CollectorCounters* counters() { return _gc_counters; } GCMemoryManager* gc_manager() const { assert(_gc_manager != nullptr, "not initialized yet"); From c37e8638c98cb4516569304e9a0ab477affb0641 Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Fri, 9 Aug 2024 09:12:41 +0000 Subject: [PATCH 71/77] 8314125: RISC-V: implement Base64 intrinsic - encoding Reviewed-by: fyang, luhenry --- src/hotspot/cpu/riscv/assembler_riscv.hpp | 13 + src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 223 ++++++++++++++++++ src/hotspot/cpu/riscv/vm_version_riscv.cpp | 5 + 3 files changed, 241 insertions(+) diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index e4280ab34e1ce..79279be7acc1b 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -1828,6 +1828,19 @@ enum Nf { #undef INSN +#define INSN(NAME, op, width, umop, mop, mew, nf) \ + void NAME(VectorRegister Vd_or_Vs3, Register Rs1, VectorMask vm = unmasked) { \ + patch_VLdSt(op, Vd_or_Vs3, width, Rs1, umop, vm, mop, mew, nf); \ + } + + // Vector Unit-Stride Segment Load Instructions + INSN(vlseg3e8_v, 0b0000111, 0b000, 0b00000, 0b00, 0b0, g3); + + // Vector Unit-Stride Segment Store Instructions + INSN(vsseg4e8_v, 0b0100111, 0b000, 0b00000, 0b00, 0b0, g4); + +#undef INSN + #define INSN(NAME, op, width, mop, mew) \ void NAME(VectorRegister Vd, Register Rs1, VectorRegister Vs2, VectorMask vm = unmasked, Nf nf = g1) { \ patch_VLdSt(op, Vd, width, Rs1, Vs2->raw_encoding(), vm, mop, mew, nf); \ diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index 198835d733f79..6a2c6c7d6c9bd 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -5103,6 +5103,225 @@ class StubGenerator: public StubCodeGenerator { return (address) start; } + /** + * vector registers: + * input VectorRegister's: intputV1-V3, for m2 they could be v2, v4, v6, for m1 they could be v1, v2, v3 + * index VectorRegister's: idxV1-V4, for m2 they could be v8, v10, v12, v14, for m1 they could be v4, v5, v6, v7 + * output VectorRegister's: outputV1-V4, for m2 they could be v16, v18, v20, v22, for m1 they could be v8, v9, v10, v11 + * + * NOTE: each field will occupy a vector register group + */ + void base64_vector_encode_round(Register src, Register dst, Register codec, + Register size, Register stepSrc, Register stepDst, + VectorRegister inputV1, VectorRegister inputV2, VectorRegister inputV3, + VectorRegister idxV1, VectorRegister idxV2, VectorRegister idxV3, VectorRegister idxV4, + VectorRegister outputV1, VectorRegister outputV2, VectorRegister outputV3, VectorRegister outputV4, + Assembler::LMUL lmul) { + // set vector register type/len + __ vsetvli(x0, size, Assembler::e8, lmul); + + // segmented load src into v registers: mem(src) => vr(3) + __ vlseg3e8_v(inputV1, src); + + // src = src + register_group_len_bytes * 3 + __ add(src, src, stepSrc); + + // encoding + // 1. compute index into lookup table: vr(3) => vr(4) + __ vsrl_vi(idxV1, inputV1, 2); + + __ vsrl_vi(idxV2, inputV2, 2); + __ vsll_vi(inputV1, inputV1, 6); + __ vor_vv(idxV2, idxV2, inputV1); + __ vsrl_vi(idxV2, idxV2, 2); + + __ vsrl_vi(idxV3, inputV3, 4); + __ vsll_vi(inputV2, inputV2, 4); + __ vor_vv(idxV3, inputV2, idxV3); + __ vsrl_vi(idxV3, idxV3, 2); + + __ vsll_vi(idxV4, inputV3, 2); + __ vsrl_vi(idxV4, idxV4, 2); + + // 2. indexed load: vr(4) => vr(4) + __ vluxei8_v(outputV1, codec, idxV1); + __ vluxei8_v(outputV2, codec, idxV2); + __ vluxei8_v(outputV3, codec, idxV3); + __ vluxei8_v(outputV4, codec, idxV4); + + // segmented store encoded data in v registers back to dst: vr(4) => mem(dst) + __ vsseg4e8_v(outputV1, dst); + + // dst = dst + register_group_len_bytes * 4 + __ add(dst, dst, stepDst); + } + + /** + * void j.u.Base64.Encoder.encodeBlock(byte[] src, int sp, int sl, byte[] dst, int dp, boolean isURL) + * + * Input arguments: + * c_rarg0 - src, source array + * c_rarg1 - sp, src start offset + * c_rarg2 - sl, src end offset + * c_rarg3 - dst, dest array + * c_rarg4 - dp, dst start offset + * c_rarg5 - isURL, Base64 or URL character set + */ + address generate_base64_encodeBlock() { + alignas(64) static const char toBase64[64] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' + }; + + alignas(64) static const char toBase64URL[64] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_' + }; + + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "encodeBlock"); + address start = __ pc(); + __ enter(); + + Register src = c_rarg0; + Register soff = c_rarg1; + Register send = c_rarg2; + Register dst = c_rarg3; + Register doff = c_rarg4; + Register isURL = c_rarg5; + + Register codec = c_rarg6; + Register length = c_rarg7; // total length of src data in bytes + + Label ProcessData, Exit; + + // length should be multiple of 3 + __ sub(length, send, soff); + // real src/dst to process data + __ add(src, src, soff); + __ add(dst, dst, doff); + + // load the codec base address + __ la(codec, ExternalAddress((address) toBase64)); + __ beqz(isURL, ProcessData); + __ la(codec, ExternalAddress((address) toBase64URL)); + __ BIND(ProcessData); + + // vector version + if (UseRVV) { + Label ProcessM2, ProcessM1, ProcessScalar; + + Register size = soff; + Register stepSrcM1 = send; + Register stepSrcM2 = doff; + Register stepDst = isURL; + + __ mv(size, MaxVectorSize * 2); + __ mv(stepSrcM1, MaxVectorSize * 3); + __ slli(stepSrcM2, stepSrcM1, 1); + __ mv(stepDst, MaxVectorSize * 2 * 4); + + __ blt(length, stepSrcM2, ProcessM1); + + __ BIND(ProcessM2); + base64_vector_encode_round(src, dst, codec, + size, stepSrcM2, stepDst, + v2, v4, v6, // inputs + v8, v10, v12, v14, // indexes + v16, v18, v20, v22, // outputs + Assembler::m2); + + __ sub(length, length, stepSrcM2); + __ bge(length, stepSrcM2, ProcessM2); + + __ BIND(ProcessM1); + __ blt(length, stepSrcM1, ProcessScalar); + + __ srli(size, size, 1); + __ srli(stepDst, stepDst, 1); + base64_vector_encode_round(src, dst, codec, + size, stepSrcM1, stepDst, + v1, v2, v3, // inputs + v4, v5, v6, v7, // indexes + v8, v9, v10, v11, // outputs + Assembler::m1); + __ sub(length, length, stepSrcM1); + + __ BIND(ProcessScalar); + } + + // scalar version + { + Register byte1 = soff, byte0 = send, byte2 = doff; + Register combined24Bits = isURL; + + __ beqz(length, Exit); + + Label ScalarLoop; + __ BIND(ScalarLoop); + { + // plain: [byte0[7:0] : byte1[7:0] : byte2[7:0]] => + // encoded: [byte0[7:2] : byte0[1:0]+byte1[7:4] : byte1[3:0]+byte2[7:6] : byte2[5:0]] + + // load 3 bytes src data + __ lbu(byte0, Address(src, 0)); + __ lbu(byte1, Address(src, 1)); + __ lbu(byte2, Address(src, 2)); + __ addi(src, src, 3); + + // construct 24 bits from 3 bytes + __ slliw(byte0, byte0, 16); + __ slliw(byte1, byte1, 8); + __ orr(combined24Bits, byte0, byte1); + __ orr(combined24Bits, combined24Bits, byte2); + + // get codec index and encode(ie. load from codec by index) + __ slliw(byte0, combined24Bits, 8); + __ srliw(byte0, byte0, 26); + __ add(byte0, codec, byte0); + __ lbu(byte0, byte0); + + __ slliw(byte1, combined24Bits, 14); + __ srliw(byte1, byte1, 26); + __ add(byte1, codec, byte1); + __ lbu(byte1, byte1); + + __ slliw(byte2, combined24Bits, 20); + __ srliw(byte2, byte2, 26); + __ add(byte2, codec, byte2); + __ lbu(byte2, byte2); + + __ andi(combined24Bits, combined24Bits, 0x3f); + __ add(combined24Bits, codec, combined24Bits); + __ lbu(combined24Bits, combined24Bits); + + // store 4 bytes encoded data + __ sb(byte0, Address(dst, 0)); + __ sb(byte1, Address(dst, 1)); + __ sb(byte2, Address(dst, 2)); + __ sb(combined24Bits, Address(dst, 3)); + + __ sub(length, length, 3); + __ addi(dst, dst, 4); + // loop back + __ bnez(length, ScalarLoop); + } + } + + __ BIND(Exit); + + __ leave(); + __ ret(); + + return (address) start; + } + void adler32_process_bytes(Register buff, Register s1, Register s2, VectorRegister vtable, VectorRegister vzero, VectorRegister vbytes, VectorRegister vs1acc, VectorRegister vs2acc, Register temp0, Register temp1, Register temp2, Register temp3, @@ -5996,6 +6215,10 @@ static const int64_t right_3_bits = right_n_bits(3); StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(true, "sha1_implCompressMB"); } + if (UseBASE64Intrinsics) { + StubRoutines::_base64_encodeBlock = generate_base64_encodeBlock(); + } + if (UseAdler32Intrinsics) { StubRoutines::_updateBytesAdler32 = generate_updateBytesAdler32(); } diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index ac2d6cde1a227..e9c6226f44639 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -265,6 +265,11 @@ void VM_Version::c2_initialize() { // as there are extra checks inside it which could disable UseRVV // in some situations. + // Base64 + if (FLAG_IS_DEFAULT(UseBASE64Intrinsics)) { + FLAG_SET_DEFAULT(UseBASE64Intrinsics, true); + } + if (FLAG_IS_DEFAULT(UseVectorizedHashCodeIntrinsic)) { FLAG_SET_DEFAULT(UseVectorizedHashCodeIntrinsic, true); } From 140716078694a338e2c2f837841761262cee5542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Fri, 9 Aug 2024 09:24:50 +0000 Subject: [PATCH 72/77] 8313931: Javadoc: links to type parameters actually generate links to classes Reviewed-by: jjg --- .../doclets/formats/html/ClassWriter.java | 50 +++++-- .../doclets/formats/html/HtmlIds.java | 16 +++ .../doclets/formats/html/HtmlLinkFactory.java | 13 +- .../formats/html/resources/script.js.template | 18 ++- .../formats/html/resources/stylesheet.css | 22 +++- .../formats/html/taglets/LinkTaglet.java | 24 +++- .../formats/html/taglets/ParamTaglet.java | 6 +- .../doclets/toolkit/util/CommentHelper.java | 6 + .../TestDeprecatedDocs.java | 8 +- .../TestDirectedInheritance.java | 6 +- .../doclet/testErasure/TestErasure.java | 8 +- .../TestGenericMethodLinkTaglet.java | 6 +- .../jdk/javadoc/doclet/testHref/TestHref.java | 5 +- .../doclet/testInterface/TestInterface.java | 36 ++--- .../TestLinkTagletTypeParam.java | 124 ++++++++++++++++++ .../TestMemberInheritance.java | 4 +- .../doclet/testModules/TestModules.java | 2 +- .../TestNewLanguageFeatures.java | 22 ++-- .../testParamTaglet/TestParamTaglet.java | 6 +- .../doclet/testProperty/TestProperty.java | 4 +- .../testRecordTypes/TestRecordTypes.java | 2 +- .../TestSerializedForm.java | 5 +- .../javadoc/doclet/testThrows/TestThrows.java | 4 +- .../testTypeParams/TestTypeParameters.java | 20 ++- .../testTypeParams/pkg/CtorTypeParam.java | 6 + .../doclet/testUnicode/TestUnicode.java | 4 +- 26 files changed, 336 insertions(+), 91 deletions(-) create mode 100644 test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletTypeParam.java diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java index a1fd27fefdd58..8218e5128be3b 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java @@ -37,6 +37,7 @@ import javax.lang.model.element.Name; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; +import javax.lang.model.element.TypeParameterElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.SimpleElementVisitor8; @@ -155,7 +156,7 @@ protected void buildClassTree(Content classContent) { * @param target the content to which the documentation will be added */ protected void buildClassInfo(Content target) { - Content c = HtmlTree.DIV(HtmlStyles.horizontalScroll); + var c = new ContentBuilder(); buildParamInfo(c); buildSuperInterfacesInfo(c); buildImplementedInterfacesInfo(c); @@ -164,11 +165,13 @@ protected void buildClassInfo(Content target) { buildInterfaceUsageInfo(c); buildNestedClassInfo(c); buildFunctionalInterfaceInfo(c); - buildClassSignature(c); - buildDeprecationInfo(c); - buildClassDescription(c); - buildClassTagInfo(c); - + c.add(new HtmlTree(HtmlTag.HR)); + var div = HtmlTree.DIV(HtmlStyles.horizontalScroll); + buildClassSignature(div); + buildDeprecationInfo(div); + buildClassDescription(div); + buildClassTagInfo(div); + c.add(div); target.add(getClassInfo(c)); } @@ -432,12 +435,9 @@ private void setRecordDocumentation(TypeElement elem) { protected Content getHeader(String header) { HtmlTree body = getBody(getWindowTitle(utils.getSimpleName(typeElement))); var div = HtmlTree.DIV(HtmlStyles.header); - HtmlLinkInfo linkInfo = new HtmlLinkInfo(configuration, - HtmlLinkInfo.Kind.SHOW_TYPE_PARAMS_AND_BOUNDS, typeElement) - .linkToSelf(false); // Let's not link to ourselves in the header var heading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, HtmlStyles.title, Text.of(header)); - heading.add(getTypeParameterLinks(linkInfo)); + heading.add(getTypeParameters()); div.add(heading); bodyContents.setHeader(getHeader(PageMode.CLASS, typeElement)) .addMainContent(MarkerComments.START_OF_CLASS_DATA) @@ -445,6 +445,35 @@ protected Content getHeader(String header) { return body; } + // Renders type parameters for the class heading, creating id attributes + // if @param block tags are missing in doc comment. + private Content getTypeParameters() { + var content = new ContentBuilder(); + var typeParams = typeElement.getTypeParameters(); + if (!typeParams.isEmpty()) { + // Generate id attributes if @param tags are missing for type parameters. + // Note that this does not handle the case where some but not all @param tags are missing. + var needsId = !utils.hasBlockTag(typeElement, DocTree.Kind.PARAM); + var linkInfo = new HtmlLinkInfo(configuration, + HtmlLinkInfo.Kind.SHOW_TYPE_PARAMS_AND_BOUNDS, typeElement) + .linkToSelf(false); // Let's not link to ourselves in the header + content.add("<"); + var first = true; + for (TypeParameterElement t : typeParams) { + if (!first) { + content.add(",").add(new HtmlTree(HtmlTag.WBR)); + } + var typeParamLink = getLink(linkInfo.forType(t.asType())); + content.add(needsId + ? HtmlTree.SPAN_ID(htmlIds.forTypeParam(t.getSimpleName().toString(), typeElement), typeParamLink) + : typeParamLink); + first = false; + } + content.add(">"); + } + return content; + } + protected Content getClassContentHeader() { return getContentHeader(); } @@ -473,7 +502,6 @@ public TypeElement getCurrentPageElement() { } protected void addClassSignature(Content classInfo) { - classInfo.add(new HtmlTree(HtmlTag.HR)); classInfo.add(new Signatures.TypeSignature(typeElement, this) .toContent()); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java index 1b9896fafa006..8b48c7a6f2262 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java @@ -462,6 +462,22 @@ public static HtmlId forText(String text, Map counts) { return HtmlId.of(count == 0 ? base : base + "-" + count); } + /** + * Returns an id for text documenting a type parameter of a class or method. + * + * @param paramName the name of the type parameter + * @param owner the enclosing element + * + * @return the id + */ + public HtmlId forTypeParam(String paramName, Element owner) { + if (utils.isExecutableElement(owner)) { + return HtmlId.of(forMember((ExecutableElement) owner).getFirst().name() + + "-type-param-" + paramName); + } + return HtmlId.of("type-param-" + paramName); + } + /** * Returns an id for one of the kinds of section in the pages for item group summaries. * diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java index 22af1e4a0244c..8e0c010dd1ae4 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java @@ -162,9 +162,11 @@ public Content visitTypeVariable(TypeVariable type, HtmlLinkInfo linkInfo) { Element owner = typevariable.asElement().getEnclosingElement(); if (linkInfo.linkTypeParameters() && utils.isTypeElement(owner)) { linkInfo.setTypeElement((TypeElement) owner); - Content label = newContent(); - label.add(utils.getTypeName(type, false)); - linkInfo.label(label).skipPreview(true); + if (linkInfo.getLabel() == null || linkInfo.getLabel().isEmpty()) { + Content label = newContent(); + label.add(utils.getTypeName(type, false)); + linkInfo.label(label).skipPreview(true); + } link.add(getClassLink(linkInfo)); } else { // No need to link method type parameters. @@ -242,6 +244,11 @@ protected Content getClassLink(HtmlLinkInfo linkInfo) { boolean isTypeLink = linkInfo.getType() != null && utils.isTypeVariable(utils.getComponentType(linkInfo.getType())); title = getClassToolTip(typeElement, isTypeLink); + if (isTypeLink) { + linkInfo.fragment(m_writer.configuration.htmlIds.forTypeParam( + utils.getTypeName(utils.getComponentType(linkInfo.getType()), false), + typeElement).name()); + } } Content label = linkInfo.getClassLinkLabel(configuration); if (linkInfo.getContext() == HtmlLinkInfo.Kind.SHOW_TYPE_PARAMS_IN_LABEL) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template index ef09e6df90fd7..71ef847670822 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template @@ -232,6 +232,20 @@ document.addEventListener("readystatechange", (e) => { }); document.addEventListener("DOMContentLoaded", function(e) { setTopMargin(); + // Reset animation for type parameter target highlight + document.querySelectorAll("a").forEach((link) => { + link.addEventListener("click", (e) => { + const href = e.currentTarget.getAttribute("href"); + if (href && href.startsWith("#") && href.indexOf("type-param-") > -1) { + const target = document.getElementById(decodeURI(href.substring(1))); + if (target) { + target.style.animation = "none"; + void target.offsetHeight; + target.style.removeProperty("animation"); + } + } + }) + }); // Make sure current element is visible in breadcrumb navigation on small displays const subnav = document.querySelector("ol.sub-nav-list"); if (subnav && subnav.lastElementChild) { @@ -286,7 +300,7 @@ document.addEventListener("DOMContentLoaded", function(e) { }); var expanded = false; var windowWidth; - function collapse() { + function collapse(e) { if (expanded) { mainnav.removeAttribute("style"); if (toc) { @@ -336,7 +350,7 @@ document.addEventListener("DOMContentLoaded", function(e) { document.querySelectorAll("h1, h2, h3, h4, h5, h6") .forEach((hdr, idx) => { // Create anchor links for headers with an associated id attribute - var id = hdr.getAttribute("id") || hdr.parentElement.getAttribute("id") + var id = hdr.parentElement.getAttribute("id") || hdr.getAttribute("id") || (hdr.querySelector("a") && hdr.querySelector("a").getAttribute("id")); if (id) { var template = document.createElement('template'); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css index 4e37588f6cda5..1130f14dc35b4 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css @@ -63,7 +63,7 @@ --search-input-text-color: #000000; --search-input-placeholder-color: #909090; /* Highlight color for active search tag target */ - --search-tag-highlight-color: #ffff00; + --search-tag-highlight-color: #ffff66; /* Adjustments for icon and active background colors of copy-to-clipboard buttons */ --copy-icon-brightness: 100%; --copy-button-background-color-active: rgba(168, 168, 176, 0.3); @@ -307,7 +307,7 @@ ol.sub-nav-list a.current-selection { */ .title { color:var(--title-color); - margin:10px 0; + margin:10px 0 12px 0; } .sub-title { margin:5px 0 0 0; @@ -988,6 +988,22 @@ input::placeholder { .search-tag-result:target { background-color:var(--search-tag-highlight-color); } +dd > span:target, +h1 > span:target { + animation: 2.4s ease-out highlight; +} +section.class-description dd > span:target, +section.class-description h1 > span:target { + scroll-margin-top: 20em; +} +@keyframes highlight { + from { + background-color: var(--search-tag-highlight-color); + } + 60% { + background-color: var(--search-tag-highlight-color); + } +} details.page-search-details { display: inline-block; } @@ -1040,7 +1056,7 @@ span#page-search-link { z-index: 5; } .inherited-list { - margin: 10px 0 10px 0; + margin: 10px 0; } .horizontal-scroll { overflow: auto hidden; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/LinkTaglet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/LinkTaglet.java index e16acd0315ad7..b16a1490b6303 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/LinkTaglet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/LinkTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -176,7 +176,7 @@ Content linkSeeReferenceOutput(Element holder, return htmlWriter.getPackageLink(refPackage, labelContent, refFragment); } else { // @see is not referencing an included class, module or package. Check for cross-links. - String refModuleName = ch.getReferencedModuleName(refSignature); + String refModuleName = ch.getReferencedModuleName(refSignature); DocLink elementCrossLink = (refPackage != null) ? htmlWriter.getCrossPackageLink(refPackage) : (config.extern.isModule(refModuleName)) ? htmlWriter.getCrossModuleLink(utils.elementUtils.getModuleElement(refModuleName)) @@ -190,12 +190,28 @@ Content linkSeeReferenceOutput(Element holder, if (!config.isDocLintReferenceGroupEnabled()) { reportWarning.accept( "doclet.link.see.reference_not_found", - new Object[] { refSignature}); + new Object[] {refSignature}); } return htmlWriter.invalidTagOutput(resources.getText("doclet.link.see.reference_invalid"), - Optional.of(labelContent.isEmpty() ? text: labelContent)); + Optional.of(labelContent.isEmpty() ? text : labelContent)); } } + } else if (utils.isTypeParameterElement(ref)) { + // This is a type parameter of a generic class, method or constructor + if (labelContent.isEmpty()) { + labelContent = plainOrCode(isPlain, Text.of(utils.getSimpleName(ref))); + } + if (refMem == null) { + return htmlWriter.getLink( + new HtmlLinkInfo(config, HtmlLinkInfo.Kind.LINK_TYPE_PARAMS, ref.asType()) + .label(labelContent)); + } else { + // HtmlLinkFactory does not render type parameters of generic methods as links, so instead of + // teaching it how to do it (making the code even more complex) just create the link directly. + return htmlWriter.getLink(new HtmlLinkInfo(config, HtmlLinkInfo.Kind.PLAIN, refClass) + .fragment(config.htmlIds.forTypeParam(ref.getSimpleName().toString(), refMem).name()) + .label((labelContent))); + } } else if (refFragment == null) { // Must be a class reference since refClass is not null and refFragment is null. if (labelContent.isEmpty() && refTree != null) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/ParamTaglet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/ParamTaglet.java index ed46e6c5c864f..8a3c47bbfd4b6 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/ParamTaglet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/ParamTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, 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 @@ -278,7 +278,9 @@ private Content paramTagOutput(Element element, ParamTree paramTag, String param body.add(" - "); List description = ch.getDescription(paramTag); body.add(htmlWriter.commentTagsToContent(element, description, context.within(paramTag))); - return HtmlTree.DD(body); + return HtmlTree.DD(paramTag.isTypeParameter() + ? HtmlTree.SPAN_ID(config.htmlIds.forTypeParam(paramName, element), body) + : body); } private record Documentation(ParamTree paramTree, ExecutableElement method) { } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java index d7a0bd2d0a070..30aa86aea7196 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java @@ -188,6 +188,12 @@ public Element getReferencedMember(Element e) { Utils utils = configuration.utils; if (e == null) { return null; + } else if (utils.isTypeParameterElement(e)) { + // Return the enclosing member for type parameters of generic methods or constructors. + Element encl = e.getEnclosingElement(); + if (utils.isExecutableElement(encl)) { + return encl; + } } return (utils.isExecutableElement(e) || utils.isVariableElement(e)) ? e : null; } diff --git a/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java b/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java index 2bd9da5957837..165fadc8e051f 100644 --- a/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java +++ b/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -102,7 +102,6 @@ public void test() { checkOutput("pkg/TestAnnotationType.html", true, """ -
    @Deprecated(forRemoval=true) @Documented public @interface
    @Deprecated(forRemoval=true) public class TestClass extends java.lang.Object
    @@ -212,7 +210,6 @@ public void test() { checkOutput("pkg/TestEnum.html", true, """ -
    @Deprecated(forRemoval=true) public enum TestEnum extends java.lang.Enum<
    @Deprecated(forRemoval=true) public class TestError extends java.lang.Error
    @@ -244,7 +240,6 @@ public void test() { checkOutput("pkg/TestException.html", true, """ -
    @Deprecated(forRemoval=true) public class TestException extends java.lang.Exception
    @@ -255,7 +250,6 @@ public void test() { checkOutput("pkg/TestInterface.html", true, """ -
    @Deprecated(forRemoval=true) public class TestInterface extends java.lang.Object
    diff --git a/test/langtools/jdk/javadoc/doclet/testDirectedInheritance/TestDirectedInheritance.java b/test/langtools/jdk/javadoc/doclet/testDirectedInheritance/TestDirectedInheritance.java index 89eb68db1dfdc..0f2b398e626bc 100644 --- a/test/langtools/jdk/javadoc/doclet/testDirectedInheritance/TestDirectedInheritance.java +++ b/test/langtools/jdk/javadoc/doclet/testDirectedInheritance/TestDirectedInheritance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -154,8 +154,8 @@ public interface E1 extends I1, I2 {
    I2: main description
    """, """
    Type Parameters:
    -
    E - I2: first type parameter
    -
    F - I2: second type parameter
    +
    E - I2: first type parameter
    +
    F - I2: second type parameter
    Parameters:
    eObj - I2: parameter
    Returns:
    diff --git a/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java b/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java index f80074c50e250..ee2ec08b884e6 100644 --- a/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java +++ b/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java @@ -199,7 +199,7 @@ class X { }
     
    \ Foo\ - (T arg)
    + (T arg)
     
     <T extends X>
    \ @@ -227,10 +227,10 @@ class X { } // methods checkOutput("Foo.html", true, """
    abstract T
    + method-summary-table-tab3">abstract T
    m\ - (T arg)
    + (T arg)
     
    Test Feature
    """); } -} \ No newline at end of file +} diff --git a/test/langtools/jdk/javadoc/doclet/testGenericMethodLinkTaglet/TestGenericMethodLinkTaglet.java b/test/langtools/jdk/javadoc/doclet/testGenericMethodLinkTaglet/TestGenericMethodLinkTaglet.java index a9a4be1b262b9..db23064e9ca8d 100644 --- a/test/langtools/jdk/javadoc/doclet/testGenericMethodLinkTaglet/TestGenericMethodLinkTaglet.java +++ b/test/langtools/jdk/javadoc/doclet/testGenericMethodLinkTaglet/TestGenericMethodLinkTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8188248 + * @bug 8188248 8313931 * @summary NullPointerException on generic methods * @library /tools/lib ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool @@ -67,7 +67,7 @@ public void test(Path base) throws Exception { checkOutput("pkg/A.html", true, """ - A"""); + param T"""); } void createTestClass(Path srcDir) throws Exception { diff --git a/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java b/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java index f21ad223fb459..b9dff5ff2a897 100644 --- a/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java +++ b/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -75,7 +75,8 @@ public void test() { checkOutput("pkg/C4.html", true, //Header does not link to the page itself. - "Class C4<E extends C4<E>>", + """ + Class C4<E extends C4<E>>""", //Signature does not link to the page itself. """ public abstract class method in interface&\ nbsp;Interface<CE>""", + href="#type-param-CE" title="type parameter in Child">CE>""", //Make sure "Overrides" has substituted type parameters. """
    Overrides:
    method in class Parent<Parent<CE>
    """); checkOutput("pkg/Parent.html", true, @@ -190,7 +190,7 @@ public void test1() {
    Overrides:
    method1 in class&\ nbsp;GrandParent<<\ - a href="Child.html" title="type parameter in Child">CE>"""); + a href="#type-param-CE" title="type parameter in Child">CE>"""); } @Test @@ -209,17 +209,17 @@ public void test2() { erface in pkg2">Spliterator Spliterator.\ OfDouble, Spliter\ - ator.OfInt<Integer>, Spliterator.OfPrimitive<T,T_C\ - ONS,T,T_C\ + ONS,T_SPLITR extends Spliterator.OfPrimitive<T,<\ - a href="Spliterator.OfPrimitive.html" title="type parameter in Spliterator.OfPri\ - mitive">T_CONS,T,<\ + a href="Spliterator.OfPrimitive.html#type-param-T_CONS" title="type parameter in Spliterator.OfPri\ + mitive">T_CONS,T_SPLITR>>"""); checkOutput("pkg2/Spliterator.html", true, """ @@ -236,21 +236,21 @@ public void test2() {
    static interface 
    Spliterator.OfInt<Integer&\ + Spliterator.OfInt.html#type-param-Integer" title="type parameter in Spliterator.OfInt">Integer&\ gt;
     
    static interface 
    Spliterator.OfPrimitive\ - <T,T,T_CONS,T_SPLITR extends <\ + e.html#type-param-T_SPLITR" title="type parameter in Spliterator.OfPrimitive">T_SPLITR extends <\ a href="Spliterator.OfPrimitive.html" title="interface in pkg2">Spliterator.OfPr\ - imitive<T,<T,T_CONS,T_SPLITRT_SPLITR>>
     
    """); diff --git a/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletTypeParam.java b/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletTypeParam.java new file mode 100644 index 0000000000000..5cb1f687d452f --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletTypeParam.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2024, 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. + * + * 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. + */ + +/* + * @test + * @bug 8313931 + * @summary Javadoc: links to type parameters actually generate links to classes + * @library /tools/lib ../../lib + * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @build toolbox.ToolBox javadoc.tester.* + * @run main TestLinkTagletTypeParam + */ + +import javadoc.tester.JavadocTester; +import toolbox.ToolBox; + +import java.io.IOException; +import java.nio.file.Path; + +public class TestLinkTagletTypeParam extends JavadocTester { + + public static void main(String... args) throws Exception { + var tester = new TestLinkTagletTypeParam(); + tester.runTests(); + } + + ToolBox tb = new ToolBox(); + + @JavadocTester.Test + public void testClassTypeParameterLink(Path base) throws IOException { + Path src = base.resolve("src"); + + tb.writeJavaFiles(src, + """ + /** + * Link to {@link F}. + * + * @param the first type param + * @param an Appendable + * + * @see APND the second type parameter + */ + public class Test { + private Test() {} + } + """); + + javadoc("-Xdoclint:none", + "-d", base.resolve("api").toString(), + "-sourcepath", src.toString(), + src.resolve("Test.java").toString()); + checkExit(JavadocTester.Exit.OK); + + checkOrder("Test.html", + """ +
    Type Parameters:
    +
    F - the first type param
    +
    APND - an Appendable
    """, + """ + Link to
    F.""", + """ +
    See Also:
    +
    + """); + } + + @JavadocTester.Test + public void testMethodTypeParameterLink(Path base) throws IOException { + Path src = base.resolve("src"); + + tb.writeJavaFiles(src, + """ + /** + * Class comment. + */ + public class Test { + /** + * Link to {@link T} and {@linkplain T link with label}. + * + * @param the T + * @param appendable the appendable + */ + public T append(final T appendable) { + return appendable; + } + } + """); + + javadoc("-Xdoclint:reference", + "-d", base.resolve("api").toString(), + "-sourcepath", src.toString(), + src.resolve("Test.java").toString()); + + checkOutput(JavadocTester.Output.OUT, true, + ""); + + checkOutput("Test.html", true, + """ + Link to T and link with label."""); + } +} diff --git a/test/langtools/jdk/javadoc/doclet/testMemberInheritance/TestMemberInheritance.java b/test/langtools/jdk/javadoc/doclet/testMemberInheritance/TestMemberInheritance.java index 705cae327e3a3..559f7b08d3877 100644 --- a/test/langtools/jdk/javadoc/doclet/testMemberInheritance/TestMemberInheritance.java +++ b/test/langtools/jdk/javadoc/doclet/testMemberInheritance/TestMemberInheritance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 @@ -120,8 +120,8 @@ interface in pkg">BaseInterface
    checkOutput("pkg2/DocumentedNonGenericChild.html", true, """
    -

    +
    public abstract class DocumentedNonGenericChild extends java.lang.Object
    diff --git a/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java index 79bad12f95db2..4d3628544f81e 100644 --- a/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java +++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java @@ -1360,8 +1360,8 @@ void checkLinkSource(boolean includePrivate) { checkOutput("moduleA/testpkgmdlA/TestClassInModuleA.html", true, """
    -

    +
    public class TestClassInModuleA diff --git a/test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java b/test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java index a54fbbcff75f0..eafad8c3245f2 100644 --- a/test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java +++ b/test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -117,7 +117,7 @@ void checkTypeParameters() { // Check class type parameters section. """
    Type Parameters:
    -
    E - the type parameter for this class.""", +
    E - the type parameter for this class.
    """, // Type parameters in @see/@link """
    @@ -130,12 +130,14 @@ void checkTypeParameters() {
    """, // Method that uses class type parameter. """ - (E param)""", + (E param)""", // Method type parameter section. """
    Type Parameters:
    -
    T - This is the first type parameter.
    -
    V - This is the second type parameter.""", +
    T - Th\ + is is the first type parameter.
    +
    V - Th\ + is is the second type parameter.
    """, // Signature of method with type parameters """
    public E[]
    methodThatReturnsTypeParameterA(E[] \ + ref="#type-param-E" title="type parameter in TypeParameters">E[] \ e)""", """
    public E[] methodThatReturnsTypePa\ - rameterA((E[] e)
    """, """ @@ -176,7 +178,7 @@ void checkTypeParameters() { """
    <X extends java.lang.Throwable>
    E
    \ + href="#type-param-E" title="type parameter in TypeParameters">E
    \
    Type Parameters: -
    T2 - type 2
    +
    T2 - type 2
    Parameters:
    t1 - param 1
    t3 - param 3
    @@ -92,7 +92,7 @@ public void test() { checkOutput("pkg/C.Nested.html", true, """
    Type Parameters:
    -
    T1 - type 1
    +
    T1 - type 1
    """); } } diff --git a/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java b/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java index 7ce046c07575c..94ad1a8040f6a 100644 --- a/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java +++ b/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, 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. * * This code is free software; you can redistribute it and/or modify it @@ -110,7 +110,7 @@ class in pkg">ObjectProperty
    <public final <\ span class="return-type">Obje\ - ctProperty<java.util.List<T>> listProperty<\ /div>
    This is an Object property where the Object is a single List<T>.
    diff --git a/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java b/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java index f9aa3cfd6fa49..3b6a8a4fc72e4 100644 --- a/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java +++ b/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java @@ -175,7 +175,7 @@ public record R(int r1) { }"""); """
    Type Parameters:
    -
    T - This is a type parameter.
    +
    T - This is a type parameter.
    Record Components:
    r1 - This is a component.
    """, diff --git a/test/langtools/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java b/test/langtools/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java index 9bf2ac362c611..af3e36aa7d897 100644 --- a/test/langtools/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java +++ b/test/langtools/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, 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 @@ -219,6 +219,7 @@ public void test2() { """ Fields[] singleArray""", """ - java.lang.Class<E> someClass"""); + java.lang.Class<E> someClass"""); } } diff --git a/test/langtools/jdk/javadoc/doclet/testThrows/TestThrows.java b/test/langtools/jdk/javadoc/doclet/testThrows/TestThrows.java index ca4592ea5f84c..e4c578578998f 100644 --- a/test/langtools/jdk/javadoc/doclet/testThrows/TestThrows.java +++ b/test/langtools/jdk/javadoc/doclet/testThrows/TestThrows.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 @@ -83,7 +83,7 @@ public interface C { """
    Type Parameters:
    -
    T - the throwable
    +
    T - the throwable
    Throws:
    T - if a specific error occurs
    java.lang.Exception - if an exception occurs
    diff --git a/test/langtools/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java b/test/langtools/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java index 0d95ee38cdc94..dad610acb302e 100644 --- a/test/langtools/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java +++ b/test/langtools/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 4927167 4974929 6381729 7010344 8025633 8081854 8182765 8187288 8261976 + * @bug 4927167 4974929 6381729 7010344 8025633 8081854 8182765 8187288 8261976 8313931 * @summary When the type parameters are more than 10 characters in length, * make sure there is a line break between type params and return type * in member summary. Also, test for type parameter links in package-summary and @@ -110,10 +110,22 @@ public void test3() {
     <T extends java.lang.Runnable>
    -
     
    """, +
    +
    Generic constructor.
    """, """
    public\  <T extends java.lang.Runnable>\ -  CtorTypeParam()
    """); +  CtorTypeParam()
    """, + """ + T""", + """ +
    Type Parameters:
    +
    T - the type parameter
    """, + """ +
    See Also:
    +
    + """); } } diff --git a/test/langtools/jdk/javadoc/doclet/testTypeParams/pkg/CtorTypeParam.java b/test/langtools/jdk/javadoc/doclet/testTypeParams/pkg/CtorTypeParam.java index a7f2309475d28..690471861dbd9 100644 --- a/test/langtools/jdk/javadoc/doclet/testTypeParams/pkg/CtorTypeParam.java +++ b/test/langtools/jdk/javadoc/doclet/testTypeParams/pkg/CtorTypeParam.java @@ -24,6 +24,12 @@ package pkg; public class CtorTypeParam { + /** + * Generic constructor. {@link T} + * + * @param the type parameter + * @see T link to type parameter + */ public CtorTypeParam() { } } diff --git a/test/langtools/jdk/javadoc/doclet/testUnicode/TestUnicode.java b/test/langtools/jdk/javadoc/doclet/testUnicode/TestUnicode.java index 76008260343ca..cf30488ec7bc2 100644 --- a/test/langtools/jdk/javadoc/doclet/testUnicode/TestUnicode.java +++ b/test/langtools/jdk/javadoc/doclet/testUnicode/TestUnicode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, 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 @@ -101,7 +101,7 @@ public class Code<##> { """
    Type Parameters:
    -
    ## - the ##
    +
    ## - the ##
    """.replaceAll("##", chineseElephant), """ From 2b5aec2aad3883d4d407ec3a572f78755d60190d Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Fri, 9 Aug 2024 11:28:59 +0000 Subject: [PATCH 73/77] 8338109: java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java duplicate in ProblemList Reviewed-by: aivanov --- test/jdk/ProblemList.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 293d9d108d32c..6cde711138310 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -375,7 +375,7 @@ java/awt/Modal/MultipleDialogs/MultipleDialogs3Test.java 8198665 macosx-all java/awt/Modal/MultipleDialogs/MultipleDialogs4Test.java 8198665 macosx-all java/awt/Modal/MultipleDialogs/MultipleDialogs5Test.java 8198665 macosx-all java/awt/Mouse/EnterExitEvents/DragWindowOutOfFrameTest.java 8177326 macosx-all -java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java 8005021 macosx-all +java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java 8005021,8332158 macosx-all,linux-x64 java/awt/Mouse/EnterExitEvents/FullscreenEnterEventTest.java 8051455 macosx-all java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Standard.java 7124407,8302787 macosx-all,windows-all java/awt/Mouse/RemovedComponentMouseListener/RemovedComponentMouseListener.java 8157170 macosx-all @@ -475,7 +475,6 @@ java/awt/Choice/SelectNewItemTest/SelectNewItemTest.java 8324782 macosx-all # Wayland related -java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java 8332158 linux-x64 java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java 8280991 linux-x64 java/awt/FullScreen/SetFullScreenTest.java 8332155 linux-x64 From 069e0ea69f43960164d3e077d2c7b950cde77927 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Fri, 9 Aug 2024 12:00:15 +0000 Subject: [PATCH 74/77] 8338064: Give better error for ConcurrentHashTable corruption Reviewed-by: dholmes, shade --- .../share/utilities/concurrentHashTable.hpp | 5 ++ .../utilities/concurrentHashTable.inline.hpp | 6 +- .../StringTableCorruptionTest.java | 59 +++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 test/hotspot/jtreg/runtime/stringtable/StringTableCorruptionTest.java diff --git a/src/hotspot/share/utilities/concurrentHashTable.hpp b/src/hotspot/share/utilities/concurrentHashTable.hpp index 991ea9fe3c609..4e506d5fe84f1 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.hpp @@ -65,6 +65,7 @@ class ConcurrentHashTable : public CHeapObj { // the InternalTable or user-defined memory. class Node { private: + DEBUG_ONLY(size_t _saved_hash); Node * volatile _next; VALUE _value; public: @@ -77,6 +78,10 @@ class ConcurrentHashTable : public CHeapObj { Node* next() const; void set_next(Node* node) { _next = node; } Node* const volatile * next_ptr() { return &_next; } +#ifdef ASSERT + size_t saved_hash() const { return _saved_hash; } + void set_saved_hash(size_t hash) { _saved_hash = hash; } +#endif VALUE* value() { return &_value; } diff --git a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp index 78c7e148bbb3c..f035aeae44847 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp @@ -679,7 +679,9 @@ inline bool ConcurrentHashTable:: // Keep in odd list odd = aux->next_ptr(); } else { - fatal("aux_index does not match even or odd indices"); + const char* msg = "Cannot resize table: Node hash code has changed possibly due to corruption of the contents."; + DEBUG_ONLY(fatal("%s Node hash code changed from " SIZE_FORMAT " to " SIZE_FORMAT, msg, aux->saved_hash(), aux_hash);) + NOT_DEBUG(fatal("%s", msg);) } } aux = aux_next; @@ -892,6 +894,7 @@ inline bool ConcurrentHashTable:: size_t i = 0; uintx hash = lookup_f.get_hash(); Node* new_node = Node::create_node(_context, value, nullptr); + DEBUG_ONLY(new_node->set_saved_hash(hash);) while (true) { { @@ -1117,6 +1120,7 @@ inline bool ConcurrentHashTable:: Bucket* bucket = get_bucket_in(table, hash); assert(!bucket->have_redirect() && !bucket->is_locked(), "bad"); Node* new_node = Node::create_node(_context, value, bucket->first()); + DEBUG_ONLY(new_node->set_saved_hash(hash);) if (!bucket->cas_first(new_node, bucket->first())) { assert(false, "bad"); } diff --git a/test/hotspot/jtreg/runtime/stringtable/StringTableCorruptionTest.java b/test/hotspot/jtreg/runtime/stringtable/StringTableCorruptionTest.java new file mode 100644 index 0000000000000..e4d6a2e5d0f95 --- /dev/null +++ b/test/hotspot/jtreg/runtime/stringtable/StringTableCorruptionTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024, 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. + * + * 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. + */ + +/* + * @test + * @bug 8333356 + * @summary Verify new error message for corrupting string table contents. + * @requires vm.flagless + * @modules java.base/java.lang:open + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @run driver StringTableCorruptionTest test + */ + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class StringTableCorruptionTest { + public static void main(String[] args) throws Exception { + if (args.length > 0) { + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("--add-opens", "java.base/java.lang=ALL-UNNAMED", + "-XX:-CreateCoredumpOnCrash", "StringTableCorruptionTest"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Node hash code has changed possibly due to corruption of the contents."); + output.shouldNotHaveExitValue(0); + return; + } + + Field f = String.class.getDeclaredField("value"); + f.setAccessible(true); + f.set("s1".intern(), f.get("s2")); + for (int i = 0; i < 4_000_000; i++) { + ("s_" + i).intern(); + } + } +} From 3cf3f300de1e9d2c8767877ed3a26679e34b7d22 Mon Sep 17 00:00:00 2001 From: Casper Norrbin Date: Fri, 9 Aug 2024 14:32:29 +0000 Subject: [PATCH 75/77] 8330191: Fix typo in precompiled.hpp Reviewed-by: jsjolen, szaldana --- src/hotspot/share/precompiled/precompiled.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/precompiled/precompiled.hpp b/src/hotspot/share/precompiled/precompiled.hpp index c53a78de87bca..07922d129697e 100644 --- a/src/hotspot/share/precompiled/precompiled.hpp +++ b/src/hotspot/share/precompiled/precompiled.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2024, 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 @@ -29,7 +29,7 @@ // These header files are included in at least 130 C++ files, as of // measurements made in November 2018. This list excludes files named -// *.include.hpp, since including them decreased build performance. +// *.inline.hpp, since including them decreased build performance. #include "classfile/classLoaderData.hpp" #include "classfile/javaClasses.hpp" From 60fa08fcfe5c6551ee3120330ade93e45df618c7 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Fri, 9 Aug 2024 17:08:19 +0000 Subject: [PATCH 76/77] 8337797: Additional ExternalAddress cleanup Reviewed-by: adinn, thartmann --- src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp | 4 ++-- src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp | 9 ++------- src/hotspot/cpu/x86/assembler_x86.cpp | 1 + src/hotspot/cpu/x86/jniFastGetField_x86_32.cpp | 8 ++++---- src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp | 6 +++--- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 4 ++-- src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp | 4 ++-- src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp | 4 ++-- src/hotspot/cpu/x86/stubGenerator_x86_64_arraycopy.cpp | 2 +- src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp | 4 ++-- 10 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp b/src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp index e79b93651b072..aea268ea94443 100644 --- a/src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -201,7 +201,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { { __ enter(); - __ lea(rscratch1, ExternalAddress(slow_case_addr)); + __ lea(rscratch1, RuntimeAddress(slow_case_addr)); __ blr(rscratch1); __ leave(); __ ret(lr); diff --git a/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp b/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp index 8423ecad8a3da..f7d702c631069 100644 --- a/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp +++ b/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -173,12 +173,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { { __ enter(); - ExternalAddress target(slow_case_addr); - __ relocate(target.rspec(), [&] { - int32_t offset; - __ la(t0, target.target(), offset); - __ jalr(t0, offset); - }); + __ rt_call(slow_case_addr); __ leave(); __ ret(); } diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index 001ff472f40bb..207d3fbb61eba 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -1780,6 +1780,7 @@ void Assembler::call(Register dst) { void Assembler::call(Address adr) { + assert(!adr._rspec.reloc()->is_data(), "should not use ExternalAddress for call"); InstructionMark im(this); prefix(adr); emit_int8((unsigned char)0xFF); diff --git a/src/hotspot/cpu/x86/jniFastGetField_x86_32.cpp b/src/hotspot/cpu/x86/jniFastGetField_x86_32.cpp index 34be2a61b5a47..52e4388c5d249 100644 --- a/src/hotspot/cpu/x86/jniFastGetField_x86_32.cpp +++ b/src/hotspot/cpu/x86/jniFastGetField_x86_32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, 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 @@ -138,7 +138,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { default: ShouldNotReachHere(); } // tail call - __ jump (ExternalAddress(slow_case_addr)); + __ jump (RuntimeAddress(slow_case_addr)); __ flush (); @@ -251,7 +251,7 @@ address JNI_FastGetField::generate_fast_get_long_field() { __ pop (rsi); address slow_case_addr = jni_GetLongField_addr();; // tail call - __ jump (ExternalAddress(slow_case_addr)); + __ jump (RuntimeAddress(slow_case_addr)); __ flush (); @@ -350,7 +350,7 @@ address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { default: ShouldNotReachHere(); } // tail call - __ jump (ExternalAddress(slow_case_addr)); + __ jump (RuntimeAddress(slow_case_addr)); __ flush (); diff --git a/src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp b/src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp index 4506205c259fb..e94b7d12b0b3c 100644 --- a/src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp +++ b/src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, 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 @@ -118,7 +118,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { default: break; } // tail call - __ jump (ExternalAddress(slow_case_addr), rscratch1); + __ jump (RuntimeAddress(slow_case_addr), rscratch1); __ flush (); @@ -206,7 +206,7 @@ address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { default: break; } // tail call - __ jump (ExternalAddress(slow_case_addr), rscratch1); + __ jump (RuntimeAddress(slow_case_addr), rscratch1); __ flush (); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index affd18f937ca8..c8234d6b9b88b 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -2329,7 +2329,7 @@ void MacroAssembler::incrementl(Address dst, int value) { void MacroAssembler::jump(AddressLiteral dst, Register rscratch) { assert(rscratch != noreg || always_reachable(dst), "missing"); - + assert(!dst.rspec().reloc()->is_data(), "should not use ExternalAddress for jump"); if (reachable(dst)) { jmp_literal(dst.target(), dst.rspec()); } else { @@ -2340,7 +2340,7 @@ void MacroAssembler::jump(AddressLiteral dst, Register rscratch) { void MacroAssembler::jump_cc(Condition cc, AddressLiteral dst, Register rscratch) { assert(rscratch != noreg || always_reachable(dst), "missing"); - + assert(!dst.rspec().reloc()->is_data(), "should not use ExternalAddress for jump_cc"); if (reachable(dst)) { InstructionMark im(this); relocate(dst.reloc()); diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp index 80be7c7d5b642..d313c1b216a40 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp @@ -704,10 +704,10 @@ static void range_check(MacroAssembler* masm, Register pc_reg, Register temp_reg address code_start, address code_end, Label& L_ok) { Label L_fail; - __ lea(temp_reg, ExternalAddress(code_start)); + __ lea(temp_reg, AddressLiteral(code_start, relocInfo::none)); __ cmpptr(pc_reg, temp_reg); __ jcc(Assembler::belowEqual, L_fail); - __ lea(temp_reg, ExternalAddress(code_end)); + __ lea(temp_reg, AddressLiteral(code_end, relocInfo::none)); __ cmpptr(pc_reg, temp_reg); __ jcc(Assembler::below, L_ok); __ bind(L_fail); diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index f2488ef4e7445..d27b1d141fc29 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -824,10 +824,10 @@ static void range_check(MacroAssembler* masm, Register pc_reg, Register temp_reg address code_start, address code_end, Label& L_ok) { Label L_fail; - __ lea(temp_reg, ExternalAddress(code_start)); + __ lea(temp_reg, AddressLiteral(code_start, relocInfo::none)); __ cmpptr(pc_reg, temp_reg); __ jcc(Assembler::belowEqual, L_fail); - __ lea(temp_reg, ExternalAddress(code_end)); + __ lea(temp_reg, AddressLiteral(code_end, relocInfo::none)); __ cmpptr(pc_reg, temp_reg); __ jcc(Assembler::below, L_ok); __ bind(L_fail); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_arraycopy.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_arraycopy.cpp index d8f7a6b272bc9..5b316881d0346 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_arraycopy.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_arraycopy.cpp @@ -215,7 +215,7 @@ void StubGenerator::array_overlap_test(address no_overlap_target, Label* NOLp, A __ cmpptr(to, from); __ lea(end_from, Address(from, count, sf, 0)); if (NOLp == nullptr) { - ExternalAddress no_overlap(no_overlap_target); + RuntimeAddress no_overlap(no_overlap_target); __ jump_cc(Assembler::belowEqual, no_overlap); __ cmpptr(to, end_from); __ jump_cc(Assembler::aboveEqual, no_overlap); diff --git a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp index 7e0814c014bec..62022d780a20b 100644 --- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp +++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, 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 @@ -180,7 +180,7 @@ bool os::win32::register_code_area(char *low, char *high) { MacroAssembler* masm = new MacroAssembler(&cb); pDCD = (pDynamicCodeData) masm->pc(); - masm->jump(ExternalAddress((address)&HandleExceptionFromCodeCache), rscratch1); + masm->jump(RuntimeAddress((address)&HandleExceptionFromCodeCache), rscratch1); masm->flush(); // Create an Unwind Structure specifying no unwind info From 358d77dafbe0e35d5b20340fccddc0fb8f3db82a Mon Sep 17 00:00:00 2001 From: Dmitry Chuyko Date: Fri, 9 Aug 2024 17:56:37 +0000 Subject: [PATCH 77/77] 8337657: AArch64: No need for acquire fence in safepoint poll during JNI calls Reviewed-by: phh --- src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp | 12 ++---------- .../aarch64/templateInterpreterGenerator_aarch64.cpp | 11 ++--------- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index 65c026b95abbd..8ce4230baa2b4 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -1883,16 +1883,8 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Check for safepoint operation in progress and/or pending suspend requests. { - // We need an acquire here to ensure that any subsequent load of the - // global SafepointSynchronize::_state flag is ordered after this load - // of the thread-local polling word. We don't want this poll to - // return false (i.e. not safepointing) and a later poll of the global - // SafepointSynchronize::_state spuriously to return true. - // - // This is to avoid a race when we're in a native->Java transition - // racing the code which wakes up from a safepoint. - - __ safepoint_poll(safepoint_in_progress, true /* at_return */, true /* acquire */, false /* in_nmethod */); + // No need for acquire as Java threads always disarm themselves. + __ safepoint_poll(safepoint_in_progress, true /* at_return */, false /* acquire */, false /* in_nmethod */); __ ldrw(rscratch1, Address(rthread, JavaThread::suspend_flags_offset())); __ cbnzw(rscratch1, safepoint_in_progress); __ bind(safepoint_in_progress_done); diff --git a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp index d639d9cf17ee5..ed2450a9110e5 100644 --- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp @@ -1413,15 +1413,8 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { { Label L, Continue; - // We need an acquire here to ensure that any subsequent load of the - // global SafepointSynchronize::_state flag is ordered after this load - // of the thread-local polling word. We don't want this poll to - // return false (i.e. not safepointing) and a later poll of the global - // SafepointSynchronize::_state spuriously to return true. - // - // This is to avoid a race when we're in a native->Java transition - // racing the code which wakes up from a safepoint. - __ safepoint_poll(L, true /* at_return */, true /* acquire */, false /* in_nmethod */); + // No need for acquire as Java threads always disarm themselves. + __ safepoint_poll(L, true /* at_return */, false /* acquire */, false /* in_nmethod */); __ ldrw(rscratch2, Address(rthread, JavaThread::suspend_flags_offset())); __ cbz(rscratch2, Continue); __ bind(L);