diff --git a/make/ZipSecurity.gmk b/make/ZipSecurity.gmk index f7435f05efe..4f960cd2fcd 100644 --- a/make/ZipSecurity.gmk +++ b/make/ZipSecurity.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 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 @@ -41,7 +41,6 @@ $(eval $(call SetupZipArchive,BUILD_SEC_BIN_ZIP, \ modules/java.base/sun/security/internal/interfaces \ modules/java.base/sun/security/internal/spec \ modules/java.base/com/sun/crypto/provider \ - modules/jdk.crypto.ec/sun/security/ec \ modules/jdk.crypto.mscapi/sun/security/mscapi \ modules/jdk.crypto.cryptoki/sun/security/pkcs11 \ modules/jdk.crypto.cryptoki/sun/security/pkcs11/wrapper \ diff --git a/make/conf/docs-modules.conf b/make/conf/docs-modules.conf index 09b26eae9a1..b88f6ff6d90 100644 --- a/make/conf/docs-modules.conf +++ b/make/conf/docs-modules.conf @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 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 @@ -36,7 +36,6 @@ DOCS_MODULES= \ jdk.charsets \ jdk.compiler \ jdk.crypto.cryptoki \ - jdk.crypto.ec \ jdk.dynalink \ jdk.editpad \ jdk.hotspot.agent \ diff --git a/make/conf/module-loader-map.conf b/make/conf/module-loader-map.conf index 2c95b8570fd..cc7e7d5a652 100644 --- a/make/conf/module-loader-map.conf +++ b/make/conf/module-loader-map.conf @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 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 @@ -77,7 +77,6 @@ PLATFORM_MODULES= \ jdk.accessibility \ jdk.charsets \ jdk.crypto.cryptoki \ - jdk.crypto.ec \ jdk.dynalink \ jdk.httpserver \ jdk.jsobject \ diff --git a/make/ide/netbeans/langtools/build.xml b/make/ide/netbeans/langtools/build.xml index b23614649b8..16e1a129e98 100644 --- a/make/ide/netbeans/langtools/build.xml +++ b/make/ide/netbeans/langtools/build.xml @@ -1,6 +1,6 @@ Allocate" transformation - // to be able scalar replace the allocation. - if (field_val->is_EncodeP()) { - field_val = field_val->in(1); - } else { - field_val = transform_later(new DecodeNNode(field_val, field_val->get_ptr_type())); - } +#endif + + return nullptr; + } + + if (UseCompressedOops && field_type->isa_narrowoop()) { + // Enable "DecodeN(EncodeP(Allocate)) --> Allocate" transformation + // to be able scalar replace the allocation. + if (field_val->is_EncodeP()) { + field_val = field_val->in(1); + } else { + field_val = transform_later(new DecodeNNode(field_val, field_val->get_ptr_type())); } - sfpt->add_req(field_val); } - JVMState *jvms = sfpt->jvms(); - jvms->set_endoff(sfpt->req()); + sfpt->add_req(field_val); + } + + sfpt->jvms()->set_endoff(sfpt->req()); + + return sobj; +} + +// Do scalar replacement. +bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray & safepoints) { + GrowableArray safepoints_done; + Node* res = alloc->result_cast(); + assert(res == nullptr || res->is_CheckCastPP(), "unexpected AllocateNode result"); + + // Process the safepoint uses + while (safepoints.length() > 0) { + SafePointNode* sfpt = safepoints.pop(); + SafePointScalarObjectNode* sobj = create_scalarized_object_description(alloc, sfpt); + + if (sobj == nullptr) { + undo_previous_scalarizations(safepoints_done, alloc); + return false; + } + // Now make a pass over the debug information replacing any references // to the allocated object with "sobj" - int start = jvms->debug_start(); - int end = jvms->debug_end(); - sfpt->replace_edges_in_range(res, sobj, start, end, &_igvn); + JVMState *jvms = sfpt->jvms(); + sfpt->replace_edges_in_range(res, sobj, jvms->debug_start(), jvms->debug_end(), &_igvn); _igvn._worklist.push(sfpt); - safepoints_done.append_if_missing(sfpt); // keep it for rollback + + // keep it for rollback + safepoints_done.append_if_missing(sfpt); } + return true; } @@ -1030,7 +1062,7 @@ bool PhaseMacroExpand::eliminate_allocate_node(AllocateNode *alloc) { alloc->extract_projections(&_callprojs, false /*separate_io_proj*/, false /*do_asserts*/); GrowableArray safepoints; - if (!can_eliminate_allocation(alloc, safepoints)) { + if (!can_eliminate_allocation(&_igvn, alloc, &safepoints)) { return false; } diff --git a/src/hotspot/share/opto/macro.hpp b/src/hotspot/share/opto/macro.hpp index 239c2af7143..e10326e9d87 100644 --- a/src/hotspot/share/opto/macro.hpp +++ b/src/hotspot/share/opto/macro.hpp @@ -99,8 +99,8 @@ class PhaseMacroExpand : public Phase { bool eliminate_boxing_node(CallStaticJavaNode *boxing); bool eliminate_allocate_node(AllocateNode *alloc); - bool can_eliminate_allocation(AllocateNode *alloc, GrowableArray & safepoints); - bool scalar_replacement(AllocateNode *alloc, GrowableArray & safepoints_done); + void undo_previous_scalarizations(GrowableArray safepoints_done, AllocateNode* alloc); + bool scalar_replacement(AllocateNode *alloc, GrowableArray & safepoints); void process_users_of_allocation(CallNode *alloc); void eliminate_gc_barrier(Node *p2x); @@ -205,6 +205,10 @@ class PhaseMacroExpand : public Phase { void eliminate_macro_nodes(); bool expand_macro_nodes(); + SafePointScalarObjectNode* create_scalarized_object_description(AllocateNode *alloc, SafePointNode* sfpt); + static bool can_eliminate_allocation(PhaseIterGVN *igvn, AllocateNode *alloc, GrowableArray *safepoints); + + PhaseIterGVN &igvn() const { return _igvn; } #ifndef PRODUCT diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index 5819acb08ad..ab72979ffcb 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -1517,9 +1517,38 @@ static bool stable_phi(PhiNode* phi, PhaseGVN *phase) { } return true; } + +//------------------------------split_through_phi------------------------------ +// Check whether a call to 'split_through_phi' would split this load through the +// Phi *base*. This method is essentially a copy of the validations performed +// by 'split_through_phi'. The first use of this method was in EA code as part +// of simplification of allocation merges. +bool LoadNode::can_split_through_phi_base(PhaseGVN* phase) { + Node* mem = in(Memory); + Node* address = in(Address); + intptr_t ignore = 0; + Node* base = AddPNode::Ideal_base_and_offset(address, phase, ignore); + bool base_is_phi = (base != nullptr) && base->is_Phi(); + + if (req() > 3 || !base_is_phi) { + return false; + } + + if (!mem->is_Phi()) { + if (!MemNode::all_controls_dominate(mem, base->in(0))) + return false; + } else if (base->in(0) != mem->in(0)) { + if (!MemNode::all_controls_dominate(mem, base->in(0))) { + return false; + } + } + + return true; +} + //------------------------------split_through_phi------------------------------ // Split instance or boxed field load through Phi. -Node* LoadNode::split_through_phi(PhaseGVN* phase) { +Node* LoadNode::split_through_phi(PhaseGVN* phase, bool ignore_missing_instance_id) { if (req() > 3) { assert(is_LoadVector() && Opcode() != Op_LoadVector, "load has too many inputs"); // LoadVector subclasses such as LoadVectorMasked have extra inputs that the logic below doesn't take into account @@ -1530,7 +1559,8 @@ Node* LoadNode::split_through_phi(PhaseGVN* phase) { const TypeOopPtr *t_oop = phase->type(address)->isa_oopptr(); assert((t_oop != nullptr) && - (t_oop->is_known_instance_field() || + (ignore_missing_instance_id || + t_oop->is_known_instance_field() || t_oop->is_ptr_to_boxed_value()), "invalid conditions"); Compile* C = phase->C; @@ -1542,8 +1572,8 @@ Node* LoadNode::split_through_phi(PhaseGVN* phase) { phase->type(base)->higher_equal(TypePtr::NOTNULL); if (!((mem->is_Phi() || base_is_phi) && - (load_boxed_values || t_oop->is_known_instance_field()))) { - return nullptr; // memory is not Phi + (ignore_missing_instance_id || load_boxed_values || t_oop->is_known_instance_field()))) { + return nullptr; // Neither memory or base are Phi } if (mem->is_Phi()) { @@ -1587,7 +1617,7 @@ Node* LoadNode::split_through_phi(PhaseGVN* phase) { } // Split through Phi (see original code in loopopts.cpp). - assert(C->have_alias_type(t_oop), "instance should have alias type"); + assert(ignore_missing_instance_id || C->have_alias_type(t_oop), "instance should have alias type"); // Do nothing here if Identity will find a value // (to avoid infinite chain of value phis generation). @@ -1623,16 +1653,20 @@ Node* LoadNode::split_through_phi(PhaseGVN* phase) { region = mem->in(0); } + Node* phi = nullptr; const Type* this_type = this->bottom_type(); - int this_index = C->get_alias_index(t_oop); - int this_offset = t_oop->offset(); - int this_iid = t_oop->instance_id(); - if (!t_oop->is_known_instance() && load_boxed_values) { - // Use _idx of address base for boxed values. - this_iid = base->_idx; - } PhaseIterGVN* igvn = phase->is_IterGVN(); - Node* phi = new PhiNode(region, this_type, nullptr, mem->_idx, this_iid, this_index, this_offset); + if (t_oop != nullptr && (t_oop->is_known_instance_field() || load_boxed_values)) { + int this_index = C->get_alias_index(t_oop); + int this_offset = t_oop->offset(); + int this_iid = t_oop->is_known_instance_field() ? t_oop->instance_id() : base->_idx; + phi = new PhiNode(region, this_type, nullptr, mem->_idx, this_iid, this_index, this_offset); + } else if (ignore_missing_instance_id) { + phi = new PhiNode(region, this_type, nullptr, mem->_idx); + } else { + return nullptr; + } + for (uint i = 1; i < region->req(); i++) { Node* x; Node* the_clone = nullptr; diff --git a/src/hotspot/share/opto/memnode.hpp b/src/hotspot/share/opto/memnode.hpp index d04cac90870..85f4380188d 100644 --- a/src/hotspot/share/opto/memnode.hpp +++ b/src/hotspot/share/opto/memnode.hpp @@ -244,8 +244,11 @@ class LoadNode : public MemNode { // try to hook me up to the exact initializing store. virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); + // Return true if it's possible to split the Load through a Phi merging the bases + bool can_split_through_phi_base(PhaseGVN *phase); + // Split instance field load through Phi. - Node* split_through_phi(PhaseGVN *phase); + Node* split_through_phi(PhaseGVN *phase, bool ignore_missing_instance_id = false); // Recover original value from boxed values Node *eliminate_autobox(PhaseIterGVN *igvn); diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index 73490e7be10..755374e18a9 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -158,6 +158,7 @@ class RegionNode; class RootNode; class SafePointNode; class SafePointScalarObjectNode; +class SafePointScalarMergeNode; class StartNode; class State; class StoreNode; @@ -726,6 +727,7 @@ class Node { DEFINE_CLASS_ID(UnorderedReduction, Reduction, 0) DEFINE_CLASS_ID(Con, Type, 8) DEFINE_CLASS_ID(ConI, Con, 0) + DEFINE_CLASS_ID(SafePointScalarMerge, Type, 9) DEFINE_CLASS_ID(Proj, Node, 3) @@ -953,6 +955,7 @@ class Node { DEFINE_CLASS_QUERY(Root) DEFINE_CLASS_QUERY(SafePoint) DEFINE_CLASS_QUERY(SafePointScalarObject) + DEFINE_CLASS_QUERY(SafePointScalarMerge) DEFINE_CLASS_QUERY(Start) DEFINE_CLASS_QUERY(Store) DEFINE_CLASS_QUERY(Sub) diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp index 998be5e1225..ef30f6297e0 100644 --- a/src/hotspot/share/opto/output.cpp +++ b/src/hotspot/share/opto/output.cpp @@ -749,7 +749,7 @@ void PhaseOutput::FillLocArray( int idx, MachSafePointNode* sfpt, Node *local, if (local->is_SafePointScalarObject()) { SafePointScalarObjectNode* spobj = local->as_SafePointScalarObject(); - ObjectValue* sv = sv_for_node_id(objs, spobj->_idx); + ObjectValue* sv = (ObjectValue*) sv_for_node_id(objs, spobj->_idx); if (sv == nullptr) { ciKlass* cik = t->is_oopptr()->exact_klass(); assert(cik->is_instance_klass() || @@ -766,6 +766,31 @@ void PhaseOutput::FillLocArray( int idx, MachSafePointNode* sfpt, Node *local, } array->append(sv); return; + } else if (local->is_SafePointScalarMerge()) { + SafePointScalarMergeNode* smerge = local->as_SafePointScalarMerge(); + ObjectMergeValue* mv = (ObjectMergeValue*) sv_for_node_id(objs, smerge->_idx); + + if (mv == NULL) { + GrowableArray deps; + + int merge_pointer_idx = smerge->merge_pointer_idx(sfpt->jvms()); + (void)FillLocArray(0, sfpt, sfpt->in(merge_pointer_idx), &deps, objs); + assert(deps.length() == 1, "missing value"); + + int selector_idx = smerge->selector_idx(sfpt->jvms()); + (void)FillLocArray(1, NULL, sfpt->in(selector_idx), &deps, NULL); + assert(deps.length() == 2, "missing value"); + + mv = new ObjectMergeValue(smerge->_idx, deps.at(0), deps.at(1)); + set_sv_for_object_node(objs, mv); + + for (uint i = 1; i < smerge->req(); i++) { + Node* obj_node = smerge->in(i); + (void)FillLocArray(mv->possible_objects()->length(), sfpt, obj_node, mv->possible_objects(), objs); + } + } + array->append(mv); + return; } // Grab the register number for the local @@ -931,6 +956,18 @@ bool PhaseOutput::starts_bundle(const Node *n) const { _node_bundling_base[n->_idx].starts_bundle()); } +// Determine if there is a monitor that has 'ov' as its owner. +bool PhaseOutput::contains_as_owner(GrowableArray *monarray, ObjectValue *ov) const { + for (int k = 0; k < monarray->length(); k++) { + MonitorValue* mv = monarray->at(k); + if (mv->owner() == ov) { + return true; + } + } + + return false; +} + //--------------------------Process_OopMap_Node-------------------------------- void PhaseOutput::Process_OopMap_Node(MachNode *mach, int current_offset) { // Handle special safepoint nodes for synchronization @@ -1061,6 +1098,21 @@ void PhaseOutput::Process_OopMap_Node(MachNode *mach, int current_offset) { monarray->append(new MonitorValue(scval, basic_lock, eliminated)); } + // Mark ObjectValue nodes as root nodes if they are directly + // referenced in the JVMS. + for (int i = 0; i < objs->length(); i++) { + ScopeValue* sv = objs->at(i); + if (sv->is_object_merge()) { + ObjectMergeValue* merge = sv->as_ObjectMergeValue(); + + for (int j = 0; j< merge->possible_objects()->length(); j++) { + ObjectValue* ov = merge->possible_objects()->at(j)->as_ObjectValue(); + bool is_root = locarray->contains(ov) || exparray->contains(ov) || contains_as_owner(monarray, ov); + ov->set_root(is_root); + } + } + } + // We dump the object pool first, since deoptimization reads it in first. C->debug_info()->dump_object_pool(objs); diff --git a/src/hotspot/share/opto/output.hpp b/src/hotspot/share/opto/output.hpp index d74751ddbf6..36352083419 100644 --- a/src/hotspot/share/opto/output.hpp +++ b/src/hotspot/share/opto/output.hpp @@ -210,6 +210,7 @@ class PhaseOutput : public Phase { bool valid_bundle_info(const Node *n); bool starts_bundle(const Node *n) const; + bool contains_as_owner(GrowableArray *monarray, ObjectValue *ov) const; // Dump formatted assembly #if defined(SUPPORT_OPTO_ASSEMBLY) diff --git a/src/hotspot/share/opto/vector.cpp b/src/hotspot/share/opto/vector.cpp index d74f7f95caa..1c2c9d982b5 100644 --- a/src/hotspot/share/opto/vector.cpp +++ b/src/hotspot/share/opto/vector.cpp @@ -276,11 +276,7 @@ void PhaseVector::scalarize_vbox_node(VectorBoxNode* vec_box) { SafePointNode* sfpt = safepoints.pop()->as_SafePoint(); uint first_ind = (sfpt->req() - sfpt->jvms()->scloff()); - Node* sobj = new SafePointScalarObjectNode(vec_box->box_type(), -#ifdef ASSERT - vec_box, -#endif // ASSERT - first_ind, n_fields); + Node* sobj = new SafePointScalarObjectNode(vec_box->box_type(), vec_box, first_ind, n_fields); sobj->init_req(0, C->root()); sfpt->add_req(vec_value); diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index bbf912f0080..1e60b7eac60 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -2659,7 +2659,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_m set_xdebug_mode(true); // -Xnoagent } else if (match_option(option, "-Xnoagent")) { - // For compatibility with classic. HotSpot refuses to load the old style agent.dll. + warning("Option -Xnoagent was deprecated in JDK 22 and will likely be removed in a future release."); } else if (match_option(option, "-Xloggc:", &tail)) { // Deprecated flag to redirect GC output to a file. -Xloggc: log_warning(gc)("-Xloggc is deprecated. Will use -Xlog:gc:%s instead.", tail); diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 5084bd4c4de..39afc56d9b6 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -330,7 +330,7 @@ static bool rematerialize_objects(JavaThread* thread, int exec_mode, CompiledMet assert(exec_mode == Deoptimization::Unpack_none || (deoptee_thread == thread), "a frame can only be deoptimized by the owner thread"); - GrowableArray* objects = chunk->at(0)->scope()->objects(); + GrowableArray* objects = chunk->at(0)->scope()->objects_to_rematerialize(deoptee, map); // The flag return_oop() indicates call sites which return oop // in compiled code. Such sites include java method calls, @@ -1564,6 +1564,7 @@ static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap // restore fields of all eliminated objects and arrays void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray* objects, bool realloc_failures, bool skip_internal) { for (int i = 0; i < objects->length(); i++) { + assert(objects->at(i)->is_object(), "invalid debug information"); ObjectValue* sv = (ObjectValue*) objects->at(i); Klass* k = java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()()); Handle obj = sv->value(); diff --git a/src/hotspot/share/runtime/stubRoutines.cpp b/src/hotspot/share/runtime/stubRoutines.cpp index 1f54b8871a3..c2c57c8f123 100644 --- a/src/hotspot/share/runtime/stubRoutines.cpp +++ b/src/hotspot/share/runtime/stubRoutines.cpp @@ -278,43 +278,6 @@ void StubRoutines::initialize_compiler_stubs() { } } -#ifdef ASSERT -typedef void (*arraycopy_fn)(address src, address dst, int count); - -// simple tests of generated arraycopy functions -static void test_arraycopy_func(address func, int alignment) { - int v = 0xcc; - int v2 = 0x11; - jlong lbuffer[8]; - jlong lbuffer2[8]; - address fbuffer = (address) lbuffer; - address fbuffer2 = (address) lbuffer2; - unsigned int i; - for (i = 0; i < sizeof(lbuffer); i++) { - fbuffer[i] = v; fbuffer2[i] = v2; - } - // C++ does not guarantee jlong[] array alignment to 8 bytes. - // Use middle of array to check that memory before it is not modified. - address buffer = align_up((address)&lbuffer[4], BytesPerLong); - address buffer2 = align_up((address)&lbuffer2[4], BytesPerLong); - // do an aligned copy - ((arraycopy_fn)func)(buffer, buffer2, 0); - for (i = 0; i < sizeof(lbuffer); i++) { - assert(fbuffer[i] == v && fbuffer2[i] == v2, "shouldn't have copied anything"); - } - // adjust destination alignment - ((arraycopy_fn)func)(buffer, buffer2 + alignment, 0); - for (i = 0; i < sizeof(lbuffer); i++) { - assert(fbuffer[i] == v && fbuffer2[i] == v2, "shouldn't have copied anything"); - } - // adjust source alignment - ((arraycopy_fn)func)(buffer + alignment, buffer2, 0); - for (i = 0; i < sizeof(lbuffer); i++) { - assert(fbuffer[i] == v && fbuffer2[i] == v2, "shouldn't have copied anything"); - } -} -#endif // ASSERT - void StubRoutines::initialize_final_stubs() { if (_final_stubs_code == nullptr) { _final_stubs_code = initialize_stubs(StubCodeGenerator::Final_stubs, @@ -323,90 +286,8 @@ void StubRoutines::initialize_final_stubs() { "StubRoutines (final stubs)", "_final_stubs_code_size"); } - -#ifdef ASSERT - - MACOS_AARCH64_ONLY(os::current_thread_enable_wx(WXExec)); - -#define TEST_ARRAYCOPY(type) \ - test_arraycopy_func( type##_arraycopy(), sizeof(type)); \ - test_arraycopy_func( type##_disjoint_arraycopy(), sizeof(type)); \ - test_arraycopy_func(arrayof_##type##_arraycopy(), sizeof(HeapWord)); \ - test_arraycopy_func(arrayof_##type##_disjoint_arraycopy(), sizeof(HeapWord)) - - // Make sure all the arraycopy stubs properly handle zero count - TEST_ARRAYCOPY(jbyte); - TEST_ARRAYCOPY(jshort); - TEST_ARRAYCOPY(jint); - TEST_ARRAYCOPY(jlong); - -#undef TEST_ARRAYCOPY - -#define TEST_FILL(type) \ - if (_##type##_fill != nullptr) { \ - union { \ - double d; \ - type body[96]; \ - } s; \ - \ - int v = 32; \ - for (int offset = -2; offset <= 2; offset++) { \ - for (int i = 0; i < 96; i++) { \ - s.body[i] = 1; \ - } \ - type* start = s.body + 8 + offset; \ - for (int aligned = 0; aligned < 2; aligned++) { \ - if (aligned) { \ - if (((intptr_t)start) % HeapWordSize == 0) { \ - ((void (*)(type*, int, int))StubRoutines::_arrayof_##type##_fill)(start, v, 80); \ - } else { \ - continue; \ - } \ - } else { \ - ((void (*)(type*, int, int))StubRoutines::_##type##_fill)(start, v, 80); \ - } \ - for (int i = 0; i < 96; i++) { \ - if (i < (8 + offset) || i >= (88 + offset)) { \ - assert(s.body[i] == 1, "what?"); \ - } else { \ - assert(s.body[i] == 32, "what?"); \ - } \ - } \ - } \ - } \ - } \ - - TEST_FILL(jbyte); - TEST_FILL(jshort); - TEST_FILL(jint); - -#undef TEST_FILL - -#define TEST_COPYRTN(type) \ - test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::conjoint_##type##s_atomic), sizeof(type)); \ - test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::arrayof_conjoint_##type##s), (int)MAX2(sizeof(HeapWord), sizeof(type))) - - // Make sure all the copy runtime routines properly handle zero count - TEST_COPYRTN(jbyte); - TEST_COPYRTN(jshort); - TEST_COPYRTN(jint); - TEST_COPYRTN(jlong); - -#undef TEST_COPYRTN - - test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::conjoint_words), sizeof(HeapWord)); - test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::disjoint_words), sizeof(HeapWord)); - test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::disjoint_words_atomic), sizeof(HeapWord)); - // Aligned to BytesPerLong - test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::aligned_conjoint_words), sizeof(jlong)); - test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::aligned_disjoint_words), sizeof(jlong)); - - MACOS_AARCH64_ONLY(os::current_thread_enable_wx(WXWrite)); - -#endif } - void initial_stubs_init() { StubRoutines::initialize_initial_stubs(); } void continuation_stubs_init() { StubRoutines::initialize_continuation_stubs(); } void final_stubs_init() { StubRoutines::initialize_final_stubs(); } diff --git a/src/java.base/share/classes/java/io/FileDescriptor.java b/src/java.base/share/classes/java/io/FileDescriptor.java index 6723877937c..c7e638a1675 100644 --- a/src/java.base/share/classes/java/io/FileDescriptor.java +++ b/src/java.base/share/classes/java/io/FileDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -31,6 +31,7 @@ import jdk.internal.access.JavaIOFileDescriptorAccess; import jdk.internal.access.SharedSecrets; +import jdk.internal.misc.Blocker; import jdk.internal.ref.PhantomCleanable; /** @@ -205,7 +206,17 @@ public boolean valid() { * buffers have been synchronized with physical media. * @since 1.1 */ - public native void sync() throws SyncFailedException; + public void sync() throws SyncFailedException { + long comp = Blocker.begin(); + try { + sync0(); + } finally { + Blocker.end(comp); + } + } + + /* fsync/equivalent this file descriptor */ + private native void sync0() throws SyncFailedException; /* This routine initializes JNI field offsets for the class */ private static native void initIDs(); diff --git a/src/java.base/share/classes/java/lang/invoke/IndirectVarHandle.java b/src/java.base/share/classes/java/lang/invoke/IndirectVarHandle.java index 3e804ec4f11..96d94bab409 100644 --- a/src/java.base/share/classes/java/lang/invoke/IndirectVarHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/IndirectVarHandle.java @@ -68,6 +68,7 @@ MethodType accessModeTypeUncached(AccessType at) { } @Override + @ForceInline VarHandle asDirect() { return directTarget; } @@ -75,8 +76,8 @@ VarHandle asDirect() { @Override public VarHandle withInvokeExactBehavior() { return hasInvokeExactBehavior() - ? this - : new IndirectVarHandle(target, value, coordinates, handleFactory, vform, true); + ? this + : new IndirectVarHandle(target, value, coordinates, handleFactory, vform, true); } @Override @@ -86,6 +87,7 @@ public VarHandle withInvokeBehavior() { : new IndirectVarHandle(target, value, coordinates, handleFactory, vform, false); } + @Override @ForceInline boolean checkAccessModeThenIsDirect(VarHandle.AccessDescriptor ad) { super.checkAccessModeThenIsDirect(ad); @@ -103,9 +105,4 @@ MethodHandle getMethodHandleUncached(int mode) { MethodHandle targetHandle = target.getMethodHandle(mode); // might throw UOE of access mode is not supported, which is ok return handleFactory.apply(AccessMode.values()[mode], targetHandle); } - - @Override - public MethodHandle toMethodHandle(AccessMode accessMode) { - return getMethodHandle(accessMode.ordinal()).bindTo(directTarget); - } } diff --git a/src/java.base/share/classes/java/lang/invoke/LazyInitializingVarHandle.java b/src/java.base/share/classes/java/lang/invoke/LazyInitializingVarHandle.java new file mode 100644 index 00000000000..ce992a2cd10 --- /dev/null +++ b/src/java.base/share/classes/java/lang/invoke/LazyInitializingVarHandle.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 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. + * + */ + +package java.lang.invoke; + +import jdk.internal.vm.annotation.ForceInline; +import jdk.internal.vm.annotation.Stable; + +import java.util.Optional; + +import static java.lang.invoke.MethodHandleStatics.UNSAFE; +import static java.lang.invoke.MethodHandleStatics.uncaughtException; + +/** + * A lazy initializing var handle. It lazily initializes the referenced class before + * any invocation of the target var handle to prevent reading uninitialized static + * field values. + */ +final class LazyInitializingVarHandle extends VarHandle { + + // Implementation notes: + // We put a barrier on both target() (for VH form impl direct invocation) + // and on getMethodHandle() (for indirect VH invocation, toMethodHandle) + private final VarHandle target; + private final Class refc; + private @Stable boolean initialized; + + LazyInitializingVarHandle(VarHandle target, Class refc) { + super(target.vform, target.exact); + this.target = target; + this.refc = refc; + } + + @Override + MethodType accessModeTypeUncached(AccessType at) { + return target.accessModeType(at.ordinal()); + } + + @Override + @ForceInline + VarHandle asDirect() { + return target; + } + + @Override + @ForceInline + VarHandle target() { + ensureInitialized(); + return target; + } + + @Override + public VarHandle withInvokeExactBehavior() { + if (!initialized && hasInvokeExactBehavior()) + return this; + var exactTarget = target.withInvokeExactBehavior(); + return initialized ? exactTarget : new LazyInitializingVarHandle(exactTarget, refc); + } + + @Override + public VarHandle withInvokeBehavior() { + if (!initialized && !hasInvokeExactBehavior()) + return this; + var nonExactTarget = target.withInvokeBehavior(); + return initialized ? nonExactTarget : new LazyInitializingVarHandle(nonExactTarget, refc); + } + + @Override + public Optional describeConstable() { + return target.describeConstable(); + } + + @Override + public MethodHandle getMethodHandleUncached(int accessMode) { + var mh = target.getMethodHandle(accessMode); + if (this.initialized) + return mh; + + return MethodHandles.collectArguments(mh, 0, ensureInitializedMh()).bindTo(this); + } + + @ForceInline + private void ensureInitialized() { + if (this.initialized) + return; + + initialize(); + } + + private void initialize() { + UNSAFE.ensureClassInitialized(refc); + this.initialized = true; + + this.methodHandleTable = target.methodHandleTable; + } + + private static @Stable MethodHandle MH_ensureInitialized; + + private static MethodHandle ensureInitializedMh() { + var mh = MH_ensureInitialized; + if (mh != null) + return mh; + + try { + return MH_ensureInitialized = MethodHandles.lookup().findVirtual( + LazyInitializingVarHandle.class, + "ensureInitialized", + MethodType.methodType(void.class)); + } catch (Throwable ex) { + throw uncaughtException(ex); + } + } +} diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index ee3da58e2dd..e0190ddab5a 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -4201,7 +4201,7 @@ private VarHandle getFieldVarHandleCommon(byte getRefKind, byte putRefKind, } refc = lookupClass(); } - return VarHandles.makeFieldHandle(getField, refc, getField.getFieldType(), + return VarHandles.makeFieldHandle(getField, refc, this.allowedModes == TRUSTED && !getField.isTrustedFinalField()); } /** Check access and get the requested constructor. */ @@ -8188,19 +8188,18 @@ public static VarHandle permuteCoordinates(VarHandle target, List> newC * filter function and the target var handle is then called on the modified (usually shortened) * coordinate list. *

- * If {@code R} is the return type of the filter (which cannot be void), the target var handle must accept a value of - * type {@code R} as its coordinate in position {@code pos}, preceded and/or followed by - * any coordinate not passed to the filter. - * No coordinates are reordered, and the result returned from the filter - * replaces (in order) the whole subsequence of coordinates originally - * passed to the adapter. - *

- * The argument types (if any) of the filter - * replace zero or one coordinate types of the target var handle, at position {@code pos}, - * in the resulting adapted var handle. - * The return type of the filter must be identical to the - * coordinate type of the target var handle at position {@code pos}, and that target var handle - * coordinate is supplied by the return value of the filter. + * If {@code R} is the return type of the filter, then: + *

    + *
  • if {@code R} is not {@code void}, the target var handle must have a coordinate of type {@code R} in + * position {@code pos}. The parameter types of the filter will replace the coordinate type at position {@code pos} + * of the target var handle. When the returned var handle is invoked, it will be as if the filter is invoked first, + * and its result is passed in place of the coordinate at position {@code pos} in a downstream invocation of the + * target var handle.
  • + *
  • if {@code R} is {@code void}, the parameter types (if any) of the filter will be inserted in the + * coordinate type list of the target var handle at position {@code pos}. In this case, when the returned var handle + * is invoked, the filter essentially acts as a side effect, consuming some of the coordinate values, before a + * downstream invocation of the target var handle.
  • + *
*

* If any of the filters throws a checked exception when invoked, the resulting var handle will * throw an {@link IllegalStateException}. @@ -8209,12 +8208,12 @@ public static VarHandle permuteCoordinates(VarHandle target, List> newC * atomic access guarantees as those featured by the target var handle. * * @param target the var handle to invoke after the coordinates have been filtered - * @param pos the position of the coordinate to be filtered + * @param pos the position in the coordinate list of the target var handle where the filter is to be inserted * @param filter the filter method handle * @return an adapter var handle which filters the incoming coordinate values, * before calling the target var handle * @throws IllegalArgumentException if the return type of {@code filter} - * is void, or it is not the same as the {@code pos} coordinate of the target var handle, + * is not void, and it is not the same as the {@code pos} coordinate of the target var handle, * if {@code pos} is not between 0 and the target var handle coordinate arity, inclusive, * if the resulting var handle's type would have too many coordinates, * or if it's determined that {@code filter} throws any checked exceptions. diff --git a/src/java.base/share/classes/java/lang/invoke/VarHandle.java b/src/java.base/share/classes/java/lang/invoke/VarHandle.java index 2ffa75cf12b..79607068801 100644 --- a/src/java.base/share/classes/java/lang/invoke/VarHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.java @@ -472,7 +472,8 @@ * @since 9 */ public abstract sealed class VarHandle implements Constable - permits IndirectVarHandle, VarHandleSegmentViewBase, + permits IndirectVarHandle, LazyInitializingVarHandle, + VarHandleSegmentViewBase, VarHandleByteArrayAsChars.ByteArrayViewVarHandle, VarHandleByteArrayAsDoubles.ByteArrayViewVarHandle, VarHandleByteArrayAsFloats.ByteArrayViewVarHandle, @@ -518,10 +519,23 @@ public abstract sealed class VarHandle implements Constable this.exact = exact; } - RuntimeException unsupported() { - return new UnsupportedOperationException(); + /** + * Returns the target VarHandle. Subclasses may override this method to implement + * additional logic for example lazily initializing the declaring class of a static field var handle. + */ + @ForceInline + VarHandle target() { + return asDirect(); } + /** + * Returns the direct target VarHandle. Indirect VarHandle subclasses should implement + * this method. + * + * @see #getMethodHandle(int) + * @see #checkAccessModeThenIsDirect(AccessDescriptor) + */ + @ForceInline VarHandle asDirect() { return this; } @@ -2062,13 +2076,19 @@ public final MethodType accessModeType(AccessMode accessMode) { /** * Validates that the given access descriptors method type matches up with - * the access mode of this VarHandle, then returns if this is a direct - * method handle. These operations were grouped together to slightly + * the access mode of this VarHandle, then returns if this is direct. + * These operations were grouped together to slightly * improve efficiency during startup/warmup. * + * A direct VarHandle's VarForm has implementation MemberNames that can + * be linked directly. If a VarHandle is indirect, it must override + * {@link #isAccessModeSupported} and {@link #getMethodHandleUncached} + * which access MemberNames. + * * @return true if this is a direct VarHandle, false if it's an indirect * VarHandle. * @throws WrongMethodTypeException if there's an access type mismatch + * @see #asDirect() */ @ForceInline boolean checkAccessModeThenIsDirect(VarHandle.AccessDescriptor ad) { @@ -2144,7 +2164,7 @@ public boolean isAccessModeSupported(AccessMode accessMode) { public MethodHandle toMethodHandle(AccessMode accessMode) { if (isAccessModeSupported(accessMode)) { MethodHandle mh = getMethodHandle(accessMode.ordinal()); - return mh.bindTo(this); + return mh.bindTo(asDirect()); } else { // Ensure an UnsupportedOperationException is thrown @@ -2186,6 +2206,14 @@ final MethodHandle getMethodHandle(int mode) { return mh; } + /** + * Computes a method handle that can be passed the {@linkplain #asDirect() direct} + * var handle of this var handle with the given access mode. Pre/postprocessing + * such as argument or return value filtering should be done by the returned + * method handle. + * + * @throws UnsupportedOperationException if the access mode is not supported + */ MethodHandle getMethodHandleUncached(int mode) { MethodType mt = accessModeType(AccessMode.values()[mode]). insertParameterTypes(0, VarHandle.class); @@ -2401,13 +2429,13 @@ public ClassDesc varType() { public VarHandle resolveConstantDesc(MethodHandles.Lookup lookup) throws ReflectiveOperationException { return switch (kind) { - case FIELD -> lookup.findVarHandle((Class) declaringClass.resolveConstantDesc(lookup), + case FIELD -> lookup.findVarHandle(declaringClass.resolveConstantDesc(lookup), constantName(), - (Class) varType.resolveConstantDesc(lookup)); - case STATIC_FIELD -> lookup.findStaticVarHandle((Class) declaringClass.resolveConstantDesc(lookup), + varType.resolveConstantDesc(lookup)); + case STATIC_FIELD -> lookup.findStaticVarHandle(declaringClass.resolveConstantDesc(lookup), constantName(), - (Class) varType.resolveConstantDesc(lookup)); - case ARRAY -> MethodHandles.arrayElementVarHandle((Class) declaringClass.resolveConstantDesc(lookup)); + varType.resolveConstantDesc(lookup)); + case ARRAY -> MethodHandles.arrayElementVarHandle(declaringClass.resolveConstantDesc(lookup)); default -> throw new InternalError("Cannot reach here"); }; } diff --git a/src/java.base/share/classes/java/lang/invoke/VarHandles.java b/src/java.base/share/classes/java/lang/invoke/VarHandles.java index a8bc817a9e7..c0db5ddb866 100644 --- a/src/java.base/share/classes/java/lang/invoke/VarHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/VarHandles.java @@ -53,9 +53,10 @@ protected ConcurrentMap computeValue(Class type) { } }; - static VarHandle makeFieldHandle(MemberName f, Class refc, Class type, boolean isWriteAllowedOnFinalFields) { + static VarHandle makeFieldHandle(MemberName f, Class refc, boolean isWriteAllowedOnFinalFields) { if (!f.isStatic()) { long foffset = MethodHandleNatives.objectFieldOffset(f); + Class type = f.getFieldType(); if (!type.isPrimitive()) { return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields ? new VarHandleReferences.FieldInstanceReadOnly(refc, foffset, type) @@ -106,66 +107,65 @@ else if (type == double.class) { } } else { - // TODO This is not lazy on first invocation - // and might cause some circular initialization issues - - // Replace with something similar to direct method handles - // where a barrier is used then elided after use - - if (UNSAFE.shouldBeInitialized(refc)) - UNSAFE.ensureClassInitialized(refc); - Class decl = f.getDeclaringClass(); - Object base = MethodHandleNatives.staticFieldBase(f); - long foffset = MethodHandleNatives.staticFieldOffset(f); - if (!type.isPrimitive()) { - return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields - ? new VarHandleReferences.FieldStaticReadOnly(decl, base, foffset, type) - : new VarHandleReferences.FieldStaticReadWrite(decl, base, foffset, type)); - } - else if (type == boolean.class) { - return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields - ? new VarHandleBooleans.FieldStaticReadOnly(decl, base, foffset) - : new VarHandleBooleans.FieldStaticReadWrite(decl, base, foffset)); - } - else if (type == byte.class) { - return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields - ? new VarHandleBytes.FieldStaticReadOnly(decl, base, foffset) - : new VarHandleBytes.FieldStaticReadWrite(decl, base, foffset)); - } - else if (type == short.class) { - return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields - ? new VarHandleShorts.FieldStaticReadOnly(decl, base, foffset) - : new VarHandleShorts.FieldStaticReadWrite(decl, base, foffset)); - } - else if (type == char.class) { - return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields - ? new VarHandleChars.FieldStaticReadOnly(decl, base, foffset) - : new VarHandleChars.FieldStaticReadWrite(decl, base, foffset)); - } - else if (type == int.class) { - return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields - ? new VarHandleInts.FieldStaticReadOnly(decl, base, foffset) - : new VarHandleInts.FieldStaticReadWrite(decl, base, foffset)); - } - else if (type == long.class) { - return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields - ? new VarHandleLongs.FieldStaticReadOnly(decl, base, foffset) - : new VarHandleLongs.FieldStaticReadWrite(decl, base, foffset)); - } - else if (type == float.class) { - return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields - ? new VarHandleFloats.FieldStaticReadOnly(decl, base, foffset) - : new VarHandleFloats.FieldStaticReadWrite(decl, base, foffset)); - } - else if (type == double.class) { - return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields - ? new VarHandleDoubles.FieldStaticReadOnly(decl, base, foffset) - : new VarHandleDoubles.FieldStaticReadWrite(decl, base, foffset)); - } - else { - throw new UnsupportedOperationException(); - } + var vh = makeStaticFieldVarHandle(decl, f, isWriteAllowedOnFinalFields); + return maybeAdapt(UNSAFE.shouldBeInitialized(decl) + ? new LazyInitializingVarHandle(vh, decl) + : vh); + } + } + + static VarHandle makeStaticFieldVarHandle(Class decl, MemberName f, boolean isWriteAllowedOnFinalFields) { + Object base = MethodHandleNatives.staticFieldBase(f); + long foffset = MethodHandleNatives.staticFieldOffset(f); + Class type = f.getFieldType(); + if (!type.isPrimitive()) { + return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields + ? new VarHandleReferences.FieldStaticReadOnly(decl, base, foffset, type) + : new VarHandleReferences.FieldStaticReadWrite(decl, base, foffset, type)); + } + else if (type == boolean.class) { + return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields + ? new VarHandleBooleans.FieldStaticReadOnly(decl, base, foffset) + : new VarHandleBooleans.FieldStaticReadWrite(decl, base, foffset)); + } + else if (type == byte.class) { + return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields + ? new VarHandleBytes.FieldStaticReadOnly(decl, base, foffset) + : new VarHandleBytes.FieldStaticReadWrite(decl, base, foffset)); + } + else if (type == short.class) { + return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields + ? new VarHandleShorts.FieldStaticReadOnly(decl, base, foffset) + : new VarHandleShorts.FieldStaticReadWrite(decl, base, foffset)); + } + else if (type == char.class) { + return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields + ? new VarHandleChars.FieldStaticReadOnly(decl, base, foffset) + : new VarHandleChars.FieldStaticReadWrite(decl, base, foffset)); + } + else if (type == int.class) { + return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields + ? new VarHandleInts.FieldStaticReadOnly(decl, base, foffset) + : new VarHandleInts.FieldStaticReadWrite(decl, base, foffset)); + } + else if (type == long.class) { + return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields + ? new VarHandleLongs.FieldStaticReadOnly(decl, base, foffset) + : new VarHandleLongs.FieldStaticReadWrite(decl, base, foffset)); + } + else if (type == float.class) { + return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields + ? new VarHandleFloats.FieldStaticReadOnly(decl, base, foffset) + : new VarHandleFloats.FieldStaticReadWrite(decl, base, foffset)); + } + else if (type == double.class) { + return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields + ? new VarHandleDoubles.FieldStaticReadOnly(decl, base, foffset) + : new VarHandleDoubles.FieldStaticReadWrite(decl, base, foffset)); + } + else { + throw new UnsupportedOperationException(); } } @@ -563,14 +563,14 @@ public static VarHandle collectCoordinates(VarHandle target, int pos, MethodHand List> targetCoordinates = target.coordinateTypes(); if (pos < 0 || pos >= targetCoordinates.size()) { throw newIllegalArgumentException("Invalid position " + pos + " for coordinate types", targetCoordinates); - } else if (filter.type().returnType() == void.class) { - throw newIllegalArgumentException("Invalid filter type " + filter.type() + " ; filter cannot be void"); - } else if (filter.type().returnType() != targetCoordinates.get(pos)) { + } else if (filter.type().returnType() != void.class && filter.type().returnType() != targetCoordinates.get(pos)) { throw newIllegalArgumentException("Invalid filter type " + filter.type() + " for coordinate type " + targetCoordinates.get(pos)); } List> newCoordinates = new ArrayList<>(targetCoordinates); - newCoordinates.remove(pos); + if (filter.type().returnType() != void.class) { + newCoordinates.remove(pos); + } newCoordinates.addAll(pos, filter.type().parameterList()); return new IndirectVarHandle(target, target.varType(), newCoordinates.toArray(new Class[0]), @@ -731,16 +731,7 @@ private static boolean isCheckedException(Class clazz) { // Object getAndUpdate(Object value); // } // -// static class HandleType { -// final Class receiver; -// final Class[] intermediates; -// final Class value; -// -// HandleType(Class receiver, Class value, Class... intermediates) { -// this.receiver = receiver; -// this.intermediates = intermediates; -// this.value = value; -// } +// record HandleType(Class receiver, Class value, Class... intermediates) { // } // // /** @@ -816,10 +807,8 @@ private static boolean isCheckedException(Class clazz) { // List> params = new ArrayList<>(); // if (receiver != null) // params.add(receiver); -// for (int i = 0; i < intermediates.length; i++) { -// params.add(intermediates[i]); -// } -// for (Parameter p : m.getParameters()) { +// java.util.Collections.addAll(params, intermediates); +// for (var p : m.getParameters()) { // params.add(value); // } // return MethodType.methodType(returnType, params); @@ -828,7 +817,7 @@ private static boolean isCheckedException(Class clazz) { // static String generateMethod(MethodType mt) { // Class returnType = mt.returnType(); // -// LinkedHashMap> params = new LinkedHashMap<>(); +// var params = new java.util.LinkedHashMap>(); // params.put("handle", VarHandle.class); // for (int i = 0; i < mt.parameterCount(); i++) { // params.put("arg" + i, mt.parameterType(i)); @@ -841,7 +830,7 @@ private static boolean isCheckedException(Class clazz) { // String SIGNATURE = getSignature(mt); // String PARAMS = params.entrySet().stream(). // map(e -> className(e.getValue()) + " " + e.getKey()). -// collect(joining(", ")); +// collect(java.util.stream.Collectors.joining(", ")); // String METHOD = GUARD_METHOD_SIG_TEMPLATE. // replace("", RETURN). // replace("", NAME). @@ -851,12 +840,10 @@ private static boolean isCheckedException(Class clazz) { // // Generate method // params.remove("ad"); // -// List LINK_TO_STATIC_ARGS = params.keySet().stream(). -// collect(toList()); +// List LINK_TO_STATIC_ARGS = new ArrayList<>(params.keySet()); // LINK_TO_STATIC_ARGS.add("handle.vform.getMemberName(ad.mode)"); // -// List LINK_TO_INVOKER_ARGS = params.keySet().stream(). -// collect(toList()); +// List LINK_TO_INVOKER_ARGS = new ArrayList<>(params.keySet()); // LINK_TO_INVOKER_ARGS.set(0, LINK_TO_INVOKER_ARGS.get(0) + ".asDirect()"); // // RETURN = returnType == void.class @@ -884,10 +871,8 @@ private static boolean isCheckedException(Class clazz) { // replaceAll("", RETURN). // replace("", RESULT_ERASED). // replace("", RETURN_ERASED). -// replaceAll("", LINK_TO_STATIC_ARGS.stream(). -// collect(joining(", "))). -// replace("", LINK_TO_INVOKER_ARGS.stream(). -// collect(joining(", "))) +// replaceAll("", String.join(", ", LINK_TO_STATIC_ARGS)). +// replace("", String.join(", ", LINK_TO_INVOKER_ARGS)) // .indent(4); // } // @@ -916,30 +901,7 @@ private static boolean isCheckedException(Class clazz) { // } // // static char getCharType(Class pt) { -// if (pt == void.class) { -// return 'V'; -// } -// else if (!pt.isPrimitive()) { -// return 'L'; -// } -// else if (pt == boolean.class) { -// return 'Z'; -// } -// else if (pt == int.class) { -// return 'I'; -// } -// else if (pt == long.class) { -// return 'J'; -// } -// else if (pt == float.class) { -// return 'F'; -// } -// else if (pt == double.class) { -// return 'D'; -// } -// else { -// throw new IllegalStateException(pt.getName()); -// } +// return Wrapper.forBasicType(pt).basicTypeChar(); // } // } } diff --git a/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template b/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template index 36a646e6398..4bc9daf8433 100644 --- a/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template +++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template @@ -440,28 +440,28 @@ final class VarHandle$Type$s { @ForceInline static $type$ get(VarHandle ob) { - FieldStaticReadOnly handle = (FieldStaticReadOnly)ob; + FieldStaticReadOnly handle = (FieldStaticReadOnly) ob.target(); return UNSAFE.get$Type$(handle.base, handle.fieldOffset); } @ForceInline static $type$ getVolatile(VarHandle ob) { - FieldStaticReadOnly handle = (FieldStaticReadOnly)ob; + FieldStaticReadOnly handle = (FieldStaticReadOnly) ob.target(); return UNSAFE.get$Type$Volatile(handle.base, handle.fieldOffset); } @ForceInline static $type$ getOpaque(VarHandle ob) { - FieldStaticReadOnly handle = (FieldStaticReadOnly)ob; + FieldStaticReadOnly handle = (FieldStaticReadOnly) ob.target(); return UNSAFE.get$Type$Opaque(handle.base, handle.fieldOffset); } @ForceInline static $type$ getAcquire(VarHandle ob) { - FieldStaticReadOnly handle = (FieldStaticReadOnly)ob; + FieldStaticReadOnly handle = (FieldStaticReadOnly) ob.target(); return UNSAFE.get$Type$Acquire(handle.base, handle.fieldOffset); } @@ -496,7 +496,7 @@ final class VarHandle$Type$s { @ForceInline static void set(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); UNSAFE.put$Type$(handle.base, handle.fieldOffset, {#if[Object]?handle.fieldType.cast(value):value}); @@ -504,7 +504,7 @@ final class VarHandle$Type$s { @ForceInline static void setVolatile(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); UNSAFE.put$Type$Volatile(handle.base, handle.fieldOffset, {#if[Object]?handle.fieldType.cast(value):value}); @@ -512,7 +512,7 @@ final class VarHandle$Type$s { @ForceInline static void setOpaque(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); UNSAFE.put$Type$Opaque(handle.base, handle.fieldOffset, {#if[Object]?handle.fieldType.cast(value):value}); @@ -520,7 +520,7 @@ final class VarHandle$Type$s { @ForceInline static void setRelease(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); UNSAFE.put$Type$Release(handle.base, handle.fieldOffset, {#if[Object]?handle.fieldType.cast(value):value}); @@ -529,7 +529,7 @@ final class VarHandle$Type$s { @ForceInline static boolean compareAndSet(VarHandle ob, $type$ expected, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.compareAndSet$Type$(handle.base, handle.fieldOffset, {#if[Object]?handle.fieldType.cast(expected):expected}, @@ -539,7 +539,7 @@ final class VarHandle$Type$s { @ForceInline static $type$ compareAndExchange(VarHandle ob, $type$ expected, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.compareAndExchange$Type$(handle.base, handle.fieldOffset, {#if[Object]?handle.fieldType.cast(expected):expected}, @@ -548,7 +548,7 @@ final class VarHandle$Type$s { @ForceInline static $type$ compareAndExchangeAcquire(VarHandle ob, $type$ expected, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.compareAndExchange$Type$Acquire(handle.base, handle.fieldOffset, {#if[Object]?handle.fieldType.cast(expected):expected}, @@ -557,7 +557,7 @@ final class VarHandle$Type$s { @ForceInline static $type$ compareAndExchangeRelease(VarHandle ob, $type$ expected, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.compareAndExchange$Type$Release(handle.base, handle.fieldOffset, {#if[Object]?handle.fieldType.cast(expected):expected}, @@ -566,7 +566,7 @@ final class VarHandle$Type$s { @ForceInline static boolean weakCompareAndSetPlain(VarHandle ob, $type$ expected, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.weakCompareAndSet$Type$Plain(handle.base, handle.fieldOffset, {#if[Object]?handle.fieldType.cast(expected):expected}, @@ -575,7 +575,7 @@ final class VarHandle$Type$s { @ForceInline static boolean weakCompareAndSet(VarHandle ob, $type$ expected, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.weakCompareAndSet$Type$(handle.base, handle.fieldOffset, {#if[Object]?handle.fieldType.cast(expected):expected}, @@ -584,7 +584,7 @@ final class VarHandle$Type$s { @ForceInline static boolean weakCompareAndSetAcquire(VarHandle ob, $type$ expected, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.weakCompareAndSet$Type$Acquire(handle.base, handle.fieldOffset, {#if[Object]?handle.fieldType.cast(expected):expected}, @@ -593,7 +593,7 @@ final class VarHandle$Type$s { @ForceInline static boolean weakCompareAndSetRelease(VarHandle ob, $type$ expected, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.weakCompareAndSet$Type$Release(handle.base, handle.fieldOffset, {#if[Object]?handle.fieldType.cast(expected):expected}, @@ -602,7 +602,7 @@ final class VarHandle$Type$s { @ForceInline static $type$ getAndSet(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.getAndSet$Type$(handle.base, handle.fieldOffset, {#if[Object]?handle.fieldType.cast(value):value}); @@ -610,7 +610,7 @@ final class VarHandle$Type$s { @ForceInline static $type$ getAndSetAcquire(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.getAndSet$Type$Acquire(handle.base, handle.fieldOffset, {#if[Object]?handle.fieldType.cast(value):value}); @@ -618,7 +618,7 @@ final class VarHandle$Type$s { @ForceInline static $type$ getAndSetRelease(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.getAndSet$Type$Release(handle.base, handle.fieldOffset, {#if[Object]?handle.fieldType.cast(value):value}); @@ -628,7 +628,7 @@ final class VarHandle$Type$s { @ForceInline static $type$ getAndAdd(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.getAndAdd$Type$(handle.base, handle.fieldOffset, value); @@ -636,7 +636,7 @@ final class VarHandle$Type$s { @ForceInline static $type$ getAndAddAcquire(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.getAndAdd$Type$Acquire(handle.base, handle.fieldOffset, value); @@ -644,7 +644,7 @@ final class VarHandle$Type$s { @ForceInline static $type$ getAndAddRelease(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.getAndAdd$Type$Release(handle.base, handle.fieldOffset, value); @@ -654,7 +654,7 @@ final class VarHandle$Type$s { @ForceInline static $type$ getAndBitwiseOr(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.getAndBitwiseOr$Type$(handle.base, handle.fieldOffset, value); @@ -662,7 +662,7 @@ final class VarHandle$Type$s { @ForceInline static $type$ getAndBitwiseOrRelease(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.getAndBitwiseOr$Type$Release(handle.base, handle.fieldOffset, value); @@ -670,7 +670,7 @@ final class VarHandle$Type$s { @ForceInline static $type$ getAndBitwiseOrAcquire(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.getAndBitwiseOr$Type$Acquire(handle.base, handle.fieldOffset, value); @@ -678,7 +678,7 @@ final class VarHandle$Type$s { @ForceInline static $type$ getAndBitwiseAnd(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.getAndBitwiseAnd$Type$(handle.base, handle.fieldOffset, value); @@ -686,7 +686,7 @@ final class VarHandle$Type$s { @ForceInline static $type$ getAndBitwiseAndRelease(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.getAndBitwiseAnd$Type$Release(handle.base, handle.fieldOffset, value); @@ -694,7 +694,7 @@ final class VarHandle$Type$s { @ForceInline static $type$ getAndBitwiseAndAcquire(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.getAndBitwiseAnd$Type$Acquire(handle.base, handle.fieldOffset, value); @@ -702,7 +702,7 @@ final class VarHandle$Type$s { @ForceInline static $type$ getAndBitwiseXor(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.getAndBitwiseXor$Type$(handle.base, handle.fieldOffset, value); @@ -710,7 +710,7 @@ final class VarHandle$Type$s { @ForceInline static $type$ getAndBitwiseXorRelease(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.getAndBitwiseXor$Type$Release(handle.base, handle.fieldOffset, value); @@ -718,7 +718,7 @@ final class VarHandle$Type$s { @ForceInline static $type$ getAndBitwiseXorAcquire(VarHandle ob, $type$ value) { - FieldStaticReadWrite handle = (FieldStaticReadWrite)ob; + FieldStaticReadWrite handle = (FieldStaticReadWrite) ob.target(); return UNSAFE.getAndBitwiseXor$Type$Acquire(handle.base, handle.fieldOffset, value); diff --git a/src/java.base/share/classes/java/nio/charset/Charset.java b/src/java.base/share/classes/java/nio/charset/Charset.java index 83dc81ba259..2958825e80c 100644 --- a/src/java.base/share/classes/java/nio/charset/Charset.java +++ b/src/java.base/share/classes/java/nio/charset/Charset.java @@ -954,15 +954,15 @@ public final ByteBuffer encode(String str) { * @return A negative integer, zero, or a positive integer as this charset * is less than, equal to, or greater than the specified charset */ + @Override public final int compareTo(Charset that) { return (name().compareToIgnoreCase(that.name())); } /** - * Computes a hashcode for this charset. - * - * @return An integer hashcode + * {@return the hashcode for this charset} */ + @Override public final int hashCode() { return name().hashCode(); } @@ -976,19 +976,17 @@ public final int hashCode() { * @return {@code true} if, and only if, this charset is equal to the * given object */ + @Override public final boolean equals(Object ob) { - if (!(ob instanceof Charset)) - return false; if (this == ob) return true; - return name.equals(((Charset)ob).name()); + return ob instanceof Charset other && name.equals(other.name()); } /** - * Returns a string describing this charset. - * - * @return A string describing this charset + * {@return a string describing this charset} */ + @Override public final String toString() { return name(); } diff --git a/src/java.base/share/classes/java/nio/file/Path.java b/src/java.base/share/classes/java/nio/file/Path.java index d121f438a4f..e5699a96849 100644 --- a/src/java.base/share/classes/java/nio/file/Path.java +++ b/src/java.base/share/classes/java/nio/file/Path.java @@ -984,6 +984,7 @@ public Path next() { * @return {@code true} if, and only if, the given object is a {@code Path} * that is identical to this {@code Path} */ + @Override boolean equals(Object other); /** @@ -995,10 +996,11 @@ public Path next() { * * @return the hash-code value for this path */ + @Override int hashCode(); /** - * Returns the string representation of this path. + * {@return the string representation of this path} * *

If this path was created by converting a path string using the * {@link FileSystem#getPath getPath} method then the path string returned @@ -1006,8 +1008,7 @@ public Path next() { * *

The returned path string uses the default name {@link * FileSystem#getSeparator separator} to separate names in the path. - * - * @return the string representation of this path */ + @Override String toString(); } diff --git a/src/java.base/share/classes/java/nio/file/attribute/AclEntry.java b/src/java.base/share/classes/java/nio/file/attribute/AclEntry.java index 9c00313591b..6f535410e02 100644 --- a/src/java.base/share/classes/java/nio/file/attribute/AclEntry.java +++ b/src/java.base/share/classes/java/nio/file/attribute/AclEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -357,10 +357,6 @@ public boolean equals(Object ob) { return true; } - private static int hash(int h, Object o) { - return h * 127 + o.hashCode(); - } - /** * Returns the hash-code value for this ACL entry. * @@ -370,14 +366,12 @@ private static int hash(int h, Object o) { @Override public int hashCode() { // return cached hash if available - if (hash != 0) - return hash; - int h = type.hashCode(); - h = hash(h, who); - h = hash(h, perms); - h = hash(h, flags); - hash = h; - return hash; + int h = hash; + if (h == 0) { + h = Objects.hash(type, who, perms, flags); + hash = h; + } + return h; } /** diff --git a/src/java.base/share/classes/java/nio/file/attribute/FileTime.java b/src/java.base/share/classes/java/nio/file/attribute/FileTime.java index 7cb3a3ea803..8a5989bf80a 100644 --- a/src/java.base/share/classes/java/nio/file/attribute/FileTime.java +++ b/src/java.base/share/classes/java/nio/file/attribute/FileTime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -291,7 +291,7 @@ else if (secs >= MAX_SECOND) */ @Override public boolean equals(Object obj) { - return (obj instanceof FileTime) ? compareTo((FileTime)obj) == 0 : false; + return obj instanceof FileTime other && compareTo(other) == 0; } /** diff --git a/src/java.base/share/classes/java/security/AccessController.java b/src/java.base/share/classes/java/security/AccessController.java index 62fcdf03ff0..6128681abb6 100644 --- a/src/java.base/share/classes/java/security/AccessController.java +++ b/src/java.base/share/classes/java/security/AccessController.java @@ -778,6 +778,13 @@ private static boolean isPrivileged() { T result = action.run(); assert isPrivileged(); // sanity check invariant + // The 'getStackAccessControlContext' call inside 'isPrivileged' + // requires that no Local was scalar replaced. However, in some + // situations, after inlining, 'result' (or part of a possibly + // allocation merge Phi leading to it) might become NonEscaping and get + // scalar replaced. The call below enforces 'result' to always escape. + ensureMaterializedForStackWalk(result); + // Keep these alive across the run() call so they can be // retrieved by getStackAccessControlContext(). Reference.reachabilityFence(context); @@ -809,6 +816,13 @@ private static boolean isPrivileged() { T result = action.run(); assert isPrivileged(); // sanity check invariant + // The 'getStackAccessControlContext' call inside 'isPrivileged' + // requires that no Local was scalar replaced. However, in some + // situations, after inlining, 'result' (or part of a possibly + // allocation merge Phi leading to it) might become NonEscaping and get + // scalar replaced. The call below enforces 'result' to always escape. + ensureMaterializedForStackWalk(result); + // Keep these alive across the run() call so they can be // retrieved by getStackAccessControlContext(). Reference.reachabilityFence(context); diff --git a/src/java.base/share/classes/java/util/TimeZone.java b/src/java.base/share/classes/java/util/TimeZone.java index c530d33c629..1a91caf8df0 100644 --- a/src/java.base/share/classes/java/util/TimeZone.java +++ b/src/java.base/share/classes/java/util/TimeZone.java @@ -130,8 +130,8 @@ * use is deprecated because the same abbreviation is often used * for multiple time zones (for example, "CST" could be U.S. "Central Standard * Time" and "China Standard Time"), and the Java platform can then only - * recognize one of them. - * + * recognize one of them. The full list of deprecated three-letter time + * zone IDs and their mappings can be viewed at {@link java.time.ZoneId#SHORT_IDS}. * * @see Calendar * @see GregorianCalendar diff --git a/src/java.base/share/classes/jdk/internal/classfile/Classfile.java b/src/java.base/share/classes/jdk/internal/classfile/Classfile.java index 7b2910e1059..e7cc0628cbe 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/Classfile.java +++ b/src/java.base/share/classes/jdk/internal/classfile/Classfile.java @@ -690,7 +690,12 @@ default byte[] transform(ClassModel model, ClassDesc newClassName, ClassTransfor int JAVA_21_VERSION = 65; int JAVA_22_VERSION = 66; - int PREVIEW_MINOR_VERSION = -1; + /** + * A minor version number indicating a class uses preview features + * of a Java SE version since 12, for major versions {@value + * #JAVA_12_VERSION} and above. + */ + int PREVIEW_MINOR_VERSION = 65535; static int latestMajorVersion() { return JAVA_22_VERSION; diff --git a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java index beca81ad815..c80d67005ae 100644 --- a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java +++ b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java @@ -1137,10 +1137,33 @@ public void forEachRemaining(DoubleConsumer consumer) { } } + /** + * Largest value that {@link #computeNextExponential} can ever return. + */ + private static final double MAX_EXPONENTIAL = 0x1.0p63 * DoubleZigguratTables.exponentialX0; + /** * Implementation support for the {@code nextExponential} method of * {@link java.util.random.RandomGenerator}. * + * @param rng an instance of {@code RandomGenerator}, used to generate uniformly + * pseudorandomly chosen {@code long} values + * + * @return a nonnegative {@code double} value chosen pseudorandomly + * from an exponential distribution whose mean is 1 + */ + public static double computeNextExponential(RandomGenerator rng) { + return computeNextExponentialSoftCapped(rng, MAX_EXPONENTIAL); + } + + /** + * Generates a pseudorandom value {@code x} such that {@code Math.min(x, maxValue)} + * follows the same distribution as it would if {@code x} was exponentially distributed + * with mean 1, but with a worst-case number of calls to {@link + * RandomGenerator#nextLong()} that's linear with {@code maxValue}. {@code maxValue} is + * a "soft" cap in that a value larger than {@code maxValue} may be returned in order + * to save a calculation. + * * Certain details of the algorithm used in this method may depend critically * on the quality of the low-order bits delivered by {@code nextLong()}. This method * should not be used with RNG algorithms (such as a simple Linear Congruential @@ -1157,7 +1180,7 @@ public void forEachRemaining(DoubleConsumer consumer) { * @return a nonnegative {@code double} value chosen pseudorandomly * from an exponential distribution whose mean is 1 */ - public static double computeNextExponential(RandomGenerator rng) { + public static double computeNextExponentialSoftCapped(RandomGenerator rng, double maxValue) { /* * The tables themselves, as well as a number of associated parameters, are * defined in class DoubleZigguratTables, which is automatically @@ -1186,9 +1209,18 @@ public static double computeNextExponential(RandomGenerator rng) { // This is the fast path (occurring more than 98% of the time). Make an early exit. return DoubleZigguratTables.exponentialX[(int)i] * (U1 >>> 1); } - // We didn't use the upper part of U1 after all. We'll be able to use it later. - - for (double extra = 0.0; ; ) { + // We didn't use the upper part of U1 after all. We'll probably be able to use it later. + if (maxValue <= 0.0) { + return 0.0; + } + final long maxExtraMinus1; + if (maxValue >= MAX_EXPONENTIAL) { + maxExtraMinus1 = Long.MAX_VALUE; + } else { + // Conversion to long rounds toward zero + maxExtraMinus1 = (long) (maxValue / DoubleZigguratTables.exponentialX0); + } + for (long extra = 0; ; ) { // Use Walker's alias method to sample an (unsigned) integer j from a discrete // probability distribution that includes the tail and all the ziggurat overhangs; // j will be less than DoubleZigguratTables.exponentialNumberOfLayers + 1. @@ -1219,25 +1251,29 @@ public static double computeNextExponential(RandomGenerator rng) { // Compute the actual x-coordinate of the randomly chosen point. double x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1); if (Udiff >= DoubleZigguratTables.exponentialConvexMargin) { - return x + extra; // The chosen point is way below the curve; accept it. + return Math.fma(extra, DoubleZigguratTables.exponentialX0, x); // The chosen point is way below the curve; accept it. } // Compute the actual y-coordinate of the randomly chosen point. double y = (Y[j] * 0x1.0p63) + ((Y[j-1] - Y[j]) * (double)U2); // Now see how that y-coordinate compares to the curve if (y <= Math.exp(-x)) { - return x + extra; // The chosen point is below the curve; accept it. + return Math.fma(extra, DoubleZigguratTables.exponentialX0, x); // The chosen point is below the curve; accept it. } // Otherwise, we reject this sample and have to try again. } } + if (extra == maxExtraMinus1) { + // We've reached the maximum, so don't waste any more time + return maxValue; + } // We are now committed to sampling from the tail. We could do a recursive call // and then add X[0], but we save some time and stack space by using an iterative loop. - extra += DoubleZigguratTables.exponentialX0; - // This is like the first five lines of this method, but if it returns, it first adds "extra". + extra++; + // This is like the first five lines of this method, but if it returns, it first adds "extra" times X0. U1 = rng.nextLong(); i = U1 & DoubleZigguratTables.exponentialLayerMask; if (i < DoubleZigguratTables.exponentialNumberOfLayers) { - return DoubleZigguratTables.exponentialX[(int)i] * (U1 >>> 1) + extra; + return Math.fma(extra, DoubleZigguratTables.exponentialX0, DoubleZigguratTables.exponentialX[(int)i] * (U1 >>> 1)); } } } @@ -1359,9 +1395,11 @@ public static double computeNextGaussian(RandomGenerator rng) { // ACM Comput. Surv. 39, 4, Article 11 (November 2007). See Algorithm 16. // http://doi.org/10.1145/1287620.1287622 // Compute two separate random exponential samples and then compare them in certain way. + double limit; do { x = (1.0 / DoubleZigguratTables.normalX0) * computeNextExponential(rng); - } while (computeNextExponential(rng) < 0.5*x*x); + limit = 0.5*x*x; + } while (computeNextExponentialSoftCapped(rng, limit) < limit); x += DoubleZigguratTables.normalX0; } else if (j < DoubleZigguratTables.normalInflectionIndex) { // Convex overhang for (;; U1 = (rng.nextLong() >>> 1)) { @@ -1392,7 +1430,7 @@ public static double computeNextGaussian(RandomGenerator rng) { for (;; U1 = (rng.nextLong() >>> 1)) { long U2 = (rng.nextLong() >>> 1); // Compute the actual x-coordinate of the randomly chosen point. - x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1); + x = Math.fma(X[j-1] - X[j], (double)U1, X[j] * 0x1.0p63); // Does the point lie below the curve? long Udiff = U2 - U1; if (Udiff >= DoubleZigguratTables.normalConvexMargin) { @@ -1402,7 +1440,7 @@ public static double computeNextGaussian(RandomGenerator rng) { continue; // The chosen point is way above the curve; reject it. } // Compute the actual y-coordinate of the randomly chosen point. - double y = (Y[j] * 0x1.0p63) + ((Y[j-1] - Y[j]) * (double)U2); + double y = Math.fma(Y[j-1] - Y[j], (double)U2, Y[j] * 0x1.0p63); // Now see how that y-coordinate compares to the curve if (y <= Math.exp(-0.5*x*x)) { break; // The chosen point is below the curve; accept it. diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index ac0ed7bee41..bf3d34abd7a 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -322,25 +322,21 @@ java.sql.rowset; exports sun.security.action to java.desktop, - java.security.jgss, - jdk.crypto.ec; + java.security.jgss; exports sun.security.internal.interfaces to jdk.crypto.cryptoki; exports sun.security.internal.spec to jdk.crypto.cryptoki; exports sun.security.jca to java.smartcardio, - jdk.crypto.ec, jdk.crypto.cryptoki, jdk.naming.dns; exports sun.security.pkcs to - jdk.crypto.ec, jdk.jartool; exports sun.security.provider to java.rmi, java.security.jgss, jdk.crypto.cryptoki, - jdk.crypto.ec, jdk.security.auth; exports sun.security.provider.certpath to java.naming, @@ -359,17 +355,11 @@ java.security.sasl, java.smartcardio, java.xml.crypto, - jdk.crypto.ec, jdk.crypto.cryptoki, jdk.jartool, jdk.security.auth, jdk.security.jgss; - exports sun.security.util.math to - jdk.crypto.ec; - exports sun.security.util.math.intpoly to - jdk.crypto.ec; exports sun.security.x509 to - jdk.crypto.ec, jdk.crypto.cryptoki, jdk.jartool; exports sun.security.validator to diff --git a/src/java.base/share/classes/sun/launcher/LauncherHelper.java b/src/java.base/share/classes/sun/launcher/LauncherHelper.java index 8985077df37..58a6be5fa1e 100644 --- a/src/java.base/share/classes/sun/launcher/LauncherHelper.java +++ b/src/java.base/share/classes/sun/launcher/LauncherHelper.java @@ -170,7 +170,7 @@ static void showSettings(boolean printToStderr, String optionFlag, printProperties(); break; case "locale": - printLocale(); + printLocale(false); break; case "security": var opt = opts.length > 2 ? opts[2].trim() : "all"; @@ -184,7 +184,7 @@ static void showSettings(boolean printToStderr, String optionFlag, default: printVmSettings(initialHeapSize, maxHeapSize, stackSize); printProperties(); - printLocale(); + printLocale(true); SecuritySettings.printSecuritySummarySettings(ostream); if (OperatingSystem.isLinux()) { printSystemMetrics(); @@ -280,9 +280,15 @@ private static void printPropertyValue(String key, String value) { /* * prints the locale subopt/section */ - private static void printLocale() { + private static void printLocale(boolean summaryMode) { Locale locale = Locale.getDefault(); - ostream.println(LOCALE_SETTINGS); + if (!summaryMode) { + ostream.println(LOCALE_SETTINGS); + } else { + ostream.println("Locale settings summary:"); + ostream.println(INDENT + "Use \"-XshowSettings:locale\" " + + "option for verbose locale settings options"); + } ostream.println(INDENT + "default locale = " + locale.getDisplayName()); ostream.println(INDENT + "default display locale = " + @@ -291,7 +297,9 @@ private static void printLocale() { Locale.getDefault(Category.FORMAT).getDisplayName()); ostream.println(INDENT + "tzdata version = " + ZoneInfoFile.getVersion()); - printLocales(); + if (!summaryMode) { + printLocales(); + } ostream.println(); } diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDHKeyAgreement.java b/src/java.base/share/classes/sun/security/ec/ECDHKeyAgreement.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ECDHKeyAgreement.java rename to src/java.base/share/classes/sun/security/ec/ECDHKeyAgreement.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSAOperations.java b/src/java.base/share/classes/sun/security/ec/ECDSAOperations.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSAOperations.java rename to src/java.base/share/classes/sun/security/ec/ECDSAOperations.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java b/src/java.base/share/classes/sun/security/ec/ECDSASignature.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java rename to src/java.base/share/classes/sun/security/ec/ECDSASignature.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECKeyFactory.java b/src/java.base/share/classes/sun/security/ec/ECKeyFactory.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ECKeyFactory.java rename to src/java.base/share/classes/sun/security/ec/ECKeyFactory.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECKeyPairGenerator.java b/src/java.base/share/classes/sun/security/ec/ECKeyPairGenerator.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ECKeyPairGenerator.java rename to src/java.base/share/classes/sun/security/ec/ECKeyPairGenerator.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECOperations.java b/src/java.base/share/classes/sun/security/ec/ECOperations.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ECOperations.java rename to src/java.base/share/classes/sun/security/ec/ECOperations.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPrivateKeyImpl.java b/src/java.base/share/classes/sun/security/ec/ECPrivateKeyImpl.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ECPrivateKeyImpl.java rename to src/java.base/share/classes/sun/security/ec/ECPrivateKeyImpl.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPublicKeyImpl.java b/src/java.base/share/classes/sun/security/ec/ECPublicKeyImpl.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ECPublicKeyImpl.java rename to src/java.base/share/classes/sun/security/ec/ECPublicKeyImpl.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ParametersMap.java b/src/java.base/share/classes/sun/security/ec/ParametersMap.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ParametersMap.java rename to src/java.base/share/classes/sun/security/ec/ParametersMap.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java b/src/java.base/share/classes/sun/security/ec/SunEC.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java rename to src/java.base/share/classes/sun/security/ec/SunEC.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyAgreement.java b/src/java.base/share/classes/sun/security/ec/XDHKeyAgreement.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyAgreement.java rename to src/java.base/share/classes/sun/security/ec/XDHKeyAgreement.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyFactory.java b/src/java.base/share/classes/sun/security/ec/XDHKeyFactory.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyFactory.java rename to src/java.base/share/classes/sun/security/ec/XDHKeyFactory.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyPairGenerator.java b/src/java.base/share/classes/sun/security/ec/XDHKeyPairGenerator.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyPairGenerator.java rename to src/java.base/share/classes/sun/security/ec/XDHKeyPairGenerator.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPrivateKeyImpl.java b/src/java.base/share/classes/sun/security/ec/XDHPrivateKeyImpl.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPrivateKeyImpl.java rename to src/java.base/share/classes/sun/security/ec/XDHPrivateKeyImpl.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPublicKeyImpl.java b/src/java.base/share/classes/sun/security/ec/XDHPublicKeyImpl.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPublicKeyImpl.java rename to src/java.base/share/classes/sun/security/ec/XDHPublicKeyImpl.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/XECOperations.java b/src/java.base/share/classes/sun/security/ec/XECOperations.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/XECOperations.java rename to src/java.base/share/classes/sun/security/ec/XECOperations.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/XECParameters.java b/src/java.base/share/classes/sun/security/ec/XECParameters.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/XECParameters.java rename to src/java.base/share/classes/sun/security/ec/XECParameters.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ed/Ed25519Operations.java b/src/java.base/share/classes/sun/security/ec/ed/Ed25519Operations.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ed/Ed25519Operations.java rename to src/java.base/share/classes/sun/security/ec/ed/Ed25519Operations.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ed/Ed448Operations.java b/src/java.base/share/classes/sun/security/ec/ed/Ed448Operations.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ed/Ed448Operations.java rename to src/java.base/share/classes/sun/security/ec/ed/Ed448Operations.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAAlgorithmParameters.java b/src/java.base/share/classes/sun/security/ec/ed/EdDSAAlgorithmParameters.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAAlgorithmParameters.java rename to src/java.base/share/classes/sun/security/ec/ed/EdDSAAlgorithmParameters.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAKeyFactory.java b/src/java.base/share/classes/sun/security/ec/ed/EdDSAKeyFactory.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAKeyFactory.java rename to src/java.base/share/classes/sun/security/ec/ed/EdDSAKeyFactory.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAKeyPairGenerator.java b/src/java.base/share/classes/sun/security/ec/ed/EdDSAKeyPairGenerator.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAKeyPairGenerator.java rename to src/java.base/share/classes/sun/security/ec/ed/EdDSAKeyPairGenerator.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAOperations.java b/src/java.base/share/classes/sun/security/ec/ed/EdDSAOperations.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAOperations.java rename to src/java.base/share/classes/sun/security/ec/ed/EdDSAOperations.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAParameters.java b/src/java.base/share/classes/sun/security/ec/ed/EdDSAParameters.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAParameters.java rename to src/java.base/share/classes/sun/security/ec/ed/EdDSAParameters.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAPrivateKeyImpl.java b/src/java.base/share/classes/sun/security/ec/ed/EdDSAPrivateKeyImpl.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAPrivateKeyImpl.java rename to src/java.base/share/classes/sun/security/ec/ed/EdDSAPrivateKeyImpl.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAPublicKeyImpl.java b/src/java.base/share/classes/sun/security/ec/ed/EdDSAPublicKeyImpl.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAPublicKeyImpl.java rename to src/java.base/share/classes/sun/security/ec/ed/EdDSAPublicKeyImpl.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSASignature.java b/src/java.base/share/classes/sun/security/ec/ed/EdDSASignature.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSASignature.java rename to src/java.base/share/classes/sun/security/ec/ed/EdDSASignature.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdECOperations.java b/src/java.base/share/classes/sun/security/ec/ed/EdECOperations.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdECOperations.java rename to src/java.base/share/classes/sun/security/ec/ed/EdECOperations.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/point/AffinePoint.java b/src/java.base/share/classes/sun/security/ec/point/AffinePoint.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/point/AffinePoint.java rename to src/java.base/share/classes/sun/security/ec/point/AffinePoint.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/point/ExtendedHomogeneousPoint.java b/src/java.base/share/classes/sun/security/ec/point/ExtendedHomogeneousPoint.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/point/ExtendedHomogeneousPoint.java rename to src/java.base/share/classes/sun/security/ec/point/ExtendedHomogeneousPoint.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/point/ImmutablePoint.java b/src/java.base/share/classes/sun/security/ec/point/ImmutablePoint.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/point/ImmutablePoint.java rename to src/java.base/share/classes/sun/security/ec/point/ImmutablePoint.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/point/MutablePoint.java b/src/java.base/share/classes/sun/security/ec/point/MutablePoint.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/point/MutablePoint.java rename to src/java.base/share/classes/sun/security/ec/point/MutablePoint.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/point/Point.java b/src/java.base/share/classes/sun/security/ec/point/Point.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/point/Point.java rename to src/java.base/share/classes/sun/security/ec/point/Point.java diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/point/ProjectivePoint.java b/src/java.base/share/classes/sun/security/ec/point/ProjectivePoint.java similarity index 100% rename from src/jdk.crypto.ec/share/classes/sun/security/ec/point/ProjectivePoint.java rename to src/java.base/share/classes/sun/security/ec/point/ProjectivePoint.java diff --git a/src/java.base/share/classes/sun/security/jca/ProviderConfig.java b/src/java.base/share/classes/sun/security/jca/ProviderConfig.java index 06f5144e9b2..90106674b9d 100644 --- a/src/java.base/share/classes/sun/security/jca/ProviderConfig.java +++ b/src/java.base/share/classes/sun/security/jca/ProviderConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -176,57 +176,60 @@ Provider getProvider() { return null; } - // Create providers which are in java.base directly - if (provName.equals("SUN") || provName.equals("sun.security.provider.Sun")) { - p = new sun.security.provider.Sun(); - } else if (provName.equals("SunRsaSign") || provName.equals("sun.security.rsa.SunRsaSign")) { - p = new sun.security.rsa.SunRsaSign(); - } else if (provName.equals("SunJCE") || provName.equals("com.sun.crypto.provider.SunJCE")) { - p = new com.sun.crypto.provider.SunJCE(); - } else if (provName.equals("SunJSSE")) { - p = new sun.security.ssl.SunJSSE(); - } else if (provName.equals("Apple") || provName.equals("apple.security.AppleProvider")) { - // need to use reflection since this class only exists on MacOsx - @SuppressWarnings("removal") - var tmp = AccessController.doPrivileged(new PrivilegedAction() { - public Provider run() { - try { - Class c = Class.forName("apple.security.AppleProvider"); - if (Provider.class.isAssignableFrom(c)) { - @SuppressWarnings("deprecation") - Object tmp = c.newInstance(); - return (Provider) tmp; - } else { + p = switch (provName) { + case "SUN", "sun.security.provider.Sun" -> + new sun.security.provider.Sun(); + case "SunRsaSign", "sun.security.rsa.SunRsaSign" -> + new sun.security.rsa.SunRsaSign(); + case "SunJCE", "com.sun.crypto.provider.SunJCE" -> + new com.sun.crypto.provider.SunJCE(); + case "SunJSSE" -> new sun.security.ssl.SunJSSE(); + case "SunEC" -> new sun.security.ec.SunEC(); + case "Apple", "apple.security.AppleProvider" -> { + // Reflection is needed for compile time as the class + // is not available for non-macosx systems + @SuppressWarnings("removal") + var tmp = AccessController.doPrivileged( + new PrivilegedAction() { + public Provider run() { + try { + Class c = Class.forName( + "apple.security.AppleProvider"); + if (Provider.class.isAssignableFrom(c)) { + @SuppressWarnings("deprecation") + Object tmp = c.newInstance(); + return (Provider) tmp; + } + } catch (Exception ex) { + if (debug != null) { + debug.println("Error loading provider Apple"); + ex.printStackTrace(); + } + } return null; } - } catch (Exception ex) { - if (debug != null) { - debug.println("Error loading provider Apple"); - ex.printStackTrace(); - } - return null; + }); + yield tmp; + } + default -> { + if (isLoading) { + // because this method is synchronized, this can only + // happen if there is recursion. + if (debug != null) { + debug.println("Recursion loading provider: " + this); + new Exception("Call trace").printStackTrace(); } + yield null; } - }); - p = tmp; - } else { - if (isLoading) { - // because this method is synchronized, this can only - // happen if there is recursion. - if (debug != null) { - debug.println("Recursion loading provider: " + this); - new Exception("Call trace").printStackTrace(); + try { + isLoading = true; + tries++; + yield doLoadProvider(); + } finally { + isLoading = false; } - return null; } - try { - isLoading = true; - tries++; - p = doLoadProvider(); - } finally { - isLoading = false; - } - } + }; provider = p; } return p; diff --git a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java index b4129964662..2dbfdcdca41 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java @@ -650,8 +650,10 @@ private void duplexCloseOutput() throws IOException { // Use user_canceled alert regardless the protocol versions. useUserCanceled = true; - // The protocol version may have been negotiated. - ProtocolVersion pv = conContext.handshakeContext.negotiatedProtocol; + // The protocol version may have been negotiated. The + // conContext.handshakeContext.negotiatedProtocol is not used as there + // may be a race to set it to null. + ProtocolVersion pv = conContext.protocolVersion; if (pv == null || (!pv.useTLS13PlusSpec())) { hasCloseReceipt = true; } @@ -1386,7 +1388,6 @@ public String getHandshakeApplicationProtocol() { } finally { socketLock.unlock(); } - return null; } diff --git a/src/java.base/share/classes/sun/security/x509/AlgorithmId.java b/src/java.base/share/classes/sun/security/x509/AlgorithmId.java index a78b50665d5..1f8dbe368bd 100644 --- a/src/java.base/share/classes/sun/security/x509/AlgorithmId.java +++ b/src/java.base/share/classes/sun/security/x509/AlgorithmId.java @@ -544,8 +544,8 @@ private static boolean isKnownProvider(Provider p) { if (pn != null && mn != null) { return ((mn.equals("java.base") && (pn.equals("SUN") || pn.equals("SunRsaSign") || - pn.equals("SunJCE") || pn.equals("SunJSSE"))) || - (mn.equals("jdk.crypto.ec") && pn.equals("SunEC")) || + pn.equals("SunJCE") || pn.equals("SunJSSE") || + pn.equals("SunEC"))) || (mn.equals("jdk.crypto.mscapi") && pn.equals("SunMSCAPI")) || (mn.equals("jdk.crypto.cryptoki") && pn.startsWith("SunPKCS11"))); diff --git a/src/java.base/share/lib/security/default.policy b/src/java.base/share/lib/security/default.policy index 86d45147709..33774adce08 100644 --- a/src/java.base/share/lib/security/default.policy +++ b/src/java.base/share/lib/security/default.policy @@ -127,15 +127,6 @@ grant codeBase "jrt:/jdk.charsets" { permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.cs"; }; -grant codeBase "jrt:/jdk.crypto.ec" { - permission java.lang.RuntimePermission - "accessClassInPackage.sun.security.*"; - permission java.lang.RuntimePermission "loadLibrary.sunec"; - permission java.security.SecurityPermission "putProviderProperty.SunEC"; - permission java.security.SecurityPermission "clearProviderProperties.SunEC"; - permission java.security.SecurityPermission "removeProviderProperty.SunEC"; -}; - grant codeBase "jrt:/jdk.crypto.cryptoki" { permission java.lang.RuntimePermission "accessClassInPackage.com.sun.crypto.provider"; diff --git a/src/java.base/unix/classes/sun/nio/ch/FileKey.java b/src/java.base/unix/classes/sun/nio/ch/FileKey.java index 0c3111464d7..e60e63f073d 100644 --- a/src/java.base/unix/classes/sun/nio/ch/FileKey.java +++ b/src/java.base/unix/classes/sun/nio/ch/FileKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -44,22 +44,19 @@ public static FileKey create(FileDescriptor fd) throws IOException { return fk; } + @Override public int hashCode() { return (int)(st_dev ^ (st_dev >>> 32)) + (int)(st_ino ^ (st_ino >>> 32)); } + @Override public boolean equals(Object obj) { if (obj == this) return true; - if (!(obj instanceof FileKey)) - return false; - FileKey other = (FileKey)obj; - if ((this.st_dev != other.st_dev) || - (this.st_ino != other.st_ino)) { - return false; - } - return true; + return obj instanceof FileKey other + && (this.st_dev == other.st_dev) + && (this.st_ino == other.st_ino); } private native void init(FileDescriptor fd) throws IOException; diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileKey.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileKey.java index 92a2f44cc1b..29b1325f3e6 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileKey.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -48,10 +48,9 @@ public int hashCode() { public boolean equals(Object obj) { if (obj == this) return true; - if (!(obj instanceof UnixFileKey)) - return false; - UnixFileKey other = (UnixFileKey)obj; - return (this.st_dev == other.st_dev) && (this.st_ino == other.st_ino); + return obj instanceof UnixFileKey other + && (this.st_dev == other.st_dev) + && (this.st_ino == other.st_ino); } @Override diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java index 0d793dc69bb..7f9348a81cb 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -234,9 +234,8 @@ public boolean supportsFileAttributeView(String name) { public boolean equals(Object ob) { if (ob == this) return true; - if (!(ob instanceof UnixFileStore)) + if (!(ob instanceof UnixFileStore other)) return false; - UnixFileStore other = (UnixFileStore)ob; return (this.dev == other.dev) && Arrays.equals(this.entry.dir(), other.entry.dir()) && this.entry.name().equals(other.entry.name()); diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixPath.java b/src/java.base/unix/classes/sun/nio/fs/UnixPath.java index 044c9321856..1a9b61fd803 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixPath.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixPath.java @@ -37,10 +37,12 @@ import java.nio.file.WatchKey; import java.nio.file.WatchService; import java.nio.file.spi.FileSystemProvider; +import java.util.Arrays; import java.util.Objects; import jdk.internal.access.JavaLangAccess; import jdk.internal.access.SharedSecrets; +import jdk.internal.util.ArraysSupport; import static sun.nio.fs.UnixConstants.*; import static sun.nio.fs.UnixNativeDispatcher.*; @@ -706,43 +708,17 @@ public boolean endsWith(Path other) { // compare bytes int thisPos = offsets[thisOffsetCount - thatOffsetCount]; int thatPos = that.offsets[0]; - if ((thatLen - thatPos) != (thisLen - thisPos)) - return false; - while (thatPos < thatLen) { - if (this.path[thisPos++] != that.path[thatPos++]) - return false; - } - - return true; + return Arrays.equals(this.path, thisPos, thisLen, that.path, thatPos, thatLen); } @Override public int compareTo(Path other) { - int len1 = path.length; - int len2 = ((UnixPath) other).path.length; - - int n = Math.min(len1, len2); - byte v1[] = path; - byte v2[] = ((UnixPath) other).path; - - int k = 0; - while (k < n) { - int c1 = v1[k] & 0xff; - int c2 = v2[k] & 0xff; - if (c1 != c2) { - return c1 - c2; - } - k++; - } - return len1 - len2; + return Arrays.compareUnsigned(path, ((UnixPath) other).path); } @Override public boolean equals(Object ob) { - if (ob instanceof UnixPath path) { - return compareTo(path) == 0; - } - return false; + return ob instanceof UnixPath p && compareTo(p) == 0; } @Override @@ -750,9 +726,8 @@ public int hashCode() { // OK if two or more threads compute hash int h = hash; if (h == 0) { - for (int i = 0; i< path.length; i++) { - h = 31*h + (path[i] & 0xff); - } + h = ArraysSupport.vectorizedHashCode(path, 0, path.length, 0, + /* unsigned bytes */ ArraysSupport.T_BOOLEAN); hash = h; } return h; diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixUserPrincipals.java b/src/java.base/unix/classes/sun/nio/fs/UnixUserPrincipals.java index 5b7612ac710..26da60fe2f8 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixUserPrincipals.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixUserPrincipals.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -81,9 +81,8 @@ public String toString() { public boolean equals(Object obj) { if (obj == this) return true; - if (!(obj instanceof User)) + if (!(obj instanceof User other)) return false; - User other = (User)obj; if ((this.id != other.id) || (this.isGroup != other.isGroup)) { return false; diff --git a/src/java.base/unix/native/libjava/FileDescriptor_md.c b/src/java.base/unix/native/libjava/FileDescriptor_md.c index 54268f10a91..095249bbcf2 100644 --- a/src/java.base/unix/native/libjava/FileDescriptor_md.c +++ b/src/java.base/unix/native/libjava/FileDescriptor_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -58,7 +58,7 @@ Java_java_io_FileDescriptor_initIDs(JNIEnv *env, jclass fdClass) { */ JNIEXPORT void JNICALL -Java_java_io_FileDescriptor_sync(JNIEnv *env, jobject this) { +Java_java_io_FileDescriptor_sync0(JNIEnv *env, jobject this) { FD fd = THIS_FD(this); if (IO_Sync(fd) == -1) { JNU_ThrowByName(env, "java/io/SyncFailedException", "sync failed"); diff --git a/src/java.base/windows/classes/sun/nio/ch/FileKey.java b/src/java.base/windows/classes/sun/nio/ch/FileKey.java index a3fe2550232..1f212ca2ba3 100644 --- a/src/java.base/windows/classes/sun/nio/ch/FileKey.java +++ b/src/java.base/windows/classes/sun/nio/ch/FileKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -45,24 +45,21 @@ public static FileKey create(FileDescriptor fd) throws IOException { return fk; } + @Override public int hashCode() { return (int)(dwVolumeSerialNumber ^ (dwVolumeSerialNumber >>> 32)) + (int)(nFileIndexHigh ^ (nFileIndexHigh >>> 32)) + - (int)(nFileIndexLow ^ (nFileIndexHigh >>> 32)); + (int)(nFileIndexLow ^ (nFileIndexLow >>> 32)); } + @Override public boolean equals(Object obj) { if (obj == this) return true; - if (!(obj instanceof FileKey)) - return false; - FileKey other = (FileKey)obj; - if ((this.dwVolumeSerialNumber != other.dwVolumeSerialNumber) || - (this.nFileIndexHigh != other.nFileIndexHigh) || - (this.nFileIndexLow != other.nFileIndexLow)) { - return false; - } - return true; + return obj instanceof FileKey other + && this.dwVolumeSerialNumber == other.dwVolumeSerialNumber + && this.nFileIndexHigh == other.nFileIndexHigh + && this.nFileIndexLow == other.nFileIndexLow; } private native void init(FileDescriptor fd) throws IOException; diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java b/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java index 332454e987a..c3dc204bb9d 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -812,10 +812,7 @@ public int compareTo(Path obj) { @Override public boolean equals(Object obj) { - if (obj instanceof WindowsPath path) { - return compareTo(path) == 0; - } - return false; + return obj instanceof WindowsPath other && compareTo(other) == 0; } @Override @@ -823,7 +820,7 @@ public int hashCode() { // OK if two or more threads compute hash int h = hash; if (h == 0) { - for (int i = 0; i< path.length(); i++) { + for (int i = 0; i < path.length(); i++) { h = 31*h + Character.toUpperCase(path.charAt(i)); } hash = h; diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsUserPrincipals.java b/src/java.base/windows/classes/sun/nio/fs/WindowsUserPrincipals.java index 32d206883cf..cdb66296a63 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsUserPrincipals.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsUserPrincipals.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -80,10 +80,8 @@ public String toString() { public boolean equals(Object obj) { if (obj == this) return true; - if (!(obj instanceof WindowsUserPrincipals.User)) - return false; - WindowsUserPrincipals.User other = (WindowsUserPrincipals.User)obj; - return this.sidString.equals(other.sidString); + return obj instanceof WindowsUserPrincipals.User other + && this.sidString.equals(other.sidString); } @Override diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java b/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java index d5b82285075..d051c833ee7 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -231,12 +231,10 @@ public int hashCode() { public boolean equals(Object obj) { if (obj == this) return true; - if (!(obj instanceof FileKey)) - return false; - FileKey other = (FileKey)obj; - if (this.volSerialNumber != other.volSerialNumber) return false; - if (this.fileIndexHigh != other.fileIndexHigh) return false; - return this.fileIndexLow == other.fileIndexLow; + return obj instanceof FileKey other + && this.volSerialNumber == other.volSerialNumber + && this.fileIndexHigh == other.fileIndexHigh + && this.fileIndexLow == other.fileIndexLow; } } diff --git a/src/java.base/windows/native/libjava/FileDescriptor_md.c b/src/java.base/windows/native/libjava/FileDescriptor_md.c index cae8e395ff0..f0a20cf0553 100644 --- a/src/java.base/windows/native/libjava/FileDescriptor_md.c +++ b/src/java.base/windows/native/libjava/FileDescriptor_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -61,7 +61,7 @@ Java_java_io_FileDescriptor_initIDs(JNIEnv *env, jclass fdClass) { */ JNIEXPORT void JNICALL -Java_java_io_FileDescriptor_sync(JNIEnv *env, jobject this) { +Java_java_io_FileDescriptor_sync0(JNIEnv *env, jobject this) { FD fd = THIS_FD(this); if (IO_Sync(fd) == -1) { JNU_ThrowByName(env, "java/io/SyncFailedException", "sync failed"); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java index 3fa1ff96676..072ff606b5b 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -28,7 +28,6 @@ import java.awt.BasicStroke; import java.awt.Color; import java.awt.Component; -import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; @@ -175,7 +174,7 @@ public static Icon createFrameResizeIcon() { @SuppressWarnings("serial") // Same-version serialization only private static class FrameButtonIcon implements Icon, Serializable { - private Part part; + private final Part part; private FrameButtonIcon(Part part) { this.part = part; @@ -286,18 +285,10 @@ public int getIconWidth() { int width; if (XPStyle.getXP() != null) { // Fix for XP bug where sometimes these sizes aren't updated properly - // Assume for now that height is correct and derive width using the - // ratio from the uxtheme part - width = UIManager.getInt("InternalFrame.titleButtonHeight") -2; - Dimension d = XPStyle.getPartSize(Part.WP_CLOSEBUTTON, State.NORMAL); - if (d != null && d.width != 0 && d.height != 0) { - width = (int) ((float) width * d.width / d.height); - } + // Assume for now that height is correct and derive width from height + width = UIManager.getInt("InternalFrame.titleButtonHeight") + 10; } else { - width = UIManager.getInt("InternalFrame.titleButtonWidth") -2; - } - if (XPStyle.getXP() != null) { - width -= 2; + width = UIManager.getInt("InternalFrame.titleButtonHeight") - 2; } return width; } diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java index 83717d6bf93..cd0987a9079 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -25,20 +25,46 @@ package com.sun.java.swing.plaf.windows; -import sun.swing.SwingUtilities2; - -import javax.swing.*; -import javax.swing.border.*; -import javax.swing.UIManager; -import javax.swing.plaf.*; -import javax.swing.plaf.basic.BasicInternalFrameTitlePane; -import java.awt.*; -import java.awt.event.*; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Paint; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyVetoException; -import static com.sun.java.swing.plaf.windows.TMSchema.*; +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.JSeparator; +import javax.swing.LookAndFeel; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.border.Border; +import javax.swing.plaf.UIResource; +import javax.swing.plaf.basic.BasicInternalFrameTitlePane; + +import sun.swing.SwingUtilities2; + +import static com.sun.java.swing.plaf.windows.TMSchema.Part; +import static com.sun.java.swing.plaf.windows.TMSchema.Prop; +import static com.sun.java.swing.plaf.windows.TMSchema.State; import static com.sun.java.swing.plaf.windows.XPStyle.Skin; @SuppressWarnings("serial") // Superclass is not serializable across versions @@ -68,7 +94,6 @@ protected void installDefaults() { super.installDefaults(); titlePaneHeight = UIManager.getInt("InternalFrame.titlePaneHeight"); - buttonWidth = UIManager.getInt("InternalFrame.titleButtonWidth") - 4; buttonHeight = UIManager.getInt("InternalFrame.titleButtonHeight") - 4; Object obj = UIManager.get("InternalFrame.titleButtonToolTipsOn"); @@ -77,15 +102,10 @@ protected void installDefaults() { if (XPStyle.getXP() != null) { // Fix for XP bug where sometimes these sizes aren't updated properly - // Assume for now that height is correct and derive width using the - // ratio from the uxtheme part - buttonWidth = buttonHeight; - Dimension d = XPStyle.getPartSize(Part.WP_CLOSEBUTTON, State.NORMAL); - if (d != null && d.width != 0 && d.height != 0) { - buttonWidth = (int) ((float) buttonWidth * d.width / d.height); - } + // Assume for now that height is correct and derive width from height + buttonWidth = buttonHeight + 14; } else { - buttonWidth += 2; + buttonWidth = buttonHeight + 2; Color activeBorderColor = UIManager.getColor("InternalFrame.activeBorderColor"); setBorder(BorderFactory.createLineBorder(activeBorderColor, 1)); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index 0d94e4bd351..d897dc3ef24 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -773,15 +773,16 @@ private boolean exhausts(JCExpression selector, List cases) { patternSet.add(new BindingPattern(e.getKey().type)); } } - List patterns = List.from(patternSet); + Set patterns = patternSet; try { boolean repeat = true; while (repeat) { - List updatedPatterns; + Set updatedPatterns; updatedPatterns = reduceBindingPatterns(selector.type, patterns); updatedPatterns = reduceNestedPatterns(updatedPatterns); updatedPatterns = reduceRecordPatterns(updatedPatterns); - repeat = updatedPatterns != patterns; + updatedPatterns = removeCoveredRecordPatterns(updatedPatterns); + repeat = !updatedPatterns.equals(patterns); patterns = updatedPatterns; if (checkCovered(selector.type, patterns)) { return true; @@ -794,7 +795,7 @@ private boolean exhausts(JCExpression selector, List cases) { } } - private boolean checkCovered(Type seltype, List patterns) { + private boolean checkCovered(Type seltype, Iterable patterns) { for (Type seltypeComponent : components(seltype)) { for (PatternDescription pd : patterns) { if (pd instanceof BindingPattern bp && @@ -830,7 +831,7 @@ private List components(Type seltype) { * is found, it is removed, and replaced with a binding pattern * for the sealed supertype. */ - private List reduceBindingPatterns(Type selectorType, List patterns) { + private Set reduceBindingPatterns(Type selectorType, Set patterns) { Set existingBindings = patterns.stream() .filter(pd -> pd instanceof BindingPattern) .map(pd -> ((BindingPattern) pd).type.tsym) @@ -838,7 +839,6 @@ private List reduceBindingPatterns(Type selectorType, List

toRemove = new HashSet<>(); Set toAdd = new HashSet<>(); for (Type sup : types.directSupertypes(bpOne.type)) { @@ -871,7 +871,6 @@ private List reduceBindingPatterns(Type selectorType, List

currentPermittedSubTypes = allPermittedSubTypes((ClassSymbol) bpOther.type.tsym, s -> true); @@ -888,33 +887,21 @@ private List reduceBindingPatterns(Type selectorType, List

newPatterns = new HashSet<>(patterns); + newPatterns.addAll(toAdd); + return newPatterns; } } } @@ -958,7 +945,7 @@ private Set allPermittedSubTypes(ClassSymbol root, Predicate reduceNestedPatterns(List patterns) { + private Set reduceNestedPatterns(Set patterns) { /* implementation note: * finding a sub-set of patterns that only differ in a single * column is time-consuming task, so this method speeds it up by: @@ -977,13 +964,14 @@ private List reduceNestedPatterns(List p for (var e : groupByRecordClass.entrySet()) { int nestedPatternsCount = e.getKey().getRecordComponents().size(); + Set current = new HashSet<>(e.getValue()); for (int mismatchingCandidate = 0; mismatchingCandidate < nestedPatternsCount; mismatchingCandidate++) { int mismatchingCandidateFin = mismatchingCandidate; var groupByHashes = - e.getValue() + current .stream() //error recovery, ignore patterns with incorrect number of nested patterns: .filter(pd -> pd.nested.length == nestedPatternsCount) @@ -1018,37 +1006,35 @@ private List reduceNestedPatterns(List p } } - var nestedPatterns = join.stream().map(rp -> rp.nested[mismatchingCandidateFin]).collect(List.collector()); + var nestedPatterns = join.stream().map(rp -> rp.nested[mismatchingCandidateFin]).collect(Collectors.toSet()); var updatedPatterns = reduceNestedPatterns(nestedPatterns); updatedPatterns = reduceRecordPatterns(updatedPatterns); + updatedPatterns = removeCoveredRecordPatterns(updatedPatterns); updatedPatterns = reduceBindingPatterns(rpOne.fullComponentTypes()[mismatchingCandidateFin], updatedPatterns); - if (nestedPatterns != updatedPatterns) { - ListBuffer result = new ListBuffer<>(); - Set toRemove = Collections.newSetFromMap(new IdentityHashMap<>()); - - toRemove.addAll(join); - - for (PatternDescription p : patterns) { - if (!toRemove.contains(p)) { - result.append(p); - } - } + if (!nestedPatterns.equals(updatedPatterns)) { + current.removeAll(join); for (PatternDescription nested : updatedPatterns) { PatternDescription[] newNested = Arrays.copyOf(rpOne.nested, rpOne.nested.length); newNested[mismatchingCandidateFin] = nested; - result.append(new RecordPattern(rpOne.recordType(), + current.add(new RecordPattern(rpOne.recordType(), rpOne.fullComponentTypes(), newNested)); } - return result.toList(); } } } } + + if (!current.equals(new HashSet<>(e.getValue()))) { + Set result = new HashSet<>(patterns); + result.removeAll(e.getValue()); + result.addAll(current); + return result; + } } return patterns; } @@ -1058,22 +1044,22 @@ private List reduceNestedPatterns(List p * all the $nestedX pattern cover the given record component, * and replace those with a simple binding pattern over $record. */ - private List reduceRecordPatterns(List patterns) { - var newPatterns = new ListBuffer(); + private Set reduceRecordPatterns(Set patterns) { + var newPatterns = new HashSet(); boolean modified = false; for (PatternDescription pd : patterns) { if (pd instanceof RecordPattern rpOne) { PatternDescription reducedPattern = reduceRecordPattern(rpOne); if (reducedPattern != rpOne) { - newPatterns.append(reducedPattern); + newPatterns.add(reducedPattern); modified = true; continue; } } - newPatterns.append(pd); + newPatterns.add(pd); } - return modified ? newPatterns.toList() : patterns; - } + return modified ? newPatterns : patterns; + } private PatternDescription reduceRecordPattern(PatternDescription pattern) { if (pattern instanceof RecordPattern rpOne) { @@ -1105,6 +1091,23 @@ private PatternDescription reduceRecordPattern(PatternDescription pattern) { return pattern; } + private Set removeCoveredRecordPatterns(Set patterns) { + Set existingBindings = patterns.stream() + .filter(pd -> pd instanceof BindingPattern) + .map(pd -> ((BindingPattern) pd).type.tsym) + .collect(Collectors.toSet()); + Set result = new HashSet<>(patterns); + + for (Iterator it = result.iterator(); it.hasNext();) { + PatternDescription pd = it.next(); + if (pd instanceof RecordPattern rp && existingBindings.contains(rp.recordType.tsym)) { + it.remove(); + } + } + + return result; + } + public void visitTry(JCTry tree) { ListBuffer prevPendingExits = pendingExits; pendingExits = new ListBuffer<>(); diff --git a/src/jdk.crypto.cryptoki/share/classes/module-info.java b/src/jdk.crypto.cryptoki/share/classes/module-info.java index 3c90b6dfe6c..57388fb8851 100644 --- a/src/jdk.crypto.cryptoki/share/classes/module-info.java +++ b/src/jdk.crypto.cryptoki/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -32,8 +32,5 @@ * @since 9 */ module jdk.crypto.cryptoki { - // Depends on SunEC provider for EC related functionality - requires jdk.crypto.ec; - provides java.security.Provider with sun.security.pkcs11.SunPKCS11; } diff --git a/src/jdk.crypto.ec/share/classes/module-info.java b/src/jdk.crypto.ec/share/classes/module-info.java index 9ba6e6195e3..2e1569c928a 100644 --- a/src/jdk.crypto.ec/share/classes/module-info.java +++ b/src/jdk.crypto.ec/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -31,6 +31,6 @@ * @moduleGraph * @since 9 */ +@Deprecated(since="22", forRemoval = true) module jdk.crypto.ec { - provides java.security.Provider with sun.security.ec.SunEC; } diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java index 806c8d352bf..66af78e53d2 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -636,20 +636,7 @@ public boolean equals(Object obj) { @Override public int compareTo(Path other) { final ZipPath o = checkPath(other); - int len1 = this.path.length; - int len2 = o.path.length; - - int n = Math.min(len1, len2); - - int k = 0; - while (k < n) { - int c1 = this.path[k] & 0xff; - int c2 = o.path[k] & 0xff; - if (c1 != c2) - return c1 - c2; - k++; - } - return len1 - len2; + return Arrays.compareUnsigned(this.path, o.path); } public WatchKey register( diff --git a/test/hotspot/gtest/runtime/test_stubRoutines.cpp b/test/hotspot/gtest/runtime/test_stubRoutines.cpp new file mode 100644 index 00000000000..1dc1d0197b5 --- /dev/null +++ b/test/hotspot/gtest/runtime/test_stubRoutines.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1997, 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. + * + * 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" +#include "runtime/stubRoutines.hpp" +#include "utilities/copy.hpp" +#include "unittest.hpp" + +typedef void (*arraycopy_fn)(address src, address dst, int count); + +// simple tests of generated arraycopy functions +static void test_arraycopy_func(address func, int alignment) { + int v = 0xcc; + int v2 = 0x11; + jlong lbuffer[8]; + jlong lbuffer2[8]; + address fbuffer = (address) lbuffer; + address fbuffer2 = (address) lbuffer2; + unsigned int i; + for (i = 0; i < sizeof(lbuffer); i++) { + fbuffer[i] = v; fbuffer2[i] = v2; + } + // C++ does not guarantee jlong[] array alignment to 8 bytes. + // Use middle of array to check that memory before it is not modified. + address buffer = align_up((address)&lbuffer[4], BytesPerLong); + address buffer2 = align_up((address)&lbuffer2[4], BytesPerLong); + // do an aligned copy + ((arraycopy_fn)func)(buffer, buffer2, 0); + for (i = 0; i < sizeof(lbuffer); i++) { + ASSERT_TRUE(fbuffer[i] == v && fbuffer2[i] == v2) << "shouldn't have copied anything"; + } + // adjust destination alignment + ((arraycopy_fn)func)(buffer, buffer2 + alignment, 0); + for (i = 0; i < sizeof(lbuffer); i++) { + ASSERT_TRUE(fbuffer[i] == v && fbuffer2[i] == v2) << "shouldn't have copied anything"; + } + // adjust source alignment + ((arraycopy_fn)func)(buffer + alignment, buffer2, 0); + for (i = 0; i < sizeof(lbuffer); i++) { + ASSERT_TRUE(fbuffer[i] == v && fbuffer2[i] == v2) << "shouldn't have copied anything"; + } +} + +TEST_VM(StubRoutines, array_copy_routine) { + MACOS_AARCH64_ONLY(os::current_thread_enable_wx(WXExec)); + +#define TEST_ARRAYCOPY(type) \ + test_arraycopy_func( StubRoutines::type##_arraycopy(), sizeof(type)); \ + test_arraycopy_func( StubRoutines::type##_disjoint_arraycopy(), sizeof(type)); \ + test_arraycopy_func(StubRoutines::arrayof_##type##_arraycopy(), sizeof(HeapWord)); \ + test_arraycopy_func(StubRoutines::arrayof_##type##_disjoint_arraycopy(), sizeof(HeapWord)) + + // Make sure all the arraycopy stubs properly handle zero count + TEST_ARRAYCOPY(jbyte); + TEST_ARRAYCOPY(jshort); + TEST_ARRAYCOPY(jint); + TEST_ARRAYCOPY(jlong); + +#undef TEST_ARRAYCOPY + + MACOS_AARCH64_ONLY(os::current_thread_enable_wx(WXWrite)); +} + +TEST_VM(StubRoutines, copy_routine) { + MACOS_AARCH64_ONLY(os::current_thread_enable_wx(WXExec)); + +#define TEST_COPYRTN(type) \ + test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::conjoint_##type##s_atomic), sizeof(type)); \ + test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::arrayof_conjoint_##type##s), (int)MAX2(sizeof(HeapWord), sizeof(type))) + + // Make sure all the copy runtime routines properly handle zero count + TEST_COPYRTN(jbyte); + TEST_COPYRTN(jshort); + TEST_COPYRTN(jint); + TEST_COPYRTN(jlong); + +#undef TEST_COPYRTN + + test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::conjoint_words), sizeof(HeapWord)); + test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::disjoint_words), sizeof(HeapWord)); + test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::disjoint_words_atomic), sizeof(HeapWord)); + // Aligned to BytesPerLong + test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::aligned_conjoint_words), sizeof(jlong)); + test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::aligned_disjoint_words), sizeof(jlong)); + + MACOS_AARCH64_ONLY(os::current_thread_enable_wx(WXWrite)); +} + +TEST_VM(StubRoutines, array_fill_routine) { + MACOS_AARCH64_ONLY(os::current_thread_enable_wx(WXExec)); + +#define TEST_FILL(type) \ + if (StubRoutines::_##type##_fill != nullptr) { \ + union { \ + double d; \ + type body[96]; \ + } s; \ + \ + int v = 32; \ + for (int offset = -2; offset <= 2; offset++) { \ + for (int i = 0; i < 96; i++) { \ + s.body[i] = 1; \ + } \ + type* start = s.body + 8 + offset; \ + for (int aligned = 0; aligned < 2; aligned++) { \ + if (aligned) { \ + if (((intptr_t)start) % HeapWordSize == 0) { \ + ((void (*)(type*, int, int))StubRoutines::_arrayof_##type##_fill)(start, v, 80); \ + } else { \ + continue; \ + } \ + } else { \ + ((void (*)(type*, int, int))StubRoutines::_##type##_fill)(start, v, 80); \ + } \ + for (int i = 0; i < 96; i++) { \ + if (i < (8 + offset) || i >= (88 + offset)) { \ + ASSERT_TRUE(s.body[i] == 1) << "what?"; \ + } else { \ + ASSERT_TRUE(s.body[i] == 32) << "what?"; \ + } \ + } \ + } \ + } \ + } \ + + TEST_FILL(jbyte); + TEST_FILL(jshort); + TEST_FILL(jint); + +#undef TEST_FILL + + MACOS_AARCH64_ONLY(os::current_thread_enable_wx(WXWrite)); +} diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index c05c2b2e7c9..b031d253d22 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -104,6 +104,7 @@ runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all runtime/ErrorHandling/TestDwarf.java 8305489 linux-all applications/jcstress/copy.java 8229852 linux-all +applications/ctw/modules/jdk_crypto_ec.java 8312194 generic-all containers/docker/TestJcmd.java 8278102 linux-all containers/docker/TestMemoryAwareness.java 8303470 linux-x64 @@ -117,6 +118,7 @@ serviceability/sa/TestRevPtrsForInvokeDynamic.java 8241235 generic-all serviceability/jvmti/ModuleAwareAgents/ThreadStart/MAAThreadStart.java 8225354 windows-all serviceability/jvmti/vthread/GetSetLocalTest/GetSetLocalTest.java 8286836 generic-all +serviceability/jvmti/vthread/VThreadTLSTest/VThreadTLSTest.java#id1 8300051 generic-all serviceability/dcmd/gc/RunFinalizationTest.java 8227120 linux-all,windows-x64 serviceability/sa/ClhsdbCDSCore.java 8267433 macosx-x64 diff --git a/test/hotspot/jtreg/compiler/c2/irTests/scalarReplacement/AllocationMergesTests.java b/test/hotspot/jtreg/compiler/c2/irTests/scalarReplacement/AllocationMergesTests.java new file mode 100644 index 00000000000..aa2f39ef6e6 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/scalarReplacement/AllocationMergesTests.java @@ -0,0 +1,1413 @@ +/* + * Copyright (c) 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. + * + * 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 compiler.c2.irTests.scalarReplacement; + +import java.util.Random; +import jdk.test.lib.Asserts; +import compiler.lib.ir_framework.*; + +/* + * @test + * @bug 8281429 + * @summary Tests that C2 can correctly scalar replace some object allocation merges. + * @library /test/lib / + * @requires vm.debug == true & vm.bits == 64 & vm.compiler2.enabled & vm.opt.final.UseCompressedOops & vm.opt.final.EliminateAllocations + * @run driver compiler.c2.irTests.scalarReplacement.AllocationMergesTests + */ +public class AllocationMergesTests { + private int invocations = 0; + private static Point global_escape = new Point(2022, 2023); + + public static void main(String[] args) { + TestFramework.runWithFlags("-XX:+UnlockDiagnosticVMOptions", + "-XX:+ReduceAllocationMerges", + "-XX:+TraceReduceAllocationMerges", + "-XX:+DeoptimizeALot", + "-XX:CompileCommand=exclude,*::dummy*"); + } + + // ------------------ No Scalar Replacement Should Happen in The Tests Below ------------------- // + + @Run(test = {"testGlobalEscape_C2", + "testArgEscape_C2", + "testEscapeInCallAfterMerge_C2", + "testNoEscapeWithWriteInLoop_C2", + "testPollutedWithWrite_C2", + "testPollutedPolymorphic_C2", + "testMergedLoadAfterDirectStore_C2", + "testMergedAccessAfterCallWithWrite_C2", + "testLoadAfterTrap_C2", + "testCondAfterMergeWithNull_C2", + "testLoadAfterLoopAlias_C2", + "testCallTwoSide_C2", + "testMergedAccessAfterCallNoWrite_C2", + "testCmpMergeWithNull_Second_C2", + "testObjectIdentity_C2", + "testSubclassesTrapping_C2", + "testCmpMergeWithNull_C2", + "testSubclasses_C2", + "testPartialPhis_C2", + "testPollutedNoWrite_C2", + "testThreeWayAliasedAlloc_C2", + "TestTrapAfterMerge_C2", + "testNestedObjectsObject_C2", + "testNestedObjectsNoEscapeObject_C2", + "testNestedObjectsArray_C2", + "testTrappingAfterMerge_C2", + "testSimpleAliasedAlloc_C2", + "testSimpleDoubleMerge_C2", + "testConsecutiveSimpleMerge_C2", + "testDoubleIfElseMerge_C2", + "testNoEscapeWithLoadInLoop_C2", + "testCmpAfterMerge_C2", + "testCondAfterMergeWithAllocate_C2", + "testCondLoadAfterMerge_C2", + "testIfElseInLoop_C2", + "testLoadInCondAfterMerge_C2", + "testLoadInLoop_C2", + "testMergesAndMixedEscape_C2", + "testSRAndNSR_NoTrap_C2", + "testSRAndNSR_Trap_C2", + "testString_one_C2", + "testString_two_C2" + }) + public void runner(RunInfo info) { + Random random = info.getRandom(); + boolean cond1 = random.nextBoolean(); + boolean cond2 = random.nextBoolean(); + + int l = random.nextInt(); + int w = random.nextInt(); + int x = random.nextInt(); + int y = random.nextInt(); + int z = random.nextInt(); + + Asserts.assertEQ(testGlobalEscape_Interp(x, y), testGlobalEscape_C2(x, y)); + Asserts.assertEQ(testArgEscape_Interp(x, y), testArgEscape_C2(x, y)); + Asserts.assertEQ(testEscapeInCallAfterMerge_Interp(cond1, cond2, x, y), testEscapeInCallAfterMerge_C2(cond1, cond2, x, y)); + Asserts.assertEQ(testNoEscapeWithWriteInLoop_Interp(cond1, cond2, x, y), testNoEscapeWithWriteInLoop_C2(cond1, cond2, x, y)); + Asserts.assertEQ(testPollutedWithWrite_Interp(cond1, x), testPollutedWithWrite_C2(cond1, x)); + Asserts.assertEQ(testPollutedPolymorphic_Interp(cond1, x), testPollutedPolymorphic_C2(cond1, x)); + Asserts.assertEQ(testMergedLoadAfterDirectStore_Interp(cond1, x, y), testMergedLoadAfterDirectStore_C2(cond1, x, y)); + Asserts.assertEQ(testMergedAccessAfterCallWithWrite_Interp(cond1, x, y), testMergedAccessAfterCallWithWrite_C2(cond1, x, y)); + Asserts.assertEQ(testLoadAfterTrap_Interp(cond1, x, y), testLoadAfterTrap_C2(cond1, x, y)); + Asserts.assertEQ(testCondAfterMergeWithNull_Interp(cond1, cond2, x, y), testCondAfterMergeWithNull_C2(cond1, cond2, x, y)); + Asserts.assertEQ(testLoadAfterLoopAlias_Interp(cond1, x, y), testLoadAfterLoopAlias_C2(cond1, x, y)); + Asserts.assertEQ(testCallTwoSide_Interp(cond1, x, y), testCallTwoSide_C2(cond1, x, y)); + Asserts.assertEQ(testMergedAccessAfterCallNoWrite_Interp(cond1, x, y), testMergedAccessAfterCallNoWrite_C2(cond1, x, y)); + Asserts.assertEQ(testCmpMergeWithNull_Second_Interp(cond1, x, y), testCmpMergeWithNull_Second_C2(cond1, x, y)); + Asserts.assertEQ(testObjectIdentity_Interp(cond1, 42, y), testObjectIdentity_C2(cond1, 42, y)); + Asserts.assertEQ(testSubclassesTrapping_Interp(cond1, cond2, x, y, w, z), testSubclassesTrapping_C2(cond1, cond2, x, y, w, z)); + Asserts.assertEQ(testCmpMergeWithNull_Interp(cond1, x, y), testCmpMergeWithNull_C2(cond1, x, y)); + Asserts.assertEQ(testSubclasses_Interp(cond1, cond2, x, y, w, z), testSubclasses_C2(cond1, cond2, x, y, w, z)); + Asserts.assertEQ(testPartialPhis_Interp(cond1, l, x, y), testPartialPhis_C2(cond1, l, x, y)); + Asserts.assertEQ(testPollutedNoWrite_Interp(cond1, l), testPollutedNoWrite_C2(cond1, l)); + Asserts.assertEQ(testThreeWayAliasedAlloc_Interp(cond1, x, y), testThreeWayAliasedAlloc_C2(cond1, x, y)); + Asserts.assertEQ(TestTrapAfterMerge_Interp(cond1, x, y), TestTrapAfterMerge_C2(cond1, x, y)); + Asserts.assertEQ(testNestedObjectsObject_Interp(cond1, x, y), testNestedObjectsObject_C2(cond1, x, y)); + Asserts.assertEQ(testNestedObjectsNoEscapeObject_Interp(cond1, x, y), testNestedObjectsNoEscapeObject_C2(cond1, x, y)); + Asserts.assertEQ(testTrappingAfterMerge_Interp(cond1, x, y), testTrappingAfterMerge_C2(cond1, x, y)); + Asserts.assertEQ(testSimpleAliasedAlloc_Interp(cond1, x, y), testSimpleAliasedAlloc_C2(cond1, x, y)); + Asserts.assertEQ(testSimpleDoubleMerge_Interp(cond1, x, y), testSimpleDoubleMerge_C2(cond1, x, y)); + Asserts.assertEQ(testConsecutiveSimpleMerge_Interp(cond1, cond2, x, y), testConsecutiveSimpleMerge_C2(cond1, cond2, x, y)); + Asserts.assertEQ(testDoubleIfElseMerge_Interp(cond1, x, y), testDoubleIfElseMerge_C2(cond1, x, y)); + Asserts.assertEQ(testNoEscapeWithLoadInLoop_Interp(cond1, x, y), testNoEscapeWithLoadInLoop_C2(cond1, x, y)); + Asserts.assertEQ(testCmpAfterMerge_Interp(cond1, cond2, x, y), testCmpAfterMerge_C2(cond1, cond2, x, y)); + Asserts.assertEQ(testCondAfterMergeWithAllocate_Interp(cond1, cond2, x, y), testCondAfterMergeWithAllocate_C2(cond1, cond2, x, y)); + Asserts.assertEQ(testCondLoadAfterMerge_Interp(cond1, cond2, x, y), testCondLoadAfterMerge_C2(cond1, cond2, x, y)); + Asserts.assertEQ(testIfElseInLoop_Interp(), testIfElseInLoop_C2()); + Asserts.assertEQ(testLoadInCondAfterMerge_Interp(cond1, x, y), testLoadInCondAfterMerge_C2(cond1, x, y)); + Asserts.assertEQ(testLoadInLoop_Interp(cond1, x, y), testLoadInLoop_C2(cond1, x, y)); + Asserts.assertEQ(testMergesAndMixedEscape_Interp(cond1, x, y), testMergesAndMixedEscape_C2(cond1, x, y)); + Asserts.assertEQ(testSRAndNSR_NoTrap_Interp(cond1, x, y), testSRAndNSR_NoTrap_C2(cond1, x, y)); + Asserts.assertEQ(testString_one_Interp(cond1), testString_one_C2(cond1)); + Asserts.assertEQ(testString_two_Interp(cond1), testString_two_C2(cond1)); + + Asserts.assertEQ(testSRAndNSR_Trap_Interp(false, cond1, cond2, x, y), + testSRAndNSR_Trap_C2(info.isTestC2Compiled("testSRAndNSR_Trap_C2"), cond1, cond2, x, y)); + + var arr1 = testNestedObjectsArray_Interp(cond1, x, y); + var arr2 = testNestedObjectsArray_C2(cond1, x, y); + + if (arr1.length != arr2.length) Asserts.fail("testNestedObjectsArray result size mismatch."); + for (int i=0; i y) { + p = new Point(x+y, x*y); + } + + if (p != null) { + return p.x * p.y; + } else { + return 1984; + } + } + + @Test + @IR(counts = { IRNode.ALLOC, "2" }) + int testCmpMergeWithNull_C2(boolean cond, int x, int y) { return testCmpMergeWithNull(cond, x, y); } + + @DontCompile + int testCmpMergeWithNull_Interp(boolean cond, int x, int y) { return testCmpMergeWithNull(cond, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + int testSubclasses(boolean c1, boolean c2, int x, int y, int w, int z) { + new A(); + Root s = new Home(x, y); + new B(); + + if (c1) { + new C(); + s = new Etc("Hello"); + new D(); + } else { + new E(); + s = new Usr(y, x, z); + new F(); + } + + new G(); + + return s.a; + } + + @Test + @IR(counts = { IRNode.ALLOC, "2" }) + // The unused allocation will be removed. + // The other two allocations assigned to 's' won't be removed because they have different type. + int testSubclasses_C2(boolean c1, boolean c2, int x, int y, int w, int z) { return testSubclasses(c1, c2, x, y, w, z); } + + @DontCompile + int testSubclasses_Interp(boolean c1, boolean c2, int x, int y, int w, int z) { return testSubclasses(c1, c2, x, y, w, z); } + + + // ------------------ Some Scalar Replacement Should Happen in The Tests Below ------------------- // + + @ForceInline + int testPartialPhis(boolean cond, int l, int x, int y) { + int k = l; + + if (l == 0) { + k = l + 1; + } else if (l == 2) { + k = l + 2; + } else if (l == 3) { + new Point(x, y); + } else if (l == 4) { + new Point(y, x); + } + + return k; + } + + @Test + @IR(failOn = { IRNode.ALLOC }) + // all allocations will be dead + int testPartialPhis_C2(boolean cond, int l, int x, int y) { return testPartialPhis(cond, l, x, y); } + + @DontCompile + int testPartialPhis_Interp(boolean cond, int l, int x, int y) { return testPartialPhis(cond, l, x, y); } + + + // ------------------------------------------------------------------------- + + @ForceInline + int testPollutedNoWrite(boolean cond, int l) { + Shape obj1 = new Square(l); + Shape obj2 = new Square(l); + Shape obj = null; + int res = 0; + + if (cond) { + obj = obj1; + } else { + obj = obj2; + } + + for (int i=1; i<132; i++) { + res += obj.x; + } + + return res + obj1.x + obj2.y; + } + + @Test + @IR(failOn = { IRNode.ALLOC }) + // Both allocations will be removed. After initialization they are read-only objects. + // Access to the input of the merge, after the merge, is fine. + int testPollutedNoWrite_C2(boolean cond, int l) { return testPollutedNoWrite(cond, l); } + + @DontCompile + int testPollutedNoWrite_Interp(boolean cond, int l) { return testPollutedNoWrite(cond, l); } + + // ------------------------------------------------------------------------- + + @ForceInline + int testThreeWayAliasedAlloc(boolean cond, int x, int y) { + Point p1 = new Point(x, y); + Point p2 = new Point(x+1, y+1); + Point p3 = new Point(x+2, y+2); + + if (cond) { + p3 = p1; + } else { + p3 = p2; + } + + return p3.x + p3.y; + } + + @Test + @IR(failOn = { IRNode.ALLOC }) + // Initial p3 will always be dead. + // The other two allocations will be reduced and scaled + int testThreeWayAliasedAlloc_C2(boolean cond, int x, int y) { return testThreeWayAliasedAlloc(cond, x, y); } + + @DontCompile + int testThreeWayAliasedAlloc_Interp(boolean cond, int x, int y) { return testThreeWayAliasedAlloc(cond, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + int TestTrapAfterMerge(boolean cond, int x, int y) { + Point p = new Point(x, x); + + if (cond) { + p = new Point(y, y); + } + + for (int i=402; i<432; i+=x) { + x++; + } + + return p.x + x; + } + + @Test + @IR(failOn = { IRNode.ALLOC }) + // Both allocations will be eliminated. + int TestTrapAfterMerge_C2(boolean cond, int x, int y) { return TestTrapAfterMerge(cond, x, y); } + + @DontCompile + int TestTrapAfterMerge_Interp(boolean cond, int x, int y) { return TestTrapAfterMerge(cond, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + Point testNestedObjectsObject(boolean cond, int x, int y) { + Picture p = new Picture(x, x, y); + + if (cond) { + p = new Picture(y, y, x); + } + + return p.position; + } + + @Test + @IR(counts = { IRNode.ALLOC, "2" }) + // The allocation of "Picture" will be removed and only allocations of "Position" will be kept + Point testNestedObjectsObject_C2(boolean cond, int x, int y) { return testNestedObjectsObject(cond, x, y); } + + @DontCompile + Point testNestedObjectsObject_Interp(boolean cond, int x, int y) { return testNestedObjectsObject(cond, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + int testNestedObjectsNoEscapeObject(boolean cond, int x, int y) { + Picture p = new Picture(x, x, y); + + if (cond) { + p = new Picture(y, y, x); + } + + return p.position.x; + } + + @Test + @IR(counts = { IRNode.ALLOC, "2" } ) + // The two Picture objects will be removed. The nested Point objects won't + // be removed because the Phi merging them will have a DecodeN user - which + // currently isn't supported. + int testNestedObjectsNoEscapeObject_C2(boolean cond, int x, int y) { return testNestedObjectsNoEscapeObject(cond, x, y); } + + @DontCompile + int testNestedObjectsNoEscapeObject_Interp(boolean cond, int x, int y) { return testNestedObjectsNoEscapeObject(cond, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + Point[] testNestedObjectsArray(boolean cond, int x, int y) { + PicturePositions p = new PicturePositions(x, y, x+y); + + if (cond) { + p = new PicturePositions(x+1, y+1, x+y+1); + } + + return p.positions; + } + + @Test + @IR(counts = { IRNode.ALLOC, "4" }) + // The two PicturePositions objects will be reduced and scaled. + Point[] testNestedObjectsArray_C2(boolean cond, int x, int y) { return testNestedObjectsArray(cond, x, y); } + + @DontCompile + Point[] testNestedObjectsArray_Interp(boolean cond, int x, int y) { return testNestedObjectsArray(cond, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + int testTrappingAfterMerge(boolean cond, int x, int y) { + Point p = new Point(x, y); + int res = 0; + + if (cond) { + p = new Point(y, y); + } + + for (int i=832; i<932; i++) { + res += p.x; + } + + if (x > y) { + res += new Point(p.x, p.y).x; + } + + return res; + } + + @Test + @IR(failOn = { IRNode.ALLOC }) + // The allocation inside the last if will be removed because it's not part of a merge + // The other two allocations will be reduced and removed + int testTrappingAfterMerge_C2(boolean cond, int x, int y) { return testTrappingAfterMerge(cond, x, y); } + + @DontCompile + int testTrappingAfterMerge_Interp(boolean cond, int x, int y) { return testTrappingAfterMerge(cond, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + int testSimpleAliasedAlloc(boolean cond, int x, int y) { + Point p1 = new Point(x, y); + Point p2 = new Point(y, x); + Point p = p1; + + if (cond) { + p = p2; + } + + return p.x * p.y; + } + + @Test + @IR(failOn = { IRNode.ALLOC }) + // Both merges will be reduced and removed + int testSimpleAliasedAlloc_C2(boolean cond, int x, int y) { return testSimpleAliasedAlloc(cond, x, y); } + + @DontCompile + int testSimpleAliasedAlloc_Interp(boolean cond, int x, int y) { return testSimpleAliasedAlloc(cond, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + int testSimpleDoubleMerge(boolean cond, int x, int y) { + Point p1 = new Point(x, y); + Point p2 = new Point(x+1, y+1); + + if (cond) { + p1 = new Point(y, x); + p2 = new Point(y+1, x+1); + } + + return p1.x + p2.y; + } + + @Test + @IR(failOn = { IRNode.ALLOC }) + // Both merges will be reduced and removed + int testSimpleDoubleMerge_C2(boolean cond, int x, int y) { return testSimpleDoubleMerge(cond, x, y); } + + @DontCompile + int testSimpleDoubleMerge_Interp(boolean cond, int x, int y) { return testSimpleDoubleMerge(cond, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + int testConsecutiveSimpleMerge(boolean cond1, boolean cond2, int x, int y) { + Point p0 = new Point(x, x); + Point p1 = new Point(x, y); + Point pA = null; + + Point p2 = new Point(y, x); + Point p3 = new Point(y, y); + Point pB = null; + + if (cond1) { + pA = p0; + } else { + pA = p1; + } + + if (cond2) { + pB = p2; + } else { + pB = p3; + } + + return pA.x * pA.y + pB.x * pB.y; + } + + @Test + @IR(failOn = { IRNode.ALLOC }) + // All allocations will be removed. + int testConsecutiveSimpleMerge_C2(boolean cond1, boolean cond2, int x, int y) { return testConsecutiveSimpleMerge(cond1, cond2, x, y); } + + @DontCompile + int testConsecutiveSimpleMerge_Interp(boolean cond1, boolean cond2, int x, int y) { return testConsecutiveSimpleMerge(cond1, cond2, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + int testDoubleIfElseMerge(boolean cond, int x, int y) { + Point p1 = new Point(x, y); + Point p2 = new Point(x+1, y+1); + + if (cond) { + p1 = new Point(y, x); + p2 = new Point(y, x); + } else { + p1 = new Point(x, y); + p2 = new Point(x+1, y+1); + } + + return p1.x * p2.y; + } + + @Test + @IR(failOn = { IRNode.ALLOC }) + // The initial allocation is always dead. The other + // two will be reduced and scaled. + int testDoubleIfElseMerge_C2(boolean cond, int x, int y) { return testDoubleIfElseMerge(cond, x, y); } + + @DontCompile + int testDoubleIfElseMerge_Interp(boolean cond, int x, int y) { return testDoubleIfElseMerge(cond, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + int testNoEscapeWithLoadInLoop(boolean cond, int x, int y) { + Point p = new Point(x, y); + int res = 0; + + if (cond) { + p = new Point(y, x); + } + + for (int i=3342; i<4234; i++) { + res += p.x + p.y + i; + } + + return res + p.x + p.y; + } + + @Test + @IR(failOn = { IRNode.ALLOC }) + // Both allocations will be reduced and scaled. + int testNoEscapeWithLoadInLoop_C2(boolean cond, int x, int y) { return testNoEscapeWithLoadInLoop(cond, x, y); } + + @DontCompile + int testNoEscapeWithLoadInLoop_Interp(boolean cond, int x, int y) { return testNoEscapeWithLoadInLoop(cond, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + int testCmpAfterMerge(boolean cond, boolean cond2, int x, int y) { + Point a = new Point(x, y); + Point b = new Point(y, x); + Point c = null; + + if (x+2 >= y-5) { + c = a; + } else { + c = b; + } + + return cond2 ? c.x : c.y; + } + + @Test + @IR(failOn = { IRNode.ALLOC }) + // Both allocations will be reduced and scaled + int testCmpAfterMerge_C2(boolean cond, boolean cond2, int x, int y) { return testCmpAfterMerge(cond, cond2, x, y); } + + @DontCompile + int testCmpAfterMerge_Interp(boolean cond, boolean cond2, int x, int y) { return testCmpAfterMerge(cond, cond2, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + int testCondAfterMergeWithAllocate(boolean cond1, boolean cond2, int x, int y) { + Point p = new Point(x, y); + + if (cond1) { + p = new Point(y, x); + } + + if (cond2 && cond1) { + return p.x; + } else { + return 321; + } + } + + @Test + @IR(failOn = { IRNode.ALLOC }) + // Both allocations will be eliminated. + int testCondAfterMergeWithAllocate_C2(boolean cond1, boolean cond2, int x, int y) { return testCondAfterMergeWithAllocate(cond1, cond2, x, y); } + + @DontCompile + int testCondAfterMergeWithAllocate_Interp(boolean cond1, boolean cond2, int x, int y) { return testCondAfterMergeWithAllocate(cond1, cond2, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + int testCondLoadAfterMerge(boolean cond1, boolean cond2, int x, int y) { + Point p = new Point(x, y); + + if (cond1) { + p = new Point(y, x); + } + + if (cond1 == false && cond2 == false) { + return p.x + 1; + } else if (cond1 == false && cond2 == true) { + return p.x + 30; + } else if (cond1 == true && cond2 == false) { + return p.x + 40; + } else if (cond1 == true && cond2 == true) { + return p.x + 50; + } else { + return -1; + } + } + + @Test + @IR(failOn = { IRNode.ALLOC }) + // Both allocations will be eliminated. + int testCondLoadAfterMerge_C2(boolean cond1, boolean cond2, int x, int y) { return testCondLoadAfterMerge(cond1, cond2, x, y); } + + @DontCompile + int testCondLoadAfterMerge_Interp(boolean cond1, boolean cond2, int x, int y) { return testCondLoadAfterMerge(cond1, cond2, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + int testIfElseInLoop() { + int res = 0; + + for (int i=1; i<1000; i++) { + Point obj = new Point(i, i); + + if (i % 2 == 1) { + obj = new Point(i, i+1); + } else { + obj = new Point(i-1, i); + } + + res += obj.x; + } + + return res; + } + + @Test + @IR(failOn = { IRNode.ALLOC }) + // The initial allocation is always dead. The other + // two will be reduced and scaled. + int testIfElseInLoop_C2() { return testIfElseInLoop(); } + + @DontCompile + int testIfElseInLoop_Interp() { return testIfElseInLoop(); } + + // ------------------------------------------------------------------------- + + @ForceInline + int testLoadInCondAfterMerge(boolean cond, int x, int y) { + Point p = new Point(x, y); + + if (cond) { + p = new Point(y, x); + } + + if (p.x == 10) { + if (p.y == 10) { + return dummy(10); + } else { + return dummy(20); + } + } else if (p.x == 20) { + if (p.y == 20) { + return dummy(30); + } else { + return dummy(40); + } + } + + return 1984; + } + + @Test + @IR(failOn = { IRNode.ALLOC }) + // Both allocations will be reduced and removed. + int testLoadInCondAfterMerge_C2(boolean cond, int x, int y) { return testLoadInCondAfterMerge(cond, x, y); } + + @DontCompile + int testLoadInCondAfterMerge_Interp(boolean cond, int x, int y) { return testLoadInCondAfterMerge(cond, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + int testLoadInLoop(boolean cond, int x, int y) { + Point obj1 = new Point(x, y); + Point obj2 = new Point(y, x); + Point obj = null; + int res = 0; + + if (cond) { + obj = obj1; + } else { + obj = obj2; + } + + for (int i = 0; i < 532; i++) { + res += obj.x; + } + + return res; + } + + @Test + @IR(failOn = { IRNode.ALLOC }) + // Both allocations will be reduced and removed. + int testLoadInLoop_C2(boolean cond, int x, int y) { return testLoadInLoop(cond, x, y); } + + @DontCompile + int testLoadInLoop_Interp(boolean cond, int x, int y) { return testLoadInLoop(cond, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + int testMergesAndMixedEscape(boolean cond, int x, int y) { + Point p1 = new Point(x, y); + Point p2 = new Point(x, y); + int val = 0; + + if (cond) { + p1 = new Point(x+1, y+1); + val = dummy(p2); + } + + return val + p1.x + p2.y; + } + + @Test + @IR(counts = { IRNode.ALLOC, "1" }) + // p2 escapes and will remain. The other two allocations will be reduced and scaled. + int testMergesAndMixedEscape_C2(boolean cond, int x, int y) { return testMergesAndMixedEscape(cond, x, y); } + + @DontCompile + int testMergesAndMixedEscape_Interp(boolean cond, int x, int y) { return testMergesAndMixedEscape(cond, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + int testSRAndNSR_NoTrap(boolean cond1, int x, int y) { + Point p = new Point(x, y); + + if (cond1) { + p = new Point(x+1, y+1); + global_escape = p; + } + + return p.y; + } + + @Test + @IR(counts = { IRNode.ALLOC, "<=1" }) + int testSRAndNSR_NoTrap_C2(boolean cond1, int x, int y) { return testSRAndNSR_NoTrap(cond1, x, y); } + + @DontCompile + int testSRAndNSR_NoTrap_Interp(boolean cond1, int x, int y) { return testSRAndNSR_NoTrap(cond1, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + int testSRAndNSR_Trap(boolean is_c2, boolean cond1, boolean cond2, int x, int y) { + Point p = new Point(x, y); + + if (cond1) { + p = new Point(x+1, y+1); + global_escape = p; + } + + if (is_c2) { + // This will show up to C2 as a trap. + dummy_defaults(); + } + + return p.y; + } + + @Test + @IR(counts = { IRNode.ALLOC, "<=1" }) + int testSRAndNSR_Trap_C2(boolean is_c2, boolean cond1, boolean cond2, int x, int y) { return testSRAndNSR_Trap(is_c2, cond1, cond2, x, y); } + + @DontCompile + int testSRAndNSR_Trap_Interp(boolean is_c2, boolean cond1, boolean cond2, int x, int y) { return testSRAndNSR_Trap(is_c2, cond1, cond2, x, y); } + + // ------------------------------------------------------------------------- + + @ForceInline + char testString_one(boolean cond1) { + String p = new String("Java"); + + if (cond1) { + p = new String("HotSpot"); + } + + return p.charAt(0); + } + + @Test + @IR(counts = { IRNode.ALLOC, "0" }) + char testString_one_C2(boolean cond1) { return testString_one(cond1); } + + @DontCompile + char testString_one_Interp(boolean cond1) { return testString_one(cond1); } + + // ------------------------------------------------------------------------- + + @ForceInline + char testString_two(boolean cond1) { + String p = new String("HotSpot"); + + if (cond1) { + p = dummy("String"); + if (p == null) return 'J'; + } + + return p.charAt(0); + } + + @Test + @IR(counts = { IRNode.ALLOC, "0" }) + char testString_two_C2(boolean cond1) { return testString_two(cond1); } + + @DontCompile + char testString_two_Interp(boolean cond1) { return testString_two(cond1); } + + // ------------------ Utility for Testing ------------------- // + + @DontCompile + static void dummy() { + } + + @DontCompile + static int dummy(Point p) { + return p.x * p.y; + } + + @DontCompile + static int dummy(int x) { + return x; + } + + @DontCompile + static Point dummy(int x, int y) { + return new Point(x, y); + } + + @DontCompile + static String dummy(String str) { + return str; + } + + @DontCompile + static ADefaults dummy_defaults() { + return new ADefaults(); + } + + static class Point { + int x, y; + Point(int x, int y) { + this.x = x; + this.y = y; + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof Point)) return false; + Point p = (Point) o; + return (p.x == x) && (p.y == y); + } + } + + class Shape { + int x, y, l; + Shape(int x, int y) { + this.x = x; + this.y = y; + } + } + + class Square extends Shape { + Square(int l) { + super(0, 0); + this.l = l; + } + } + + class Circle extends Shape { + Circle(int l) { + super(0, 0); + this.l = l; + } + } + + static class ADefaults { + static int ble; + int i; + @DontCompile + ADefaults(int i) { this.i = i; } + @DontCompile + ADefaults() { } + } + + static class Picture { + public int id; + public Point position; + + public Picture(int id, int x, int y) { + this.id = id; + this.position = new Point(x, y); + } + } + + static class PicturePositions { + public int id; + public Point[] positions; + + public PicturePositions(int id, int x, int y) { + this.id = id; + this.positions = new Point[] { new Point(x, y), new Point(y, x) }; + } + } + + class Root { + public int a; + public int b; + public int c; + public int d; + public int e; + + public Root(int a, int b, int c, int d, int e) { + this.a = a; + this.b = b; + this.c = c; + this.d = d; + this.e = e; + } + } + + class Usr extends Root { + public float flt; + + public Usr(float a, float b, float c) { + super((int)a, (int)b, (int)c, 0, 0); + this.flt = a; + } + } + + class Home extends Root { + public double[] arr; + + public Home(double a, double b) { + super((int)a, (int)b, 0, 0, 0); + this.arr = new double[] {a, b}; + } + + } + + class Tmp extends Root { + public String s; + + public Tmp(String s) { + super((int)s.length(), 0, 0, 0, 0); + this.s = s; + } + } + + class Etc extends Root { + public String a; + + public Etc(String s) { + super((int)s.length(), 0, 0, 0, 0); + this.a = s; + } + } + + class A { } + class B { } + class C { } + class D { } + class E { } + class F { } + class G { } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach001.java index 8203095e3fc..e8eaf772695 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -97,7 +97,7 @@ private int runIt(String argv[], PrintStream out) { String java = argHandler.getLaunchExecPath() + " " + argHandler.getLaunchOptions(); String cmd = java - + " -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,address=0" + + " -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=0" + " " + DEBUGEE_CLASS; Binder binder = new Binder(argHandler, log); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002.java index 22720edadc1..d62659a9dfb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -102,7 +102,7 @@ private int runIt(String argv[], PrintStream out) { String java = argHandler.getLaunchExecPath() + " " + argHandler.getLaunchOptions(); String cmd = java + - " -Xdebug -Xnoagent -Xrunjdwp:transport=dt_shmem,server=y,address=" + + " -Xdebug -Xrunjdwp:transport=dt_shmem,server=y,address=" + name + " " + DEBUGEE_CLASS; Binder binder = new Binder(argHandler, log); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001.java index e5bd791b1ed..6ba44eb9b42 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -97,7 +97,7 @@ private int runIt(String argv[], PrintStream out) { String java = argHandler.getLaunchExecPath() + " " + argHandler.getLaunchOptions(); String cmd = java - + " -Xdebug -Xnoagent -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0" + + " -Xdebug -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0" + " " + DEBUGEE_CLASS; Binder binder = new Binder(argHandler, log); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch003.java index 05d1dffeadb..aeb21e4b4a7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -134,7 +134,7 @@ private Map setupConnec Connector.Argument a = (Connector.Argument) cava[i]; if (a.name().equals("command")) a.setValue(java + - " -Xdebug -Xnoagent -Xrunjdwp:suspend=y,transport=" + + " -Xdebug -Xrunjdwp:suspend=y,transport=" + TRANSPORT_NAME + ",address=" + host + ":" + port + " " + DEBUGEE_CLASS); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch004.java index 7822023ac94..3febb3b9733 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -133,7 +133,7 @@ private Map s Connector.Argument a = (Connector.Argument) cava[i]; if (a.name().equals("command")) a.setValue(java + - " -Xdebug -Xnoagent -Xrunjdwp:suspend=y,transport=" + + " -Xdebug -Xrunjdwp:suspend=y,transport=" + TRANSPORT_NAME + ",address=" + name + " " + DEBUGEE_CLASS); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001.java index 450ad57f8e4..c38279031b8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -81,7 +81,7 @@ private int runIt(String argv[], PrintStream out) { String java = argHandler.getLaunchExecPath() + " " + argHandler.getLaunchOptions(); String cmd = java + - " -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=n,address=" + + " -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=" + connAddr + " " + DEBUGEE_CLASS; Binder binder = new Binder(argHandler, log); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002.java index 5eeabb30a97..1e80e07ae74 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -82,7 +82,7 @@ private int runIt(String argv[], PrintStream out) { String java = argHandler.getLaunchExecPath() + " " + argHandler.getLaunchOptions(); String cmd = java + - " -Xdebug -Xnoagent -Xrunjdwp:transport=dt_shmem,server=n,address=" + + " -Xdebug -Xrunjdwp:transport=dt_shmem,server=n,address=" + connAddr + " " + DEBUGEE_CLASS; Binder binder = new Binder(argHandler, log); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001.java index cff662f9296..3ea73669bc9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -81,7 +81,7 @@ private int runIt(String argv[], PrintStream out) { String java = argHandler.getLaunchExecPath() + " " + argHandler.getLaunchOptions(); String cmd = java + - " -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=n,suspend=n,address=" + + " -Xdebug -Xrunjdwp:transport=dt_socket,server=n,suspend=n,address=" + connAddr + " " + DEBUGEE_CLASS; Binder binder = new Binder(argHandler, log); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001.java index 877b17cd7f9..5e736560fc5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -157,7 +157,7 @@ private int runIt(String argv[], PrintStream out) { + " " + argHandler.getLaunchOptions(); String cmd = java + - " -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=n,address=" + + " -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=" + addr + " " + DEBUGEE_CLASS; Binder binder = new Binder(argHandler, log); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002.java index 0b3eb3656af..7abdfb0156b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -132,7 +132,7 @@ private int runIt(String argv[], PrintStream out) { + " " + argHandler.getLaunchOptions(); String cmd = java + - " -Xdebug -Xnoagent -Xrunjdwp:transport=dt_shmem,server=n,address=" + + " -Xdebug -Xrunjdwp:transport=dt_shmem,server=n,address=" + addr + " " + DEBUGEE_CLASS; Binder binder = new Binder(argHandler, log); diff --git a/test/jdk/java/foreign/TestAdaptVarHandles.java b/test/jdk/java/foreign/TestAdaptVarHandles.java index 893755f15d4..5074b8d793b 100644 --- a/test/jdk/java/foreign/TestAdaptVarHandles.java +++ b/test/jdk/java/foreign/TestAdaptVarHandles.java @@ -351,6 +351,12 @@ public void testCollectCoordinates() throws Throwable { assertEquals(value, 42); } + @Test + public void testCollectCoordinatesVoidFilterType() { + VarHandle handle = MethodHandles.collectCoordinates(intHandle, 0, VOID_FILTER); + assertEquals(handle.coordinateTypes(), List.of(String.class, MemorySegment.class)); + } + @Test(expectedExceptions = IllegalArgumentException.class) public void testBadCollectCoordinatesNegativePos() { MethodHandles.collectCoordinates(intHandle, -1, SUM_OFFSETS); @@ -366,11 +372,6 @@ public void testBadCollectCoordinatesWrongFilterType() { MethodHandles.collectCoordinates(intHandle, 0, SUM_OFFSETS); } - @Test(expectedExceptions = IllegalArgumentException.class) - public void testBadCollectCoordinatesWrongVoidFilterType() { - MethodHandles.collectCoordinates(intHandle, 0, VOID_FILTER); - } - @Test(expectedExceptions = IllegalArgumentException.class) public void testBadCollectCoordinatesWrongFilterException() { MethodHandles.collectCoordinates(intHandle, 0, S2L_EX); diff --git a/test/jdk/java/lang/SecurityManager/CheckSecurityProvider.java b/test/jdk/java/lang/SecurityManager/CheckSecurityProvider.java index 5e0092f8011..468cd4c57d5 100644 --- a/test/jdk/java/lang/SecurityManager/CheckSecurityProvider.java +++ b/test/jdk/java/lang/SecurityManager/CheckSecurityProvider.java @@ -60,8 +60,7 @@ public static void main(String[] args) throws Exception { // NOTE: the ordering must match what's defined inside java.security expected.add("sun.security.provider.Sun"); expected.add("sun.security.rsa.SunRsaSign"); - layer.findModule("jdk.crypto.ec") - .ifPresent(m -> expected.add("sun.security.ec.SunEC")); + expected.add("sun.security.ec.SunEC"); expected.add("sun.security.ssl.SunJSSE"); expected.add("com.sun.crypto.provider.SunJCE"); layer.findModule("jdk.security.jgss") diff --git a/test/jdk/java/lang/invoke/VarHandles/LazyInitializingTest.java b/test/jdk/java/lang/invoke/VarHandles/LazyInitializingTest.java new file mode 100644 index 00000000000..8b8831538b0 --- /dev/null +++ b/test/jdk/java/lang/invoke/VarHandles/LazyInitializingTest.java @@ -0,0 +1,217 @@ +/* + * Copyright (c) 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. + * + * 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 8291065 + * @summary Checks interaction of static field VarHandle with class + * initialization mechanism.. + * @run junit LazyInitializingTest + * @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true LazyInitializingTest + * @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false LazyInitializingTest + * @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true + * -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false LazyInitializingTest + */ + +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.lang.constant.ConstantDescs; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.util.Objects; + +import static org.junit.jupiter.api.Assertions.*; + +public class LazyInitializingTest { + + record SampleData(Runnable callback, int initialValue) { + private static final Runnable FAIL_ON_CLINIT_CALLBACK = () -> { + throw new AssertionError("Class shouldn't be initialized"); + }; + static final SampleData FAIL_ON_CLINIT = new SampleData(); + + SampleData() { + this(FAIL_ON_CLINIT_CALLBACK, 0); + } + } + record ClassInfo(MethodHandles.Lookup definingLookup, VarHandle vh) {} + + private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); + + /** + * Meta test to ensure the testing mechanism to check initialization is correct. + */ + @Test + public void testMeta() throws IllegalAccessException { + boolean[] val = new boolean[1]; + var v0 = createSampleClass(new SampleData(() -> val[0] = true, 0)); + assertFalse(val[0], "callback run before class init"); + v0.definingLookup.ensureInitialized(v0.definingLookup.lookupClass()); + assertTrue(val[0], "callback not run at class init"); + } + + @Test + public void testUninitializedOperations() { + var ci = createSampleClass(SampleData.FAIL_ON_CLINIT); + var vh = ci.vh; + vh.describeConstable(); + vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE); + vh.withInvokeExactBehavior(); + vh.withInvokeBehavior(); + vh.toMethodHandle(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE); + vh.hasInvokeExactBehavior(); + vh.accessModeType(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE); + } + + @Test + public void testInitializationOnVarHandleUse() { + var initialized = new boolean[1]; + var ci = createSampleClass(new SampleData(() -> initialized[0] = true, 42)); + var vh = ci.vh; + + assertEquals(42, (int) vh.get(), "VH does not read value set in class initializer"); + assertTrue(initialized[0], "class initialization not captured"); + } + + @Test + public void testInitializationOnToMethodHandleUse() throws Throwable { + var initialized = new boolean[1]; + var ci = createSampleClass(new SampleData(() -> initialized[0] = true, 42)); + var mh = ci.vh.toMethodHandle(VarHandle.AccessMode.GET); + + assertEquals(42, (int) mh.invokeExact(), "VH does not read value set in class initializer"); + assertTrue(initialized[0], "class initialization not captured"); + } + + @Test + public void testParentChildLoading() throws Throwable { + // ChildSample: ensure only ParentSample (field declarer) is initialized + var l = new ParentChildLoader(); + var childSampleClass = l.childClass(); + var lookup = MethodHandles.privateLookupIn(childSampleClass, LOOKUP); + var childVh = lookup.findStaticVarHandle(childSampleClass, "f", int.class); + + assertEquals(3, (int) childVh.get(), "Child class initialized unnecessarily"); + + lookup.ensureInitialized(childSampleClass); + + assertEquals(6, (int) childVh.get(), "Child class was not initialized"); + } + + static ClassInfo createSampleClass(SampleData sampleData) { + try { + var lookup = LOOKUP.defineHiddenClassWithClassData(sampleClassBytes(), sampleData, false); + var vh = lookup.findStaticVarHandle(lookup.lookupClass(), "f", int.class); + return new ClassInfo(lookup, vh); + } catch (IllegalAccessException | NoSuchFieldException ex) { + throw new AssertionError(ex); + } + } + + private static byte[] sampleClassBytes; + + private static byte[] sampleClassBytes() { + var bytes = sampleClassBytes; + if (bytes != null) + return bytes; + + try (var in = LazyInitializingTest.class.getResourceAsStream("LazyInitializingSample.class")) { + if (in == null) + throw new AssertionError("class file not found"); + return sampleClassBytes = in.readAllBytes(); + } catch (IOException ex) { + throw new AssertionError(ex); + } + } +} + +// This is used as a template class, whose bytes are used to define +// hidden classes instead +class LazyInitializingSample { + static int f; + + static { + try { + var data = MethodHandles.classData(MethodHandles.lookup(), ConstantDescs.DEFAULT_NAME, + LazyInitializingTest.SampleData.class); + Objects.requireNonNull(data); + + data.callback().run(); + f = data.initialValue(); + } catch (IllegalAccessException e) { + throw new ExceptionInInitializerError(e); + } + } +} + +class ParentChildLoader extends ClassLoader { + ParentChildLoader() { + super(LazyInitializingTest.class.getClassLoader().getParent()); + } + + Class parentClass() { + try { + return loadClass("ParentSample"); + } catch (ClassNotFoundException e) { + throw new AssertionError(e); + } + } + + Class childClass() { + try { + return loadClass("ChildSample"); + } catch (ClassNotFoundException e) { + throw new AssertionError(e); + } + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + try (var stream = switch (name) { + case "ParentSample", "ChildSample" -> LazyInitializingTest.class.getResourceAsStream(name + ".class"); + default -> throw new ClassNotFoundException(name); + }) { + if (stream == null) + throw new AssertionError(); + var b = stream.readAllBytes(); + return defineClass(name, b, 0, b.length); + } catch (IOException ex) { + throw new AssertionError(ex); + } + } +} + +class ParentSample { + static int f; + + static { + f = 3; + } +} + +class ChildSample extends ParentSample { + static { + f = 6; + } +} \ No newline at end of file diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleBaseTest.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleBaseTest.java index 81978c7a79c..0c9a7fd3953 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleBaseTest.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleBaseTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -145,7 +145,9 @@ static void checkWithThrowable(Class re, } message = message == null ? "" : message + ". "; assertNotNull(_e, String.format("%sNo throwable thrown. Expected %s", message, re)); - assertTrue(re.isInstance(_e), String.format("%sIncorrect throwable thrown, %s. Expected %s", message, _e, re)); + if (!re.isInstance(_e)) { + fail(String.format("%sIncorrect throwable thrown, %s. Expected %s", message, _e, re), _e); + } } diff --git a/test/jdk/javax/net/ssl/TLS/TEST.properties b/test/jdk/javax/net/ssl/TLS/TEST.properties index 7ff68d5f4b2..5cd72951d1d 100644 --- a/test/jdk/javax/net/ssl/TLS/TEST.properties +++ b/test/jdk/javax/net/ssl/TLS/TEST.properties @@ -6,4 +6,4 @@ modules = \ java.security.jgss/sun.security.krb5.internal.ccache \ java.security.jgss/sun.security.krb5.internal:+open \ java.base/sun.security.util \ - jdk.crypto.ec/sun.security.ec + java.base/sun.security.ec diff --git a/test/jdk/javax/net/ssl/TLS/TestJSSEClientDefaultProtocol.java b/test/jdk/javax/net/ssl/TLS/TestJSSEClientDefaultProtocol.java index ed952234756..9429c9dc02b 100644 --- a/test/jdk/javax/net/ssl/TLS/TestJSSEClientDefaultProtocol.java +++ b/test/jdk/javax/net/ssl/TLS/TestJSSEClientDefaultProtocol.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -25,7 +25,7 @@ * @test * @bug 8049429 8234723 * @modules java.management - * jdk.crypto.ec/sun.security.ec + * java.base/sun.security.ec * @summary Test that all cipher suites work in all versions and all client * authentication types. The way this is setup the server is stateless * and all checking is done on the client side. diff --git a/test/jdk/javax/net/ssl/TLS/TestJSSEClientProtocol.java b/test/jdk/javax/net/ssl/TLS/TestJSSEClientProtocol.java index f2444c4b30f..e9eb0aef103 100644 --- a/test/jdk/javax/net/ssl/TLS/TestJSSEClientProtocol.java +++ b/test/jdk/javax/net/ssl/TLS/TestJSSEClientProtocol.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -25,7 +25,7 @@ * @test * @bug 8049429 8172273 8234723 * @modules java.management - * jdk.crypto.ec/sun.security.ec + * java.base/sun.security.ec * @summary Test that all cipher suites work in all versions and all client * authentication types. The way this is setup the server is stateless * and all checking is done on the client side. @@ -75,4 +75,9 @@ * -DCLIENT_PROTOCOL=TLSv1.3 * -DCIPHER=TLS_AES_256_GCM_SHA384 * TestJSSE + * @run main/othervm --limit-modules java.base + * -DSERVER_PROTOCOL=SSLv3,TLSv1,TLSv1.1,TLSv1.2,TLSv1.3 + * -DCLIENT_PROTOCOL=TLSv1.3 + * -DCIPHER=TLS_AES_256_GCM_SHA384 + * TestJSSE */ diff --git a/test/jdk/javax/net/ssl/TLS/TestJSSENoCommonProtocols.java b/test/jdk/javax/net/ssl/TLS/TestJSSENoCommonProtocols.java index 8473c8ee4f3..eb1a4e9ef8c 100644 --- a/test/jdk/javax/net/ssl/TLS/TestJSSENoCommonProtocols.java +++ b/test/jdk/javax/net/ssl/TLS/TestJSSENoCommonProtocols.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -25,7 +25,7 @@ * @test * @bug 8049429 * @modules java.management - * jdk.crypto.ec/sun.security.ec + * java.base/sun.security.ec * @summary Test that all cipher suites work in all versions and all client * authentication types. The way this is setup the server is stateless * and all checking is done on the client side. diff --git a/test/jdk/javax/net/ssl/TLS/TestJSSEServerProtocol.java b/test/jdk/javax/net/ssl/TLS/TestJSSEServerProtocol.java index 7cd45756aad..8faed61f49b 100644 --- a/test/jdk/javax/net/ssl/TLS/TestJSSEServerProtocol.java +++ b/test/jdk/javax/net/ssl/TLS/TestJSSEServerProtocol.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -25,7 +25,7 @@ * @test * @bug 8049429 8234723 * @modules java.management - * jdk.crypto.ec/sun.security.ec + * java.base/sun.security.ec * @summary Test that all cipher suites work in all versions and all client * authentication types. The way this is setup the server is stateless * and all checking is done on the client side. @@ -60,4 +60,9 @@ * -DCLIENT_PROTOCOL=TLSv1.3 * -DCIPHER=TLS_AES_256_GCM_SHA384 * TestJSSE javax.net.ssl.SSLHandshakeException + * @run main/othervm --limit-modules java.base + * -DSERVER_PROTOCOL=TLSv1.2 + * -DCLIENT_PROTOCOL=TLSv1.3 + * -DCIPHER=TLS_AES_256_GCM_SHA384 + * TestJSSE javax.net.ssl.SSLHandshakeException */ diff --git a/test/jdk/javax/swing/JInternalFrame/InternalFrameTitleButtonTest.java b/test/jdk/javax/swing/JInternalFrame/InternalFrameTitleButtonTest.java new file mode 100644 index 00000000000..55ea19de00f --- /dev/null +++ b/test/jdk/javax/swing/JInternalFrame/InternalFrameTitleButtonTest.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 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. + * + * 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 8140527 + * @key headful + * @requires (os.family == "windows") + * @summary InternalFrame has incorrect title button width + * @run main InternalFrameTitleButtonTest + */ + +import java.awt.Component; +import java.awt.Robot; + +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.plaf.basic.BasicInternalFrameUI; + +public class InternalFrameTitleButtonTest { + + private static JFrame frame; + private static JInternalFrame iframe; + + public static void main(String[] args) throws Exception { + String osName = System.getProperty("os.name"); + if (!osName.toLowerCase().contains("win")) { + System.out.println("The test is applicable only for Windows."); + return; + } + + UIManager.setLookAndFeel( + "com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel"); + try { + test(2); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + UIManager.setLookAndFeel( + "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + try { + test(14); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + System.out.println("ok"); + } + + private static void test(final int widthAdd) throws Exception { + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame(); + + JDesktopPane pane = new JDesktopPane(); + frame.setContentPane(pane); + frame.setSize(400, 400); + frame.setVisible(true); + + iframe = new JInternalFrame("Mail Reader", true, + true, true, true); + iframe.setSize(200, 200); + pane.add(iframe); + iframe.setVisible(true); + }); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); + + SwingUtilities.invokeAndWait(() -> { + JComponent title = ((BasicInternalFrameUI) iframe.getUI()).getNorthPane(); + for (int i = 0; i < title.getComponentCount(); i++) { + Component c = title.getComponent(i); + if (c instanceof JButton button + && !testButtonSize(button, widthAdd)) { + throw new RuntimeException("Wrong title icon size"); + } + } + }); + } + + private static boolean testButtonSize(final JButton button, + final int widthAdd) { + int height = UIManager.getInt("InternalFrame.titleButtonHeight") - 4; + Icon icon = button.getIcon(); + return height == button.getHeight() + && (height + widthAdd) == button.getWidth() + && height == icon.getIconHeight() + && (height + widthAdd) == icon.getIconWidth(); + } +} + diff --git a/test/jdk/jdk/classfile/PreviewMinorVersionTest.java b/test/jdk/jdk/classfile/PreviewMinorVersionTest.java new file mode 100644 index 00000000000..cee2fd94673 --- /dev/null +++ b/test/jdk/jdk/classfile/PreviewMinorVersionTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 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. + */ +import jdk.internal.classfile.Classfile; +import org.junit.jupiter.api.Test; + +import java.lang.constant.ClassDesc; + +import static java.lang.constant.ConstantDescs.*; +import static jdk.internal.classfile.Classfile.*; +import static org.junit.jupiter.api.Assertions.*; + +/* + * @test + * @bug 8311172 + * @run junit PreviewMinorVersionTest + * @summary Ensures Classfile.PREVIEW_MINOR_VERSION equals that of classes with + * preview minor version from ClassModel::minorVersion + */ +public class PreviewMinorVersionTest { + + @Test + public void testMinorVersionMatches() { + // compile a class with --enable-preview + // uses Record feature to trigger forcePreview + var cf = Classfile.of(); + var cd = ClassDesc.of("Test"); + var bytes = cf.build(cd, cb -> cb + .withSuperclass(CD_Object) + // old preview minor version, + // with all bits set to 1 + .withVersion(JAVA_17_VERSION, -1) + ); + + var cm = Classfile.of().parse(bytes); + assertEquals(Classfile.PREVIEW_MINOR_VERSION, cm.minorVersion()); + } +} diff --git a/test/jdk/sun/security/ec/ecModuleCheck.java b/test/jdk/sun/security/ec/ecModuleCheck.java new file mode 100644 index 00000000000..4c8ce628970 --- /dev/null +++ b/test/jdk/sun/security/ec/ecModuleCheck.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 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. + * + * 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.module.ModuleFinder; +import static jdk.test.lib.Asserts.*; + +/* + * @test + * @bug 8308398 + * @library /test/lib + * @summary Verify jdk.crypto.ec empty module + * @run main ecModuleCheck + */ + +/* This test verifies jdk.crypto.ec is in the image, but not resolvable. + */ +public class ecModuleCheck { + public static void main(String[] args) throws Exception { + // True if module is found in the image. + assertTrue(ModuleFinder.ofSystem().find("jdk.crypto.ec").isPresent(), + "jdk.crypto.ec was not found in image."); + // Since the module empty, isPresent() should be false. + assertFalse(ModuleLayer.boot().findModule("jdk.crypto.ec"). + isPresent(), "jdk.crypto.ec shouldn't be resolvable."); + } +} diff --git a/test/jdk/sun/security/ec/ed/TestEdOps.java b/test/jdk/sun/security/ec/ed/TestEdOps.java index 79502be45e0..6ef1446db46 100644 --- a/test/jdk/sun/security/ec/ed/TestEdOps.java +++ b/test/jdk/sun/security/ec/ed/TestEdOps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -30,7 +30,7 @@ * java.base/sun.security.util * java.base/sun.security.util.math * java.base/sun.security.util.math.intpoly - * jdk.crypto.ec/sun.security.ec.ed + * java.base/sun.security.ec.ed * @run main TestEdOps */ diff --git a/test/jdk/sun/security/ec/xec/TestXECOps.java b/test/jdk/sun/security/ec/xec/TestXECOps.java index 15f5a813bb2..cdbcf95fc0b 100644 --- a/test/jdk/sun/security/ec/xec/TestXECOps.java +++ b/test/jdk/sun/security/ec/xec/TestXECOps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -25,7 +25,7 @@ * @test * @bug 8171277 * @summary Test XEC curve operations - * @modules jdk.crypto.ec/sun.security.ec + * @modules java.base/sun.security.ec * @library /test/lib * @build jdk.test.lib.Convert * @run main TestXECOps diff --git a/test/jdk/sun/security/ec/xec/XECIterative.java b/test/jdk/sun/security/ec/xec/XECIterative.java index 0d5d2931145..2550bd1a290 100644 --- a/test/jdk/sun/security/ec/xec/XECIterative.java +++ b/test/jdk/sun/security/ec/xec/XECIterative.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -27,7 +27,7 @@ * @summary XEC curve operations iterative test vectors * @library /test/lib * @build jdk.test.lib.Convert - * @modules jdk.crypto.ec/sun.security.ec + * @modules java.base/sun.security.ec * @run main XECIterative 0 10000 * @run main XECIterative 10000 20000 * @run main XECIterative 20000 30000 diff --git a/test/jdk/sun/security/pkcs11/ec/ReadPKCS12.java b/test/jdk/sun/security/pkcs11/ec/ReadPKCS12.java index 6005d88aec4..d35310488d4 100644 --- a/test/jdk/sun/security/pkcs11/ec/ReadPKCS12.java +++ b/test/jdk/sun/security/pkcs11/ec/ReadPKCS12.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -29,7 +29,7 @@ * @library /test/lib .. * @library ../../../../java/security/testlibrary * @key randomness - * @modules jdk.crypto.cryptoki jdk.crypto.ec/sun.security.ec + * @modules jdk.crypto.cryptoki java.base/sun.security.ec * @run main/othervm ReadPKCS12 * @run main/othervm -Djava.security.manager=allow ReadPKCS12 sm policy */ diff --git a/test/jdk/sun/security/provider/PolicyFile/DefaultPolicy.java b/test/jdk/sun/security/provider/PolicyFile/DefaultPolicy.java index 697db6c86e2..e16cef02657 100644 --- a/test/jdk/sun/security/provider/PolicyFile/DefaultPolicy.java +++ b/test/jdk/sun/security/provider/PolicyFile/DefaultPolicy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -64,14 +64,14 @@ public static void main(String[] args) throws Exception { } private static void checkPolicy(Policy p) throws Exception { - // check if jdk.crypto.ec module has been de-privileged + // check if jdk.crypto.cryptoki module has been de-privileged CodeSource cs = - new CodeSource(new URL("jrt:/jdk.crypto.ec"), (CodeSigner[])null); + new CodeSource(new URL("jrt:/jdk.crypto.cryptoki"), (CodeSigner[])null); ProtectionDomain pd = new ProtectionDomain(cs, null, null, null); if (p.implies(pd, new AllPermission())) { throw new Exception("module should not be granted AllPermission"); } - if (!p.implies(pd, new RuntimePermission("loadLibrary.sunec"))) { + if (!p.implies(pd, new RuntimePermission("loadLibrary.j2pkcs11"))) { throw new Exception("module should be granted RuntimePermission"); } } diff --git a/test/jdk/sun/security/tools/keytool/fakegen/DefaultSignatureAlgorithm.java b/test/jdk/sun/security/tools/keytool/fakegen/DefaultSignatureAlgorithm.java index 5f0822440fc..cc6a2df2081 100644 --- a/test/jdk/sun/security/tools/keytool/fakegen/DefaultSignatureAlgorithm.java +++ b/test/jdk/sun/security/tools/keytool/fakegen/DefaultSignatureAlgorithm.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -28,9 +28,11 @@ * @library /test/lib * @build java.base/sun.security.rsa.RSAKeyPairGenerator * java.base/sun.security.provider.DSAKeyPairGenerator - * jdk.crypto.ec/sun.security.ec.ECKeyPairGenerator + * java.base/sun.security.ec.ECKeyPairGenerator * @run main DefaultSignatureAlgorithm - * @modules jdk.crypto.ec + * + * This test uses RSA, DSA, and EC inside this test directory, not the providers + * from the jdk */ import jdk.test.lib.Asserts; @@ -82,10 +84,7 @@ static OutputAnalyzer genkeypair(String alias, String options) throws Exception { String patchArg = "-J--patch-module=java.base=" + System.getProperty("test.classes") - + File.separator + "patches" + File.separator + "java.base" - + " -J--patch-module=jdk.crypto.ec=" - + System.getProperty("test.classes") - + File.separator + "patches" + File.separator + "jdk.crypto.ec"; + + File.separator + "patches" + File.separator + "java.base"; return kt(patchArg + " -genkeypair -alias " + alias + " -dname CN=" + alias + " " + options); } diff --git a/test/jdk/sun/security/tools/keytool/fakegen/jdk.crypto.ec/sun/security/ec/ECKeyPairGenerator.java b/test/jdk/sun/security/tools/keytool/fakegen/java.base/sun/security/ec/ECKeyPairGenerator.java similarity index 100% rename from test/jdk/sun/security/tools/keytool/fakegen/jdk.crypto.ec/sun/security/ec/ECKeyPairGenerator.java rename to test/jdk/sun/security/tools/keytool/fakegen/java.base/sun/security/ec/ECKeyPairGenerator.java diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JLinkOptionsTest.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JLinkOptionsTest.java index 5f97df482bf..40e143763fd 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JLinkOptionsTest.java +++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JLinkOptionsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -63,7 +63,7 @@ public static Collection input() { "--bind-services", }, // with bind-services should have some services - new String[]{"java.smartcardio", "jdk.crypto.ec"}, + new String[]{"java.smartcardio", "jdk.crypto.cryptoki"}, null, }, // bind-services @@ -80,7 +80,7 @@ public static Collection input() { "--jlink-options", "--bind-services", }, // with bind-services should have some services - new String[]{"java.smartcardio", "jdk.crypto.ec"}, + new String[]{"java.smartcardio", "jdk.crypto.cryptoki"}, null, }, @@ -105,7 +105,7 @@ public static Collection input() { // with bind-services should have some services new String[]{"java.smartcardio"}, // but not limited - new String[]{"jdk.crypto.ec"}, + new String[]{"jdk.crypto.cryptoki"}, }, }); diff --git a/test/jdk/tools/launcher/Settings.java b/test/jdk/tools/launcher/Settings.java index 29af50d5c02..36ae06640a1 100644 --- a/test/jdk/tools/launcher/Settings.java +++ b/test/jdk/tools/launcher/Settings.java @@ -25,7 +25,7 @@ /* * @test - * @bug 6994753 7123582 8305950 8281658 + * @bug 6994753 7123582 8305950 8281658 8310201 * @summary tests -XshowSettings options * @modules jdk.compiler * jdk.zipfs @@ -67,6 +67,9 @@ static void checkNotContains(TestResult tr, String str) { private static final String VM_SETTINGS = "VM settings:"; private static final String PROP_SETTINGS = "Property settings:"; private static final String LOCALE_SETTINGS = "Locale settings:"; + private static final String LOCALE_SUMMARY_SETTINGS = + "Locale settings summary:"; + private static final String AVAILABLE_LOCALES = "available locales"; private static final String SEC_PROPS_SETTINGS = "Security properties:"; private static final String SEC_SUMMARY_PROPS_SETTINGS = "Security settings summary:"; @@ -81,7 +84,9 @@ static void checkNotContains(TestResult tr, String str) { static void containsAllOptions(TestResult tr) { checkContains(tr, VM_SETTINGS); checkContains(tr, PROP_SETTINGS); - checkContains(tr, LOCALE_SETTINGS); + checkNotContains(tr, LOCALE_SETTINGS); + checkNotContains(tr, AVAILABLE_LOCALES); + checkContains(tr, LOCALE_SUMMARY_SETTINGS); // no verbose security settings unless "security" used checkNotContains(tr, SEC_PROPS_SETTINGS); checkContains(tr, SEC_SUMMARY_PROPS_SETTINGS); @@ -153,6 +158,8 @@ static void runTestOptionLocale() throws IOException { checkNotContains(tr, VM_SETTINGS); checkNotContains(tr, PROP_SETTINGS); checkContains(tr, LOCALE_SETTINGS); + checkContains(tr, AVAILABLE_LOCALES); + checkNotContains(tr, LOCALE_SUMMARY_SETTINGS); checkContains(tr, TZDATA_SETTINGS); } diff --git a/test/langtools/tools/javac/patterns/Exhaustiveness.java b/test/langtools/tools/javac/patterns/Exhaustiveness.java index 88c897e6edc..dad1a0c86f8 100644 --- a/test/langtools/tools/javac/patterns/Exhaustiveness.java +++ b/test/langtools/tools/javac/patterns/Exhaustiveness.java @@ -23,7 +23,7 @@ /** * @test - * @bug 8262891 8268871 8274363 8281100 8294670 8311038 + * @bug 8262891 8268871 8274363 8281100 8294670 8311038 8311815 * @summary Check exhaustiveness of switches over sealed types. * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -1540,7 +1540,7 @@ int test(Object o) { "1 error"); } - private static final int NESTING_CONSTANT = 5; + private static final int NESTING_CONSTANT = 4; Set createDeeplyNestedVariants() { Set variants = new HashSet<>(); @@ -1968,6 +1968,34 @@ record Rec(Object o) {} """); } + @Test //JDK-8311815: + public void testAmbiguousRecordUsage(Path base) throws Exception { + doTest(base, + new String[0], + """ + package test; + public class Test { + record Pair(I i1, I i2) {} + sealed interface I {} + record C() implements I {} + record D() implements I {} + + void exhaustinvenessWithInterface(Pair pairI) { + switch (pairI) { + case Pair(D fst, C snd) -> { + } + case Pair(C fst, C snd) -> { + } + case Pair(C fst, I snd) -> { + } + case Pair(D fst, D snd) -> { + } + } + } + } + """); + } + private void doTest(Path base, String[] libraryCode, String testCode, String... expectedErrors) throws IOException { doTest(base, libraryCode, testCode, false, expectedErrors); } diff --git a/test/micro/org/openjdk/bench/java/lang/invoke/LazyStaticColdStart.java b/test/micro/org/openjdk/bench/java/lang/invoke/LazyStaticColdStart.java new file mode 100644 index 00000000000..976554a259a --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/LazyStaticColdStart.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 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. + * + * 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.invoke; + +import jdk.internal.classfile.Classfile; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +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.infra.Blackhole; + +import java.lang.constant.ClassDesc; +import java.lang.constant.MethodTypeDesc; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; + +import static java.lang.constant.ConstantDescs.*; +import static jdk.internal.classfile.Classfile.ACC_STATIC; + +/** + * A benchmark ensuring that var and method handle lazy initialization are not + * too slow compared to eager initialization. + */ +@BenchmarkMode(Mode.SingleShotTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Thread) +@Fork(value = 10, warmups = 5, jvmArgsAppend = { + "--add-exports", "java.base/jdk.internal.classfile=ALL-UNNAMED", + "--add-exports", "java.base/jdk.internal.classfile.attribute=ALL-UNNAMED", + "--add-exports", "java.base/jdk.internal.classfile.constantpool=ALL-UNNAMED", + "--add-exports", "java.base/jdk.internal.classfile.instruction=ALL-UNNAMED", + "--add-exports", "java.base/jdk.internal.classfile.components=ALL-UNNAMED" +}) +public class LazyStaticColdStart { + private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); + + private Class targetClass; + + /** + * Ensures non-initialized targetClass is used and initializes the lazy/non-lazy handles + * to prevent further creation costs. (see static initializer block comments) + */ + @Setup(Level.Iteration) + public void setup() throws Throwable { + class Holder { + static final ClassDesc describedClass = LazyStaticColdStart.class.describeConstable().orElseThrow().nested("Data"); + static final ClassDesc CD_ThreadLocalRandom = ThreadLocalRandom.class.describeConstable().orElseThrow(); + static final ClassDesc CD_Blackhole = Blackhole.class.describeConstable().orElseThrow(); + static final MethodTypeDesc MTD_void_long = MethodTypeDesc.of(CD_void, CD_long); + static final MethodTypeDesc MTD_ThreadLocalRandom = MethodTypeDesc.of(CD_ThreadLocalRandom); + static final MethodTypeDesc MTD_long = MethodTypeDesc.of(CD_long); + static final byte[] classBytes = Classfile.of().build(describedClass, clb -> { + clb.withField("v", CD_long, ACC_STATIC); + clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, cob -> { + cob.constantInstruction(100L); + cob.invokestatic(CD_Blackhole, "consumeCPU", MTD_void_long); + cob.invokestatic(CD_ThreadLocalRandom, "current", MTD_ThreadLocalRandom); + cob.invokevirtual(CD_ThreadLocalRandom, "nextLong", MTD_long); + cob.putstatic(describedClass, "v", CD_long); + cob.return_(); + }); + }); + + /* + * This static initializer eliminates overheads with initializing VarHandle/ + * MethodHandle infrastructure that's not done in startup, so + * we are only measuring new Class initialization costs. + */ + static { + class AnotherLazy { + static long f; + } + try { + LOOKUP.findStaticVarHandle(AnotherLazy.class, "f", long.class); // lazy static VH + LOOKUP.findStaticGetter(AnotherLazy.class, "f", long.class); // lazy static MH + AnotherLazy.f = 5L; // initialize class + LOOKUP.findStaticVarHandle(AnotherLazy.class, "f", long.class); // static VH + LOOKUP.findStaticGetter(AnotherLazy.class, "f", long.class); // static MH + } catch (RuntimeException | Error e) { + throw e; + } catch (Throwable ex) { + throw new ExceptionInInitializerError(ex); + } + } + } + targetClass = LOOKUP.defineHiddenClass(Holder.classBytes, false).lookupClass(); + } + + @Benchmark + public VarHandle varHandleCreateLazy() throws Throwable { + return LOOKUP.findStaticVarHandle(targetClass, "v", long.class); + } + + @Benchmark + public VarHandle varHandleCreateEager() throws Throwable { + LOOKUP.ensureInitialized(targetClass); + return LOOKUP.findStaticVarHandle(targetClass, "v", long.class); + } + + @Benchmark + public long varHandleInitializeCallLazy() throws Throwable { + return (long) LOOKUP.findStaticVarHandle(targetClass, "v", long.class).get(); + } + + @Benchmark + public long varHandleInitializeCallEager() throws Throwable { + LOOKUP.ensureInitialized(targetClass); + return (long) LOOKUP.findStaticVarHandle(targetClass, "v", long.class).get(); + } + + @Benchmark + public MethodHandle methodHandleCreateLazy() throws Throwable { + return LOOKUP.findStaticGetter(targetClass, "v", long.class); + } + + @Benchmark + public MethodHandle methodHandleCreateEager() throws Throwable { + LOOKUP.ensureInitialized(targetClass); + return LOOKUP.findStaticGetter(targetClass, "v", long.class); + } + + @Benchmark + public long methodHandleInitializeCallLazy() throws Throwable { + return (long) LOOKUP.findStaticGetter(targetClass, "v", long.class).invokeExact(); + } + + @Benchmark + public long methodHandleInitializeCallEager() throws Throwable { + LOOKUP.ensureInitialized(targetClass); + return (long) LOOKUP.findStaticGetter(targetClass, "v", long.class).invokeExact(); + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/invoke/VarHandleLazyStaticInvocation.java b/test/micro/org/openjdk/bench/java/lang/invoke/VarHandleLazyStaticInvocation.java new file mode 100644 index 00000000000..372caa55b00 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/VarHandleLazyStaticInvocation.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 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. + * + * 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.invoke; + +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.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; + +/** + * A benchmark testing lazy static var handle vs regular static var handle, + * to ensure the lazy static var handle doesn't have too much post-initialization + * invocation penalties. + */ +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@State(Scope.Thread) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Fork(3) +public class VarHandleLazyStaticInvocation { + + static final VarHandle initialized; + static final VarHandle lazy; + static long longField; + + static { + try { + lazy = MethodHandles.lookup().findStaticVarHandle(Data.class, "longField", long.class); + initialized = MethodHandles.lookup().findStaticVarHandle(VarHandleLazyStaticInvocation.class, "longField", long.class); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + + static class Data { + static long longField; + } + + @Benchmark + public long lazyInvocation() { + lazy.set((long) ThreadLocalRandom.current().nextLong()); + return (long) lazy.get(); + } + + @Benchmark + public long initializedInvocation() { + initialized.set((long) ThreadLocalRandom.current().nextLong()); + return (long) initialized.get(); + } +} diff --git a/test/micro/org/openjdk/bench/java/util/random/RandomGeneratorExponentialGaussian.java b/test/micro/org/openjdk/bench/java/util/random/RandomGeneratorExponentialGaussian.java new file mode 100644 index 00000000000..1eff22f3785 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/random/RandomGeneratorExponentialGaussian.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 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. + * + * 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.util.random; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +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.Param; +import java.util.random.RandomGenerator; +import java.util.random.RandomGeneratorFactory; +import java.util.concurrent.TimeUnit; + +/** + * Tests java.util.random.RandomGenerator's implementations of nextExponential and nextGaussian + */ +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class RandomGeneratorExponentialGaussian { + + RandomGenerator randomGenerator; + + @Param({"L64X128MixRandom", "L64X1024MixRandom"}) + String randomGeneratorName; + + @Param({"false","true"}) + boolean fixedSeed; + + double[] buffer; + + @Param("1024") + int size; + + @Setup + public void setup() { + buffer = new double[size]; + RandomGeneratorFactory factory = RandomGeneratorFactory.of(randomGeneratorName); + randomGenerator = fixedSeed ? factory.create(randomGeneratorName.hashCode()) : factory.create(); + } + + @Benchmark + @BenchmarkMode({Mode.SampleTime, Mode.AverageTime}) + public double testNextGaussian() { + return randomGenerator.nextGaussian(); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + public double[] testFillBufferWithNextGaussian() { + for (int i = 0; i < size; i++) buffer[i] = randomGenerator.nextGaussian(); + return buffer; + } + + @Benchmark + @BenchmarkMode({Mode.SampleTime, Mode.AverageTime}) + public double testNextExponential() { + return randomGenerator.nextExponential(); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + public double[] testFillBufferWithNextExponential() { + for (int i = 0; i < size; i++) buffer[i] = randomGenerator.nextExponential(); + return buffer; + } + +} diff --git a/test/micro/org/openjdk/bench/java/util/RandomGeneratorNext.java b/test/micro/org/openjdk/bench/java/util/random/RandomGeneratorNext.java similarity index 96% rename from test/micro/org/openjdk/bench/java/util/RandomGeneratorNext.java rename to test/micro/org/openjdk/bench/java/util/random/RandomGeneratorNext.java index 4ab265080dd..f0aed89619b 100644 --- a/test/micro/org/openjdk/bench/java/util/RandomGeneratorNext.java +++ b/test/micro/org/openjdk/bench/java/util/random/RandomGeneratorNext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.java.util; +package org.openjdk.bench.java.util.random; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; diff --git a/test/micro/org/openjdk/bench/java/util/RandomNext.java b/test/micro/org/openjdk/bench/java/util/random/RandomNext.java similarity index 95% rename from test/micro/org/openjdk/bench/java/util/RandomNext.java rename to test/micro/org/openjdk/bench/java/util/random/RandomNext.java index 4b68a062b76..f3d09996c66 100644 --- a/test/micro/org/openjdk/bench/java/util/RandomNext.java +++ b/test/micro/org/openjdk/bench/java/util/random/RandomNext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.java.util; +package org.openjdk.bench.java.util.random; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode;