diff --git a/.jcheck/conf b/.jcheck/conf index 18228df5dfe46..b374bde90a538 100644 --- a/.jcheck/conf +++ b/.jcheck/conf @@ -15,7 +15,7 @@ version=0 domain=openjdk.org [checks "whitespace"] -files=.*\.cpp|.*\.hpp|.*\.c|.*\.h|.*\.java|.*\.cc|.*\.hh|.*\.m|.*\.mm|.*\.md|.*\.gmk|.*\.m4|.*\.ac|Makefile +files=.*\.cpp|.*\.hpp|.*\.c|.*\.h|.*\.java|.*\.cc|.*\.hh|.*\.m|.*\.mm|.*\.md|.*\.properties|.*\.gmk|.*\.m4|.*\.ac|Makefile ignore-tabs=.*\.gmk|Makefile [checks "merge"] diff --git a/doc/building.html b/doc/building.html index d51e74d1454be..8a0acada254ac 100644 --- a/doc/building.html +++ b/doc/building.html @@ -526,7 +526,7 @@

Linux

The basic tooling is provided as part of the core operating system, but you will most likely need to install developer packages.

For apt-based distributions (Debian, Ubuntu, etc), try this:

-
sudo apt-get install build-essential
+
sudo apt-get install build-essential autoconf

For rpm-based distributions (Fedora, Red Hat, etc), try this:

sudo yum groupinstall "Development Tools"

For Alpine Linux, aside from basic tooling, install the GNU versions @@ -2166,15 +2166,26 @@

Using Multiple configure from there, e.g. mkdir build/<name> && cd build/<name> && bash ../../configure.

Then you can build that configuration using -make CONF_NAME=<name> or -make CONF=<pattern>, where -<pattern> is a substring matching one or several -configurations, e.g. CONF=debug. The special empty pattern -(CONF=) will match all available configuration, so -make CONF= hotspot will build the hotspot -target for all configurations. Alternatively, you can execute -make in the configuration directory, e.g. -cd build/<name> && make.

+make CONF=<selector>, where +<selector> is interpreted as follows:

+ +

A more specialized version, CONF_NAME=<name> also +exists, which will only match if the given <name> +exactly matches a single configuration.

+

Alternatively, you can execute make in the configuration +directory, e.g. cd build/<name> && make.

+

make CONF_NAME=<name> or

Handling Reconfigurations

If you update the repository and part of the configure script has changed, the build system will force you to re-run diff --git a/doc/building.md b/doc/building.md index 9d928a3924557..ed8a06693551d 100644 --- a/doc/building.md +++ b/doc/building.md @@ -349,7 +349,7 @@ will most likely need to install developer packages. For apt-based distributions (Debian, Ubuntu, etc), try this: ``` -sudo apt-get install build-essential +sudo apt-get install build-essential autoconf ``` For rpm-based distributions (Fedora, Red Hat, etc), try this: @@ -1952,12 +1952,25 @@ configuration with the name ``. Alternatively, you can create a directory under `build` and run `configure` from there, e.g. `mkdir build/ && cd build/ && bash ../../configure`. -Then you can build that configuration using `make CONF_NAME=` or `make -CONF=`, where `` is a substring matching one or several -configurations, e.g. `CONF=debug`. The special empty pattern (`CONF=`) will -match *all* available configuration, so `make CONF= hotspot` will build the -`hotspot` target for all configurations. Alternatively, you can execute `make` -in the configuration directory, e.g. `cd build/ && make`. +Then you can build that configuration using `make CONF=`, where +`` is interpreted as follows: + +* If `` exacly matches the name of a configuration, this and only + this configuration will be selected. +* If `` matches (i.e. is a substring of) the names of several + configurations, then all these configurations will be selected. +* If `` is empty (i.e. `CONF=`), then all configurations will be + selected. +* If `` begins with `!`, then all configurations **not** matching the + string following `!` will be selected. + +A more specialized version, `CONF_NAME=` also exists, which will only +match if the given `` exactly matches a single configuration. + +Alternatively, you can execute `make` in the configuration directory, e.g. `cd +build/ && make`. + +`make CONF_NAME=` or ### Handling Reconfigurations diff --git a/make/Global.gmk b/make/Global.gmk index e5e76b475b941..1df6c5fb6bc4b 100644 --- a/make/Global.gmk +++ b/make/Global.gmk @@ -87,10 +87,9 @@ help: $(info $(_) # (gensrc, java, copy, libs, launchers, gendata)) $(info ) $(info Make control variables) - $(info $(_) CONF= # Build all configurations (note, assignment is empty)) - $(info $(_) CONF= # Build the configuration(s) with a name matching) - $(info $(_) # ) - $(info $(_) CONF_NAME= # Build the configuration with exactly the ) + $(info $(_) CONF= # Select which configuration(s) to build) + $(info $(_) CONF= # Select all configurations (note, assignment is empty)) + $(info $(_) CONF_NAME= # Select the configuration with the name ) $(info $(_) SPEC= # Build the configuration given by the spec file) $(info $(_) LOG= # Change the log level from warn to ) $(info $(_) # Available log levels are:) diff --git a/make/InitSupport.gmk b/make/InitSupport.gmk index 31c80e2f7267f..9ea01d375ced9 100644 --- a/make/InitSupport.gmk +++ b/make/InitSupport.gmk @@ -202,8 +202,14 @@ ifeq ($(HAS_SPEC),) matching_confs := $$(strip $$(all_confs)) else # Otherwise select those that contain the given CONF string - matching_confs := $$(strip $$(foreach var, $$(all_confs), \ - $$(if $$(findstring $$(CONF), $$(var)), $$(var)))) + ifeq ($$(patsubst !%,,$$(CONF)),) + # A CONF starting with ! means we should negate the search term + matching_confs := $$(strip $$(foreach var, $$(all_confs), \ + $$(if $$(findstring $$(subst !,,$$(CONF)), $$(var)), ,$$(var)))) + else + matching_confs := $$(strip $$(foreach var, $$(all_confs), \ + $$(if $$(findstring $$(CONF), $$(var)), $$(var)))) + endif ifneq ($$(filter $$(CONF), $$(matching_confs)), ) # If we found an exact match, use that matching_confs := $$(CONF) diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 45a1e6528b358..af164624877a4 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1181,12 +1181,6 @@ var getJibProfilesDependencies = function (input, common) { revision: (input.build_cpu == "x64" ? "Xcode11.3.1-MacOSX10.15+1.2" : devkit_platform_revisions[devkit_platform]) }, - cups: { - organization: common.organization, - ext: "tar.gz", - revision: "1.0118+1.0" - }, - jtreg: { server: "jpg", product: "jtreg", diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index f22af58f40ab5..501d9df08c1c2 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -2205,14 +2205,14 @@ void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const { st->print_cr("# MachUEPNode"); if (UseCompressedClassPointers) { - st->print_cr("\tldrw rscratch1, j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); - if (CompressedKlassPointers::shift() != 0) { - st->print_cr("\tdecode_klass_not_null rscratch1, rscratch1"); - } + st->print_cr("\tldrw rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); + st->print_cr("\tldrw r10, [rscratch2 + CompiledICData::speculated_klass_offset()]\t# compressed klass"); + st->print_cr("\tcmpw rscratch1, r10"); } else { - st->print_cr("\tldr rscratch1, j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); + st->print_cr("\tldr rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); + st->print_cr("\tldr r10, [rscratch2 + CompiledICData::speculated_klass_offset()]\t# compressed klass"); + st->print_cr("\tcmp rscratch1, r10"); } - st->print_cr("\tcmp r0, rscratch1\t # Inline cache check"); st->print_cr("\tbne, SharedRuntime::_ic_miss_stub"); } #endif @@ -2221,14 +2221,7 @@ void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { // This is the unverified entry point. C2_MacroAssembler _masm(&cbuf); - - __ cmp_klass(j_rarg0, rscratch2, rscratch1); - Label skip; - // TODO - // can we avoid this skip and still use a reloc? - __ br(Assembler::EQ, skip); - __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); - __ bind(skip); + __ ic_check(InteriorEntryAlignment); } uint MachUEPNode::size(PhaseRegAlloc* ra_) const @@ -2582,7 +2575,7 @@ Assembler::Condition to_assembler_cond(BoolTest::mask cond) { } // Binary src (Replicate con) -bool is_valid_sve_arith_imm_pattern(Node* n, Node* m) { +static bool is_valid_sve_arith_imm_pattern(Node* n, Node* m) { if (n == nullptr || m == nullptr) { return false; } @@ -2623,7 +2616,7 @@ bool is_valid_sve_arith_imm_pattern(Node* n, Node* m) { // (XorV src (Replicate m1)) // (XorVMask src (MaskAll m1)) -bool is_vector_bitwise_not_pattern(Node* n, Node* m) { +static bool is_vector_bitwise_not_pattern(Node* n, Node* m) { if (n != nullptr && m != nullptr) { return (n->Opcode() == Op_XorV || n->Opcode() == Op_XorVMask) && VectorNode::is_all_ones_vector(m); @@ -3715,7 +3708,7 @@ encode %{ cbuf.shared_stub_to_interp_for(_method, call - cbuf.insts_begin()); } else { // Emit stub for static call - address stub = CompiledStaticCall::emit_to_interp_stub(cbuf, call); + address stub = CompiledDirectCall::emit_to_interp_stub(cbuf, call); if (stub == nullptr) { ciEnv::current()->record_failure("CodeCache is full"); return; @@ -8289,7 +8282,7 @@ instruct membar_acquire() %{ ins_cost(VOLATILE_REF_COST); format %{ "membar_acquire\n\t" - "dmb ishld" %} + "dmb ish" %} ins_encode %{ __ block_comment("membar_acquire"); @@ -8343,12 +8336,11 @@ instruct membar_release() %{ ins_cost(VOLATILE_REF_COST); format %{ "membar_release\n\t" - "dmb ishst\n\tdmb ishld" %} + "dmb ish" %} ins_encode %{ __ block_comment("membar_release"); - __ membar(Assembler::StoreStore); - __ membar(Assembler::LoadStore); + __ membar(Assembler::LoadStore|Assembler::StoreStore); %} ins_pipe(pipe_serial); %} diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp index b83d618506298..ba613b62a3e2a 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp @@ -53,7 +53,6 @@ #endif NEEDS_CLEANUP // remove this definitions ? -const Register IC_Klass = rscratch2; // where the IC klass is cached const Register SYNC_header = r0; // synchronization header const Register SHIFT_count = r0; // where count for shift operations must be @@ -293,27 +292,7 @@ void LIR_Assembler::osr_entry() { // inline cache check; done before the frame is built. int LIR_Assembler::check_icache() { - Register receiver = FrameMap::receiver_opr->as_register(); - Register ic_klass = IC_Klass; - int start_offset = __ offset(); - __ inline_cache_check(receiver, ic_klass); - - // if icache check fails, then jump to runtime routine - // Note: RECEIVER must still contain the receiver! - Label dont; - __ br(Assembler::EQ, dont); - __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); - - // We align the verified entry point unless the method body - // (including its inline cache check) will fit in a single 64-byte - // icache line. - if (! method()->is_accessor() || __ offset() - start_offset > 4 * 4) { - // force alignment after the cache check. - __ align(CodeEntryAlignment); - } - - __ bind(dont); - return start_offset; + return __ ic_check(CodeEntryAlignment); } void LIR_Assembler::clinit_barrier(ciMethod* method) { @@ -2042,7 +2021,7 @@ void LIR_Assembler::emit_static_call_stub() { __ relocate(static_stub_Relocation::spec(call_pc)); __ emit_static_call_stub(); - assert(__ offset() - start + CompiledStaticCall::to_trampoline_stub_size() + assert(__ offset() - start + CompiledDirectCall::to_trampoline_stub_size() <= call_stub_size(), "stub too big"); __ end_a_stub(); } diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp index 43ec189255f9c..ef1b5fe2703e6 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp @@ -71,8 +71,8 @@ friend class ArrayCopyStub; void deoptimize_trap(CodeEmitInfo *info); enum { - // call stub: CompiledStaticCall::to_interp_stub_size() + - // CompiledStaticCall::to_trampoline_stub_size() + // call stub: CompiledDirectCall::to_interp_stub_size() + + // CompiledDirectCall::to_trampoline_stub_size() _call_stub_size = 13 * NativeInstruction::instruction_size, _exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(175), _deopt_handler_size = 7 * NativeInstruction::instruction_size diff --git a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp index d3a746178f14e..c0d1d1747ab28 100644 --- a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp @@ -308,17 +308,6 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, verify_oop(obj); } - -void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) { - verify_oop(receiver); - // explicit null check not needed since load from [klass_offset] causes a trap - // check against inline cache - assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "must add explicit null check"); - - cmp_klass(receiver, iCache, rscratch1); -} - - void C1_MacroAssembler::build_frame(int framesize, int bang_size_in_bytes) { assert(bang_size_in_bytes >= framesize, "stack bang size incorrect"); // Make sure there is enough stack space for this method's activation. diff --git a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp index d2f4744a04914..63a32e714e365 100644 --- a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp @@ -38,7 +38,6 @@ #include "interpreter/interpreter.hpp" #include "memory/universe.hpp" #include "nativeInst_aarch64.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "register_aarch64.hpp" diff --git a/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp b/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp index c58ff8828bce6..23c08f11d1a8b 100644 --- a/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp @@ -26,7 +26,6 @@ #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" #include "code/compiledIC.hpp" -#include "code/icBuffer.hpp" #include "code/nmethod.hpp" #include "logging/log.hpp" #include "memory/resourceArea.hpp" @@ -36,7 +35,7 @@ // ---------------------------------------------------------------------------- #define __ _masm. -address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) { +address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) { precond(cbuf.stubs()->start() != badAddress); precond(cbuf.stubs()->end() != badAddress); @@ -71,11 +70,11 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) } #undef __ -int CompiledStaticCall::to_interp_stub_size() { +int CompiledDirectCall::to_interp_stub_size() { return MacroAssembler::static_call_stub_size(); } -int CompiledStaticCall::to_trampoline_stub_size() { +int CompiledDirectCall::to_trampoline_stub_size() { // Somewhat pessimistically, we count 3 instructions here (although // there are only two) because we sometimes emit an alignment nop. // Trampoline stubs are always word aligned. @@ -83,21 +82,14 @@ int CompiledStaticCall::to_trampoline_stub_size() { } // Relocation entries for call stub, compiled java to interpreter. -int CompiledStaticCall::reloc_to_interp_stub() { +int CompiledDirectCall::reloc_to_interp_stub() { return 4; // 3 in emit_to_interp_stub + 1 in emit_call } -void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) { +void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) { address stub = find_stub(); guarantee(stub != nullptr, "stub not found"); - { - ResourceMark rm; - log_trace(inlinecache)("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s", - p2i(instruction_address()), - callee->name_and_sig_as_C_string()); - } - // Creation also verifies the object. NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + NativeInstruction::instruction_size); @@ -115,7 +107,7 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad set_destination_mt_safe(stub); } -void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) { +void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) { // Reset stub. address stub = static_stub->addr(); assert(stub != nullptr, "stub not found"); @@ -132,7 +124,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_ // Non-product mode code #ifndef PRODUCT -void CompiledDirectStaticCall::verify() { +void CompiledDirectCall::verify() { // Verify call. _call->verify(); _call->verify_alignment(); diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.cpp b/src/hotspot/cpu/aarch64/frame_aarch64.cpp index c5b2ff8a4c01c..8d0fa8895d15c 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -678,7 +678,7 @@ static void printbc(Method *m, intptr_t bcx) { printf("%s : %s ==> %s\n", m->name_and_sig_as_C_string(), buf, name); } -void internal_pf(uintptr_t sp, uintptr_t fp, uintptr_t pc, uintptr_t bcx) { +static void internal_pf(uintptr_t sp, uintptr_t fp, uintptr_t pc, uintptr_t bcx) { if (! fp) return; diff --git a/src/hotspot/cpu/aarch64/globals_aarch64.hpp b/src/hotspot/cpu/aarch64/globals_aarch64.hpp index 13f2e4b61b9a4..293cc6eb0d0c6 100644 --- a/src/hotspot/cpu/aarch64/globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/globals_aarch64.hpp @@ -127,8 +127,6 @@ define_pd_global(intx, InlineSmallCode, 1000); range(1, 99) \ product(ccstr, UseBranchProtection, "none", \ "Branch Protection to use: none, standard, pac-ret") \ - product(bool, AlwaysMergeDMB, false, DIAGNOSTIC, \ - "Always merge DMB instructions in code emission") \ // end of ARCH_FLAGS diff --git a/src/hotspot/cpu/aarch64/icBuffer_aarch64.cpp b/src/hotspot/cpu/aarch64/icBuffer_aarch64.cpp deleted file mode 100644 index bd8cfc42600e2..0000000000000 --- a/src/hotspot/cpu/aarch64/icBuffer_aarch64.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, Red Hat Inc. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "asm/macroAssembler.inline.hpp" -#include "code/icBuffer.hpp" -#include "gc/shared/collectedHeap.inline.hpp" -#include "interpreter/bytecodes.hpp" -#include "memory/resourceArea.hpp" -#include "nativeInst_aarch64.hpp" -#include "oops/oop.inline.hpp" - -int InlineCacheBuffer::ic_stub_code_size() { - return (MacroAssembler::far_branches() ? 6 : 4) * NativeInstruction::instruction_size; -} - -#define __ masm-> - -void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) { - ResourceMark rm; - CodeBuffer code(code_begin, ic_stub_code_size()); - MacroAssembler* masm = new MacroAssembler(&code); - // note: even though the code contains an embedded value, we do not need reloc info - // because - // (1) the value is old (i.e., doesn't matter for scavenges) - // (2) these ICStubs are removed *before* a GC happens, so the roots disappear - // assert(cached_value == nullptr || cached_oop->is_perm(), "must be perm oop"); - - address start = __ pc(); - Label l; - __ ldr(rscratch2, l); - int jump_code_size = __ far_jump(ExternalAddress(entry_point)); - // IC stub code size is not expected to vary depending on target address. - // We use NOPs to make the [ldr + far_jump + nops + int64] stub size equal to ic_stub_code_size. - for (int size = NativeInstruction::instruction_size + jump_code_size + 8; - size < ic_stub_code_size(); size += NativeInstruction::instruction_size) { - __ nop(); - } - __ bind(l); - assert((uintptr_t)__ pc() % wordSize == 0, ""); - __ emit_int64((int64_t)cached_value); - // Only need to invalidate the 1st two instructions - not the whole ic stub - ICache::invalidate_range(code_begin, InlineCacheBuffer::ic_stub_code_size()); - assert(__ pc() - start == ic_stub_code_size(), "must be"); -} - -address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) { - NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object - NativeJump* jump = nativeJump_at(code_begin + 4); - return jump->jump_destination(); -} - - -void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) { - // The word containing the cached value is at the end of this IC buffer - uintptr_t *p = (uintptr_t *)(code_begin + ic_stub_code_size() - wordSize); - void* o = (void*)*p; - return o; -} diff --git a/src/hotspot/cpu/aarch64/immediate_aarch64.cpp b/src/hotspot/cpu/aarch64/immediate_aarch64.cpp index 3d87fde2b5bcd..7caafc19fbd31 100644 --- a/src/hotspot/cpu/aarch64/immediate_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/immediate_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -53,7 +53,7 @@ struct li_pair { static struct li_pair InverseLITable[LI_TABLE_SIZE]; // comparator to sort entries in the inverse table -int compare_immediate_pair(const void *i1, const void *i2) +static int compare_immediate_pair(const void *i1, const void *i2) { struct li_pair *li1 = (struct li_pair *)i1; struct li_pair *li2 = (struct li_pair *)i2; @@ -142,7 +142,7 @@ static inline uint32_t uimm(uint32_t val, int hi, int lo) // result // a bit string containing count copies of input bit string // -uint64_t replicate(uint64_t bits, int nbits, int count) +static uint64_t replicate(uint64_t bits, int nbits, int count) { assert(count > 0, "must be"); assert(nbits > 0, "must be"); @@ -231,8 +231,8 @@ uint64_t replicate(uint64_t bits, int nbits, int count) // For historical reasons the implementation of this function is much // more convoluted than is really necessary. -int expandLogicalImmediate(uint32_t immN, uint32_t immr, - uint32_t imms, uint64_t &bimm) +static int expandLogicalImmediate(uint32_t immN, uint32_t immr, + uint32_t imms, uint64_t &bimm) { int len; // ought to be <= 6 uint32_t levels; // 6 bits @@ -446,4 +446,3 @@ uint32_t encoding_for_fp_immediate(float immediate) res = (s << 7) | (r << 4) | f; return res; } - diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 124af3bafbe3a..b19587ebe760a 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -29,6 +29,7 @@ #include "asm/assembler.hpp" #include "asm/assembler.inline.hpp" #include "ci/ciEnv.hpp" +#include "code/compiledIC.hpp" #include "compiler/compileTask.hpp" #include "compiler/disassembler.hpp" #include "compiler/oopMap.hpp" @@ -965,7 +966,7 @@ int MacroAssembler::max_trampoline_stub_size() { } void MacroAssembler::emit_static_call_stub() { - // CompiledDirectStaticCall::set_to_interpreted knows the + // CompiledDirectCall::set_to_interpreted knows the // exact layout of this stub. isb(); @@ -995,10 +996,51 @@ address MacroAssembler::ic_call(address entry, jint method_index) { // address const_ptr = long_constant((jlong)Universe::non_oop_word()); // uintptr_t offset; // ldr_constant(rscratch2, const_ptr); - movptr(rscratch2, (uintptr_t)Universe::non_oop_word()); + movptr(rscratch2, (intptr_t)Universe::non_oop_word()); return trampoline_call(Address(entry, rh)); } +int MacroAssembler::ic_check_size() { + if (target_needs_far_branch(CAST_FROM_FN_PTR(address, SharedRuntime::get_ic_miss_stub()))) { + return NativeInstruction::instruction_size * 7; + } else { + return NativeInstruction::instruction_size * 5; + } +} + +int MacroAssembler::ic_check(int end_alignment) { + Register receiver = j_rarg0; + Register data = rscratch2; + Register tmp1 = rscratch1; + Register tmp2 = r10; + + // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed + // before the inline cache check, so we don't have to execute any nop instructions when dispatching + // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align + // before the inline cache check here, and not after + align(end_alignment, offset() + ic_check_size()); + + int uep_offset = offset(); + + if (UseCompressedClassPointers) { + ldrw(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes())); + ldrw(tmp2, Address(data, CompiledICData::speculated_klass_offset())); + cmpw(tmp1, tmp2); + } else { + ldr(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes())); + ldr(tmp2, Address(data, CompiledICData::speculated_klass_offset())); + cmp(tmp1, tmp2); + } + + Label dont; + br(Assembler::EQ, dont); + far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); + bind(dont); + assert((offset() % end_alignment) == 0, "Misaligned verified entry point"); + + return uep_offset; +} + // Implementation of call_VM versions void MacroAssembler::call_VM(Register oop_result, @@ -1100,7 +1142,14 @@ void MacroAssembler::get_vm_result_2(Register metadata_result, Register java_thr } void MacroAssembler::align(int modulus) { - while (offset() % modulus != 0) nop(); + align(modulus, offset()); +} + +// Ensure that the code at target bytes offset from the current offset() is aligned +// according to modulus. +void MacroAssembler::align(int modulus, int target) { + int delta = target - offset(); + while ((offset() + delta) % modulus != 0) nop(); } void MacroAssembler::post_call_nop() { @@ -1197,7 +1246,7 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, } // Look up the method for a megamorphic invokeinterface call in a single pass over itable: -// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICHolder +// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICData // - find a holder_klass (class that implements the method) vtable offset and get the method from vtable by index // The target method is determined by . // The receiver klass is in recv_klass. @@ -2066,21 +2115,14 @@ void MacroAssembler::membar(Membar_mask_bits order_constraint) { address last = code()->last_insn(); if (last != nullptr && nativeInstruction_at(last)->is_Membar() && prev == last) { NativeMembar *bar = NativeMembar_at(prev); - // Don't promote DMB ST|DMB LD to DMB (a full barrier) because - // doing so would introduce a StoreLoad which the caller did not - // intend - if (AlwaysMergeDMB || bar->get_kind() == order_constraint - || bar->get_kind() == AnyAny - || order_constraint == AnyAny) { - // We are merging two memory barrier instructions. On AArch64 we - // can do this simply by ORing them together. - bar->set_kind(bar->get_kind() | order_constraint); - BLOCK_COMMENT("merged membar"); - return; - } + // We are merging two memory barrier instructions. On AArch64 we + // can do this simply by ORing them together. + bar->set_kind(bar->get_kind() | order_constraint); + BLOCK_COMMENT("merged membar"); + } else { + code()->set_last_insn(pc()); + dmb(Assembler::barrier(order_constraint)); } - code()->set_last_insn(pc()); - dmb(Assembler::barrier(order_constraint)); } bool MacroAssembler::try_merge_ldst(Register rt, const Address &adr, size_t size_in_bytes, bool is_store) { diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index e92e0ee6aa934..990e725d099eb 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -720,6 +720,7 @@ class MacroAssembler: public Assembler { // Alignment void align(int modulus); + void align(int modulus, int target); // nop void post_call_nop(); @@ -1247,6 +1248,8 @@ class MacroAssembler: public Assembler { // Emit the CompiledIC call idiom address ic_call(address entry, jint method_index = 0); + static int ic_check_size(); + int ic_check(int end_alignment); public: diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index 82da734611693..216c1ff35092a 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -30,7 +30,6 @@ #include "code/codeCache.hpp" #include "code/compiledIC.hpp" #include "code/debugInfoRec.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "compiler/oopMap.hpp" #include "gc/shared/barrierSetAssembler.hpp" @@ -39,7 +38,6 @@ #include "logging/log.hpp" #include "memory/resourceArea.hpp" #include "nativeInst_aarch64.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/klass.inline.hpp" #include "oops/method.inline.hpp" #include "prims/methodHandles.hpp" @@ -740,9 +738,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm address c2i_unverified_entry = __ pc(); Label skip_fixup; - Label ok; - - Register holder = rscratch2; + Register data = rscratch2; Register receiver = j_rarg0; Register tmp = r10; // A call-clobbered register not used for arg passing @@ -757,17 +753,12 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm { __ block_comment("c2i_unverified_entry {"); - __ load_klass(rscratch1, receiver); - __ ldr(tmp, Address(holder, CompiledICHolder::holder_klass_offset())); - __ cmp(rscratch1, tmp); - __ ldr(rmethod, Address(holder, CompiledICHolder::holder_metadata_offset())); - __ br(Assembler::EQ, ok); - __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); - - __ bind(ok); // Method might have been compiled since the call site was patched to // interpreted; if that is the case treat it as a miss so we can get // the call site corrected. + __ ic_check(1 /* end_alignment */); + __ ldr(rmethod, Address(data, CompiledICData::speculated_method_offset())); + __ ldr(rscratch1, Address(rmethod, in_bytes(Method::code_offset()))); __ cbz(rscratch1, skip_fixup); __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); @@ -1118,7 +1109,7 @@ static void gen_continuation_enter(MacroAssembler* masm, __ b(exit); CodeBuffer* cbuf = masm->code_section()->outer(); - address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call); + address stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, tr_call); if (stub == nullptr) { fatal("CodeCache is full at gen_continuation_enter"); } @@ -1183,7 +1174,7 @@ static void gen_continuation_enter(MacroAssembler* masm, } CodeBuffer* cbuf = masm->code_section()->outer(); - address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call); + address stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, tr_call); if (stub == nullptr) { fatal("CodeCache is full at gen_continuation_enter"); } @@ -1539,25 +1530,15 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // restoring them except rfp. rfp is the only callee save register // as far as the interpreter and the compiler(s) are concerned. - - const Register ic_reg = rscratch2; const Register receiver = j_rarg0; - Label hit; Label exception_pending; - assert_different_registers(ic_reg, receiver, rscratch1); + assert_different_registers(receiver, rscratch1); __ verify_oop(receiver); - __ cmp_klass(receiver, ic_reg, rscratch1); - __ br(Assembler::EQ, hit); - - __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); + __ ic_check(8 /* end_alignment */); // Verified entry point must be aligned - __ align(8); - - __ bind(hit); - int vep_offset = ((intptr_t)__ pc()) - start; // If we have to make this method not-entrant we'll overwrite its diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index b53e427649781..18f310c746cd4 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -191,9 +191,6 @@ void VM_Version::initialize() { if (FLAG_IS_DEFAULT(UseSIMDForMemoryOps)) { FLAG_SET_DEFAULT(UseSIMDForMemoryOps, true); } - if (FLAG_IS_DEFAULT(AlwaysMergeDMB)) { - FLAG_SET_DEFAULT(AlwaysMergeDMB, true); - } } // Cortex A53 diff --git a/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp b/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp index c895ff5cc0ec1..2bb53d16a3c97 100644 --- a/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp @@ -26,10 +26,10 @@ #include "precompiled.hpp" #include "asm/assembler.inline.hpp" #include "asm/macroAssembler.inline.hpp" +#include "code/compiledIC.hpp" #include "code/vtableStubs.hpp" #include "interp_masm_aarch64.hpp" #include "memory/resourceArea.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/instanceKlass.hpp" #include "oops/klassVtable.hpp" #include "runtime/sharedRuntime.hpp" @@ -168,22 +168,22 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) { assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0"); // Entry arguments: - // rscratch2: CompiledICHolder + // rscratch2: CompiledICData // j_rarg0: Receiver // This stub is called from compiled code which has no callee-saved registers, // so all registers except arguments are free at this point. const Register recv_klass_reg = r10; - const Register holder_klass_reg = r16; // declaring interface klass (DECC) + const Register holder_klass_reg = r16; // declaring interface klass (DEFC) const Register resolved_klass_reg = r17; // resolved interface klass (REFC) const Register temp_reg = r11; const Register temp_reg2 = r15; - const Register icholder_reg = rscratch2; + const Register icdata_reg = rscratch2; Label L_no_such_interface; - __ ldr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset())); - __ ldr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset())); + __ ldr(resolved_klass_reg, Address(icdata_reg, CompiledICData::itable_refc_klass_offset())); + __ ldr(holder_klass_reg, Address(icdata_reg, CompiledICData::itable_defc_klass_offset())); start_pc = __ pc(); diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad index 6b18e76e6d7eb..1a833b08c4cf4 100644 --- a/src/hotspot/cpu/arm/arm.ad +++ b/src/hotspot/cpu/arm/arm.ad @@ -869,12 +869,7 @@ uint BoxLockNode::size(PhaseRegAlloc *ra_) const { #define R_RTEMP "R_R12" void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { st->print_cr("\nUEP:"); - if (UseCompressedClassPointers) { - st->print_cr("\tLDR_w " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check"); - st->print_cr("\tdecode_klass " R_RTEMP); - } else { - st->print_cr("\tLDR " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check"); - } + st->print_cr("\tLDR " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check"); st->print_cr("\tCMP " R_RTEMP ",R_R8" ); st->print ("\tB.NE SharedRuntime::handle_ic_miss_stub"); } @@ -882,13 +877,7 @@ void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { C2_MacroAssembler _masm(&cbuf); - Register iCache = reg_to_register_object(Matcher::inline_cache_reg_encode()); - assert(iCache == Ricklass, "should be"); - Register receiver = R0; - - __ load_klass(Rtemp, receiver); - __ cmp(Rtemp, iCache); - __ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type, noreg, ne); + __ ic_check(InteriorEntryAlignment); } uint MachUEPNode::size(PhaseRegAlloc *ra_) const { @@ -1241,7 +1230,7 @@ encode %{ emit_call_reloc(cbuf, as_MachCall(), $meth, rspec); // Emit stubs for static call. - address stub = CompiledStaticCall::emit_to_interp_stub(cbuf); + address stub = CompiledDirectCall::emit_to_interp_stub(cbuf); if (stub == nullptr) { ciEnv::current()->record_failure("CodeCache is full"); return; diff --git a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp index 999309c02258d..16aeaa20c04b8 100644 --- a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp @@ -161,10 +161,7 @@ void LIR_Assembler::osr_entry() { int LIR_Assembler::check_icache() { - Register receiver = LIR_Assembler::receiverOpr()->as_register(); - int offset = __ offset(); - __ inline_cache_check(receiver, Ricklass); - return offset; + return __ ic_check(CodeEntryAlignment); } void LIR_Assembler::clinit_barrier(ciMethod* method) { @@ -1950,7 +1947,7 @@ void LIR_Assembler::emit_static_call_stub() { __ relocate(static_stub_Relocation::spec(call_pc)); // If not a single instruction, NativeMovConstReg::next_instruction_address() // must jump over the whole following ldr_literal. - // (See CompiledStaticCall::set_to_interpreted()) + // (See CompiledDirectCall::set_to_interpreted()) #ifdef ASSERT address ldr_site = __ pc(); #endif diff --git a/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp index c09e54e0e57ad..d9d042bb2e4e7 100644 --- a/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp @@ -43,16 +43,6 @@ // arm [macro]assembler) and used with care in the other C1 specific // files. -void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) { - Label verified; - load_klass(Rtemp, receiver); - cmp(Rtemp, iCache); - b(verified, eq); // jump over alignment no-ops - jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type); - align(CodeEntryAlignment); - bind(verified); -} - void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_bytes) { assert(bang_size_in_bytes >= frame_size_in_bytes, "stack bang size incorrect"); assert((frame_size_in_bytes % StackAlignmentInBytes) == 0, "frame size should be aligned"); diff --git a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp index 62faa6170833b..9862a074a687f 100644 --- a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp +++ b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp @@ -37,7 +37,6 @@ #include "interpreter/interpreter.hpp" #include "memory/universe.hpp" #include "nativeInst_arm.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "register_arm.hpp" diff --git a/src/hotspot/cpu/arm/compiledIC_arm.cpp b/src/hotspot/cpu/arm/compiledIC_arm.cpp index 2d4187b7d6c6a..71389d2353d66 100644 --- a/src/hotspot/cpu/arm/compiledIC_arm.cpp +++ b/src/hotspot/cpu/arm/compiledIC_arm.cpp @@ -25,7 +25,6 @@ #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" #include "code/compiledIC.hpp" -#include "code/icBuffer.hpp" #include "code/nativeInst.hpp" #include "code/nmethod.hpp" #include "logging/log.hpp" @@ -37,7 +36,7 @@ #if COMPILER2_OR_JVMCI #define __ _masm. // emit call stub, compiled java to interpreter -address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) { +address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) { // Stub is fixed up when the corresponding call is converted from calling // compiled code to calling interpreted code. // set (empty), R9 @@ -59,7 +58,7 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) InlinedMetadata object_literal(nullptr); // single instruction, see NativeMovConstReg::next_instruction_address() in - // CompiledStaticCall::set_to_interpreted() + // CompiledDirectCall::set_to_interpreted() __ ldr_literal(Rmethod, object_literal); __ set_inst_mark(); // Who uses this? @@ -87,32 +86,25 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) #undef __ // Relocation entries for call stub, compiled java to interpreter. -int CompiledStaticCall::reloc_to_interp_stub() { +int CompiledDirectCall::reloc_to_interp_stub() { return 10; // 4 in emit_to_interp_stub + 1 in Java_Static_Call } #endif // COMPILER2_OR_JVMCI -int CompiledStaticCall::to_trampoline_stub_size() { +int CompiledDirectCall::to_trampoline_stub_size() { // ARM doesn't use trampolines. return 0; } // size of C2 call stub, compiled java to interpreter -int CompiledStaticCall::to_interp_stub_size() { +int CompiledDirectCall::to_interp_stub_size() { return 8 * NativeInstruction::instruction_size; } -void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) { +void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) { address stub = find_stub(); guarantee(stub != nullptr, "stub not found"); - { - ResourceMark rm; - log_trace(inlinecache)("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s", - p2i(instruction_address()), - callee->name_and_sig_as_C_string()); - } - // Creation also verifies the object. NativeMovConstReg* method_holder = nativeMovConstReg_at(stub); NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); @@ -128,7 +120,7 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad set_destination_mt_safe(stub); } -void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) { +void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) { // Reset stub. address stub = static_stub->addr(); assert(stub != nullptr, "stub not found"); @@ -144,7 +136,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_ // Non-product mode code #ifndef PRODUCT -void CompiledDirectStaticCall::verify() { +void CompiledDirectCall::verify() { // Verify call. _call->verify(); _call->verify_alignment(); diff --git a/src/hotspot/cpu/arm/icBuffer_arm.cpp b/src/hotspot/cpu/arm/icBuffer_arm.cpp deleted file mode 100644 index e3a1c148ec6a0..0000000000000 --- a/src/hotspot/cpu/arm/icBuffer_arm.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2008, 2016, 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 "asm/assembler.inline.hpp" -#include "code/icBuffer.hpp" -#include "gc/shared/collectedHeap.inline.hpp" -#include "interpreter/bytecodes.hpp" -#include "memory/resourceArea.hpp" -#include "nativeInst_arm.hpp" -#include "oops/oop.inline.hpp" - -#define __ masm-> - -int InlineCacheBuffer::ic_stub_code_size() { - return (4 * Assembler::InstructionSize); -} - -void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) { - ResourceMark rm; - CodeBuffer code(code_begin, ic_stub_code_size()); - MacroAssembler* masm = new MacroAssembler(&code); - - InlinedAddress oop_literal((address) cached_value); - __ ldr_literal(Ricklass, oop_literal); - // FIXME: OK to remove reloc here? - __ patchable_jump(entry_point, relocInfo::runtime_call_type, Rtemp); - __ bind_literal(oop_literal); - __ flush(); -} - -address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) { - address jump_address; - jump_address = code_begin + NativeInstruction::instruction_size; - NativeJump* jump = nativeJump_at(jump_address); - return jump->jump_destination(); -} - -void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) { - NativeMovConstReg* move = nativeMovConstReg_at(code_begin); - return (void*)move->data(); -} - -#undef __ diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.cpp b/src/hotspot/cpu/arm/macroAssembler_arm.cpp index b827e69d02233..99d619bddb55a 100644 --- a/src/hotspot/cpu/arm/macroAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/macroAssembler_arm.cpp @@ -28,6 +28,7 @@ #include "asm/assembler.inline.hpp" #include "asm/macroAssembler.hpp" #include "ci/ciEnv.hpp" +#include "code/compiledIC.hpp" #include "code/nativeInst.hpp" #include "compiler/disassembler.hpp" #include "gc/shared/barrierSet.hpp" @@ -297,11 +298,13 @@ Address MacroAssembler::receiver_argument_address(Register params_base, Register return Address(tmp, -Interpreter::stackElementSize); } +void MacroAssembler::align(int modulus, int target) { + int delta = target - offset(); + while ((offset() + delta) % modulus != 0) nop(); +} void MacroAssembler::align(int modulus) { - while (offset() % modulus != 0) { - nop(); - } + align(modulus, offset()); } int MacroAssembler::set_last_Java_frame(Register last_java_sp, @@ -1860,3 +1863,31 @@ void MacroAssembler::lightweight_unlock(Register obj, Register t1, Register t2, // Fallthrough: success } + +int MacroAssembler::ic_check_size() { + return NativeInstruction::instruction_size * 7; +} + +int MacroAssembler::ic_check(int end_alignment) { + Register receiver = j_rarg0; + Register tmp1 = R4; + Register tmp2 = R5; + + // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed + // before the inline cache check, so we don't have to execute any nop instructions when dispatching + // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align + // before the inline cache check here, and not after + align(end_alignment, offset() + ic_check_size()); + + int uep_offset = offset(); + + ldr(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes())); + ldr(tmp2, Address(Ricklass, CompiledICData::speculated_klass_offset())); + cmp(tmp1, tmp2); + + Label dont; + b(dont, eq); + jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type); + bind(dont); + return uep_offset; +} diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.hpp b/src/hotspot/cpu/arm/macroAssembler_arm.hpp index d9e49ab986c3a..691c8fa70ee8b 100644 --- a/src/hotspot/cpu/arm/macroAssembler_arm.hpp +++ b/src/hotspot/cpu/arm/macroAssembler_arm.hpp @@ -221,6 +221,7 @@ class MacroAssembler: public Assembler { inline bool ignore_non_patchable_relocations() { return true; } void align(int modulus); + void align(int modulus, int target); // Support for VM calls // @@ -1077,6 +1078,9 @@ class MacroAssembler: public Assembler { void safepoint_poll(Register tmp1, Label& slow_path); void get_polling_page(Register dest); void read_polling_page(Register dest, relocInfo::relocType rtype); + + static int ic_check_size(); + int ic_check(int end_alignment); }; diff --git a/src/hotspot/cpu/arm/nativeInst_arm_32.cpp b/src/hotspot/cpu/arm/nativeInst_arm_32.cpp index 23ee01d335264..6a4062f29b3ba 100644 --- a/src/hotspot/cpu/arm/nativeInst_arm_32.cpp +++ b/src/hotspot/cpu/arm/nativeInst_arm_32.cpp @@ -25,7 +25,6 @@ #include "precompiled.hpp" #include "asm/assembler.inline.hpp" #include "code/codeCache.hpp" -#include "code/icBuffer.hpp" #include "memory/resourceArea.hpp" #include "nativeInst_arm.hpp" #include "oops/oop.inline.hpp" diff --git a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp index 7006d7709813a..15b57188730df 100644 --- a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp +++ b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp @@ -385,7 +385,7 @@ class NativeMovConstReg: public NativeInstruction { } void set_pc_relative_offset(address addr, address pc); address next_instruction_address() const { - // NOTE: CompiledStaticCall::set_to_interpreted() calls this but + // NOTE: CompiledDirectCall::set_to_interpreted() calls this but // are restricted to single-instruction ldr. No need to jump over // several instructions. assert(is_ldr_literal(), "Should only use single-instructions load"); diff --git a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp index 716c7b7575e9c..3792fab082ba6 100644 --- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp +++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp @@ -24,15 +24,14 @@ #include "precompiled.hpp" #include "asm/assembler.inline.hpp" +#include "code/compiledIC.hpp" #include "code/debugInfoRec.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "compiler/oopMap.hpp" #include "gc/shared/barrierSetAssembler.hpp" #include "interpreter/interpreter.hpp" #include "logging/log.hpp" #include "memory/resourceArea.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/klass.inline.hpp" #include "prims/methodHandles.hpp" #include "runtime/jniHandles.hpp" @@ -626,12 +625,9 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm Label skip_fixup; const Register receiver = R0; const Register holder_klass = Rtemp; // XXX should be OK for C2 but not 100% sure - const Register receiver_klass = R4; - __ load_klass(receiver_klass, receiver); - __ ldr(holder_klass, Address(Ricklass, CompiledICHolder::holder_klass_offset())); - __ ldr(Rmethod, Address(Ricklass, CompiledICHolder::holder_metadata_offset())); - __ cmp(receiver_klass, holder_klass); + __ ic_check(1 /* end_alignment */); + __ ldr(Rmethod, Address(Ricklass, CompiledICData::speculated_method_offset())); __ ldr(Rtemp, Address(Rmethod, Method::code_offset()), eq); __ cmp(Rtemp, 0, eq); @@ -819,21 +815,14 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Unverified entry point address start = __ pc(); - // Inline cache check, same as in C1_MacroAssembler::inline_cache_check() const Register receiver = R0; // see receiverOpr() - __ load_klass(Rtemp, receiver); - __ cmp(Rtemp, Ricklass); - Label verified; - - __ b(verified, eq); // jump over alignment no-ops too - __ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type, Rtemp); - __ align(CodeEntryAlignment); + __ verify_oop(receiver); + // Inline cache check + __ ic_check(CodeEntryAlignment /* end_alignment */); // Verified entry point - __ bind(verified); int vep_offset = __ pc() - start; - if ((InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) || (method->intrinsic_id() == vmIntrinsics::_identityHashCode)) { // Object.hashCode, System.identityHashCode can pull the hashCode from the header word // instead of doing a full VM transition once it's been computed. diff --git a/src/hotspot/cpu/arm/vtableStubs_arm.cpp b/src/hotspot/cpu/arm/vtableStubs_arm.cpp index 539e288f63fb2..1229b5073f506 100644 --- a/src/hotspot/cpu/arm/vtableStubs_arm.cpp +++ b/src/hotspot/cpu/arm/vtableStubs_arm.cpp @@ -25,10 +25,10 @@ #include "precompiled.hpp" #include "asm/assembler.inline.hpp" #include "asm/macroAssembler.inline.hpp" +#include "code/compiledIC.hpp" #include "code/vtableStubs.hpp" #include "interp_masm_arm.hpp" #include "memory/resourceArea.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/instanceKlass.hpp" #include "oops/klassVtable.hpp" #include "oops/klass.inline.hpp" @@ -160,7 +160,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) { __ load_klass(Rclass, R0); // Receiver subtype check against REFC. - __ ldr(Rintf, Address(Ricklass, CompiledICHolder::holder_klass_offset())); + __ ldr(Rintf, Address(Ricklass, CompiledICData::itable_refc_klass_offset())); __ lookup_interface_method(// inputs: rec. class, interface, itable index Rclass, Rintf, noreg, // outputs: temp reg1, temp reg2 @@ -171,7 +171,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) { start_pc = __ pc(); // Get Method* and entry point for compiler - __ ldr(Rintf, Address(Ricklass, CompiledICHolder::holder_metadata_offset())); + __ ldr(Rintf, Address(Ricklass, CompiledICData::itable_defc_klass_offset())); __ lookup_interface_method(// inputs: rec. class, interface, itable index Rclass, Rintf, itable_index, // outputs: temp reg1, temp reg2, temp reg3 diff --git a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp index 47b681ce26be4..d78dec964cbb0 100644 --- a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp +++ b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp @@ -451,7 +451,7 @@ inline void Assembler::bcctrl(int boint, int biint, int bhint, relocInfo::relocT // helper function for b inline bool Assembler::is_within_range_of_b(address a, address pc) { - // Guard against illegal branch targets, e.g. -1 (see CompiledStaticCall and ad-file). + // Guard against illegal branch targets, e.g. -1 (see CompiledDirectCall and ad-file). if ((((uint64_t)a) & 0x3) != 0) return false; const int range = 1 << (29-6); // li field is from bit 6 to bit 29. @@ -465,7 +465,7 @@ inline bool Assembler::is_within_range_of_b(address a, address pc) { // helper functions for bcxx. inline bool Assembler::is_within_range_of_bcxx(address a, address pc) { - // Guard against illegal branch targets, e.g. -1 (see CompiledStaticCall and ad-file). + // Guard against illegal branch targets, e.g. -1 (see CompiledDirectCall and ad-file). if ((((uint64_t)a) & 0x3) != 0) return false; const int range = 1 << (29-16); // bd field is from bit 16 to bit 29. diff --git a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp index d316c2b3db2be..4b29bcf57e4d3 100644 --- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp @@ -77,9 +77,7 @@ int LIR_Assembler::initial_frame_size_in_bytes() const { // we fetch the class of the receiver and compare it with the cached class. // If they do not match we jump to slow case. int LIR_Assembler::check_icache() { - int offset = __ offset(); - __ inline_cache_check(R3_ARG1, R19_inline_cache_reg); - return offset; + return __ ic_check(CodeEntryAlignment); } void LIR_Assembler::clinit_barrier(ciMethod* method) { diff --git a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp index 577dcae25f4bc..b379d4141a32b 100644 --- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp @@ -40,29 +40,6 @@ #include "utilities/macros.hpp" #include "utilities/powerOfTwo.hpp" -void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) { - const Register temp_reg = R12_scratch2; - Label Lmiss; - - verify_oop(receiver, FILE_AND_LINE); - load_klass_check_null(temp_reg, receiver, &Lmiss); - - if (TrapBasedICMissChecks && TrapBasedNullChecks) { - trap_ic_miss_check(temp_reg, iCache); - } else { - Label Lok; - cmpd(CCR0, temp_reg, iCache); - beq(CCR0, Lok); - bind(Lmiss); - //load_const_optimized(temp_reg, SharedRuntime::get_ic_miss_stub(), R0); - calculate_address_from_global_toc(temp_reg, SharedRuntime::get_ic_miss_stub(), true, true, false); - mtctr(temp_reg); - bctr(); - align(32, 12); - bind(Lok); - } -} - void C1_MacroAssembler::explicit_null_check(Register base) { Unimplemented(); diff --git a/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp b/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp index 2ba6a6bca4e03..63914c5d1cb93 100644 --- a/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp @@ -34,7 +34,6 @@ #include "gc/shared/cardTableBarrierSet.hpp" #include "interpreter/interpreter.hpp" #include "nativeInst_ppc.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "register_ppc.hpp" diff --git a/src/hotspot/cpu/ppc/compiledIC_ppc.cpp b/src/hotspot/cpu/ppc/compiledIC_ppc.cpp index 54f9cfa936797..355ac4815d551 100644 --- a/src/hotspot/cpu/ppc/compiledIC_ppc.cpp +++ b/src/hotspot/cpu/ppc/compiledIC_ppc.cpp @@ -26,7 +26,6 @@ #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" #include "code/compiledIC.hpp" -#include "code/icBuffer.hpp" #include "code/nmethod.hpp" #include "memory/resourceArea.hpp" #include "runtime/mutexLocker.hpp" @@ -37,7 +36,7 @@ // ---------------------------------------------------------------------------- -// A PPC CompiledDirectStaticCall looks like this: +// A PPC CompiledDirectCall looks like this: // // >>>> consts // @@ -79,7 +78,7 @@ const int IC_pos_in_java_to_interp_stub = 8; #define __ _masm. -address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* = nullptr*/) { +address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* = nullptr*/) { #ifdef COMPILER2 if (mark == nullptr) { // Get the mark within main instrs section which is set to the address of the call. @@ -91,7 +90,7 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* MacroAssembler _masm(&cbuf); // Start the stub. - address stub = __ start_a_stub(CompiledStaticCall::to_interp_stub_size()); + address stub = __ start_a_stub(CompiledDirectCall::to_interp_stub_size()); if (stub == nullptr) { return nullptr; // CodeCache is full } @@ -135,7 +134,7 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* // FIXME: Assert that the stub can be identified and patched. // Java_to_interp_stub_size should be good. - assert((__ offset() - stub_start_offset) <= CompiledStaticCall::to_interp_stub_size(), + assert((__ offset() - stub_start_offset) <= CompiledDirectCall::to_interp_stub_size(), "should be good size"); assert(!is_NativeCallTrampolineStub_at(__ addr_at(stub_start_offset)), "must not confuse java_to_interp with trampoline stubs"); @@ -153,27 +152,20 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* // Size of java_to_interp stub, this doesn't need to be accurate but it must // be larger or equal to the real size of the stub. // Used for optimization in Compile::Shorten_branches. -int CompiledStaticCall::to_interp_stub_size() { +int CompiledDirectCall::to_interp_stub_size() { return 12 * BytesPerInstWord; } // Relocation entries for call stub, compiled java to interpreter. // Used for optimization in Compile::Shorten_branches. -int CompiledStaticCall::reloc_to_interp_stub() { +int CompiledDirectCall::reloc_to_interp_stub() { return 5; } -void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) { +void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) { address stub = find_stub(); guarantee(stub != nullptr, "stub not found"); - { - ResourceMark rm; - log_trace(inlinecache)("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s", - p2i(instruction_address()), - callee->name_and_sig_as_C_string()); - } - // Creation also verifies the object. NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + IC_pos_in_java_to_interp_stub); NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); @@ -188,7 +180,7 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad set_destination_mt_safe(stub); } -void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) { +void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) { // Reset stub. address stub = static_stub->addr(); assert(stub != nullptr, "stub not found"); @@ -204,7 +196,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_ // Non-product mode code #ifndef PRODUCT -void CompiledDirectStaticCall::verify() { +void CompiledDirectCall::verify() { // Verify call. _call->verify(); _call->verify_alignment(); diff --git a/src/hotspot/cpu/ppc/icBuffer_ppc.cpp b/src/hotspot/cpu/ppc/icBuffer_ppc.cpp deleted file mode 100644 index 4157a5b0fd788..0000000000000 --- a/src/hotspot/cpu/ppc/icBuffer_ppc.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2013 SAP SE. 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 "asm/assembler.inline.hpp" -#include "code/icBuffer.hpp" -#include "gc/shared/collectedHeap.inline.hpp" -#include "interpreter/bytecodes.hpp" -#include "memory/resourceArea.hpp" -#include "nativeInst_ppc.hpp" -#include "oops/oop.inline.hpp" - -#define __ masm. - -int InlineCacheBuffer::ic_stub_code_size() { - return MacroAssembler::load_const_size + MacroAssembler::b64_patchable_size; -} - -void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) { - ResourceMark rm; - CodeBuffer code(code_begin, ic_stub_code_size()); - MacroAssembler masm(&code); - // Note: even though the code contains an embedded metadata, we do not need reloc info - // because - // (1) the metadata is old (i.e., doesn't matter for scavenges) - // (2) these ICStubs are removed *before* a GC happens, so the roots disappear. - - // Load the oop ... - __ load_const(R19_method, (address) cached_value, R0); - // ... and jump to entry point. - __ b64_patchable((address) entry_point, relocInfo::none); - - __ flush(); -} - -address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) { - NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object - NativeJump* jump = nativeJump_at(move->next_instruction_address()); - return jump->jump_destination(); -} - -void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) { - NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object - void* o = (void*)move->data(); - return o; -} - diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index b9d1cdb19ac9d..fe19cf0350020 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" +#include "code/compiledIC.hpp" #include "compiler/disassembler.hpp" #include "gc/shared/collectedHeap.inline.hpp" #include "gc/shared/barrierSet.hpp" @@ -1195,6 +1196,81 @@ void MacroAssembler::post_call_nop() { assert(is_post_call_nop(*(int*)(pc() - 4)), "post call not not found"); } +int MacroAssembler::ic_check_size() { + bool implicit_null_checks_available = ImplicitNullChecks && os::zero_page_read_protected(), + use_fast_receiver_null_check = implicit_null_checks_available || TrapBasedNullChecks, + use_trap_based_null_check = !implicit_null_checks_available && TrapBasedNullChecks; + + int num_ins; + if (use_fast_receiver_null_check && TrapBasedICMissChecks) { + num_ins = 3; + if (use_trap_based_null_check) num_ins += 1; + } else { + num_ins = 7; + if (!implicit_null_checks_available) num_ins += 2; + } + return num_ins * BytesPerInstWord; +} + +int MacroAssembler::ic_check(int end_alignment) { + bool implicit_null_checks_available = ImplicitNullChecks && os::zero_page_read_protected(), + use_fast_receiver_null_check = implicit_null_checks_available || TrapBasedNullChecks, + use_trap_based_null_check = !implicit_null_checks_available && TrapBasedNullChecks; + + Register receiver = R3_ARG1; + Register data = R19_inline_cache_reg; + Register tmp1 = R11_scratch1; + Register tmp2 = R12_scratch2; + + // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed + // before the inline cache check, so we don't have to execute any nop instructions when dispatching + // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align + // before the inline cache check here, and not after + align(end_alignment, end_alignment, end_alignment - ic_check_size()); + + int uep_offset = offset(); + + if (use_fast_receiver_null_check && TrapBasedICMissChecks) { + // Fast version which uses SIGTRAP + + if (use_trap_based_null_check) { + trap_null_check(receiver); + } + if (UseCompressedClassPointers) { + lwz(tmp1, oopDesc::klass_offset_in_bytes(), receiver); + } else { + ld(tmp1, oopDesc::klass_offset_in_bytes(), receiver); + } + ld(tmp2, in_bytes(CompiledICData::speculated_klass_offset()), data); + trap_ic_miss_check(tmp1, tmp2); + + } else { + // Slower version which doesn't use SIGTRAP + + // Load stub address using toc (fixed instruction size, unlike load_const_optimized) + calculate_address_from_global_toc(tmp1, SharedRuntime::get_ic_miss_stub(), + true, true, false); // 2 instructions + mtctr(tmp1); + + if (!implicit_null_checks_available) { + cmpdi(CCR0, receiver, 0); + beqctr(CCR0); + } + if (UseCompressedClassPointers) { + lwz(tmp1, oopDesc::klass_offset_in_bytes(), receiver); + } else { + ld(tmp1, oopDesc::klass_offset_in_bytes(), receiver); + } + ld(tmp2, in_bytes(CompiledICData::speculated_klass_offset()), data); + cmpd(CCR0, tmp1, tmp2); + bnectr(CCR0); + } + + assert((offset() % end_alignment) == 0, "Misaligned verified entry point"); + + return uep_offset; +} + void MacroAssembler::call_VM_base(Register oop_result, Register last_java_sp, address entry_point, diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp index cddc8b92fa09a..ec370a450ac35 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp @@ -367,6 +367,9 @@ class MacroAssembler: public Assembler { Register toc); #endif + static int ic_check_size(); + int ic_check(int end_alignment); + protected: // It is imperative that all calls into the VM are handled via the diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 783edf727b3bc..6f5e6dabec5a2 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -1978,42 +1978,7 @@ void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { // This is the unverified entry point. C2_MacroAssembler _masm(&cbuf); - // Inline_cache contains a klass. - Register ic_klass = as_Register(Matcher::inline_cache_reg_encode()); - Register receiver_klass = R12_scratch2; // tmp - - assert_different_registers(ic_klass, receiver_klass, R11_scratch1, R3_ARG1); - assert(R11_scratch1 == R11, "need prologue scratch register"); - - // Check for nullptr argument if we don't have implicit null checks. - if (!ImplicitNullChecks || !os::zero_page_read_protected()) { - if (TrapBasedNullChecks) { - __ trap_null_check(R3_ARG1); - } else { - Label valid; - __ cmpdi(CCR0, R3_ARG1, 0); - __ bne_predict_taken(CCR0, valid); - // We have a null argument, branch to ic_miss_stub. - __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(), - relocInfo::runtime_call_type); - __ bind(valid); - } - } - // Assume argument is not nullptr, load klass from receiver. - __ load_klass(receiver_klass, R3_ARG1); - - if (TrapBasedICMissChecks) { - __ trap_ic_miss_check(receiver_klass, ic_klass); - } else { - Label valid; - __ cmpd(CCR0, receiver_klass, ic_klass); - __ beq_predict_taken(CCR0, valid); - // We have an unexpected klass, branch to ic_miss_stub. - __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(), - relocInfo::runtime_call_type); - __ bind(valid); - } - + __ ic_check(CodeEntryAlignment); // Argument is valid and klass is as expected, continue. } @@ -3452,7 +3417,7 @@ encode %{ __ bl(__ pc()); // Emits a relocation. // The stub for call to interpreter. - address stub = CompiledStaticCall::emit_to_interp_stub(cbuf); + address stub = CompiledDirectCall::emit_to_interp_stub(cbuf); if (stub == nullptr) { ciEnv::current()->record_failure("CodeCache is full"); return; @@ -3507,7 +3472,7 @@ encode %{ // Create the nodes for loading the IC from the TOC. loadConLNodesTuple loadConLNodes_IC = - loadConLNodesTuple_create(ra_, n_toc, new immLOper((jlong)Universe::non_oop_word()), + loadConLNodesTuple_create(ra_, n_toc, new immLOper((jlong) Universe::non_oop_word()), OptoReg::Name(R19_H_num), OptoReg::Name(R19_num)); // Create the call node. diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp index ebe918785edc0..5a080adc7a9fa 100644 --- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp +++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp @@ -27,7 +27,6 @@ #include "asm/macroAssembler.inline.hpp" #include "code/debugInfoRec.hpp" #include "code/compiledIC.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "frame_ppc.hpp" #include "compiler/oopMap.hpp" @@ -35,7 +34,6 @@ #include "interpreter/interpreter.hpp" #include "interpreter/interp_masm.hpp" #include "memory/resourceArea.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/klass.inline.hpp" #include "prims/methodHandles.hpp" #include "runtime/continuation.hpp" @@ -1174,8 +1172,8 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm BLOCK_COMMENT("c2i unverified entry"); c2i_unverified_entry = __ pc(); - // inline_cache contains a compiledICHolder - const Register ic = R19_method; + // inline_cache contains a CompiledICData + const Register ic = R19_inline_cache_reg; const Register ic_klass = R11_scratch1; const Register receiver_klass = R12_scratch2; const Register code = R21_tmp1; @@ -1186,45 +1184,10 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm Label call_interpreter; - assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), - "klass offset should reach into any page"); - // Check for null argument if we don't have implicit null checks. - if (!ImplicitNullChecks || !os::zero_page_read_protected()) { - if (TrapBasedNullChecks) { - __ trap_null_check(R3_ARG1); - } else { - Label valid; - __ cmpdi(CCR0, R3_ARG1, 0); - __ bne_predict_taken(CCR0, valid); - // We have a null argument, branch to ic_miss_stub. - __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(), - relocInfo::runtime_call_type); - __ BIND(valid); - } - } - // Assume argument is not null, load klass from receiver. - __ load_klass(receiver_klass, R3_ARG1); - - __ ld(ic_klass, CompiledICHolder::holder_klass_offset(), ic); - - if (TrapBasedICMissChecks) { - __ trap_ic_miss_check(receiver_klass, ic_klass); - } else { - Label valid; - __ cmpd(CCR0, receiver_klass, ic_klass); - __ beq_predict_taken(CCR0, valid); - // We have an unexpected klass, branch to ic_miss_stub. - __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(), - relocInfo::runtime_call_type); - __ BIND(valid); - } - + __ ic_check(4 /* end_alignment */); + __ ld(R19_method, CompiledICData::speculated_method_offset(), ic); // Argument is valid and klass is as expected, continue. - // Extract method from inline cache, verified entry point needs it. - __ ld(R19_method, CompiledICHolder::holder_metadata_offset(), ic); - assert(R19_method == ic, "the inline cache register is dead here"); - __ ld(code, method_(code)); __ cmpdi(CCR0, code, 0); __ ld(ientry, method_(interpreter_entry)); // preloaded @@ -1798,7 +1761,7 @@ static void gen_continuation_enter(MacroAssembler* masm, // static stub for the call above CodeBuffer* cbuf = masm->code_section()->outer(); - stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, c2i_call_pc); + stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, c2i_call_pc); guarantee(stub != nullptr, "no space for static stub"); } @@ -1891,7 +1854,7 @@ static void gen_continuation_enter(MacroAssembler* masm, // static stub for the call above CodeBuffer* cbuf = masm->code_section()->outer(); - stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, call_pc); + stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, call_pc); guarantee(stub != nullptr, "no space for static stub"); } @@ -2188,7 +2151,6 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, intptr_t frame_done_pc; intptr_t oopmap_pc; - Label ic_miss; Label handle_pending_exception; Register r_callers_sp = R21; @@ -2212,19 +2174,9 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, // Check ic: object class == cached class? if (!method_is_static) { - Register ic = R19_inline_cache_reg; - Register receiver_klass = r_temp_1; - - __ cmpdi(CCR0, R3_ARG1, 0); - __ beq(CCR0, ic_miss); - __ verify_oop(R3_ARG1, FILE_AND_LINE); - __ load_klass(receiver_klass, R3_ARG1); - - __ cmpd(CCR0, receiver_klass, ic); - __ bne(CCR0, ic_miss); + __ ic_check(4 /* end_alignment */); } - // Generate the Verified Entry Point (VEP). // -------------------------------------------------------------------------- vep_start_pc = (intptr_t)__ pc(); @@ -2704,16 +2656,6 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, __ b64_patchable((address)StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); - // Handler for a cache miss (out-of-line). - // -------------------------------------------------------------------------- - - if (!method_is_static) { - __ bind(ic_miss); - - __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(), - relocInfo::runtime_call_type); - } - // Done. // -------------------------------------------------------------------------- diff --git a/src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp b/src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp index fe4eb3df8f12f..28ba04d833bed 100644 --- a/src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp @@ -25,10 +25,10 @@ #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" +#include "code/compiledIC.hpp" #include "code/vtableStubs.hpp" #include "interp_masm_ppc.hpp" #include "memory/resourceArea.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/instanceKlass.hpp" #include "oops/klass.inline.hpp" #include "oops/klassVtable.hpp" @@ -181,13 +181,13 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) { __ load_klass_check_null(rcvr_klass, R3_ARG1); // Receiver subtype check against REFC. - __ ld(interface, CompiledICHolder::holder_klass_offset(), R19_method); + __ ld(interface, CompiledICData::itable_refc_klass_offset(), R19_method); __ lookup_interface_method(rcvr_klass, interface, noreg, R0, tmp1, tmp2, L_no_such_interface, /*return_method=*/ false); // Get Method* and entrypoint for compiler - __ ld(interface, CompiledICHolder::holder_metadata_offset(), R19_method); + __ ld(interface, CompiledICData::itable_defc_klass_offset(), R19_method); __ lookup_interface_method(rcvr_klass, interface, itable_index, R19_method, tmp1, tmp2, L_no_such_interface, /*return_method=*/ true); diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp index 0bbf3771a04bc..e3ec023aef260 100644 --- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp @@ -51,7 +51,6 @@ #endif NEEDS_CLEANUP // remove this definitions ? -const Register IC_Klass = t1; // where the IC klass is cached const Register SYNC_header = x10; // synchronization header const Register SHIFT_count = x10; // where count for shift operations must be @@ -265,26 +264,7 @@ void LIR_Assembler::osr_entry() { // inline cache check; done before the frame is built. int LIR_Assembler::check_icache() { - Register receiver = FrameMap::receiver_opr->as_register(); - Register ic_klass = IC_Klass; - int start_offset = __ offset(); - Label dont; - __ inline_cache_check(receiver, ic_klass, dont); - - // if icache check fails, then jump to runtime routine - // Note: RECEIVER must still contain the receiver! - __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); - - // We align the verified entry point unless the method body - // (including its inline cache check) will fit in a single 64-byte - // icache line. - if (!method()->is_accessor() || __ offset() - start_offset > 4 * 4) { - // force alignment after the cache check. - __ align(CodeEntryAlignment); - } - - __ bind(dont); - return start_offset; + return __ ic_check(CodeEntryAlignment); } void LIR_Assembler::jobject2reg(jobject o, Register reg) { @@ -1398,7 +1378,7 @@ void LIR_Assembler::emit_static_call_stub() { __ relocate(static_stub_Relocation::spec(call_pc)); __ emit_static_call_stub(); - assert(__ offset() - start + CompiledStaticCall::to_trampoline_stub_size() + assert(__ offset() - start + CompiledDirectCall::to_trampoline_stub_size() <= call_stub_size(), "stub too big"); __ end_a_stub(); } diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp index b088498e6fc08..ce23213776c08 100644 --- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp @@ -68,7 +68,7 @@ friend class ArrayCopyStub; enum { // See emit_static_call_stub for detail - // CompiledStaticCall::to_interp_stub_size() (14) + CompiledStaticCall::to_trampoline_stub_size() (1 + 3 + address) + // CompiledDirectCall::to_interp_stub_size() (14) + CompiledDirectCall::to_trampoline_stub_size() (1 + 3 + address) _call_stub_size = 14 * NativeInstruction::instruction_size + (NativeInstruction::instruction_size + NativeCallTrampolineStub::instruction_size), // See emit_exception_handler for detail diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp index 6c1dce0de1598..2961b1a91ceab 100644 --- a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp @@ -314,15 +314,6 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register tmp1 verify_oop(obj); } -void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache, Label &L) { - verify_oop(receiver); - // explicit null check not needed since load from [klass_offset] causes a trap - // check against inline cache - assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "must add explicit null check"); - assert_different_registers(receiver, iCache, t0, t2); - cmp_klass(receiver, iCache, t0, t2 /* call-clobbered t2 as a tmp */, L); -} - void C1_MacroAssembler::build_frame(int framesize, int bang_size_in_bytes) { assert(bang_size_in_bytes >= framesize, "stack bang size incorrect"); // Make sure there is enough stack space for this method's activation. diff --git a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp index b76163a30841d..9fa8939837a85 100644 --- a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp @@ -37,7 +37,6 @@ #include "interpreter/interpreter.hpp" #include "memory/universe.hpp" #include "nativeInst_riscv.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "register_riscv.hpp" diff --git a/src/hotspot/cpu/riscv/compiledIC_riscv.cpp b/src/hotspot/cpu/riscv/compiledIC_riscv.cpp index e29dee56de8d8..fdb2bcb06ff97 100644 --- a/src/hotspot/cpu/riscv/compiledIC_riscv.cpp +++ b/src/hotspot/cpu/riscv/compiledIC_riscv.cpp @@ -27,7 +27,6 @@ #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" #include "code/compiledIC.hpp" -#include "code/icBuffer.hpp" #include "code/nmethod.hpp" #include "logging/log.hpp" #include "memory/resourceArea.hpp" @@ -37,7 +36,7 @@ // ---------------------------------------------------------------------------- #define __ _masm. -address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) { +address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) { precond(cbuf.stubs()->start() != badAddress); precond(cbuf.stubs()->end() != badAddress); // Stub is fixed up when the corresponding call is converted from @@ -69,11 +68,11 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) } #undef __ -int CompiledStaticCall::to_interp_stub_size() { +int CompiledDirectCall::to_interp_stub_size() { return MacroAssembler::static_call_stub_size(); } -int CompiledStaticCall::to_trampoline_stub_size() { +int CompiledDirectCall::to_trampoline_stub_size() { // Somewhat pessimistically, we count 4 instructions here (although // there are only 3) because we sometimes emit an alignment nop. // Trampoline stubs are always word aligned. @@ -81,21 +80,14 @@ int CompiledStaticCall::to_trampoline_stub_size() { } // Relocation entries for call stub, compiled java to interpreter. -int CompiledStaticCall::reloc_to_interp_stub() { +int CompiledDirectCall::reloc_to_interp_stub() { return 4; // 3 in emit_to_interp_stub + 1 in emit_call } -void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) { +void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) { address stub = find_stub(); guarantee(stub != nullptr, "stub not found"); - { - ResourceMark rm; - log_trace(inlinecache)("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s", - p2i(instruction_address()), - callee->name_and_sig_as_C_string()); - } - // Creation also verifies the object. NativeMovConstReg* method_holder = nativeMovConstReg_at(stub); @@ -112,7 +104,7 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad set_destination_mt_safe(stub); } -void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) { +void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) { // Reset stub. address stub = static_stub->addr(); assert(stub != nullptr, "stub not found"); @@ -129,7 +121,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_ // Non-product mode code #ifndef PRODUCT -void CompiledDirectStaticCall::verify() { +void CompiledDirectCall::verify() { // Verify call. _call->verify(); _call->verify_alignment(); diff --git a/src/hotspot/cpu/riscv/icBuffer_riscv.cpp b/src/hotspot/cpu/riscv/icBuffer_riscv.cpp deleted file mode 100644 index ab904817816fc..0000000000000 --- a/src/hotspot/cpu/riscv/icBuffer_riscv.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, Red Hat Inc. All rights reserved. - * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * 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 "asm/macroAssembler.hpp" -#include "asm/macroAssembler.inline.hpp" -#include "code/icBuffer.hpp" -#include "gc/shared/collectedHeap.inline.hpp" -#include "interpreter/bytecodes.hpp" -#include "memory/resourceArea.hpp" -#include "nativeInst_riscv.hpp" -#include "oops/oop.inline.hpp" - -int InlineCacheBuffer::ic_stub_code_size() { - // 6: auipc + ld + auipc + jalr + address(2 * instruction_size) - return 6 * NativeInstruction::instruction_size; -} - -#define __ masm-> - -void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) { - assert_cond(code_begin != nullptr && entry_point != nullptr); - ResourceMark rm; - CodeBuffer code(code_begin, ic_stub_code_size()); - MacroAssembler* masm = new MacroAssembler(&code); - // Note: even though the code contains an embedded value, we do not need reloc info - // because - // (1) the value is old (i.e., doesn't matter for scavenges) - // (2) these ICStubs are removed *before* a GC happens, so the roots disappear - - address start = __ pc(); - Label l; - __ ld(t1, l); - __ far_jump(ExternalAddress(entry_point)); - __ align(wordSize); - __ bind(l); - __ emit_int64((intptr_t)cached_value); - // Only need to invalidate the 1st two instructions - not the whole ic stub - ICache::invalidate_range(code_begin, InlineCacheBuffer::ic_stub_code_size()); - assert(__ pc() - start == ic_stub_code_size(), "must be"); -} - -address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) { - NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object - NativeJump* jump = nativeJump_at(move->next_instruction_address()); - return jump->jump_destination(); -} - - -void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) { - // The word containing the cached value is at the end of this IC buffer - uintptr_t *p = (uintptr_t *)(code_begin + ic_stub_code_size() - wordSize); - void* o = (void*)*p; - return o; -} diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index ce336c16aa718..96e07319e843f 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -27,6 +27,7 @@ #include "precompiled.hpp" #include "asm/assembler.hpp" #include "asm/assembler.inline.hpp" +#include "code/compiledIC.hpp" #include "compiler/disassembler.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetAssembler.hpp" @@ -634,8 +635,8 @@ void MacroAssembler::unimplemented(const char* what) { } void MacroAssembler::emit_static_call_stub() { - IncompressibleRegion ir(this); // Fixed length: see CompiledStaticCall::to_interp_stub_size(). - // CompiledDirectStaticCall::set_to_interpreted knows the + IncompressibleRegion ir(this); // Fixed length: see CompiledDirectCall::to_interp_stub_size(). + // CompiledDirectCall::set_to_interpreted knows the // exact layout of this stub. mov_metadata(xmethod, (Metadata*)nullptr); @@ -2542,7 +2543,7 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, } // Look up the method for a megamorphic invokeinterface call in a single pass over itable: -// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICHolder +// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICData // - find a holder_klass (class that implements the method) vtable offset and get the method from vtable by index // The target method is determined by . // The receiver klass is in recv_klass. @@ -3542,6 +3543,48 @@ address MacroAssembler::ic_call(address entry, jint method_index) { return trampoline_call(Address(entry, rh)); } +int MacroAssembler::ic_check_size() { + // No compressed + return (NativeInstruction::instruction_size * (2 /* 2 loads */ + 1 /* branch */)) + + far_branch_size(); +} + +int MacroAssembler::ic_check(int end_alignment) { + IncompressibleRegion ir(this); + Register receiver = j_rarg0; + Register data = t1; + + Register tmp1 = t0; // t0 always scratch + // t2 is saved on call, thus should have been saved before this check. + // Hence we can clobber it. + Register tmp2 = t2; + + // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed + // before the inline cache check, so we don't have to execute any nop instructions when dispatching + // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align + // before the inline cache check here, and not after + align(end_alignment, ic_check_size()); + int uep_offset = offset(); + + if (UseCompressedClassPointers) { + lwu(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes())); + lwu(tmp2, Address(data, CompiledICData::speculated_klass_offset())); + } else { + ld(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes())); + ld(tmp2, Address(data, CompiledICData::speculated_klass_offset())); + } + + Label ic_hit; + beq(tmp1, tmp2, ic_hit); + // Note, far_jump is not fixed size. + // Is this ever generates a movptr alignment/size will be off. + far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); + bind(ic_hit); + + assert((offset() % end_alignment) == 0, "Misaligned verified entry point."); + return uep_offset; +} + // Emit a trampoline stub for a call to a target which is too far away. // // code sequences: diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index d283654e6e179..63cfb22855180 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -1193,7 +1193,10 @@ class MacroAssembler: public Assembler { // // Return: the call PC or null if CodeCache is full. address trampoline_call(Address entry); + address ic_call(address entry, jint method_index = 0); + static int ic_check_size(); + int ic_check(int end_alignment = NativeInstruction::instruction_size); // Support for memory inc/dec // n.b. increment/decrement calls with an Address destination will diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index a6f0959942414..10a80cd094024 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -1808,14 +1808,13 @@ void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const assert_cond(st != nullptr); st->print_cr("# MachUEPNode"); if (UseCompressedClassPointers) { - st->print_cr("\tlwu t0, [j_rarg0, oopDesc::klass_offset_in_bytes()]\t# compressed klass"); - if (CompressedKlassPointers::shift() != 0) { - st->print_cr("\tdecode_klass_not_null t0, t0"); - } + st->print_cr("\tlwu t0, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); + st->print_cr("\tlwu t2, [t1 + CompiledICData::speculated_klass_offset()]\t# compressed klass"); } else { - st->print_cr("\tld t0, [j_rarg0, oopDesc::klass_offset_in_bytes()]\t# compressed klass"); + st->print_cr("\tld t0, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); + st->print_cr("\tld t2, [t1 + CompiledICData::speculated_klass_offset()]\t# compressed klass"); } - st->print_cr("\tbeq t0, t1, ic_hit"); + st->print_cr("\tbeq t0, t2, ic_hit"); st->print_cr("\tj, SharedRuntime::_ic_miss_stub\t # Inline cache check"); st->print_cr("\tic_hit:"); } @@ -1825,15 +1824,11 @@ void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { // This is the unverified entry point. C2_MacroAssembler _masm(&cbuf); + __ ic_check(CodeEntryAlignment); - Label skip; - __ cmp_klass(j_rarg0, t1, t0, t2 /* call-clobbered t2 as a tmp */, skip); - __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); - __ bind(skip); - - // These NOPs are critical so that verified entry point is properly - // 4 bytes aligned for patching by NativeJump::patch_verified_entry() - __ align(NativeInstruction::instruction_size); + // Verified entry point must be properly 4 bytes aligned for patching by NativeJump::patch_verified_entry(). + // ic_check() aligns to CodeEntryAlignment >= InteriorEntryAlignment(min 16) > NativeInstruction::instruction_size(4). + assert(((__ offset()) % CodeEntryAlignment) == 0, "Misaligned verified entry point"); } uint MachUEPNode::size(PhaseRegAlloc* ra_) const @@ -2402,7 +2397,7 @@ encode %{ cbuf.shared_stub_to_interp_for(_method, call - cbuf.insts_begin()); } else { // Emit stub for static call - address stub = CompiledStaticCall::emit_to_interp_stub(cbuf, call); + address stub = CompiledDirectCall::emit_to_interp_stub(cbuf, call); if (stub == nullptr) { ciEnv::current()->record_failure("CodeCache is full"); return; diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp index 9f04e20ea3b73..7435b552d15de 100644 --- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp +++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp @@ -29,7 +29,6 @@ #include "asm/macroAssembler.inline.hpp" #include "code/compiledIC.hpp" #include "code/debugInfoRec.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "compiler/oopMap.hpp" #include "gc/shared/barrierSetAssembler.hpp" @@ -38,7 +37,6 @@ #include "logging/log.hpp" #include "memory/resourceArea.hpp" #include "nativeInst_riscv.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/klass.inline.hpp" #include "oops/method.inline.hpp" #include "prims/methodHandles.hpp" @@ -622,10 +620,8 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm address c2i_unverified_entry = __ pc(); Label skip_fixup; - Label ok; - - const Register holder = t1; const Register receiver = j_rarg0; + const Register data = t1; const Register tmp = t2; // A call-clobbered register not used for arg passing // ------------------------------------------------------------------------- @@ -639,16 +635,10 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm { __ block_comment("c2i_unverified_entry {"); - __ load_klass(t0, receiver, tmp); - __ ld(tmp, Address(holder, CompiledICHolder::holder_klass_offset())); - __ ld(xmethod, Address(holder, CompiledICHolder::holder_metadata_offset())); - __ beq(t0, tmp, ok); - __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); - __ bind(ok); - // Method might have been compiled since the call site was patched to - // interpreted; if that is the case treat it as a miss so we can get - // the call site corrected. + __ ic_check(); + __ ld(xmethod, Address(data, CompiledICData::speculated_method_offset())); + __ ld(t0, Address(xmethod, in_bytes(Method::code_offset()))); __ beqz(t0, skip_fixup); __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); @@ -985,7 +975,7 @@ static void gen_continuation_enter(MacroAssembler* masm, __ j(exit); CodeBuffer* cbuf = masm->code_section()->outer(); - address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call); + address stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, tr_call); if (stub == nullptr) { fatal("CodeCache is full at gen_continuation_enter"); } @@ -1051,7 +1041,7 @@ static void gen_continuation_enter(MacroAssembler* masm, } CodeBuffer* cbuf = masm->code_section()->outer(); - address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call); + address stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, tr_call); if (stub == nullptr) { fatal("CodeCache is full at gen_continuation_enter"); } @@ -1425,19 +1415,10 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, const Register ic_reg = t1; const Register receiver = j_rarg0; - Label hit; - Label exception_pending; - __ verify_oop(receiver); - assert_different_registers(ic_reg, receiver, t0, t2); - __ cmp_klass(receiver, ic_reg, t0, t2 /* call-clobbered t2 as a tmp */, hit); - - __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); + assert_different_registers(receiver, t0, t1); - // Verified entry point must be aligned - __ align(8); - - __ bind(hit); + __ ic_check(); int vep_offset = ((intptr_t)__ pc()) - start; @@ -1872,6 +1853,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ leave(); // Any exception pending? + Label exception_pending; __ ld(t0, Address(xthread, in_bytes(Thread::pending_exception_offset()))); __ bnez(t0, exception_pending); diff --git a/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp b/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp index 9d08796681f3f..5d945dbc32309 100644 --- a/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp +++ b/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp @@ -27,10 +27,10 @@ #include "precompiled.hpp" #include "asm/assembler.inline.hpp" #include "asm/macroAssembler.inline.hpp" +#include "code/compiledIC.hpp" #include "code/vtableStubs.hpp" #include "interp_masm_riscv.hpp" #include "memory/resourceArea.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/instanceKlass.hpp" #include "oops/klassVtable.hpp" #include "runtime/sharedRuntime.hpp" @@ -171,22 +171,22 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) { assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0"); // Entry arguments: - // t1: CompiledICHolder + // t1: CompiledICData // j_rarg0: Receiver // This stub is called from compiled code which has no callee-saved registers, // so all registers except arguments are free at this point. const Register recv_klass_reg = x18; - const Register holder_klass_reg = x19; // declaring interface klass (DECC) + const Register holder_klass_reg = x19; // declaring interface klass (DEFC) const Register resolved_klass_reg = x30; // resolved interface klass (REFC) const Register temp_reg = x28; const Register temp_reg2 = x29; - const Register icholder_reg = t1; + const Register icdata_reg = t1; Label L_no_such_interface; - __ ld(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset())); - __ ld(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset())); + __ ld(resolved_klass_reg, Address(icdata_reg, CompiledICData::itable_refc_klass_offset())); + __ ld(holder_klass_reg, Address(icdata_reg, CompiledICData::itable_defc_klass_offset())); start_pc = __ pc(); diff --git a/src/hotspot/cpu/s390/assembler_s390.hpp b/src/hotspot/cpu/s390/assembler_s390.hpp index 9bb143001b944..91cc7e611bfd1 100644 --- a/src/hotspot/cpu/s390/assembler_s390.hpp +++ b/src/hotspot/cpu/s390/assembler_s390.hpp @@ -107,7 +107,7 @@ class RelAddr { static bool is_in_range_of_RelAddr(address target, address pc, bool shortForm) { // Guard against illegal branch targets, e.g. -1. Occurrences in - // CompiledStaticCall and ad-file. Do not assert (it's a test + // CompiledDirectCall and ad-file. Do not assert (it's a test // function!). Just return false in case of illegal operands. if ((((uint64_t)target) & 0x0001L) != 0) return false; if ((((uint64_t)pc) & 0x0001L) != 0) return false; diff --git a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp index 355c66047c1b2..13c45bb9fe708 100644 --- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp @@ -76,10 +76,7 @@ int LIR_Assembler::initial_frame_size_in_bytes() const { // We fetch the class of the receiver and compare it with the cached class. // If they do not match we jump to the slow case. int LIR_Assembler::check_icache() { - Register receiver = receiverOpr()->as_register(); - int offset = __ offset(); - __ inline_cache_check(receiver, Z_inline_cache); - return offset; + return __ ic_check(CodeEntryAlignment); } void LIR_Assembler::clinit_barrier(ciMethod* method) { diff --git a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp index 229216ef20d44..c8815f3a729a4 100644 --- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp +++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp @@ -45,7 +45,7 @@ } enum { - _call_stub_size = 512, // See Compile::MAX_stubs_size and CompiledStaticCall::emit_to_interp_stub. + _call_stub_size = 512, // See Compile::MAX_stubs_size and CompiledDirectCall::emit_to_interp_stub. _exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(128), _deopt_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(64) }; diff --git a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp index 40edca6559aa4..5dddc7a756f4c 100644 --- a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp @@ -40,31 +40,6 @@ #include "runtime/stubRoutines.hpp" #include "utilities/macros.hpp" -void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) { - Label ic_miss, ic_hit; - verify_oop(receiver, FILE_AND_LINE); - int klass_offset = oopDesc::klass_offset_in_bytes(); - - if (!ImplicitNullChecks || MacroAssembler::needs_explicit_null_check(klass_offset)) { - if (VM_Version::has_CompareBranch()) { - z_cgij(receiver, 0, Assembler::bcondEqual, ic_miss); - } else { - z_ltgr(receiver, receiver); - z_bre(ic_miss); - } - } - - compare_klass_ptr(iCache, klass_offset, receiver, false); - z_bre(ic_hit); - - // If icache check fails, then jump to runtime routine. - // Note: RECEIVER must still contain the receiver! - load_const_optimized(Z_R1_scratch, AddressLiteral(SharedRuntime::get_ic_miss_stub())); - z_br(Z_R1_scratch); - align(CodeEntryAlignment); - bind(ic_hit); -} - void C1_MacroAssembler::explicit_null_check(Register base) { ShouldNotCallThis(); // unused } diff --git a/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp b/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp index 257148827be4e..decb3a1cafc31 100644 --- a/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp +++ b/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp @@ -35,7 +35,6 @@ #include "interpreter/interpreter.hpp" #include "memory/universe.hpp" #include "nativeInst_s390.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "register_s390.hpp" diff --git a/src/hotspot/cpu/s390/compiledIC_s390.cpp b/src/hotspot/cpu/s390/compiledIC_s390.cpp index 7ea90c1de7c69..3adcfbc85f185 100644 --- a/src/hotspot/cpu/s390/compiledIC_s390.cpp +++ b/src/hotspot/cpu/s390/compiledIC_s390.cpp @@ -26,7 +26,6 @@ #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" #include "code/compiledIC.hpp" -#include "code/icBuffer.hpp" #include "code/nmethod.hpp" #include "memory/resourceArea.hpp" #include "runtime/mutexLocker.hpp" @@ -40,7 +39,7 @@ #undef __ #define __ _masm. -address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* = nullptr*/) { +address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* = nullptr*/) { #ifdef COMPILER2 // Stub is fixed up when the corresponding call is converted from calling // compiled code to calling interpreted code. @@ -54,7 +53,7 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* // That's why we must use the macroassembler to generate a stub. MacroAssembler _masm(&cbuf); - address stub = __ start_a_stub(CompiledStaticCall::to_interp_stub_size()); + address stub = __ start_a_stub(CompiledDirectCall::to_interp_stub_size()); if (stub == nullptr) { return nullptr; // CodeBuffer::expand failed. } @@ -81,27 +80,20 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* #undef __ -int CompiledStaticCall::to_interp_stub_size() { +int CompiledDirectCall::to_interp_stub_size() { return 2 * MacroAssembler::load_const_from_toc_size() + 2; // branch } // Relocation entries for call stub, compiled java to interpreter. -int CompiledStaticCall::reloc_to_interp_stub() { +int CompiledDirectCall::reloc_to_interp_stub() { return 5; // 4 in emit_java_to_interp + 1 in Java_Static_Call } -void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) { +void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) { address stub = find_stub(); guarantee(stub != nullptr, "stub not found"); - { - ResourceMark rm; - log_trace(inlinecache)("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s", - p2i(instruction_address()), - callee->name_and_sig_as_C_string()); - } - // Creation also verifies the object. NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + NativeCall::get_IC_pos_in_java_to_interp_stub()); NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); @@ -115,7 +107,7 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad set_destination_mt_safe(stub); } -void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) { +void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) { // Reset stub. address stub = static_stub->addr(); assert(stub != nullptr, "stub not found"); @@ -131,7 +123,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_ #ifndef PRODUCT -void CompiledDirectStaticCall::verify() { +void CompiledDirectCall::verify() { // Verify call. _call->verify(); _call->verify_alignment(); diff --git a/src/hotspot/cpu/s390/icBuffer_s390.cpp b/src/hotspot/cpu/s390/icBuffer_s390.cpp deleted file mode 100644 index 0dc936d6fad0c..0000000000000 --- a/src/hotspot/cpu/s390/icBuffer_s390.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. 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 "asm/macroAssembler.inline.hpp" -#include "code/icBuffer.hpp" -#include "gc/shared/collectedHeap.inline.hpp" -#include "interpreter/bytecodes.hpp" -#include "memory/resourceArea.hpp" -#include "nativeInst_s390.hpp" -#include "oops/oop.inline.hpp" - -#define __ masm. - -int InlineCacheBuffer::ic_stub_code_size() { - return MacroAssembler::load_const_size() + Assembler::z_brul_size(); -} - -void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_oop, address entry_point) { - ResourceMark rm; - CodeBuffer code(code_begin, ic_stub_code_size()); - MacroAssembler masm(&code); - // Note: even though the code contains an embedded oop, we do not need reloc info - // because - // (1) the oop is old (i.e., doesn't matter for scavenges) - // (2) these ICStubs are removed *before* a GC happens, so the roots disappear. - - // Load the oop, - __ load_const(Z_method, (address) cached_oop); // inline cache reg = Z_method - // and do a tail-call (pc-relative). - __ z_brul((address) entry_point); - __ flush(); -} - -address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) { - NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // Creation also verifies the object. - return MacroAssembler::get_target_addr_pcrel(move->next_instruction_address()); -} - -void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) { - NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // Creation also verifies the object. - return (void*)move->data(); -} diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp index 14fc07ec00794..0226d494c8958 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp @@ -26,6 +26,7 @@ #include "precompiled.hpp" #include "asm/codeBuffer.hpp" #include "asm/macroAssembler.inline.hpp" +#include "code/compiledIC.hpp" #include "compiler/disassembler.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetAssembler.hpp" @@ -1097,7 +1098,13 @@ void MacroAssembler::clear_mem(const Address& addr, unsigned int size) { } void MacroAssembler::align(int modulus) { - while (offset() % modulus != 0) z_nop(); + align(modulus, offset()); +} + +void MacroAssembler::align(int modulus, int target) { + assert(((modulus % 2 == 0) && (target % 2 == 0)), "needs to be even"); + int delta = target - offset(); + while ((offset() + delta) % modulus != 0) z_nop(); } // Special version for non-relocateable code if required alignment @@ -2150,6 +2157,45 @@ void MacroAssembler::call_VM_leaf_base(address entry_point) { call_VM_leaf_base(entry_point, allow_relocation); } +int MacroAssembler::ic_check_size() { + return 30 + (ImplicitNullChecks ? 0 : 6); +} + +int MacroAssembler::ic_check(int end_alignment) { + Register R2_receiver = Z_ARG1; + Register R0_scratch = Z_R0_scratch; + Register R1_scratch = Z_R1_scratch; + Register R9_data = Z_inline_cache; + Label success, failure; + + // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed + // before the inline cache check, so we don't have to execute any nop instructions when dispatching + // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align + // before the inline cache check here, and not after + align(end_alignment, offset() + ic_check_size()); + + int uep_offset = offset(); + if (!ImplicitNullChecks) { + z_cgij(R2_receiver, 0, Assembler::bcondEqual, failure); + } + + if (UseCompressedClassPointers) { + z_llgf(R1_scratch, Address(R2_receiver, oopDesc::klass_offset_in_bytes())); + } else { + z_lg(R1_scratch, Address(R2_receiver, oopDesc::klass_offset_in_bytes())); + } + z_cg(R1_scratch, Address(R9_data, in_bytes(CompiledICData::speculated_klass_offset()))); + z_bre(success); + + bind(failure); + load_const(R1_scratch, AddressLiteral(SharedRuntime::get_ic_miss_stub())); + z_br(R1_scratch); + bind(success); + + assert((offset() % end_alignment) == 0, "Misaligned verified entry point, offset() = %d, end_alignment = %d", offset(), end_alignment); + return uep_offset; +} + void MacroAssembler::call_VM_base(Register oop_result, Register last_java_sp, address entry_point, diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.hpp b/src/hotspot/cpu/s390/macroAssembler_s390.hpp index bf14b42e2d1b3..924583abdf563 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp @@ -257,6 +257,7 @@ class MacroAssembler: public Assembler { // nop padding void align(int modulus); + void align(int modulus, int target); void align_address(int modulus); // @@ -566,6 +567,9 @@ class MacroAssembler: public Assembler { // Get the pc where the last call will return to. Returns _last_calls_return_pc. inline address last_calls_return_pc(); + static int ic_check_size(); + int ic_check(int end_alignment); + private: static bool is_call_far_patchable_variant0_at(address instruction_addr); // Dynamic TOC: load target addr from CP and call. static bool is_call_far_patchable_variant2_at(address instruction_addr); // PC-relative call, prefixed with NOPs. diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index fa53c73269196..5db2db9d32c73 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -1341,51 +1341,9 @@ void MachUEPNode::format(PhaseRegAlloc *ra_, outputStream *os) const { #endif void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { + // This is Unverified Entry Point C2_MacroAssembler _masm(&cbuf); - const int ic_miss_offset = 2; - - // Inline_cache contains a klass. - Register ic_klass = as_Register(Matcher::inline_cache_reg_encode()); - // ARG1 is the receiver oop. - Register R2_receiver = Z_ARG1; - int klass_offset = oopDesc::klass_offset_in_bytes(); - AddressLiteral icmiss(SharedRuntime::get_ic_miss_stub()); - Register R1_ic_miss_stub_addr = Z_R1_scratch; - - // Null check of receiver. - // This is the null check of the receiver that actually should be - // done in the caller. It's here because in case of implicit null - // checks we get it for free. - assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), - "second word in oop should not require explicit null check."); - if (!ImplicitNullChecks) { - Label valid; - if (VM_Version::has_CompareBranch()) { - __ z_cgij(R2_receiver, 0, Assembler::bcondNotEqual, valid); - } else { - __ z_ltgr(R2_receiver, R2_receiver); - __ z_bre(valid); - } - // The ic_miss_stub will handle the null pointer exception. - __ load_const_optimized(R1_ic_miss_stub_addr, icmiss); - __ z_br(R1_ic_miss_stub_addr); - __ bind(valid); - } - - // Check whether this method is the proper implementation for the class of - // the receiver (ic miss check). - { - Label valid; - // Compare cached class against klass from receiver. - // This also does an implicit null check! - __ compare_klass_ptr(ic_klass, klass_offset, R2_receiver, false); - __ z_bre(valid); - // The inline cache points to the wrong method. Call the - // ic_miss_stub to find the proper method. - __ load_const_optimized(R1_ic_miss_stub_addr, icmiss); - __ z_br(R1_ic_miss_stub_addr); - __ bind(valid); - } + __ ic_check(CodeEntryAlignment); } uint MachUEPNode::size(PhaseRegAlloc *ra_) const { @@ -2146,7 +2104,7 @@ encode %{ assert(__ inst_mark() != nullptr, "emit_call_reloc must set_inst_mark()"); if (_method) { // Emit stub for static call. - address stub = CompiledStaticCall::emit_to_interp_stub(cbuf); + address stub = CompiledDirectCall::emit_to_interp_stub(cbuf); if (stub == nullptr) { ciEnv::current()->record_failure("CodeCache is full"); return; diff --git a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp index ed1795cfa339f..11e1e617d8e3a 100644 --- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp +++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp @@ -26,8 +26,8 @@ #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" #include "code/debugInfoRec.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" +#include "code/compiledIC.hpp" #include "compiler/oopMap.hpp" #include "gc/shared/barrierSetAssembler.hpp" #include "gc/shared/gcLocker.hpp" @@ -35,7 +35,6 @@ #include "interpreter/interp_masm.hpp" #include "memory/resourceArea.hpp" #include "nativeInst_s390.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/klass.inline.hpp" #include "prims/methodHandles.hpp" #include "registerSaver_s390.hpp" @@ -1500,17 +1499,15 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, unsigned int wrapper_FrameDone; unsigned int wrapper_CRegsSet; Label handle_pending_exception; - Label ic_miss; //--------------------------------------------------------------------- // Unverified entry point (UEP) //--------------------------------------------------------------------- - wrapper_UEPStart = __ offset(); // check ic: object class <-> cached class - if (!method_is_static) __ nmethod_UEP(ic_miss); - // Fill with nops (alignment of verified entry point). - __ align(CodeEntryAlignment); + if (!method_is_static) { + wrapper_UEPStart = __ ic_check(CodeEntryAlignment /* end_alignment */); + } //--------------------------------------------------------------------- // Verified entry point (VEP) @@ -2026,13 +2023,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, __ restore_return_pc(); __ z_br(Z_R1_scratch); - //--------------------------------------------------------------------- - // Handler for a cache miss (out-of-line) - //--------------------------------------------------------------------- - __ call_ic_miss_handler(ic_miss, 0x77, 0, Z_R1_scratch); __ flush(); - - ////////////////////////////////////////////////////////////////////// // end of code generation ////////////////////////////////////////////////////////////////////// @@ -2318,9 +2309,6 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm Label skip_fixup; { Label ic_miss; - const int klass_offset = oopDesc::klass_offset_in_bytes(); - const int holder_klass_offset = in_bytes(CompiledICHolder::holder_klass_offset()); - const int holder_metadata_offset = in_bytes(CompiledICHolder::holder_metadata_offset()); // Out-of-line call to ic_miss handler. __ call_ic_miss_handler(ic_miss, 0x11, 0, Z_R1_scratch); @@ -2329,27 +2317,11 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm __ align(CodeEntryAlignment); c2i_unverified_entry = __ pc(); - // Check the pointers. - if (!ImplicitNullChecks || MacroAssembler::needs_explicit_null_check(klass_offset)) { - __ z_ltgr(Z_ARG1, Z_ARG1); - __ z_bre(ic_miss); - } - __ verify_oop(Z_ARG1, FILE_AND_LINE); - - // Check ic: object class <-> cached class - // Compress cached class for comparison. That's more efficient. - if (UseCompressedClassPointers) { - __ z_lg(Z_R11, holder_klass_offset, Z_method); // Z_R11 is overwritten a few instructions down anyway. - __ compare_klass_ptr(Z_R11, klass_offset, Z_ARG1, false); // Cached class can't be zero. - } else { - __ z_clc(klass_offset, sizeof(void *)-1, Z_ARG1, holder_klass_offset, Z_method); - } - __ z_brne(ic_miss); // Cache miss: call runtime to handle this. - + __ ic_check(2); + __ z_lg(Z_method, Address(Z_inline_cache, CompiledICData::speculated_method_offset())); // This def MUST MATCH code in gen_c2i_adapter! const Register code = Z_R11; - __ z_lg(Z_method, holder_metadata_offset, Z_method); __ load_and_test_long(Z_R0, method_(code)); __ z_brne(ic_miss); // Cache miss: call runtime to handle this. diff --git a/src/hotspot/cpu/s390/vtableStubs_s390.cpp b/src/hotspot/cpu/s390/vtableStubs_s390.cpp index 5a79369ceab47..573c23d796708 100644 --- a/src/hotspot/cpu/s390/vtableStubs_s390.cpp +++ b/src/hotspot/cpu/s390/vtableStubs_s390.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2021 SAP SE. All rights reserved. + * Copyright (c) 2016, 2023 SAP SE. 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,10 +25,10 @@ #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" +#include "code/compiledIC.hpp" #include "code/vtableStubs.hpp" #include "interp_masm_s390.hpp" #include "memory/resourceArea.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/instanceKlass.hpp" #include "oops/klass.inline.hpp" #include "oops/klassVtable.hpp" @@ -197,12 +197,12 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) { __ load_klass(rcvr_klass, Z_ARG1); // Receiver subtype check against REFC. - __ z_lg(interface, Address(Z_method, CompiledICHolder::holder_klass_offset())); + __ z_lg(interface, Address(Z_method, CompiledICData::itable_refc_klass_offset())); __ lookup_interface_method(rcvr_klass, interface, noreg, noreg, Z_R1, no_such_interface, /*return_method=*/ false); // Get Method* and entrypoint for compiler - __ z_lg(interface, Address(Z_method, CompiledICHolder::holder_metadata_offset())); + __ z_lg(interface, Address(Z_method, CompiledICData::itable_defc_klass_offset())); __ lookup_interface_method(rcvr_klass, interface, itable_index, Z_method, Z_R1, no_such_interface, /*return_method=*/ true); diff --git a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp index ff0726840d30a..3b7a3cec2d815 100644 --- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp @@ -72,7 +72,6 @@ static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], (jl NEEDS_CLEANUP // remove this definitions ? -const Register IC_Klass = rax; // where the IC klass is cached const Register SYNC_header = rax; // synchronization header const Register SHIFT_count = rcx; // where count for shift operations must be @@ -336,23 +335,7 @@ void LIR_Assembler::osr_entry() { // inline cache check; done before the frame is built. int LIR_Assembler::check_icache() { - Register receiver = FrameMap::receiver_opr->as_register(); - Register ic_klass = IC_Klass; - const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9); - const bool do_post_padding = VerifyOops || UseCompressedClassPointers; - if (!do_post_padding) { - // insert some nops so that the verified entry point is aligned on CodeEntryAlignment - __ align(CodeEntryAlignment, __ offset() + ic_cmp_size); - } - int offset = __ offset(); - __ inline_cache_check(receiver, IC_Klass); - assert(__ offset() % CodeEntryAlignment == 0 || do_post_padding, "alignment must be correct"); - if (do_post_padding) { - // force alignment after the cache check. - // It's been verified to be aligned if !VerifyOops - __ align(CodeEntryAlignment); - } - return offset; + return __ ic_check(CodeEntryAlignment); } void LIR_Assembler::clinit_barrier(ciMethod* method) { diff --git a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp index b6a27abf0f37e..7088cf33cf646 100644 --- a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1207,9 +1207,10 @@ void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) { __ move(result_reg, result); } +#ifndef _LP64 // _i2l, _i2f, _i2d, _l2i, _l2f, _l2d, _f2i, _f2l, _f2d, _d2i, _d2l, _d2f // _i2b, _i2c, _i2s -LIR_Opr fixed_register_for(BasicType type) { +static LIR_Opr fixed_register_for(BasicType type) { switch (type) { case T_FLOAT: return FrameMap::fpu0_float_opr; case T_DOUBLE: return FrameMap::fpu0_double_opr; @@ -1218,6 +1219,7 @@ LIR_Opr fixed_register_for(BasicType type) { default: ShouldNotReachHere(); return LIR_OprFact::illegalOpr; } } +#endif void LIRGenerator::do_Convert(Convert* x) { #ifdef _LP64 diff --git a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp index 78361a305aeeb..0c4544f5bc49e 100644 --- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "c1/c1_MacroAssembler.hpp" #include "c1/c1_Runtime1.hpp" +#include "code/compiledIC.hpp" #include "compiler/compilerDefinitions.inline.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetAssembler.hpp" @@ -34,10 +35,12 @@ #include "oops/arrayOop.hpp" #include "oops/markWord.hpp" #include "runtime/basicLock.hpp" +#include "runtime/globals.hpp" #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/checkedCast.hpp" +#include "utilities/globalDefinitions.hpp" int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Register tmp, Label& slow_case) { const int aligned_mask = BytesPerWord -1; @@ -60,9 +63,6 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr jcc(Assembler::notZero, slow_case); } - // Load object header - movptr(hdr, Address(obj, hdr_offset)); - if (LockingMode == LM_LIGHTWEIGHT) { #ifdef _LP64 const Register thread = r15_thread; @@ -73,6 +73,8 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr lightweight_lock(obj, hdr, thread, tmp, slow_case); } else if (LockingMode == LM_LEGACY) { Label done; + // Load object header + movptr(hdr, Address(obj, hdr_offset)); // and mark it as unlocked orptr(hdr, markWord::unlocked_value); // save unlocked object header into the displaced header location on the stack @@ -134,9 +136,14 @@ void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_ verify_oop(obj); if (LockingMode == LM_LIGHTWEIGHT) { - movptr(disp_hdr, Address(obj, hdr_offset)); - andptr(disp_hdr, ~(int32_t)markWord::lock_mask_in_place); - lightweight_unlock(obj, disp_hdr, hdr, slow_case); +#ifdef _LP64 + lightweight_unlock(obj, disp_hdr, r15_thread, hdr, slow_case); +#else + // This relies on the implementation of lightweight_unlock being able to handle + // that the reg_rax and thread Register parameters may alias each other. + get_thread(disp_hdr); + lightweight_unlock(obj, disp_hdr, disp_hdr, hdr, slow_case); +#endif } else if (LockingMode == LM_LEGACY) { // test if object header is pointing to the displaced header, and if so, restore // the displaced header in the object - if the object header is not pointing to @@ -295,30 +302,6 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, verify_oop(obj); } - - -void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) { - verify_oop(receiver); - // explicit null check not needed since load from [klass_offset] causes a trap - // check against inline cache - assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "must add explicit null check"); - int start_offset = offset(); - - if (UseCompressedClassPointers) { - load_klass(rscratch1, receiver, rscratch2); - cmpptr(rscratch1, iCache); - } else { - cmpptr(iCache, Address(receiver, oopDesc::klass_offset_in_bytes())); - } - // if icache check fails, then jump to runtime routine - // Note: RECEIVER must still contain the receiver! - jump_cc(Assembler::notEqual, - RuntimeAddress(SharedRuntime::get_ic_miss_stub())); - const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9); - assert(UseCompressedClassPointers || offset() - start_offset == ic_cmp_size, "check alignment in emit_method_entry"); -} - - void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_bytes) { assert(bang_size_in_bytes >= frame_size_in_bytes, "stack bang size incorrect"); // Make sure there is enough stack space for this method's activation. diff --git a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp index 8b56f464f2739..2c24c0c2cfb17 100644 --- a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp +++ b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp @@ -38,7 +38,6 @@ #include "interpreter/interpreter.hpp" #include "memory/universe.hpp" #include "nativeInst_x86.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "register_x86.hpp" diff --git a/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp b/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp index b9b4e8af02c5f..6dc8d14064ad2 100644 --- a/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp +++ b/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,26 +73,74 @@ void C2EntryBarrierStub::emit(C2_MacroAssembler& masm) { __ jmp(continuation(), false /* maybe_short */); } -#ifdef _LP64 -int C2HandleAnonOMOwnerStub::max_size() const { - // Max size of stub has been determined by testing with 0, in which case - // C2CodeStubList::emit() will throw an assertion and report the actual size that - // is needed. - return DEBUG_ONLY(36) NOT_DEBUG(21); +int C2FastUnlockLightweightStub::max_size() const { + return 128; } -void C2HandleAnonOMOwnerStub::emit(C2_MacroAssembler& masm) { - __ bind(entry()); - Register mon = monitor(); - Register t = tmp(); - __ movptr(Address(mon, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), r15_thread); - __ subl(Address(r15_thread, JavaThread::lock_stack_top_offset()), oopSize); +void C2FastUnlockLightweightStub::emit(C2_MacroAssembler& masm) { + assert(_t == rax, "must be"); + + Label restore_held_monitor_count_and_slow_path; + + { // Restore lock-stack and handle the unlock in runtime. + + __ bind(_push_and_slow_path); #ifdef ASSERT - __ movl(t, Address(r15_thread, JavaThread::lock_stack_top_offset())); - __ movptr(Address(r15_thread, t), 0); + // The obj was only cleared in debug. + __ movl(_t, Address(_thread, JavaThread::lock_stack_top_offset())); + __ movptr(Address(_thread, _t), _obj); #endif - __ jmp(continuation()); -} + __ addl(Address(_thread, JavaThread::lock_stack_top_offset()), oopSize); + } + + { // Restore held monitor count and slow path. + + __ bind(restore_held_monitor_count_and_slow_path); + // Restore held monitor count. + __ increment(Address(_thread, JavaThread::held_monitor_count_offset())); + // increment will always result in ZF = 0 (no overflows). + __ jmp(slow_path_continuation()); + } + + { // Handle monitor medium path. + + __ bind(_check_successor); + + Label fix_zf_and_unlocked; + const Register monitor = _mark; + +#ifndef _LP64 + __ jmpb(restore_held_monitor_count_and_slow_path); +#else // _LP64 + // successor null check. + __ cmpptr(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), NULL_WORD); + __ jccb(Assembler::equal, restore_held_monitor_count_and_slow_path); + + // Release lock. + __ movptr(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD); + + // Fence. + // Instead of MFENCE we use a dummy locked add of 0 to the top-of-stack. + __ lock(); __ addl(Address(rsp, 0), 0); + + // Recheck successor. + __ cmpptr(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), NULL_WORD); + // Observed a successor after the release -> fence we have handed off the monitor + __ jccb(Assembler::notEqual, fix_zf_and_unlocked); + + // Try to relock, if it fails the monitor has been handed over + // TODO: Caveat, this may fail due to deflation, which does + // not handle the monitor handoff. Currently only works + // due to the responsible thread. + __ xorptr(rax, rax); + __ lock(); __ cmpxchgptr(_thread, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); + __ jccb (Assembler::equal, restore_held_monitor_count_and_slow_path); #endif + __ bind(fix_zf_and_unlocked); + __ xorl(rax, rax); + __ jmp(unlocked_continuation()); + } +} + #undef __ diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 7512a366e7ea0..b6ecde62af655 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -33,9 +33,13 @@ #include "opto/output.hpp" #include "opto/opcodes.hpp" #include "opto/subnode.hpp" +#include "runtime/globals.hpp" #include "runtime/objectMonitor.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/checkedCast.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/powerOfTwo.hpp" +#include "utilities/sizes.hpp" #ifdef PRODUCT #define BLOCK_COMMENT(str) /* nothing */ @@ -554,6 +558,7 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp RTMLockingCounters* stack_rtm_counters, Metadata* method_data, bool use_rtm, bool profile_rtm) { + assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_lock_lightweight"); // Ensure the register assignments are disjoint assert(tmpReg == rax, ""); @@ -605,7 +610,8 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp if (LockingMode == LM_MONITOR) { // Clear ZF so that we take the slow path at the DONE label. objReg is known to be not 0. testptr(objReg, objReg); - } else if (LockingMode == LM_LEGACY) { + } else { + assert(LockingMode == LM_LEGACY, "must be"); // Attempt stack-locking ... orptr (tmpReg, markWord::unlocked_value); movptr(Address(boxReg, 0), tmpReg); // Anticipate successful CAS @@ -620,10 +626,6 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp // Next instruction set ZFlag == 1 (Success) if difference is less then one page. andptr(tmpReg, (int32_t) (NOT_LP64(0xFFFFF003) LP64_ONLY(7 - (int)os::vm_page_size())) ); movptr(Address(boxReg, 0), tmpReg); - } else { - assert(LockingMode == LM_LIGHTWEIGHT, ""); - lightweight_lock(objReg, tmpReg, thread, scrReg, NO_COUNT); - jmp(COUNT); } jmp(DONE_LABEL); @@ -754,6 +756,7 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp // Xcheck:jni is enabled. void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpReg, bool use_rtm) { + assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_unlock_lightweight"); assert(boxReg == rax, ""); assert_different_registers(objReg, boxReg, tmpReg); @@ -784,23 +787,6 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t } // It's inflated. - if (LockingMode == LM_LIGHTWEIGHT) { - // If the owner is ANONYMOUS, we need to fix it - in an outline stub. - testb(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), (int32_t) ObjectMonitor::ANONYMOUS_OWNER); -#ifdef _LP64 - if (!Compile::current()->output()->in_scratch_emit_size()) { - C2HandleAnonOMOwnerStub* stub = new (Compile::current()->comp_arena()) C2HandleAnonOMOwnerStub(tmpReg, boxReg); - Compile::current()->output()->add_stub(stub); - jcc(Assembler::notEqual, stub->entry()); - bind(stub->continuation()); - } else -#endif - { - // We can't easily implement this optimization on 32 bit because we don't have a thread register. - // Call the slow-path instead. - jcc(Assembler::notEqual, NO_COUNT); - } - } #if INCLUDE_RTM_OPT if (use_rtm) { @@ -922,19 +908,14 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t jmpb (DONE_LABEL); #endif - if (LockingMode != LM_MONITOR) { + if (LockingMode == LM_LEGACY) { bind (Stacked); - if (LockingMode == LM_LIGHTWEIGHT) { - mov(boxReg, tmpReg); - lightweight_unlock(objReg, boxReg, tmpReg, NO_COUNT); - jmp(COUNT); - } else if (LockingMode == LM_LEGACY) { - movptr(tmpReg, Address (boxReg, 0)); // re-fetch - lock(); - cmpxchgptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Uses RAX which is box - } + movptr(tmpReg, Address (boxReg, 0)); // re-fetch + lock(); + cmpxchgptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Uses RAX which is box // Intentional fall-thru into DONE_LABEL } + bind(DONE_LABEL); // ZFlag == 1 count in fast path @@ -955,6 +936,247 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t bind(NO_COUNT); } +void C2_MacroAssembler::fast_lock_lightweight(Register obj, Register box, Register rax_reg, + Register t, Register thread) { + assert(LockingMode == LM_LIGHTWEIGHT, "must be"); + assert(rax_reg == rax, "Used for CAS"); + assert_different_registers(obj, box, rax_reg, t, thread); + + // Handle inflated monitor. + Label inflated; + // Finish fast lock successfully. ZF value is irrelevant. + Label locked; + // Finish fast lock unsuccessfully. MUST jump with ZF == 0 + Label slow_path; + + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(rax_reg, obj, t); + movl(rax_reg, Address(rax_reg, Klass::access_flags_offset())); + testl(rax_reg, JVM_ACC_IS_VALUE_BASED_CLASS); + jcc(Assembler::notZero, slow_path); + } + + const Register mark = t; + + { // Lightweight Lock + + Label push; + + const Register top = box; + + // Load the mark. + movptr(mark, Address(obj, oopDesc::mark_offset_in_bytes())); + + // Prefetch top. + movl(top, Address(thread, JavaThread::lock_stack_top_offset())); + + // Check for monitor (0b10). + testptr(mark, markWord::monitor_value); + jcc(Assembler::notZero, inflated); + + // Check if lock-stack is full. + cmpl(top, LockStack::end_offset() - 1); + jcc(Assembler::greater, slow_path); + + // Check if recursive. + cmpptr(obj, Address(thread, top, Address::times_1, -oopSize)); + jccb(Assembler::equal, push); + + // Try to lock. Transition lock bits 0b01 => 0b00 + movptr(rax_reg, mark); + orptr(rax_reg, markWord::unlocked_value); + andptr(mark, ~(int32_t)markWord::unlocked_value); + lock(); cmpxchgptr(mark, Address(obj, oopDesc::mark_offset_in_bytes())); + jcc(Assembler::notEqual, slow_path); + + bind(push); + // After successful lock, push object on lock-stack. + movptr(Address(thread, top), obj); + addl(Address(thread, JavaThread::lock_stack_top_offset()), oopSize); + jmpb(locked); + } + + { // Handle inflated monitor. + bind(inflated); + + const Register tagged_monitor = mark; + + // CAS owner (null => current thread). + xorptr(rax_reg, rax_reg); + lock(); cmpxchgptr(thread, Address(tagged_monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); + jccb(Assembler::equal, locked); + + // Check if recursive. + cmpptr(thread, rax_reg); + jccb(Assembler::notEqual, slow_path); + + // Recursive. + increment(Address(tagged_monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions))); + } + + bind(locked); + increment(Address(thread, JavaThread::held_monitor_count_offset())); + // Set ZF = 1 + xorl(rax_reg, rax_reg); + +#ifdef ASSERT + // Check that locked label is reached with ZF set. + Label zf_correct; + jccb(Assembler::zero, zf_correct); + stop("Fast Lock ZF != 1"); +#endif + + bind(slow_path); +#ifdef ASSERT + // Check that slow_path label is reached with ZF not set. + jccb(Assembler::notZero, zf_correct); + stop("Fast Lock ZF != 0"); + bind(zf_correct); +#endif + // C2 uses the value of ZF to determine the continuation. +} + +void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register reg_rax, Register t, Register thread) { + assert(LockingMode == LM_LIGHTWEIGHT, "must be"); + assert(reg_rax == rax, "Used for CAS"); + assert_different_registers(obj, reg_rax, t); + + // Handle inflated monitor. + Label inflated, inflated_check_lock_stack; + // Finish fast unlock successfully. MUST jump with ZF == 1 + Label unlocked; + + // Assume success. + decrement(Address(thread, JavaThread::held_monitor_count_offset())); + + const Register mark = t; + const Register top = reg_rax; + + Label dummy; + C2FastUnlockLightweightStub* stub = nullptr; + + if (!Compile::current()->output()->in_scratch_emit_size()) { + stub = new (Compile::current()->comp_arena()) C2FastUnlockLightweightStub(obj, mark, reg_rax, thread); + Compile::current()->output()->add_stub(stub); + } + + Label& push_and_slow_path = stub == nullptr ? dummy : stub->push_and_slow_path(); + Label& check_successor = stub == nullptr ? dummy : stub->check_successor(); + + { // Lightweight Unlock + + // Load top. + movl(top, Address(thread, JavaThread::lock_stack_top_offset())); + + // Prefetch mark. + movptr(mark, Address(obj, oopDesc::mark_offset_in_bytes())); + + // Check if obj is top of lock-stack. + cmpptr(obj, Address(thread, top, Address::times_1, -oopSize)); + // Top of lock stack was not obj. Must be monitor. + jcc(Assembler::notEqual, inflated_check_lock_stack); + + // Pop lock-stack. + DEBUG_ONLY(movptr(Address(thread, top, Address::times_1, -oopSize), 0);) + subl(Address(thread, JavaThread::lock_stack_top_offset()), oopSize); + + // Check if recursive. + cmpptr(obj, Address(thread, top, Address::times_1, -2 * oopSize)); + jcc(Assembler::equal, unlocked); + + // We elide the monitor check, let the CAS fail instead. + + // Try to unlock. Transition lock bits 0b00 => 0b01 + movptr(reg_rax, mark); + andptr(reg_rax, ~(int32_t)markWord::lock_mask); + orptr(mark, markWord::unlocked_value); + lock(); cmpxchgptr(mark, Address(obj, oopDesc::mark_offset_in_bytes())); + jcc(Assembler::notEqual, push_and_slow_path); + jmp(unlocked); + } + + + { // Handle inflated monitor. + bind(inflated_check_lock_stack); +#ifdef ASSERT + Label check_done; + subl(top, oopSize); + cmpl(top, in_bytes(JavaThread::lock_stack_base_offset())); + jcc(Assembler::below, check_done); + cmpptr(obj, Address(thread, top)); + jccb(Assembler::notEqual, inflated_check_lock_stack); + stop("Fast Unlock lock on stack"); + bind(check_done); + testptr(mark, markWord::monitor_value); + jccb(Assembler::notZero, inflated); + stop("Fast Unlock not monitor"); +#endif + + bind(inflated); + + // mark contains the tagged ObjectMonitor*. + const Register monitor = mark; + +#ifndef _LP64 + // Check if recursive. + xorptr(reg_rax, reg_rax); + orptr(reg_rax, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions))); + jcc(Assembler::notZero, check_successor); + + // Check if the entry lists are empty. + movptr(reg_rax, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList))); + orptr(reg_rax, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq))); + jcc(Assembler::notZero, check_successor); + + // Release lock. + movptr(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD); +#else // _LP64 + Label recursive; + + // Check if recursive. + cmpptr(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)), 0); + jccb(Assembler::notEqual, recursive); + + // Check if the entry lists are empty. + movptr(reg_rax, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq))); + orptr(reg_rax, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList))); + jcc(Assembler::notZero, check_successor); + + // Release lock. + movptr(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD); + jmpb(unlocked); + + // Recursive unlock. + bind(recursive); + decrement(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions))); + xorl(t, t); +#endif + } + + bind(unlocked); + if (stub != nullptr) { + bind(stub->unlocked_continuation()); + } + +#ifdef ASSERT + // Check that unlocked label is reached with ZF set. + Label zf_correct; + jccb(Assembler::zero, zf_correct); + stop("Fast Unlock ZF != 1"); +#endif + + if (stub != nullptr) { + bind(stub->slow_path_continuation()); + } +#ifdef ASSERT + // Check that stub->continuation() label is reached with ZF not set. + jccb(Assembler::notZero, zf_correct); + stop("Fast Unlock ZF != 0"); + bind(zf_correct); +#endif + // C2 uses the value of ZF to determine the continuation. +} + //------------------------------------------------------------------------------------------- // Generic instructions support for use in .ad files C2 code generation diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp index 151f2148372d5..26f7fb44aa939 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp @@ -43,6 +43,10 @@ bool use_rtm, bool profile_rtm); void fast_unlock(Register obj, Register box, Register tmp, bool use_rtm); + void fast_lock_lightweight(Register obj, Register box, Register rax_reg, + Register t, Register thread); + void fast_unlock_lightweight(Register obj, Register reg_rax, Register t, Register thread); + #if INCLUDE_RTM_OPT void rtm_counters_update(Register abort_status, Register rtm_counters); void branch_on_random_using_rdtsc(Register tmp, Register scr, int count, Label& brLabel); diff --git a/src/hotspot/cpu/x86/compiledIC_x86.cpp b/src/hotspot/cpu/x86/compiledIC_x86.cpp index 8fc001039fbd3..95b41f62b6aab 100644 --- a/src/hotspot/cpu/x86/compiledIC_x86.cpp +++ b/src/hotspot/cpu/x86/compiledIC_x86.cpp @@ -26,7 +26,6 @@ #include "asm/macroAssembler.inline.hpp" #include "code/codeCache.hpp" #include "code/compiledIC.hpp" -#include "code/icBuffer.hpp" #include "code/nmethod.hpp" #include "logging/log.hpp" #include "memory/resourceArea.hpp" @@ -36,7 +35,7 @@ // ---------------------------------------------------------------------------- #define __ _masm. -address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) { +address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) { // Stub is fixed up when the corresponding call is converted from // calling compiled code to calling interpreted code. // movq rbx, 0 @@ -66,32 +65,25 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) } #undef __ -int CompiledStaticCall::to_interp_stub_size() { +int CompiledDirectCall::to_interp_stub_size() { return NOT_LP64(10) // movl; jmp LP64_ONLY(15); // movq (1+1+8); jmp (1+4) } -int CompiledStaticCall::to_trampoline_stub_size() { +int CompiledDirectCall::to_trampoline_stub_size() { // x86 doesn't use trampolines. return 0; } // Relocation entries for call stub, compiled java to interpreter. -int CompiledStaticCall::reloc_to_interp_stub() { +int CompiledDirectCall::reloc_to_interp_stub() { return 4; // 3 in emit_to_interp_stub + 1 in emit_call } -void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) { +void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) { address stub = find_stub(); guarantee(stub != nullptr, "stub not found"); - { - ResourceMark rm; - log_trace(inlinecache)("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s", - p2i(instruction_address()), - callee->name_and_sig_as_C_string()); - } - // Creation also verifies the object. NativeMovConstReg* method_holder = nativeMovConstReg_at(stub); NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); @@ -105,7 +97,7 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad set_destination_mt_safe(stub); } -void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) { +void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) { assert(CompiledICLocker::is_safe(static_stub->addr()), "mt unsafe call"); // Reset stub. address stub = static_stub->addr(); @@ -122,7 +114,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_ // Non-product mode code #ifndef PRODUCT -void CompiledDirectStaticCall::verify() { +void CompiledDirectCall::verify() { // Verify call. _call->verify(); _call->verify_alignment(); diff --git a/src/hotspot/cpu/x86/icBuffer_x86.cpp b/src/hotspot/cpu/x86/icBuffer_x86.cpp deleted file mode 100644 index af374b5741659..0000000000000 --- a/src/hotspot/cpu/x86/icBuffer_x86.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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 "asm/macroAssembler.hpp" -#include "asm/macroAssembler.inline.hpp" -#include "code/icBuffer.hpp" -#include "gc/shared/collectedHeap.inline.hpp" -#include "interpreter/bytecodes.hpp" -#include "memory/resourceArea.hpp" -#include "nativeInst_x86.hpp" -#include "oops/oop.inline.hpp" - -int InlineCacheBuffer::ic_stub_code_size() { - // Worst case, if destination is not a near call: - // lea rax, lit1 - // lea scratch, lit2 - // jmp scratch - - // Best case - // lea rax, lit1 - // jmp lit2 - - int best = NativeMovConstReg::instruction_size + NativeJump::instruction_size; - int worst = 2 * NativeMovConstReg::instruction_size + 3; - return MAX2(best, worst); -} - - - -void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) { - ResourceMark rm; - CodeBuffer code(code_begin, ic_stub_code_size()); - MacroAssembler* masm = new MacroAssembler(&code); - // note: even though the code contains an embedded value, we do not need reloc info - // because - // (1) the value is old (i.e., doesn't matter for scavenges) - // (2) these ICStubs are removed *before* a GC happens, so the roots disappear - // assert(cached_value == nullptr || cached_oop->is_perm(), "must be perm oop"); - masm->lea(rax, AddressLiteral((address) cached_value, relocInfo::metadata_type)); - masm->jump(ExternalAddress(entry_point)); -} - - -address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) { - NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object - address jmp = move->next_instruction_address(); - NativeInstruction* ni = nativeInstruction_at(jmp); - if (ni->is_jump()) { - NativeJump* jump = nativeJump_at(jmp); - return jump->jump_destination(); - } else { - assert(ni->is_far_jump(), "unexpected instruction"); - NativeFarJump* jump = nativeFarJump_at(jmp); - return jump->jump_destination(); - } -} - - -void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) { - // creation also verifies the object - NativeMovConstReg* move = nativeMovConstReg_at(code_begin); - // Verifies the jump - address jmp = move->next_instruction_address(); - NativeInstruction* ni = nativeInstruction_at(jmp); - if (ni->is_jump()) { - NativeJump* jump = nativeJump_at(jmp); - } else { - assert(ni->is_far_jump(), "unexpected instruction"); - NativeFarJump* jump = nativeFarJump_at(jmp); - } - void* o = (void*)move->data(); - return o; -} diff --git a/src/hotspot/cpu/x86/interp_masm_x86.cpp b/src/hotspot/cpu/x86/interp_masm_x86.cpp index f5f83ae21f475..33570f3155b15 100644 --- a/src/hotspot/cpu/x86/interp_masm_x86.cpp +++ b/src/hotspot/cpu/x86/interp_masm_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1192,8 +1192,6 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) { const Register thread = lock_reg; get_thread(thread); #endif - // Load object header, prepare for CAS from unlocked to locked. - movptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); lightweight_lock(obj_reg, swap_reg, thread, tmp_reg, slow_case); } else if (LockingMode == LM_LEGACY) { // Load immediate 1 into swap_reg %rax @@ -1311,20 +1309,13 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg) { if (LockingMode == LM_LIGHTWEIGHT) { #ifdef _LP64 - const Register thread = r15_thread; + lightweight_unlock(obj_reg, swap_reg, r15_thread, header_reg, slow_case); #else - const Register thread = header_reg; - get_thread(thread); + // This relies on the implementation of lightweight_unlock being able to handle + // that the reg_rax and thread Register parameters may alias each other. + get_thread(swap_reg); + lightweight_unlock(obj_reg, swap_reg, swap_reg, header_reg, slow_case); #endif - // Handle unstructured locking. - Register tmp = swap_reg; - movl(tmp, Address(thread, JavaThread::lock_stack_top_offset())); - cmpptr(obj_reg, Address(thread, tmp, Address::times_1, -oopSize)); - jcc(Assembler::notEqual, slow_case); - // Try to swing header from locked to unlocked. - movptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - andptr(swap_reg, ~(int32_t)markWord::lock_mask_in_place); - lightweight_unlock(obj_reg, swap_reg, header_reg, slow_case); } else if (LockingMode == LM_LEGACY) { // Load the old header from BasicLock structure movptr(header_reg, Address(swap_reg, diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index ba4b089c7aa6e..f0e7a08dd5f2a 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "asm/assembler.hpp" #include "asm/assembler.inline.hpp" +#include "code/compiledIC.hpp" #include "compiler/compiler_globals.hpp" #include "compiler/disassembler.hpp" #include "crc32c.h" @@ -1341,13 +1342,45 @@ void MacroAssembler::ic_call(address entry, jint method_index) { RelocationHolder rh = virtual_call_Relocation::spec(pc(), method_index); #ifdef _LP64 // Needs full 64-bit immediate for later patching. - mov64(rax, (intptr_t)Universe::non_oop_word()); + mov64(rax, (int64_t)Universe::non_oop_word()); #else movptr(rax, (intptr_t)Universe::non_oop_word()); #endif call(AddressLiteral(entry, rh)); } +int MacroAssembler::ic_check_size() { + return LP64_ONLY(14) NOT_LP64(12); +} + +int MacroAssembler::ic_check(int end_alignment) { + Register receiver = LP64_ONLY(j_rarg0) NOT_LP64(rcx); + Register data = rax; + Register temp = LP64_ONLY(rscratch1) NOT_LP64(rbx); + + // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed + // before the inline cache check, so we don't have to execute any nop instructions when dispatching + // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align + // before the inline cache check here, and not after + align(end_alignment, offset() + ic_check_size()); + + int uep_offset = offset(); + + if (UseCompressedClassPointers) { + movl(temp, Address(receiver, oopDesc::klass_offset_in_bytes())); + cmpl(temp, Address(data, CompiledICData::speculated_klass_offset())); + } else { + movptr(temp, Address(receiver, oopDesc::klass_offset_in_bytes())); + cmpptr(temp, Address(data, CompiledICData::speculated_klass_offset())); + } + + // if inline cache check fails, then jump to runtime routine + jump_cc(Assembler::notEqual, RuntimeAddress(SharedRuntime::get_ic_miss_stub())); + assert((offset() % end_alignment) == 0, "Misaligned verified entry point"); + + return uep_offset; +} + void MacroAssembler::emit_static_call_stub() { // Static stub relocation also tags the Method* in the code-stream. mov_metadata(rbx, (Metadata*) nullptr); // Method is zapped till fixup time. @@ -4087,8 +4120,9 @@ static void restore_xmm_register(MacroAssembler* masm, int offset, XMMRegister r } } -int register_section_sizes(RegSet gp_registers, XMMRegSet xmm_registers, bool save_fpu, - int& gp_area_size, int& fp_area_size, int& xmm_area_size) { +static int register_section_sizes(RegSet gp_registers, XMMRegSet xmm_registers, + bool save_fpu, int& gp_area_size, + int& fp_area_size, int& xmm_area_size) { gp_area_size = align_up(gp_registers.size() * Register::max_slots_per_register * VMRegImpl::stack_slot_size, StackAlignmentInBytes); @@ -4354,7 +4388,7 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, } // Look up the method for a megamorphic invokeinterface call in a single pass over itable: -// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICHolder +// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICData // - find a holder_klass (class that implements the method) vtable offset and get the method from vtable by index // The target method is determined by . // The receiver klass is in recv_klass. @@ -9877,68 +9911,116 @@ void MacroAssembler::check_stack_alignment(Register sp, const char* msg, unsigne } // Implements lightweight-locking. -// Branches to slow upon failure to lock the object, with ZF cleared. -// Falls through upon success with unspecified ZF. // // obj: the object to be locked -// hdr: the (pre-loaded) header of the object, must be rax +// reg_rax: rax // thread: the thread which attempts to lock obj // tmp: a temporary register -void MacroAssembler::lightweight_lock(Register obj, Register hdr, Register thread, Register tmp, Label& slow) { - assert(hdr == rax, "header must be in rax for cmpxchg"); - assert_different_registers(obj, hdr, thread, tmp); - - // First we need to check if the lock-stack has room for pushing the object reference. - // Note: we subtract 1 from the end-offset so that we can do a 'greater' comparison, instead - // of 'greaterEqual' below, which readily clears the ZF. This makes C2 code a little simpler and - // avoids one branch. - cmpl(Address(thread, JavaThread::lock_stack_top_offset()), LockStack::end_offset() - 1); - jcc(Assembler::greater, slow); - - // Now we attempt to take the fast-lock. - // Clear lock_mask bits (locked state). - andptr(hdr, ~(int32_t)markWord::lock_mask_in_place); - movptr(tmp, hdr); - // Set unlocked_value bit. - orptr(hdr, markWord::unlocked_value); - lock(); - cmpxchgptr(tmp, Address(obj, oopDesc::mark_offset_in_bytes())); +void MacroAssembler::lightweight_lock(Register obj, Register reg_rax, Register thread, Register tmp, Label& slow) { + assert(reg_rax == rax, ""); + assert_different_registers(obj, reg_rax, thread, tmp); + + Label push; + const Register top = tmp; + + // Preload the markWord. It is important that this is the first + // instruction emitted as it is part of C1's null check semantics. + movptr(reg_rax, Address(obj, oopDesc::mark_offset_in_bytes())); + + // Load top. + movl(top, Address(thread, JavaThread::lock_stack_top_offset())); + + // Check if the lock-stack is full. + cmpl(top, LockStack::end_offset()); + jcc(Assembler::greaterEqual, slow); + + // Check for recursion. + cmpptr(obj, Address(thread, top, Address::times_1, -oopSize)); + jcc(Assembler::equal, push); + + // Check header for monitor (0b10). + testptr(reg_rax, markWord::monitor_value); + jcc(Assembler::notZero, slow); + + // Try to lock. Transition lock bits 0b01 => 0b00 + movptr(tmp, reg_rax); + andptr(tmp, ~(int32_t)markWord::unlocked_value); + orptr(reg_rax, markWord::unlocked_value); + lock(); cmpxchgptr(tmp, Address(obj, oopDesc::mark_offset_in_bytes())); jcc(Assembler::notEqual, slow); - // If successful, push object to lock-stack. - movl(tmp, Address(thread, JavaThread::lock_stack_top_offset())); - movptr(Address(thread, tmp), obj); - incrementl(tmp, oopSize); - movl(Address(thread, JavaThread::lock_stack_top_offset()), tmp); + // Restore top, CAS clobbers register. + movl(top, Address(thread, JavaThread::lock_stack_top_offset())); + + bind(push); + // After successful lock, push object on lock-stack. + movptr(Address(thread, top), obj); + incrementl(top, oopSize); + movl(Address(thread, JavaThread::lock_stack_top_offset()), top); } // Implements lightweight-unlocking. -// Branches to slow upon failure, with ZF cleared. -// Falls through upon success, with unspecified ZF. // // obj: the object to be unlocked -// hdr: the (pre-loaded) header of the object, must be rax +// reg_rax: rax +// thread: the thread // tmp: a temporary register -void MacroAssembler::lightweight_unlock(Register obj, Register hdr, Register tmp, Label& slow) { - assert(hdr == rax, "header must be in rax for cmpxchg"); - assert_different_registers(obj, hdr, tmp); - - // Mark-word must be lock_mask now, try to swing it back to unlocked_value. - movptr(tmp, hdr); // The expected old value - orptr(tmp, markWord::unlocked_value); - lock(); - cmpxchgptr(tmp, Address(obj, oopDesc::mark_offset_in_bytes())); +// +// x86_32 Note: reg_rax and thread may alias each other due to limited register +// availiability. +void MacroAssembler::lightweight_unlock(Register obj, Register reg_rax, Register thread, Register tmp, Label& slow) { + assert(reg_rax == rax, ""); + assert_different_registers(obj, reg_rax, tmp); + LP64_ONLY(assert_different_registers(obj, reg_rax, thread, tmp);) + + Label unlocked, push_and_slow; + const Register top = tmp; + + // Check if obj is top of lock-stack. + movl(top, Address(thread, JavaThread::lock_stack_top_offset())); + cmpptr(obj, Address(thread, top, Address::times_1, -oopSize)); jcc(Assembler::notEqual, slow); - // Pop the lock object from the lock-stack. -#ifdef _LP64 - const Register thread = r15_thread; -#else - const Register thread = rax; - get_thread(thread); -#endif + + // Pop lock-stack. + DEBUG_ONLY(movptr(Address(thread, top, Address::times_1, -oopSize), 0);) subl(Address(thread, JavaThread::lock_stack_top_offset()), oopSize); + + // Check if recursive. + cmpptr(obj, Address(thread, top, Address::times_1, -2 * oopSize)); + jcc(Assembler::equal, unlocked); + + // Not recursive. Check header for monitor (0b10). + movptr(reg_rax, Address(obj, oopDesc::mark_offset_in_bytes())); + testptr(reg_rax, markWord::monitor_value); + jcc(Assembler::notZero, push_and_slow); + +#ifdef ASSERT + // Check header not unlocked (0b01). + Label not_unlocked; + testptr(reg_rax, markWord::unlocked_value); + jcc(Assembler::zero, not_unlocked); + stop("lightweight_unlock already unlocked"); + bind(not_unlocked); +#endif + + // Try to unlock. Transition lock bits 0b00 => 0b01 + movptr(tmp, reg_rax); + orptr(tmp, markWord::unlocked_value); + lock(); cmpxchgptr(tmp, Address(obj, oopDesc::mark_offset_in_bytes())); + jcc(Assembler::equal, unlocked); + + bind(push_and_slow); + // Restore lock-stack and handle the unlock in runtime. + if (thread == reg_rax) { + // On x86_32 we may lose the thread. + get_thread(thread); + } #ifdef ASSERT - movl(tmp, Address(thread, JavaThread::lock_stack_top_offset())); - movptr(Address(thread, tmp), 0); + movl(top, Address(thread, JavaThread::lock_stack_top_offset())); + movptr(Address(thread, top), obj); #endif + addl(Address(thread, JavaThread::lock_stack_top_offset()), oopSize); + jmp(slow); + + bind(unlocked); } diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 4b30168452796..4789b63decc6c 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -896,6 +896,8 @@ class MacroAssembler: public Assembler { // Emit the CompiledIC call idiom void ic_call(address entry, jint method_index = 0); + static int ic_check_size(); + int ic_check(int end_alignment); void emit_static_call_stub(); @@ -2031,8 +2033,8 @@ class MacroAssembler: public Assembler { void check_stack_alignment(Register sp, const char* msg, unsigned bias = 0, Register tmp = noreg); - void lightweight_lock(Register obj, Register hdr, Register thread, Register tmp, Label& slow); - void lightweight_unlock(Register obj, Register hdr, Register tmp, Label& slow); + void lightweight_lock(Register obj, Register reg_rax, Register thread, Register tmp, Label& slow); + void lightweight_unlock(Register obj, Register reg_rax, Register thread, Register tmp, Label& slow); }; /** diff --git a/src/hotspot/cpu/x86/peephole_x86_64.cpp b/src/hotspot/cpu/x86/peephole_x86_64.cpp index 8c956aeb05393..92a29490edaf8 100644 --- a/src/hotspot/cpu/x86/peephole_x86_64.cpp +++ b/src/hotspot/cpu/x86/peephole_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,8 +33,8 @@ // lea d, [s1 + s2] and // mov d, s1; shl d, s2 into // lea d, [s1 << s2] with s2 = 1, 2, 3 -bool lea_coalesce_helper(Block* block, int block_index, PhaseCFG* cfg_, PhaseRegAlloc* ra_, - MachNode* (*new_root)(), uint inst0_rule, bool imm) { +static bool lea_coalesce_helper(Block* block, int block_index, PhaseCFG* cfg_, PhaseRegAlloc* ra_, + MachNode* (*new_root)(), uint inst0_rule, bool imm) { MachNode* inst0 = block->get_node(block_index)->as_Mach(); assert(inst0->rule() == inst0_rule, "sanity"); @@ -136,7 +136,7 @@ bool lea_coalesce_helper(Block* block, int block_index, PhaseCFG* cfg_, PhaseReg // This helper func takes a condition and returns the flags that need to be set for the condition // It uses the same flags as the test instruction, so if the e.g. the overflow bit is required, // this func returns clears_overflow, as that is what the test instruction does and what the downstream path expects -juint map_condition_to_required_test_flags(Assembler::Condition condition) { +static juint map_condition_to_required_test_flags(Assembler::Condition condition) { switch (condition) { case Assembler::Condition::zero: // Same value as equal case Assembler::Condition::notZero: // Same value as notEqual diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp index 571160523cbe4..febc1b2c3b143 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,8 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" +#include "code/compiledIC.hpp" #include "code/debugInfoRec.hpp" -#include "code/icBuffer.hpp" #include "code/nativeInst.hpp" #include "code/vtableStubs.hpp" #include "compiler/oopMap.hpp" @@ -36,7 +36,6 @@ #include "interpreter/interpreter.hpp" #include "logging/log.hpp" #include "memory/resourceArea.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/klass.inline.hpp" #include "prims/methodHandles.hpp" #include "runtime/jniHandles.hpp" @@ -944,25 +943,18 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm address c2i_unverified_entry = __ pc(); Label skip_fixup; - Register holder = rax; + Register data = rax; Register receiver = rcx; Register temp = rbx; { - - Label missed; - __ movptr(temp, Address(receiver, oopDesc::klass_offset_in_bytes())); - __ cmpptr(temp, Address(holder, CompiledICHolder::holder_klass_offset())); - __ movptr(rbx, Address(holder, CompiledICHolder::holder_metadata_offset())); - __ jcc(Assembler::notEqual, missed); + __ ic_check(1 /* end_alignment */); + __ movptr(rbx, Address(data, CompiledICData::speculated_method_offset())); // Method might have been compiled since the call site was patched to // interpreted if that is the case treat it as a miss so we can get // the call site corrected. __ cmpptr(Address(rbx, in_bytes(Method::code_offset())), NULL_WORD); __ jcc(Assembler::equal, skip_fixup); - - __ bind(missed); - __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); } address c2i_entry = __ pc(); @@ -1449,23 +1441,12 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // as far as the interpreter and the compiler(s) are concerned. - const Register ic_reg = rax; const Register receiver = rcx; - Label hit; Label exception_pending; __ verify_oop(receiver); - __ cmpptr(ic_reg, Address(receiver, oopDesc::klass_offset_in_bytes())); - __ jcc(Assembler::equal, hit); - - __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); - // verified entry must be aligned for code patching. - // and the first 5 bytes must be in the same cache line - // if we align at 8 then we will be sure 5 bytes are in the same line - __ align(8); - - __ bind(hit); + __ ic_check(8 /* end_alignment */); int vep_offset = ((intptr_t)__ pc()) - start; @@ -1713,8 +1694,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ jcc(Assembler::notEqual, slow_path_lock); } else { assert(LockingMode == LM_LIGHTWEIGHT, "must be"); - // Load object header - __ movptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); __ lightweight_lock(obj_reg, swap_reg, thread, lock_reg, slow_path_lock); } __ bind(count_mon); @@ -1872,9 +1851,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ dec_held_monitor_count(); } else { assert(LockingMode == LM_LIGHTWEIGHT, "must be"); - __ movptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - __ andptr(swap_reg, ~(int32_t)markWord::lock_mask_in_place); - __ lightweight_unlock(obj_reg, swap_reg, lock_reg, slow_path_unlock); + __ lightweight_unlock(obj_reg, swap_reg, thread, lock_reg, slow_path_unlock); __ dec_held_monitor_count(); } diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index cab50e85ec51c..c666f982d0f52 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ #include "asm/macroAssembler.inline.hpp" #include "code/compiledIC.hpp" #include "code/debugInfoRec.hpp" -#include "code/icBuffer.hpp" #include "code/nativeInst.hpp" #include "code/vtableStubs.hpp" #include "compiler/oopMap.hpp" @@ -42,7 +41,6 @@ #include "logging/log.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/klass.inline.hpp" #include "oops/method.inline.hpp" #include "prims/methodHandles.hpp" @@ -1000,20 +998,14 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm address c2i_unverified_entry = __ pc(); Label skip_fixup; - Label ok; - Register holder = rax; + Register data = rax; Register receiver = j_rarg0; Register temp = rbx; { - __ load_klass(temp, receiver, rscratch1); - __ cmpptr(temp, Address(holder, CompiledICHolder::holder_klass_offset())); - __ movptr(rbx, Address(holder, CompiledICHolder::holder_metadata_offset())); - __ jcc(Assembler::equal, ok); - __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); - - __ bind(ok); + __ ic_check(1 /* end_alignment */); + __ movptr(rbx, Address(data, CompiledICData::speculated_method_offset())); // Method might have been compiled since the call site was patched to // interpreted if that is the case treat it as a miss so we can get // the call site corrected. @@ -1450,7 +1442,7 @@ static void gen_continuation_enter(MacroAssembler* masm, __ align(BytesPerWord, __ offset() + NativeCall::displacement_offset); // Emit stub for static call CodeBuffer* cbuf = masm->code_section()->outer(); - address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, __ pc()); + address stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, __ pc()); if (stub == nullptr) { fatal("CodeCache is full at gen_continuation_enter"); } @@ -1487,7 +1479,7 @@ static void gen_continuation_enter(MacroAssembler* masm, // Emit stub for static call CodeBuffer* cbuf = masm->code_section()->outer(); - address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, __ pc()); + address stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, __ pc()); if (stub == nullptr) { fatal("CodeCache is full at gen_continuation_enter"); } @@ -1883,25 +1875,13 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // restoring them except rbp. rbp is the only callee save register // as far as the interpreter and the compiler(s) are concerned. - - const Register ic_reg = rax; const Register receiver = j_rarg0; - Label hit; Label exception_pending; - assert_different_registers(ic_reg, receiver, rscratch1, rscratch2); + assert_different_registers(receiver, rscratch1, rscratch2); __ verify_oop(receiver); - __ load_klass(rscratch1, receiver, rscratch2); - __ cmpq(ic_reg, rscratch1); - __ jcc(Assembler::equal, hit); - - __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); - - // Verified entry point must be aligned - __ align(8); - - __ bind(hit); + __ ic_check(8 /* end_alignment */); int vep_offset = ((intptr_t)__ pc()) - start; @@ -2190,8 +2170,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ jcc(Assembler::notEqual, slow_path_lock); } else { assert(LockingMode == LM_LIGHTWEIGHT, "must be"); - // Load object header - __ movptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); __ lightweight_lock(obj_reg, swap_reg, r15_thread, rscratch1, slow_path_lock); } __ bind(count_mon); @@ -2334,9 +2312,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ dec_held_monitor_count(); } else { assert(LockingMode == LM_LIGHTWEIGHT, "must be"); - __ movptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - __ andptr(swap_reg, ~(int32_t)markWord::lock_mask_in_place); - __ lightweight_unlock(obj_reg, swap_reg, lock_reg, slow_path_unlock); + __ lightweight_unlock(obj_reg, swap_reg, r15_thread, lock_reg, slow_path_unlock); __ dec_held_monitor_count(); } diff --git a/src/hotspot/cpu/x86/stubRoutines_x86.cpp b/src/hotspot/cpu/x86/stubRoutines_x86.cpp index 3be83eed9d22f..bc1cbdbba26b5 100644 --- a/src/hotspot/cpu/x86/stubRoutines_x86.cpp +++ b/src/hotspot/cpu/x86/stubRoutines_x86.cpp @@ -279,7 +279,7 @@ uint32_t _crc32c_pow_2k_table[TILL_CYCLE]; // because _crc32c_pow_2k_table[TILL_ // A. Kadatch and B. Jenkins / Everything we know about CRC but afraid to forget September 3, 2010 8 // Listing 1: Multiplication of normalized polynomials // "a" and "b" occupy D least significant bits. -uint32_t crc32c_multiply(uint32_t a, uint32_t b) { +static uint32_t crc32c_multiply(uint32_t a, uint32_t b) { uint32_t product = 0; uint32_t b_pow_x_table[D + 1]; // b_pow_x_table[k] = (b * x**k) mod P b_pow_x_table[0] = b; @@ -303,7 +303,7 @@ uint32_t crc32c_multiply(uint32_t a, uint32_t b) { #undef P // A. Kadatch and B. Jenkins / Everything we know about CRC but afraid to forget September 3, 2010 9 -void crc32c_init_pow_2k(void) { +static void crc32c_init_pow_2k(void) { // _crc32c_pow_2k_table(0) = // x^(2^k) mod P(x) = x mod P(x) = x // Since we are operating on a reflected values @@ -318,7 +318,7 @@ void crc32c_init_pow_2k(void) { } // x^N mod P(x) -uint32_t crc32c_f_pow_n(uint32_t n) { +static uint32_t crc32c_f_pow_n(uint32_t n) { // result = 1 (polynomial) uint32_t one, result = 0x80000000, i = 0; diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index cfc16acabc674..bf5e052e16702 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -770,6 +770,10 @@ class VM_Version : public Abstract_VM_Version { return true; } + constexpr static bool supports_recursive_lightweight_locking() { + return true; + } + // For AVX CPUs only. f16c support is disabled if UseAVX == 0. static bool supports_float16() { return supports_f16c() || supports_avx512vl(); diff --git a/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp b/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp index 0e78e0274d7f2..398f2e37eb5cc 100644 --- a/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp +++ b/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp @@ -24,10 +24,10 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" +#include "code/compiledIC.hpp" #include "code/vtableStubs.hpp" #include "interp_masm_x86.hpp" #include "memory/resourceArea.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/instanceKlass.hpp" #include "oops/klassVtable.hpp" #include "runtime/sharedRuntime.hpp" @@ -176,21 +176,21 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) { #endif /* PRODUCT */ // Entry arguments: - // rax: CompiledICHolder + // rax: CompiledICData // rcx: Receiver // Most registers are in use; we'll use rax, rbx, rcx, rdx, rsi, rdi // (If we need to make rsi, rdi callee-save, do a push/pop here.) const Register recv_klass_reg = rsi; - const Register holder_klass_reg = rax; // declaring interface klass (DECC) + const Register holder_klass_reg = rax; // declaring interface klass (DEFC) const Register resolved_klass_reg = rdi; // resolved interface klass (REFC) const Register temp_reg = rdx; const Register method = rbx; - const Register icholder_reg = rax; + const Register icdata_reg = rax; const Register receiver = rcx; - __ movptr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset())); - __ movptr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset())); + __ movptr(resolved_klass_reg, Address(icdata_reg, CompiledICData::itable_refc_klass_offset())); + __ movptr(holder_klass_reg, Address(icdata_reg, CompiledICData::itable_defc_klass_offset())); Label L_no_such_interface; diff --git a/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp b/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp index f162a651183f9..158d6f9c6922b 100644 --- a/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp +++ b/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp @@ -24,10 +24,10 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" +#include "code/compiledIC.hpp" #include "code/vtableStubs.hpp" #include "interp_masm_x86.hpp" #include "memory/resourceArea.hpp" -#include "oops/compiledICHolder.hpp" #include "oops/instanceKlass.hpp" #include "oops/klassVtable.hpp" #include "runtime/sharedRuntime.hpp" @@ -168,21 +168,21 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) { #endif // PRODUCT // Entry arguments: - // rax: CompiledICHolder + // rax: CompiledICData // j_rarg0: Receiver // Most registers are in use; we'll use rax, rbx, r10, r11 // (various calling sequences use r[cd]x, r[sd]i, r[89]; stay away from them) const Register recv_klass_reg = r10; - const Register holder_klass_reg = rax; // declaring interface klass (DECC) + const Register holder_klass_reg = rax; // declaring interface klass (DEFC) const Register resolved_klass_reg = r14; // resolved interface klass (REFC) const Register temp_reg = r11; const Register temp_reg2 = r13; const Register method = rbx; - const Register icholder_reg = rax; + const Register icdata_reg = rax; - __ movptr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset())); - __ movptr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset())); + __ movptr(resolved_klass_reg, Address(icdata_reg, CompiledICData::itable_refc_klass_offset())); + __ movptr(holder_klass_reg, Address(icdata_reg, CompiledICData::itable_defc_klass_offset())); Label L_no_such_interface; diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index a31548eb8c3f9..6df02d280bcef 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -1358,7 +1358,7 @@ int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) { return offset; } -Assembler::Width widthForType(BasicType bt) { +static Assembler::Width widthForType(BasicType bt) { if (bt == T_BYTE) { return Assembler::B; } else if (bt == T_SHORT) { diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad index 9aa0051043575..2fe655a576778 100644 --- a/src/hotspot/cpu/x86/x86_32.ad +++ b/src/hotspot/cpu/x86/x86_32.ad @@ -504,7 +504,7 @@ void emit_cmpfp_fixup(MacroAssembler& _masm) { __ bind(exit); } -void emit_cmpfp3(MacroAssembler& _masm, Register dst) { +static void emit_cmpfp3(MacroAssembler& _masm, Register dst) { Label done; __ movl(dst, -1); __ jcc(Assembler::parity, done); @@ -1383,24 +1383,12 @@ void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream* st ) const { void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { MacroAssembler masm(&cbuf); -#ifdef ASSERT - uint insts_size = cbuf.insts_size(); -#endif - masm.cmpptr(rax, Address(rcx, oopDesc::klass_offset_in_bytes())); - masm.jump_cc(Assembler::notEqual, - RuntimeAddress(SharedRuntime::get_ic_miss_stub())); - /* WARNING these NOPs are critical so that verified entry point is properly - aligned for patching by NativeJump::patch_verified_entry() */ - int nops_cnt = 2; - if( !OptoBreakpoint ) // Leave space for int3 - nops_cnt += 1; - masm.nop(nops_cnt); - - assert(cbuf.insts_size() - insts_size == size(ra_), "checking code size of inline cache node"); + masm.ic_check(CodeEntryAlignment); } uint MachUEPNode::size(PhaseRegAlloc *ra_) const { - return OptoBreakpoint ? 11 : 12; + return MachNode::size(ra_); // too many variables; just compute it + // the hard way } @@ -1842,7 +1830,7 @@ encode %{ cbuf.shared_stub_to_interp_for(_method, cbuf.insts()->mark_off()); } else { // Emit stubs for static call. - address stub = CompiledStaticCall::emit_to_interp_stub(cbuf, mark); + address stub = CompiledDirectCall::emit_to_interp_stub(cbuf, mark); if (stub == nullptr) { ciEnv::current()->record_failure("CodeCache is full"); return; @@ -13776,7 +13764,7 @@ instruct cmpFastLockRTM(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eD %} instruct cmpFastLock(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eRegP scr, eRegP thread) %{ - predicate(!Compile::current()->use_rtm()); + predicate(LockingMode != LM_LIGHTWEIGHT && !Compile::current()->use_rtm()); match(Set cr (FastLock object box)); effect(TEMP tmp, TEMP scr, USE_KILL box, TEMP thread); ins_cost(300); @@ -13790,6 +13778,7 @@ instruct cmpFastLock(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eRegP %} instruct cmpFastUnlock(eFlagsReg cr, eRegP object, eAXRegP box, eRegP tmp ) %{ + predicate(LockingMode != LM_LIGHTWEIGHT); match(Set cr (FastUnlock object box)); effect(TEMP tmp, USE_KILL box); ins_cost(300); @@ -13800,6 +13789,32 @@ instruct cmpFastUnlock(eFlagsReg cr, eRegP object, eAXRegP box, eRegP tmp ) %{ ins_pipe(pipe_slow); %} +instruct cmpFastLockLightweight(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI eax_reg, eRegP tmp, eRegP thread) %{ + predicate(LockingMode == LM_LIGHTWEIGHT); + match(Set cr (FastLock object box)); + effect(TEMP eax_reg, TEMP tmp, USE_KILL box, TEMP thread); + ins_cost(300); + format %{ "FASTLOCK $object,$box\t! kills $box,$eax_reg,$tmp" %} + ins_encode %{ + __ get_thread($thread$$Register); + __ fast_lock_lightweight($object$$Register, $box$$Register, $eax_reg$$Register, $tmp$$Register, $thread$$Register); + %} + ins_pipe(pipe_slow); +%} + +instruct cmpFastUnlockLightweight(eFlagsReg cr, eRegP object, eAXRegP eax_reg, eRegP tmp, eRegP thread) %{ + predicate(LockingMode == LM_LIGHTWEIGHT); + match(Set cr (FastUnlock object eax_reg)); + effect(TEMP tmp, USE_KILL eax_reg, TEMP thread); + ins_cost(300); + format %{ "FASTUNLOCK $object,$eax_reg\t! kills $eax_reg,$tmp" %} + ins_encode %{ + __ get_thread($thread$$Register); + __ fast_unlock_lightweight($object$$Register, $eax_reg$$Register, $tmp$$Register, $thread$$Register); + %} + ins_pipe(pipe_slow); +%} + instruct mask_all_evexL_LT32(kReg dst, eRegL src) %{ predicate(Matcher::vector_length(n) <= 32); match(Set dst (MaskAll src)); diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index a248daaa1917b..a8136688cdedd 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -519,7 +519,7 @@ int CallDynamicJavaDirectNode::compute_padding(int current_offset) const } // This could be in MacroAssembler but it's fairly C2 specific -void emit_cmpfp_fixup(MacroAssembler& _masm) { +static void emit_cmpfp_fixup(MacroAssembler& _masm) { Label exit; __ jccb(Assembler::noParity, exit); __ pushf(); @@ -539,7 +539,7 @@ void emit_cmpfp_fixup(MacroAssembler& _masm) { __ bind(exit); } -void emit_cmpfp3(MacroAssembler& _masm, Register dst) { +static void emit_cmpfp3(MacroAssembler& _masm, Register dst) { Label done; __ movl(dst, -1); __ jcc(Assembler::parity, done); @@ -558,10 +558,10 @@ void emit_cmpfp3(MacroAssembler& _masm, Register dst) { // je # // |-jz -> a | b # a & b // | -> a # -void emit_fp_min_max(MacroAssembler& _masm, XMMRegister dst, - XMMRegister a, XMMRegister b, - XMMRegister xmmt, Register rt, - bool min, bool single) { +static void emit_fp_min_max(MacroAssembler& _masm, XMMRegister dst, + XMMRegister a, XMMRegister b, + XMMRegister xmmt, Register rt, + bool min, bool single) { Label nan, zero, below, above, done; @@ -1472,40 +1472,19 @@ void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const { if (UseCompressedClassPointers) { st->print_cr("movl rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); - st->print_cr("\tdecode_klass_not_null rscratch1, rscratch1"); - st->print_cr("\tcmpq rax, rscratch1\t # Inline cache check"); + st->print_cr("\tcmpl rscratch1, [rax + CompiledICData::speculated_klass_offset()]\t # Inline cache check"); } else { - st->print_cr("\tcmpq rax, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t" - "# Inline cache check"); + st->print_cr("movq rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); + st->print_cr("\tcmpq rscratch1, [rax + CompiledICData::speculated_klass_offset()]\t # Inline cache check"); } st->print_cr("\tjne SharedRuntime::_ic_miss_stub"); - st->print_cr("\tnop\t# nops to align entry point"); } #endif void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { MacroAssembler masm(&cbuf); - uint insts_size = cbuf.insts_size(); - if (UseCompressedClassPointers) { - masm.load_klass(rscratch1, j_rarg0, rscratch2); - masm.cmpptr(rax, rscratch1); - } else { - masm.cmpptr(rax, Address(j_rarg0, oopDesc::klass_offset_in_bytes())); - } - - masm.jump_cc(Assembler::notEqual, RuntimeAddress(SharedRuntime::get_ic_miss_stub())); - - /* WARNING these NOPs are critical so that verified entry point is properly - 4 bytes aligned for patching by NativeJump::patch_verified_entry() */ - int nops_cnt = 4 - ((cbuf.insts_size() - insts_size) & 0x3); - if (OptoBreakpoint) { - // Leave space for int3 - nops_cnt -= 1; - } - nops_cnt &= 0x3; // Do not add nops if code is aligned. - if (nops_cnt > 0) - masm.nop(nops_cnt); + masm.ic_check(InteriorEntryAlignment); } uint MachUEPNode::size(PhaseRegAlloc* ra_) const @@ -1840,7 +1819,7 @@ encode %{ cbuf.shared_stub_to_interp_for(_method, call_offset); } else { // Emit stubs for static call. - address stub = CompiledStaticCall::emit_to_interp_stub(cbuf, mark); + address stub = CompiledDirectCall::emit_to_interp_stub(cbuf, mark); if (stub == nullptr) { ciEnv::current()->record_failure("CodeCache is full"); return; @@ -12404,7 +12383,7 @@ instruct cmpFastLockRTM(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp, %} instruct cmpFastLock(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp, rRegP scr) %{ - predicate(!Compile::current()->use_rtm()); + predicate(LockingMode != LM_LIGHTWEIGHT && !Compile::current()->use_rtm()); match(Set cr (FastLock object box)); effect(TEMP tmp, TEMP scr, USE_KILL box); ins_cost(300); @@ -12417,6 +12396,7 @@ instruct cmpFastLock(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp, rRe %} instruct cmpFastUnlock(rFlagsReg cr, rRegP object, rax_RegP box, rRegP tmp) %{ + predicate(LockingMode != LM_LIGHTWEIGHT); match(Set cr (FastUnlock object box)); effect(TEMP tmp, USE_KILL box); ins_cost(300); @@ -12427,6 +12407,30 @@ instruct cmpFastUnlock(rFlagsReg cr, rRegP object, rax_RegP box, rRegP tmp) %{ ins_pipe(pipe_slow); %} +instruct cmpFastLockLightweight(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI rax_reg, rRegP tmp) %{ + predicate(LockingMode == LM_LIGHTWEIGHT); + match(Set cr (FastLock object box)); + effect(TEMP rax_reg, TEMP tmp, USE_KILL box); + ins_cost(300); + format %{ "fastlock $object,$box\t! kills $box,$rax_reg,$tmp" %} + ins_encode %{ + __ fast_lock_lightweight($object$$Register, $box$$Register, $rax_reg$$Register, $tmp$$Register, r15_thread); + %} + ins_pipe(pipe_slow); +%} + +instruct cmpFastUnlockLightweight(rFlagsReg cr, rRegP object, rax_RegP rax_reg, rRegP tmp) %{ + predicate(LockingMode == LM_LIGHTWEIGHT); + match(Set cr (FastUnlock object rax_reg)); + effect(TEMP tmp, USE_KILL rax_reg); + ins_cost(300); + format %{ "fastunlock $object,$rax_reg\t! kills $rax_reg,$tmp" %} + ins_encode %{ + __ fast_unlock_lightweight($object$$Register, $rax_reg$$Register, $tmp$$Register, r15_thread); + %} + ins_pipe(pipe_slow); +%} + // ============================================================================ // Safepoint Instructions diff --git a/src/hotspot/cpu/zero/compiledIC_zero.cpp b/src/hotspot/cpu/zero/compiledIC_zero.cpp index b0564643af080..24153aeacc5e1 100644 --- a/src/hotspot/cpu/zero/compiledIC_zero.cpp +++ b/src/hotspot/cpu/zero/compiledIC_zero.cpp @@ -25,7 +25,6 @@ #include "precompiled.hpp" #include "code/codeCache.hpp" #include "code/compiledIC.hpp" -#include "code/icBuffer.hpp" #include "code/nmethod.hpp" #include "code/vtableStubs.hpp" #include "interpreter/interpreter.hpp" @@ -43,27 +42,27 @@ // ---------------------------------------------------------------------------- -address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) { +address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) { ShouldNotReachHere(); // Only needed for COMPILER2. return nullptr; } -int CompiledStaticCall::to_interp_stub_size() { +int CompiledDirectCall::to_interp_stub_size() { ShouldNotReachHere(); // Only needed for COMPILER2. return 0; } // Relocation entries for call stub, compiled java to interpreter. -int CompiledStaticCall::reloc_to_interp_stub() { +int CompiledDirectCall::reloc_to_interp_stub() { ShouldNotReachHere(); // Only needed for COMPILER2. return 0; } -void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) { +void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) { ShouldNotReachHere(); // Only needed for COMPILER2. } -void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) { +void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) { ShouldNotReachHere(); // Only needed for COMPILER2. } @@ -71,7 +70,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_ // Non-product mode code. #ifndef PRODUCT -void CompiledDirectStaticCall::verify() { +void CompiledDirectCall::verify() { ShouldNotReachHere(); // Only needed for COMPILER2. } diff --git a/src/hotspot/cpu/zero/icBuffer_zero.cpp b/src/hotspot/cpu/zero/icBuffer_zero.cpp deleted file mode 100644 index adde916a4c4ad..0000000000000 --- a/src/hotspot/cpu/zero/icBuffer_zero.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright 2007 Red Hat, Inc. - * 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 "asm/assembler.inline.hpp" -#include "code/icBuffer.hpp" -#include "gc/shared/collectedHeap.inline.hpp" -#include "interpreter/bytecodes.hpp" -#include "memory/resourceArea.hpp" -#include "nativeInst_zero.hpp" -#include "oops/oop.inline.hpp" - -int InlineCacheBuffer::ic_stub_code_size() { - // NB set this once the functions below are implemented - return 4; -} - -void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, - void* cached_oop, - address entry_point) { - // NB ic_stub_code_size() must return the size of the code we generate - ShouldNotCallThis(); -} - -address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) { - // NB ic_stub_code_size() must return the size of the code we generate - ShouldNotCallThis(); - return nullptr; -} - -void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) { - ShouldNotCallThis(); - return nullptr; -} diff --git a/src/hotspot/cpu/zero/sharedRuntime_zero.cpp b/src/hotspot/cpu/zero/sharedRuntime_zero.cpp index 4244b5817db98..986cee685123b 100644 --- a/src/hotspot/cpu/zero/sharedRuntime_zero.cpp +++ b/src/hotspot/cpu/zero/sharedRuntime_zero.cpp @@ -26,10 +26,8 @@ #include "precompiled.hpp" #include "asm/assembler.inline.hpp" #include "code/debugInfoRec.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "interpreter/interpreter.hpp" -#include "oops/compiledICHolder.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/vframeArray.hpp" diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index e701e0aef6082..5d5ea364b6652 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -29,7 +29,6 @@ // no precompiled headers #include "classfile/vmSymbols.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "compiler/compileBroker.hpp" #include "interpreter/interpreter.hpp" diff --git a/src/hotspot/os/aix/os_perf_aix.cpp b/src/hotspot/os/aix/os_perf_aix.cpp index e1719df48c331..b5ae1a6a725a5 100644 --- a/src/hotspot/os/aix/os_perf_aix.cpp +++ b/src/hotspot/os/aix/os_perf_aix.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2022, IBM Corp. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, IBM Corp. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,6 +87,7 @@ static bool read_psinfo(const u_longlong_t& pid, psinfo_t& psinfo) { } len = fread(&psinfo, 1, sizeof(psinfo_t), fp); + fclose(fp); return len == sizeof(psinfo_t); } diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index 42a0b9c083239..dbc18794cfec7 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -24,7 +24,6 @@ // no precompiled headers #include "classfile/vmSymbols.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "compiler/compileBroker.hpp" #include "compiler/disassembler.hpp" @@ -1269,7 +1268,8 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) { } #endif // !__APPLE__ -int _print_dll_info_cb(const char * name, address base_address, address top_address, void * param) { +static int _print_dll_info_cb(const char * name, address base_address, + address top_address, void * param) { outputStream * out = (outputStream *) param; out->print_cr(INTPTR_FORMAT " \t%s", (intptr_t)base_address, name); return 0; diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index f02ca95be5593..d912f9f44a916 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -25,7 +25,6 @@ // no precompiled headers #include "classfile/vmSymbols.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "compiler/compileBroker.hpp" #include "compiler/disassembler.hpp" diff --git a/src/hotspot/os/posix/signals_posix.cpp b/src/hotspot/os/posix/signals_posix.cpp index eaadb36731518..6a958f8903b8e 100644 --- a/src/hotspot/os/posix/signals_posix.cpp +++ b/src/hotspot/os/posix/signals_posix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -340,7 +340,7 @@ static const struct { //////////////////////////////////////////////////////////////////////////////// // sun.misc.Signal and BREAK_SIGNAL support -void jdk_misc_signal_init() { +static void jdk_misc_signal_init() { // Initialize signal structures ::memset((void*)pending_signals, 0, sizeof(pending_signals)); @@ -380,7 +380,7 @@ int os::signal_wait() { //////////////////////////////////////////////////////////////////////////////// // signal chaining support -struct sigaction* get_chained_signal_action(int sig) { +static struct sigaction* get_chained_signal_action(int sig) { struct sigaction *actp = nullptr; if (libjsig_is_loaded) { @@ -1245,7 +1245,7 @@ int os::get_signal_number(const char* signal_name) { return -1; } -void set_signal_handler(int sig) { +static void set_signal_handler(int sig) { // Check for overwrite. struct sigaction oldAct; sigaction(sig, (struct sigaction*)nullptr, &oldAct); @@ -1292,7 +1292,7 @@ void set_signal_handler(int sig) { // install signal handlers for signals that HotSpot needs to // handle in order to support Java-level exception handling. -void install_signal_handlers() { +static void install_signal_handlers() { // signal-chaining typedef void (*signal_setting_t)(); signal_setting_t begin_signal_setting = nullptr; @@ -1723,7 +1723,7 @@ static void SR_handler(int sig, siginfo_t* siginfo, void* context) { errno = old_errno; } -int SR_initialize() { +static int SR_initialize() { struct sigaction act; char *s; // Get signal number to use for suspend/resume diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 3613edfc7d9e6..f9c3f23f0a67b 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -27,7 +27,6 @@ // no precompiled headers #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" -#include "code/icBuffer.hpp" #include "code/nativeInst.hpp" #include "code/vtableStubs.hpp" #include "compiler/compileBroker.hpp" diff --git a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp index 5e0086521aad9..242042d4247aa 100644 --- a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp +++ b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp @@ -28,7 +28,6 @@ #include "asm/assembler.inline.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "interpreter/interpreter.hpp" #include "jvm.h" diff --git a/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp b/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp index fbd7c4eccd403..4750ed8805644 100644 --- a/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp +++ b/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp @@ -29,7 +29,6 @@ #include "classfile/classLoader.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "interpreter/interpreter.hpp" #include "jvm.h" diff --git a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp index 37b92bc7ffd48..c73e83996ff57 100644 --- a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp +++ b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ #include "asm/macroAssembler.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "interpreter/interpreter.hpp" #include "jvm.h" @@ -351,7 +350,7 @@ frame os::get_sender_for_C_frame(frame* fr) { return frame(fr->sender_sp(), fr->link(), fr->sender_pc()); } -intptr_t* _get_previous_fp() { +static intptr_t* _get_previous_fp() { #if defined(__clang__) || defined(__llvm__) intptr_t **ebp; __asm__("mov %%" SPELL_REG_FP ", %0":"=r"(ebp)); diff --git a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp index 012f85ac0ff4a..0fc9484ce23ef 100644 --- a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp +++ b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp @@ -27,7 +27,6 @@ #include "asm/assembler.inline.hpp" #include "atomic_bsd_zero.hpp" #include "classfile/vmSymbols.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "interpreter/interpreter.hpp" #include "jvm.h" diff --git a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp index 4835eb9405a1b..3698896abb78a 100644 --- a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp @@ -27,7 +27,6 @@ #include "asm/macroAssembler.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "code/nativeInst.hpp" #include "interpreter/interpreter.hpp" diff --git a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp index 86e8ed25618c1..551270588438e 100644 --- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp +++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp @@ -25,7 +25,6 @@ // no precompiled headers #include "asm/assembler.inline.hpp" #include "classfile/vmSymbols.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "interpreter/interpreter.hpp" #include "jvm.h" diff --git a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp index b570e3b6d7f12..0b666f29c312b 100644 --- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp +++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp @@ -28,7 +28,6 @@ #include "asm/assembler.inline.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "interpreter/interpreter.hpp" #include "jvm.h" diff --git a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp index 282467bc9e096..3d923c03094ab 100644 --- a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp +++ b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp @@ -27,7 +27,6 @@ #include "asm/macroAssembler.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" -#include "code/icBuffer.hpp" #include "code/nativeInst.hpp" #include "code/vtableStubs.hpp" #include "interpreter/interpreter.hpp" diff --git a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp index 033ea14ead6a4..5aa65e705d9ed 100644 --- a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp +++ b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp @@ -28,7 +28,6 @@ // no precompiled headers #include "asm/assembler.inline.hpp" #include "classfile/vmSymbols.hpp" -#include "code/icBuffer.hpp" #include "code/nativeInst.hpp" #include "code/vtableStubs.hpp" #include "compiler/disassembler.hpp" diff --git a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp index b211330409d59..4dcaedf71da8c 100644 --- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp +++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ #include "asm/macroAssembler.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "interpreter/interpreter.hpp" #include "jvm.h" @@ -165,7 +164,7 @@ frame os::get_sender_for_C_frame(frame* fr) { return frame(fr->sender_sp(), fr->link(), fr->sender_pc()); } -intptr_t* _get_previous_fp() { +static intptr_t* _get_previous_fp() { #if defined(__clang__) intptr_t **ebp; __asm__ __volatile__ ("mov %%" SPELL_REG_FP ", %0":"=r"(ebp):); diff --git a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp index 1ce73588524c1..d593c46d15d91 100644 --- a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp +++ b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp @@ -27,7 +27,6 @@ #include "asm/assembler.inline.hpp" #include "atomic_linux_zero.hpp" #include "classfile/vmSymbols.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "interpreter/interpreter.hpp" #include "jvm.h" diff --git a/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp b/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp index 46f718a9cd0f5..78e98609b6bdc 100644 --- a/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp +++ b/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp @@ -27,7 +27,6 @@ #include "asm/macroAssembler.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "code/nativeInst.hpp" #include "interpreter/interpreter.hpp" diff --git a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp index 4e18334315a37..7e0814c014bec 100644 --- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp +++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp @@ -25,7 +25,6 @@ // no precompiled headers #include "asm/macroAssembler.hpp" #include "classfile/vmSymbols.hpp" -#include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "interpreter/interpreter.hpp" #include "jvm.h" diff --git a/src/hotspot/share/adlc/main.cpp b/src/hotspot/share/adlc/main.cpp index 6d921cf5e7bee..4d1c5491044a7 100644 --- a/src/hotspot/share/adlc/main.cpp +++ b/src/hotspot/share/adlc/main.cpp @@ -216,7 +216,6 @@ int main(int argc, char *argv[]) AD.addInclude(AD._CPP_file, "code/nativeInst.hpp"); AD.addInclude(AD._CPP_file, "code/vmreg.inline.hpp"); AD.addInclude(AD._CPP_file, "gc/shared/collectedHeap.inline.hpp"); - AD.addInclude(AD._CPP_file, "oops/compiledICHolder.hpp"); AD.addInclude(AD._CPP_file, "oops/compressedOops.hpp"); AD.addInclude(AD._CPP_file, "oops/markWord.hpp"); AD.addInclude(AD._CPP_file, "oops/method.hpp"); diff --git a/src/hotspot/share/asm/codeBuffer.cpp b/src/hotspot/share/asm/codeBuffer.cpp index 7a0a31abf597f..5b1e113f15d10 100644 --- a/src/hotspot/share/asm/codeBuffer.cpp +++ b/src/hotspot/share/asm/codeBuffer.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "asm/codeBuffer.hpp" +#include "code/compiledIC.hpp" #include "code/oopRecorder.inline.hpp" #include "compiler/disassembler.hpp" #include "logging/log.hpp" diff --git a/src/hotspot/share/asm/codeBuffer.inline.hpp b/src/hotspot/share/asm/codeBuffer.inline.hpp index 838447ad882dc..06ec9174b34bb 100644 --- a/src/hotspot/share/asm/codeBuffer.inline.hpp +++ b/src/hotspot/share/asm/codeBuffer.inline.hpp @@ -48,7 +48,7 @@ bool emit_shared_stubs_to_interp(CodeBuffer* cb, SharedStubToInterpRequests* sha shared_stub_to_interp_requests->sort(by_shared_method); MacroAssembler masm(cb); for (int i = 0; i < shared_stub_to_interp_requests->length();) { - address stub = __ start_a_stub(CompiledStaticCall::to_interp_stub_size()); + address stub = __ start_a_stub(CompiledDirectCall::to_interp_stub_size()); if (stub == nullptr) { return false; } diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp index 6e5fb99242c8c..396c83c6ab976 100644 --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp @@ -523,7 +523,7 @@ inline bool BlockListBuilder::is_successor(BlockBegin* block, BlockBegin* sux) { #ifndef PRODUCT -int compare_depth_first(BlockBegin** a, BlockBegin** b) { +static int compare_depth_first(BlockBegin** a, BlockBegin** b) { return (*a)->depth_first_number() - (*b)->depth_first_number(); } diff --git a/src/hotspot/share/c1/c1_LIRAssembler.cpp b/src/hotspot/share/c1/c1_LIRAssembler.cpp index a601696d8df7e..51fb851d00c0e 100644 --- a/src/hotspot/share/c1/c1_LIRAssembler.cpp +++ b/src/hotspot/share/c1/c1_LIRAssembler.cpp @@ -606,13 +606,14 @@ void LIR_Assembler::emit_op0(LIR_Op0* op) { Unimplemented(); break; - case lir_std_entry: + case lir_std_entry: { // init offsets offsets()->set_value(CodeOffsets::OSR_Entry, _masm->offset()); - _masm->align(CodeEntryAlignment); if (needs_icache(compilation()->method())) { - check_icache(); + int offset = check_icache(); + offsets()->set_value(CodeOffsets::Entry, offset); } + _masm->align(CodeEntryAlignment); offsets()->set_value(CodeOffsets::Verified_Entry, _masm->offset()); _masm->verified_entry(compilation()->directive()->BreakAtExecuteOption); if (needs_clinit_barrier_on_entry(compilation()->method())) { @@ -621,6 +622,7 @@ void LIR_Assembler::emit_op0(LIR_Op0* op) { build_frame(); offsets()->set_value(CodeOffsets::Frame_Complete, _masm->offset()); break; + } case lir_osr_entry: offsets()->set_value(CodeOffsets::OSR_Entry, _masm->offset()); diff --git a/src/hotspot/share/c1/c1_LinearScan.cpp b/src/hotspot/share/c1/c1_LinearScan.cpp index 9e9195a0d60d0..a4d955e52a004 100644 --- a/src/hotspot/share/c1/c1_LinearScan.cpp +++ b/src/hotspot/share/c1/c1_LinearScan.cpp @@ -1446,12 +1446,12 @@ int LinearScan::interval_cmp(Interval** a, Interval** b) { } } -#ifndef PRODUCT -int interval_cmp(Interval* const& l, Interval* const& r) { +#ifdef ASSERT +static int interval_cmp(Interval* const& l, Interval* const& r) { return l->from() - r->from(); } -bool find_interval(Interval* interval, IntervalArray* intervals) { +static bool find_interval(Interval* interval, IntervalArray* intervals) { bool found; int idx = intervals->find_sorted(interval, found); @@ -2303,11 +2303,11 @@ void assert_no_register_values(GrowableArray* values) { } } -void assert_equal(Location l1, Location l2) { +static void assert_equal(Location l1, Location l2) { assert(l1.where() == l2.where() && l1.type() == l2.type() && l1.offset() == l2.offset(), ""); } -void assert_equal(ScopeValue* v1, ScopeValue* v2) { +static void assert_equal(ScopeValue* v1, ScopeValue* v2) { if (v1->is_location()) { assert(v2->is_location(), ""); assert_equal(((LocationValue*)v1)->location(), ((LocationValue*)v2)->location()); @@ -2328,12 +2328,12 @@ void assert_equal(ScopeValue* v1, ScopeValue* v2) { } } -void assert_equal(MonitorValue* m1, MonitorValue* m2) { +static void assert_equal(MonitorValue* m1, MonitorValue* m2) { assert_equal(m1->owner(), m2->owner()); assert_equal(m1->basic_lock(), m2->basic_lock()); } -void assert_equal(IRScopeDebugInfo* d1, IRScopeDebugInfo* d2) { +static void assert_equal(IRScopeDebugInfo* d1, IRScopeDebugInfo* d2) { assert(d1->scope() == d2->scope(), "not equal"); assert(d1->bci() == d2->bci(), "not equal"); @@ -2375,7 +2375,7 @@ void assert_equal(IRScopeDebugInfo* d1, IRScopeDebugInfo* d2) { } } -void check_stack_depth(CodeEmitInfo* info, int stack_end) { +static void check_stack_depth(CodeEmitInfo* info, int stack_end) { if (info->stack()->bci() != SynchronizationEntryBCI && !info->scope()->method()->is_native()) { Bytecodes::Code code = info->scope()->method()->java_code_at_bci(info->stack()->bci()); switch (code) { diff --git a/src/hotspot/share/c1/c1_MacroAssembler.hpp b/src/hotspot/share/c1/c1_MacroAssembler.hpp index 6a8304bd405fa..1e193ce086961 100644 --- a/src/hotspot/share/c1/c1_MacroAssembler.hpp +++ b/src/hotspot/share/c1/c1_MacroAssembler.hpp @@ -38,7 +38,6 @@ class C1_MacroAssembler: public MacroAssembler { //---------------------------------------------------- void explicit_null_check(Register base); - void inline_cache_check(Register receiver, Register iCache); void build_frame(int frame_size_in_bytes, int bang_size_in_bytes); void remove_frame(int frame_size_in_bytes); diff --git a/src/hotspot/share/c1/c1_Optimizer.cpp b/src/hotspot/share/c1/c1_Optimizer.cpp index 6cd282d02ad7e..dd428a5895bc4 100644 --- a/src/hotspot/share/c1/c1_Optimizer.cpp +++ b/src/hotspot/share/c1/c1_Optimizer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -335,7 +335,7 @@ void Optimizer::eliminate_conditional_expressions() { } // This removes others' relation to block, but doesn't empty block's lists -void disconnect_from_graph(BlockBegin* block) { +static void disconnect_from_graph(BlockBegin* block) { for (int p = 0; p < block->number_of_preds(); p++) { BlockBegin* pred = block->pred_at(p); int idx; diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 5a0bf2e61b5d0..f6e02594b5c7b 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -1664,9 +1664,9 @@ void FileMapInfo::close() { /* * Same as os::map_memory() but also pretouches if AlwaysPreTouch is enabled. */ -char* map_memory(int fd, const char* file_name, size_t file_offset, - char *addr, size_t bytes, bool read_only, - bool allow_exec, MEMFLAGS flags = mtNone) { +static char* map_memory(int fd, const char* file_name, size_t file_offset, + char *addr, size_t bytes, bool read_only, + bool allow_exec, MEMFLAGS flags = mtNone) { char* mem = os::map_memory(fd, file_name, file_offset, addr, bytes, AlwaysPreTouch ? false : read_only, allow_exec, flags); diff --git a/src/hotspot/share/classfile/altHashing.cpp b/src/hotspot/share/classfile/altHashing.cpp index 158a8a232a7b4..1d43d6ebf1ed0 100644 --- a/src/hotspot/share/classfile/altHashing.cpp +++ b/src/hotspot/share/classfile/altHashing.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -120,7 +120,7 @@ static void halfsiphash_init64(uint32_t v[4], uint64_t seed) { v[1] ^= 0xee; } -uint32_t halfsiphash_finish32(uint32_t v[4], int rounds) { +static uint32_t halfsiphash_finish32(uint32_t v[4], int rounds) { v[2] ^= 0xff; halfsiphash_rounds(v, rounds); return (v[1] ^ v[3]); diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index 43aa82b67f85f..9ce49b71734b1 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -134,7 +134,8 @@ ClassPathEntry* ClassLoader::_last_module_path_entry = nullptr; #endif // helper routines -bool string_starts_with(const char* str, const char* str_to_find) { +#if INCLUDE_CDS +static bool string_starts_with(const char* str, const char* str_to_find) { size_t str_len = strlen(str); size_t str_to_find_len = strlen(str_to_find); if (str_to_find_len > str_len) { @@ -142,6 +143,7 @@ bool string_starts_with(const char* str, const char* str_to_find) { } return (strncmp(str, str_to_find, str_to_find_len) == 0); } +#endif static const char* get_jimage_version_string() { static char version_string[10] = ""; @@ -1009,8 +1011,8 @@ const char* ClassLoader::file_name_for_class_name(const char* class_name, return file_name; } -ClassPathEntry* find_first_module_cpe(ModuleEntry* mod_entry, - const GrowableArray* const module_list) { +static ClassPathEntry* find_first_module_cpe(ModuleEntry* mod_entry, + const GrowableArray* const module_list) { int num_of_entries = module_list->length(); const Symbol* class_module_name = mod_entry->name(); @@ -1355,7 +1357,7 @@ void ClassLoader::initialize(TRAPS) { setup_bootstrap_search_path(THREAD); } -char* lookup_vm_resource(JImageFile *jimage, const char *jimage_version, const char *path) { +static char* lookup_vm_resource(JImageFile *jimage, const char *jimage_version, const char *path) { jlong size; JImageLocationRef location = (*JImageFindResource)(jimage, "java.base", jimage_version, path, &size); if (location == 0) diff --git a/src/hotspot/share/classfile/loaderConstraints.cpp b/src/hotspot/share/classfile/loaderConstraints.cpp index e6021e00d3391..99d0c07ed42d4 100644 --- a/src/hotspot/share/classfile/loaderConstraints.cpp +++ b/src/hotspot/share/classfile/loaderConstraints.cpp @@ -296,8 +296,8 @@ void LoaderConstraintTable::purge_loader_constraints() { _loader_constraint_table->unlink(&purge); } -void log_ldr_constraint_msg(Symbol* class_name, const char* reason, - ClassLoaderData* loader1, ClassLoaderData* loader2) { +static void log_ldr_constraint_msg(Symbol* class_name, const char* reason, + ClassLoaderData* loader1, ClassLoaderData* loader2) { LogTarget(Info, class, loader, constraints) lt; if (lt.is_enabled()) { ResourceMark rm; diff --git a/src/hotspot/share/classfile/modules.cpp b/src/hotspot/share/classfile/modules.cpp index bd4be93b86877..4664d9565d353 100644 --- a/src/hotspot/share/classfile/modules.cpp +++ b/src/hotspot/share/classfile/modules.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -259,7 +259,7 @@ static void define_javabase_module(Handle module_handle, jstring version, jstrin } // Caller needs ResourceMark. -void throw_dup_pkg_exception(const char* module_name, PackageEntry* package, TRAPS) { +static void throw_dup_pkg_exception(const char* module_name, PackageEntry* package, TRAPS) { const char* package_name = package->name()->as_C_string(); if (package->module()->is_named()) { THROW_MSG(vmSymbols::java_lang_IllegalStateException(), diff --git a/src/hotspot/share/classfile/placeholders.cpp b/src/hotspot/share/classfile/placeholders.cpp index 1bb5f87870417..a6a86473ea794 100644 --- a/src/hotspot/share/classfile/placeholders.cpp +++ b/src/hotspot/share/classfile/placeholders.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -198,8 +198,8 @@ void PlaceholderEntry::set_supername(Symbol* supername) { // All threads examining the placeholder table must hold the // SystemDictionary_lock, so we don't need special precautions // on store ordering here. -PlaceholderEntry* add_entry(Symbol* class_name, ClassLoaderData* loader_data, - Symbol* supername){ +static PlaceholderEntry* add_entry(Symbol* class_name, ClassLoaderData* loader_data, + Symbol* supername){ assert_locked_or_safepoint(SystemDictionary_lock); assert(class_name != nullptr, "adding nullptr obj"); @@ -213,7 +213,7 @@ PlaceholderEntry* add_entry(Symbol* class_name, ClassLoaderData* loader_data, } // Remove a placeholder object. -void remove_entry(Symbol* class_name, ClassLoaderData* loader_data) { +static void remove_entry(Symbol* class_name, ClassLoaderData* loader_data) { assert_locked_or_safepoint(SystemDictionary_lock); PlaceholderKey key(class_name, loader_data); diff --git a/src/hotspot/share/classfile/stringTable.cpp b/src/hotspot/share/classfile/stringTable.cpp index 9e96340d82b9c..be2971288ef12 100644 --- a/src/hotspot/share/classfile/stringTable.cpp +++ b/src/hotspot/share/classfile/stringTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,7 +122,7 @@ volatile bool _alt_hash = false; static bool _rehashed = false; static uint64_t _alt_hash_seed = 0; -unsigned int hash_string(const jchar* s, int len, bool useAlt) { +static unsigned int hash_string(const jchar* s, int len, bool useAlt) { return useAlt ? AltHashing::halfsiphash_32(_alt_hash_seed, s, len) : java_lang_String::hash_code(s, len); diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index 82c20a962ce14..f2a88f00e0d9e 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -212,13 +212,13 @@ void SystemDictionary::set_platform_loader(ClassLoaderData *cld) { // ---------------------------------------------------------------------------- // Parallel class loading check -bool is_parallelCapable(Handle class_loader) { +static bool is_parallelCapable(Handle class_loader) { if (class_loader.is_null()) return true; return java_lang_ClassLoader::parallelCapable(class_loader()); } // ---------------------------------------------------------------------------- // ParallelDefineClass flag does not apply to bootclass loader -bool is_parallelDefine(Handle class_loader) { +static bool is_parallelDefine(Handle class_loader) { if (class_loader.is_null()) return false; if (AllowParallelDefineClass && java_lang_ClassLoader::parallelCapable(class_loader())) { return true; @@ -280,7 +280,7 @@ Symbol* SystemDictionary::class_name_symbol(const char* name, Symbol* exception, #ifdef ASSERT // Used to verify that class loading succeeded in adding k to the dictionary. -void verify_dictionary_entry(Symbol* class_name, InstanceKlass* k) { +static void verify_dictionary_entry(Symbol* class_name, InstanceKlass* k) { MutexLocker mu(SystemDictionary_lock); ClassLoaderData* loader_data = k->class_loader_data(); Dictionary* dictionary = loader_data->dictionary(); diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index 297483526846c..44d7da5c4a4f1 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1348,7 +1348,7 @@ void SystemDictionaryShared::update_shared_entry(InstanceKlass* k, int id) { info->_id = id; } -const char* class_loader_name_for_shared(Klass* k) { +static const char* class_loader_name_for_shared(Klass* k) { assert(k != nullptr, "Sanity"); assert(k->is_shared(), "Must be"); assert(k->is_instance_klass(), "Must be"); diff --git a/src/hotspot/share/code/codeBlob.cpp b/src/hotspot/share/code/codeBlob.cpp index b30a88e90cb48..d24e29c288d5c 100644 --- a/src/hotspot/share/code/codeBlob.cpp +++ b/src/hotspot/share/code/codeBlob.cpp @@ -25,7 +25,6 @@ #include "precompiled.hpp" #include "code/codeBlob.hpp" #include "code/codeCache.hpp" -#include "code/icBuffer.hpp" #include "code/relocInfo.hpp" #include "code/vtableStubs.hpp" #include "compiler/disassembler.hpp" @@ -649,11 +648,6 @@ void CodeBlob::dump_for_addr(address addr, outputStream* st, bool verbose) const st->print_cr(INTPTR_FORMAT " is pointing to an (unnamed) stub routine", p2i(addr)); return; } - // the InlineCacheBuffer is using stubs generated into a buffer blob - if (InlineCacheBuffer::contains(addr)) { - st->print_cr(INTPTR_FORMAT " is pointing into InlineCacheBuffer", p2i(addr)); - return; - } VtableStub* v = VtableStubs::stub_containing(addr); if (v != nullptr) { st->print_cr(INTPTR_FORMAT " is at entry_point+%d in a vtable stub", p2i(addr), (int)(addr - v->entry_point())); diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index bf8c1d84e71a0..cdc9f3f50dc15 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -29,7 +29,6 @@ #include "code/compiledIC.hpp" #include "code/dependencies.hpp" #include "code/dependencyContext.hpp" -#include "code/icBuffer.hpp" #include "code/nmethod.hpp" #include "code/pcDesc.hpp" #include "compiler/compilationPolicy.hpp" @@ -913,23 +912,6 @@ void CodeCache::verify_clean_inline_caches() { #endif } -void CodeCache::verify_icholder_relocations() { -#ifdef ASSERT - // make sure that we aren't leaking icholders - int count = 0; - FOR_ALL_HEAPS(heap) { - FOR_ALL_BLOBS(cb, *heap) { - CompiledMethod *nm = cb->as_compiled_method_or_null(); - if (nm != nullptr) { - count += nm->verify_icholder_relocations(); - } - } - } - assert(count + InlineCacheBuffer::pending_icholder_count() + CompiledICHolder::live_not_claimed_count() == - CompiledICHolder::live_count(), "must agree"); -#endif -} - // Defer freeing of concurrently cleaned ExceptionCache entries until // after a global handshake operation. void CodeCache::release_exception_cache(ExceptionCache* entry) { diff --git a/src/hotspot/share/code/codeCache.hpp b/src/hotspot/share/code/codeCache.hpp index 103268c8ffcd1..d1c91727bf124 100644 --- a/src/hotspot/share/code/codeCache.hpp +++ b/src/hotspot/share/code/codeCache.hpp @@ -294,7 +294,6 @@ class CodeCache : AllStatic { } static void verify_clean_inline_caches(); - static void verify_icholder_relocations(); // Deoptimization private: diff --git a/src/hotspot/share/code/compiledIC.cpp b/src/hotspot/share/code/compiledIC.cpp index c5063560ee570..250ef063a2a33 100644 --- a/src/hotspot/share/code/compiledIC.cpp +++ b/src/hotspot/share/code/compiledIC.cpp @@ -26,27 +26,19 @@ #include "code/codeBehaviours.hpp" #include "code/codeCache.hpp" #include "code/compiledIC.hpp" -#include "code/icBuffer.hpp" #include "code/nmethod.hpp" #include "code/vtableStubs.hpp" -#include "interpreter/interpreter.hpp" -#include "interpreter/linkResolver.hpp" -#include "memory/metadataFactory.hpp" -#include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" +#include "oops/compressedKlass.hpp" #include "oops/klass.inline.hpp" #include "oops/method.inline.hpp" -#include "oops/oop.inline.hpp" -#include "oops/symbol.hpp" +#include "runtime/atomic.hpp" #include "runtime/continuationEntry.hpp" #include "runtime/handles.inline.hpp" -#include "runtime/icache.hpp" -#include "runtime/safepoint.hpp" +#include "runtime/interfaceSupport.inline.hpp" #include "runtime/sharedRuntime.hpp" -#include "runtime/stubRoutines.hpp" #include "sanitizers/leak.hpp" -#include "utilities/events.hpp" // Every time a compiled IC is changed or its type is being accessed, @@ -75,191 +67,175 @@ bool CompiledICLocker::is_safe(address code) { return CompiledICProtectionBehaviour::current()->is_safe(cm); } -//----------------------------------------------------------------------------- -// Low-level access to an inline cache. Private, since they might not be -// MT-safe to use. +CompiledICData::CompiledICData() + : _speculated_method(), + _speculated_klass(), + _itable_defc_klass(), + _itable_refc_klass(), + _is_initialized() {} -void* CompiledIC::cached_value() const { - assert(CompiledICLocker::is_safe(_method), "mt unsafe call"); - assert (!is_optimized(), "an optimized virtual call does not have a cached metadata"); - - if (!is_in_transition_state()) { - void* data = get_data(); - // If we let the metadata value here be initialized to zero... - assert(data != nullptr || Universe::non_oop_word() == nullptr, - "no raw nulls in CompiledIC metadatas, because of patching races"); - return (data == (void*)Universe::non_oop_word()) ? nullptr : data; +// Inline cache callsite info is initialized once the first time it is resolved +void CompiledICData::initialize(CallInfo* call_info, Klass* receiver_klass) { + _speculated_method = call_info->selected_method(); + if (UseCompressedClassPointers) { + _speculated_klass = (uintptr_t)CompressedKlassPointers::encode_not_null(receiver_klass); } else { - return InlineCacheBuffer::cached_value_for((CompiledIC *)this); + _speculated_klass = (uintptr_t)receiver_klass; } + if (call_info->call_kind() == CallInfo::itable_call) { + _itable_defc_klass = call_info->resolved_method()->method_holder(); + _itable_refc_klass = call_info->resolved_klass(); + } + _is_initialized = true; } +bool CompiledICData::is_speculated_klass_unloaded() const { + return is_initialized() && _speculated_klass == 0; +} -void CompiledIC::internal_set_ic_destination(address entry_point, bool is_icstub, void* cache, bool is_icholder) { - assert(entry_point != nullptr, "must set legal entry point"); - assert(CompiledICLocker::is_safe(_method), "mt unsafe call"); - assert (!is_optimized() || cache == nullptr, "an optimized virtual call does not have a cached metadata"); - assert (cache == nullptr || cache != (Metadata*)badOopVal, "invalid metadata"); - - assert(!is_icholder || is_icholder_entry(entry_point), "must be"); - - // Don't use ic_destination for this test since that forwards - // through ICBuffer instead of returning the actual current state of - // the CompiledIC. - if (is_icholder_entry(_call->destination())) { - // When patching for the ICStub case the cached value isn't - // overwritten until the ICStub copied into the CompiledIC during - // the next safepoint. Make sure that the CompiledICHolder* is - // marked for release at this point since it won't be identifiable - // once the entry point is overwritten. - InlineCacheBuffer::queue_for_release((CompiledICHolder*)get_data()); +void CompiledICData::clean_metadata() { + if (!is_initialized() || is_speculated_klass_unloaded()) { + return; } - if (TraceCompiledIC) { - tty->print(" "); - print_compiled_ic(); - tty->print(" changing destination to " INTPTR_FORMAT, p2i(entry_point)); - if (!is_optimized()) { - tty->print(" changing cached %s to " INTPTR_FORMAT, is_icholder ? "icholder" : "metadata", p2i((address)cache)); - } - if (is_icstub) { - tty->print(" (icstub)"); - } - tty->cr(); + // GC cleaning doesn't need to change the state of the inline cache, + // only nuke stale speculated metadata if it gets unloaded. If the + // inline cache is monomorphic, the unverified entries will miss, and + // subsequent miss handlers will upgrade the callsite to megamorphic, + // which makes sense as it obviously is megamorphic then. + if (!speculated_klass()->is_loader_alive()) { + Atomic::store(&_speculated_klass, (uintptr_t)0); + Atomic::store(&_speculated_method, (Method*)nullptr); } -#ifdef ASSERT - { - CodeBlob* cb = CodeCache::find_blob(_call->instruction_address()); - assert(cb != nullptr && cb->is_compiled(), "must be compiled"); - } -#endif - _call->set_destination_mt_safe(entry_point); + assert(_speculated_method == nullptr || _speculated_method->method_holder()->is_loader_alive(), + "Speculated method is not unloaded despite class being unloaded"); +} - if (is_optimized() || is_icstub) { - // Optimized call sites don't have a cache value and ICStub call - // sites only change the entry point. Changing the value in that - // case could lead to MT safety issues. - assert(cache == nullptr, "must be null"); +void CompiledICData::metadata_do(MetadataClosure* cl) { + if (!is_initialized()) { return; } - if (cache == nullptr) cache = Universe::non_oop_word(); - - set_data((intptr_t)cache); -} - - -void CompiledIC::set_ic_destination(ICStub* stub) { - internal_set_ic_destination(stub->code_begin(), true, nullptr, false); + if (!is_speculated_klass_unloaded()) { + cl->do_metadata(_speculated_method); + cl->do_metadata(speculated_klass()); + } + if (_itable_refc_klass != nullptr) { + cl->do_metadata(_itable_refc_klass); + } + if (_itable_defc_klass != nullptr) { + cl->do_metadata(_itable_defc_klass); + } } +Klass* CompiledICData::speculated_klass() const { + if (is_speculated_klass_unloaded()) { + return nullptr; + } - -address CompiledIC::ic_destination() const { - assert(CompiledICLocker::is_safe(_method), "mt unsafe call"); - if (!is_in_transition_state()) { - return _call->destination(); + if (UseCompressedClassPointers) { + return CompressedKlassPointers::decode_not_null((narrowKlass)_speculated_klass); } else { - return InlineCacheBuffer::ic_destination_for((CompiledIC *)this); + return (Klass*)_speculated_klass; } } +//----------------------------------------------------------------------------- +// High-level access to an inline cache. Guaranteed to be MT-safe. -bool CompiledIC::is_in_transition_state() const { - assert(CompiledICLocker::is_safe(_method), "mt unsafe call"); - return InlineCacheBuffer::contains(_call->destination());; +CompiledICData* CompiledIC::data() const { + return _data; } +CompiledICData* data_from_reloc_iter(RelocIterator* iter) { + assert(iter->type() == relocInfo::virtual_call_type, "wrong reloc. info"); + + virtual_call_Relocation* r = iter->virtual_call_reloc(); + NativeMovConstReg* value = nativeMovConstReg_at(r->cached_value()); + + return (CompiledICData*)value->data(); +} -bool CompiledIC::is_icholder_call() const { +CompiledIC::CompiledIC(RelocIterator* iter) + : _method(iter->code()), + _data(data_from_reloc_iter(iter)), + _call(nativeCall_at(iter->addr())) +{ + assert(_method != nullptr, "must pass compiled method"); + assert(_method->contains(iter->addr()), "must be in compiled method"); assert(CompiledICLocker::is_safe(_method), "mt unsafe call"); - return !_is_optimized && is_icholder_entry(ic_destination()); } -// Returns native address of 'call' instruction in inline-cache. Used by -// the InlineCacheBuffer when it needs to find the stub. -address CompiledIC::stub_address() const { - assert(is_in_transition_state(), "should only be called when we are in a transition state"); - return _call->destination(); +CompiledIC* CompiledIC_before(CompiledMethod* nm, address return_addr) { + address call_site = nativeCall_before(return_addr)->instruction_address(); + return CompiledIC_at(nm, call_site); } -// Clears the IC stub if the compiled IC is in transition state -void CompiledIC::clear_ic_stub() { - if (is_in_transition_state()) { - ICStub* stub = ICStub::from_destination_address(stub_address()); - stub->clear(); - } +CompiledIC* CompiledIC_at(CompiledMethod* nm, address call_site) { + RelocIterator iter(nm, call_site, call_site + 1); + iter.next(); + return CompiledIC_at(&iter); } -//----------------------------------------------------------------------------- -// High-level access to an inline cache. Guaranteed to be MT-safe. +CompiledIC* CompiledIC_at(Relocation* call_reloc) { + address call_site = call_reloc->addr(); + CompiledMethod* cm = CodeCache::find_blob(call_reloc->addr())->as_compiled_method(); + return CompiledIC_at(cm, call_site); +} -void CompiledIC::initialize_from_iter(RelocIterator* iter) { - assert(iter->addr() == _call->instruction_address(), "must find ic_call"); +CompiledIC* CompiledIC_at(RelocIterator* reloc_iter) { + CompiledIC* c_ic = new CompiledIC(reloc_iter); + c_ic->verify(); + return c_ic; +} - if (iter->type() == relocInfo::virtual_call_type) { - virtual_call_Relocation* r = iter->virtual_call_reloc(); - _is_optimized = false; - _value = _call->get_load_instruction(r); - } else { - assert(iter->type() == relocInfo::opt_virtual_call_type, "must be a virtual call"); - _is_optimized = true; - _value = nullptr; +void CompiledIC::ensure_initialized(CallInfo* call_info, Klass* receiver_klass) { + if (!_data->is_initialized()) { + _data->initialize(call_info, receiver_klass); } } -CompiledIC::CompiledIC(CompiledMethod* cm, NativeCall* call) - : _method(cm) -{ - _call = _method->call_wrapper_at((address) call); - address ic_call = _call->instruction_address(); - - assert(ic_call != nullptr, "ic_call address must be set"); - assert(cm != nullptr, "must pass compiled method"); - assert(cm->contains(ic_call), "must be in compiled method"); - - // Search for the ic_call at the given address. - RelocIterator iter(cm, ic_call, ic_call+1); - bool ret = iter.next(); - assert(ret == true, "relocInfo must exist at this address"); - assert(iter.addr() == ic_call, "must find ic_call"); - - initialize_from_iter(&iter); +void CompiledIC::set_to_clean() { + log_debug(inlinecache)("IC@" INTPTR_FORMAT ": set to clean", p2i(_call->instruction_address())); + _call->set_destination_mt_safe(SharedRuntime::get_resolve_virtual_call_stub()); } -CompiledIC::CompiledIC(RelocIterator* iter) - : _method(iter->code()) -{ - _call = _method->call_wrapper_at(iter->addr()); - address ic_call = _call->instruction_address(); +void CompiledIC::set_to_monomorphic() { + assert(data()->is_initialized(), "must be initialized"); + Method* method = data()->speculated_method(); + CompiledMethod* code = method->code(); + address entry; + bool to_compiled = code != nullptr && code->is_in_use() && !code->is_unloading(); + + if (to_compiled) { + entry = code->entry_point(); + } else { + entry = method->get_c2i_unverified_entry(); + } - CompiledMethod* nm = iter->code(); - assert(ic_call != nullptr, "ic_call address must be set"); - assert(nm != nullptr, "must pass compiled method"); - assert(nm->contains(ic_call), "must be in compiled method"); + log_trace(inlinecache)("IC@" INTPTR_FORMAT ": monomorphic to %s: %s", + p2i(_call->instruction_address()), + to_compiled ? "compiled" : "interpreter", + method->print_value_string()); - initialize_from_iter(iter); + _call->set_destination_mt_safe(entry); } -// This function may fail for two reasons: either due to running out of vtable -// stubs, or due to running out of IC stubs in an attempted transition to a -// transitional state. The needs_ic_stub_refill value will be set if the failure -// was due to running out of IC stubs, in which case the caller will refill IC -// stubs and retry. -bool CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, - bool& needs_ic_stub_refill, TRAPS) { - assert(CompiledICLocker::is_safe(_method), "mt unsafe call"); - assert(!is_optimized(), "cannot set an optimized virtual call to megamorphic"); - assert(is_call_to_compiled() || is_call_to_interpreted(), "going directly to megamorphic?"); +void CompiledIC::set_to_megamorphic(CallInfo* call_info) { + assert(data()->is_initialized(), "must be initialized"); address entry; - if (call_info->call_kind() == CallInfo::itable_call) { - assert(bytecode == Bytecodes::_invokeinterface, ""); + if (call_info->call_kind() == CallInfo::direct_call) { + // C1 sometimes compiles a callsite before the target method is loaded, resulting in + // dynamically bound callsites that should really be statically bound. However, the + // target method might not have a vtable or itable. We just wait for better code to arrive + return; + } else if (call_info->call_kind() == CallInfo::itable_call) { int itable_index = call_info->itable_index(); entry = VtableStubs::find_itable_stub(itable_index); if (entry == nullptr) { - return false; + return; } #ifdef ASSERT int index = call_info->resolved_method()->itable_index(); @@ -267,401 +243,151 @@ bool CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecod InstanceKlass* k = call_info->resolved_method()->method_holder(); assert(k->verify_itable_index(itable_index), "sanity check"); #endif //ASSERT - CompiledICHolder* holder = new CompiledICHolder(call_info->resolved_method()->method_holder(), - call_info->resolved_klass(), false); - holder->claim(); - if (!InlineCacheBuffer::create_transition_stub(this, holder, entry)) { - delete holder; - needs_ic_stub_refill = true; - return false; - } - // LSan appears unable to follow malloc-based memory consistently when embedded as an immediate - // in generated machine code. So we have to ignore it. - LSAN_IGNORE_OBJECT(holder); } else { - assert(call_info->call_kind() == CallInfo::vtable_call, "either itable or vtable"); + assert(call_info->call_kind() == CallInfo::vtable_call, "what else?"); // Can be different than selected_method->vtable_index(), due to package-private etc. int vtable_index = call_info->vtable_index(); assert(call_info->resolved_klass()->verify_vtable_index(vtable_index), "sanity check"); entry = VtableStubs::find_vtable_stub(vtable_index); if (entry == nullptr) { - return false; + return; } - if (!InlineCacheBuffer::create_transition_stub(this, nullptr, entry)) { - needs_ic_stub_refill = true; - return false; - } - } - - { - ResourceMark rm; - assert(call_info->selected_method() != nullptr, "Unexpected null selected method"); - log_trace(inlinecache)("IC@" INTPTR_FORMAT ": to megamorphic %s entry: " INTPTR_FORMAT, - p2i(instruction_address()), call_info->selected_method()->print_value_string(), p2i(entry)); } - // We can't check this anymore. With lazy deopt we could have already - // cleaned this IC entry before we even return. This is possible if - // we ran out of space in the inline cache buffer trying to do the - // set_next and we safepointed to free up space. This is a benign - // race because the IC entry was complete when we safepointed so - // cleaning it immediately is harmless. - // assert(is_megamorphic(), "sanity check"); - return true; -} - + log_trace(inlinecache)("IC@" INTPTR_FORMAT ": to megamorphic %s entry: " INTPTR_FORMAT, + p2i(_call->instruction_address()), call_info->selected_method()->print_value_string(), p2i(entry)); -// true if destination is megamorphic stub -bool CompiledIC::is_megamorphic() const { - assert(CompiledICLocker::is_safe(_method), "mt unsafe call"); - assert(!is_optimized(), "an optimized call cannot be megamorphic"); - - // Cannot rely on cached_value. It is either an interface or a method. - return VtableStubs::entry_point(ic_destination()) != nullptr; + _call->set_destination_mt_safe(entry); + assert(is_megamorphic(), "sanity check"); } -bool CompiledIC::is_call_to_compiled() const { - assert(CompiledICLocker::is_safe(_method), "mt unsafe call"); - - CodeBlob* cb = CodeCache::find_blob(ic_destination()); - bool is_monomorphic = (cb != nullptr && cb->is_compiled()); - // Check that the cached_value is a klass for non-optimized monomorphic calls - // This assertion is invalid for compiler1: a call that does not look optimized (no static stub) can be used - // for calling directly to vep without using the inline cache (i.e., cached_value == nullptr). - // For JVMCI this occurs because CHA is only used to improve inlining so call sites which could be optimized - // virtuals because there are no currently loaded subclasses of a type are left as virtual call sites. -#ifdef ASSERT - CodeBlob* caller = CodeCache::find_blob(instruction_address()); - bool is_c1_or_jvmci_method = caller->is_compiled_by_c1() || caller->is_compiled_by_jvmci(); - assert( is_c1_or_jvmci_method || - !is_monomorphic || - is_optimized() || - (cached_metadata() != nullptr && cached_metadata()->is_klass()), "sanity check"); -#endif // ASSERT - return is_monomorphic; -} +void CompiledIC::update(CallInfo* call_info, Klass* receiver_klass) { + // If this is the first time we fix the inline cache, we ensure it's initialized + ensure_initialized(call_info, receiver_klass); + if (is_megamorphic()) { + // Terminal state for the inline cache + return; + } -bool CompiledIC::is_call_to_interpreted() const { - assert(CompiledICLocker::is_safe(_method), "mt unsafe call"); - // Call to interpreter if destination is either calling to a stub (if it - // is optimized), or calling to an I2C blob - bool is_call_to_interpreted = false; - if (!is_optimized()) { - CodeBlob* cb = CodeCache::find_blob(ic_destination()); - is_call_to_interpreted = (cb != nullptr && cb->is_adapter_blob()); - assert(!is_call_to_interpreted || (is_icholder_call() && cached_icholder() != nullptr), "sanity check"); + if (is_speculated_klass(receiver_klass)) { + // If the speculated class matches the receiver klass, we can speculate that will + // continue to be the case with a monomorphic inline cache + set_to_monomorphic(); } else { - // Check if we are calling into our own codeblob (i.e., to a stub) - address dest = ic_destination(); -#ifdef ASSERT - { - _call->verify_resolve_call(dest); - } -#endif /* ASSERT */ - is_call_to_interpreted = _call->is_call_to_interpreted(dest); + // If the dynamic type speculation fails, we try to transform to a megamorphic state + // for the inline cache using stubs to dispatch in tables + set_to_megamorphic(call_info); } - return is_call_to_interpreted; } -bool CompiledIC::set_to_clean(bool in_use) { - assert(CompiledICLocker::is_safe(_method), "mt unsafe call"); - if (TraceInlineCacheClearing) { - tty->print_cr("IC@" INTPTR_FORMAT ": set to clean", p2i(instruction_address())); - print(); - } - log_trace(inlinecache)("IC@" INTPTR_FORMAT ": set to clean", p2i(instruction_address())); - - address entry = _call->get_resolve_call_stub(is_optimized()); - - bool safe_transition = _call->is_safe_for_patching() || !in_use || is_optimized() || SafepointSynchronize::is_at_safepoint(); +bool CompiledIC::is_clean() const { + return destination() == SharedRuntime::get_resolve_virtual_call_stub(); +} - if (safe_transition) { - // Kill any leftover stub we might have too - clear_ic_stub(); - if (is_optimized()) { - set_ic_destination(entry); - } else { - set_ic_destination_and_value(entry, (void*)nullptr); - } - } else { - // Unsafe transition - create stub. - if (!InlineCacheBuffer::create_transition_stub(this, nullptr, entry)) { - return false; - } - } - // We can't check this anymore. With lazy deopt we could have already - // cleaned this IC entry before we even return. This is possible if - // we ran out of space in the inline cache buffer trying to do the - // set_next and we safepointed to free up space. This is a benign - // race because the IC entry was complete when we safepointed so - // cleaning it immediately is harmless. - // assert(is_clean(), "sanity check"); - return true; +bool CompiledIC::is_monomorphic() const { + return !is_clean() && !is_megamorphic(); } -bool CompiledIC::is_clean() const { - assert(CompiledICLocker::is_safe(_method), "mt unsafe call"); - bool is_clean = false; - address dest = ic_destination(); - is_clean = dest == _call->get_resolve_call_stub(is_optimized()); - assert(!is_clean || is_optimized() || cached_value() == nullptr, "sanity check"); - return is_clean; +bool CompiledIC::is_megamorphic() const { + return VtableStubs::entry_point(destination()) != nullptr;; } -bool CompiledIC::set_to_monomorphic(CompiledICInfo& info) { - assert(CompiledICLocker::is_safe(_method), "mt unsafe call"); - // Updating a cache to the wrong entry can cause bugs that are very hard - // to track down - if cache entry gets invalid - we just clean it. In - // this way it is always the same code path that is responsible for - // updating and resolving an inline cache - // - // The above is no longer true. SharedRuntime::fixup_callers_callsite will change optimized - // callsites. In addition ic_miss code will update a site to monomorphic if it determines - // that an monomorphic call to the interpreter can now be monomorphic to compiled code. - // - // In both of these cases the only thing being modified is the jump/call target and these - // transitions are mt_safe - - Thread *thread = Thread::current(); - if (info.to_interpreter()) { - // Call to interpreter - if (info.is_optimized() && is_optimized()) { - assert(is_clean(), "unsafe IC path"); - // the call analysis (callee structure) specifies that the call is optimized - // (either because of CHA or the static target is final) - // At code generation time, this call has been emitted as static call - // Call via stub - assert(info.cached_metadata() != nullptr && info.cached_metadata()->is_method(), "sanity check"); - methodHandle method (thread, (Method*)info.cached_metadata()); - _call->set_to_interpreted(method, info); - - { - ResourceMark rm(thread); - log_trace(inlinecache)("IC@" INTPTR_FORMAT ": monomorphic to interpreter: %s", - p2i(instruction_address()), - method->print_value_string()); - } - } else { - // Call via method-klass-holder - CompiledICHolder* holder = info.claim_cached_icholder(); - if (!InlineCacheBuffer::create_transition_stub(this, holder, info.entry())) { - delete holder; - return false; - } - // LSan appears unable to follow malloc-based memory consistently when embedded as an - // immediate in generated machine code. So we have to ignore it. - LSAN_IGNORE_OBJECT(holder); - { - ResourceMark rm(thread); - log_trace(inlinecache)("IC@" INTPTR_FORMAT ": monomorphic to interpreter via icholder ", p2i(instruction_address())); - } - } - } else { - // Call to compiled code - bool static_bound = info.is_optimized() || (info.cached_metadata() == nullptr); -#ifdef ASSERT - CodeBlob* cb = CodeCache::find_blob(info.entry()); - assert (cb != nullptr && cb->is_compiled(), "must be compiled!"); -#endif /* ASSERT */ - - // This is MT safe if we come from a clean-cache and go through a - // non-verified entry point - bool safe = SafepointSynchronize::is_at_safepoint() || - (!is_in_transition_state() && (info.is_optimized() || static_bound || is_clean())); - - if (!safe) { - if (!InlineCacheBuffer::create_transition_stub(this, info.cached_metadata(), info.entry())) { - return false; - } - } else { - if (is_optimized()) { - set_ic_destination(info.entry()); - } else { - set_ic_destination_and_value(info.entry(), info.cached_metadata()); - } - } +bool CompiledIC::is_speculated_klass(Klass* receiver_klass) { + return data()->speculated_klass() == receiver_klass; +} - { - ResourceMark rm(thread); - assert(info.cached_metadata() == nullptr || info.cached_metadata()->is_klass(), "must be"); - log_trace(inlinecache)("IC@" INTPTR_FORMAT ": monomorphic to compiled (rcvr klass = %s) %s", - p2i(instruction_address()), - (info.cached_metadata() != nullptr) ? ((Klass*)info.cached_metadata())->print_value_string() : "nullptr", - (safe) ? "" : " via stub"); - } - } - // We can't check this anymore. With lazy deopt we could have already - // cleaned this IC entry before we even return. This is possible if - // we ran out of space in the inline cache buffer trying to do the - // set_next and we safepointed to free up space. This is a benign - // race because the IC entry was complete when we safepointed so - // cleaning it immediately is harmless. - // assert(is_call_to_compiled() || is_call_to_interpreted(), "sanity check"); - return true; -} - - -// is_optimized: Compiler has generated an optimized call (i.e. fixed, no inline cache) -// static_bound: The call can be static bound. If it isn't also optimized, the property -// wasn't provable at time of compilation. An optimized call will have any necessary -// null check, while a static_bound won't. A static_bound (but not optimized) must -// therefore use the unverified entry point. -void CompiledIC::compute_monomorphic_entry(const methodHandle& method, - Klass* receiver_klass, - bool is_optimized, - bool static_bound, - bool caller_is_nmethod, - CompiledICInfo& info, - TRAPS) { - CompiledMethod* method_code = method->code(); - - address entry = nullptr; - if (method_code != nullptr && method_code->is_in_use() && !method_code->is_unloading()) { - assert(method_code->is_compiled(), "must be compiled"); - // Call to compiled code - // - // Note: the following problem exists with Compiler1: - // - at compile time we may or may not know if the destination is final - // - if we know that the destination is final (is_optimized), we will emit - // an optimized virtual call (no inline cache), and need a Method* to make - // a call to the interpreter - // - if we don't know if the destination is final, we emit a standard - // virtual call, and use CompiledICHolder to call interpreted code - // (no static call stub has been generated) - // - In the case that we here notice the call is static bound we - // convert the call into what looks to be an optimized virtual call, - // but we must use the unverified entry point (since there will be no - // null check on a call when the target isn't loaded). - // This causes problems when verifying the IC because - // it looks vanilla but is optimized. Code in is_call_to_interpreted - // is aware of this and weakens its asserts. - if (is_optimized) { - entry = method_code->verified_entry_point(); - } else { - entry = method_code->entry_point(); - } - } - if (entry != nullptr) { - // Call to near compiled code. - info.set_compiled_entry(entry, is_optimized ? nullptr : receiver_klass, is_optimized); - } else { - if (is_optimized) { - // Use stub entry - info.set_interpreter_entry(method()->get_c2i_entry(), method()); - } else { - // Use icholder entry - assert(method_code == nullptr || method_code->is_compiled(), "must be compiled"); - CompiledICHolder* holder = new CompiledICHolder(method(), receiver_klass); - info.set_icholder_entry(method()->get_c2i_unverified_entry(), holder); - } - } - assert(info.is_optimized() == is_optimized, "must agree"); +// GC support +void CompiledIC::clean_metadata() { + data()->clean_metadata(); } +void CompiledIC::metadata_do(MetadataClosure* cl) { + data()->metadata_do(cl); +} -bool CompiledIC::is_icholder_entry(address entry) { - CodeBlob* cb = CodeCache::find_blob(entry); - if (cb == nullptr) { - return false; - } - if (cb->is_adapter_blob()) { - return true; - } else if (cb->is_vtable_blob()) { - return VtableStubs::is_icholder_entry(entry); - } - return false; +#ifndef PRODUCT +void CompiledIC::print() { + tty->print("Inline cache at " INTPTR_FORMAT ", calling " INTPTR_FORMAT " cached_value " INTPTR_FORMAT, + p2i(instruction_address()), p2i(destination()), p2i(data())); + tty->cr(); } -bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site, const CompiledMethod* cm) { - // This call site might have become stale so inspect it carefully. - address dest = cm->call_wrapper_at(call_site->addr())->destination(); - return is_icholder_entry(dest); +void CompiledIC::verify() { + _call->verify(); } +#endif // ---------------------------------------------------------------------------- -bool CompiledStaticCall::set_to_clean(bool in_use) { +void CompiledDirectCall::set_to_clean() { // in_use is unused but needed to match template function in CompiledMethod assert(CompiledICLocker::is_safe(instruction_address()), "mt unsafe call"); // Reset call site - set_destination_mt_safe(resolve_call_stub()); + RelocIterator iter((nmethod*)nullptr, instruction_address(), instruction_address() + 1); + while (iter.next()) { + switch(iter.type()) { + case relocInfo::static_call_type: + _call->set_destination_mt_safe(SharedRuntime::get_resolve_static_call_stub()); + break; + case relocInfo::opt_virtual_call_type: + _call->set_destination_mt_safe(SharedRuntime::get_resolve_opt_virtual_call_stub()); + break; + default: + ShouldNotReachHere(); + } + } + assert(is_clean(), "should be clean after cleaning"); - // Do not reset stub here: It is too expensive to call find_stub. - // Instead, rely on caller (nmethod::clear_inline_caches) to clear - // both the call and its stub. - return true; + log_debug(inlinecache)("DC@" INTPTR_FORMAT ": set to clean", p2i(_call->instruction_address())); } -bool CompiledStaticCall::is_clean() const { - return destination() == resolve_call_stub(); -} +void CompiledDirectCall::set(const methodHandle& callee_method) { + CompiledMethod* code = callee_method->code(); + CompiledMethod* caller = CodeCache::find_compiled(instruction_address()); -bool CompiledStaticCall::is_call_to_compiled() const { - return CodeCache::contains(destination()); -} + bool to_interp_cont_enter = caller->method()->is_continuation_enter_intrinsic() && + ContinuationEntry::is_interpreted_call(instruction_address()); -bool CompiledDirectStaticCall::is_call_to_interpreted() const { - // It is a call to interpreted, if it calls to a stub. Hence, the destination - // must be in the stub part of the nmethod that contains the call - CompiledMethod* cm = CodeCache::find_compiled(instruction_address()); - return cm->stub_contains(destination()); -} + bool to_compiled = !to_interp_cont_enter && code != nullptr && code->is_in_use() && !code->is_unloading(); -void CompiledStaticCall::set_to_compiled(address entry) { - { - ResourceMark rm; - log_trace(inlinecache)("%s@" INTPTR_FORMAT ": set_to_compiled " INTPTR_FORMAT, - name(), - p2i(instruction_address()), - p2i(entry)); + if (to_compiled) { + _call->set_destination_mt_safe(code->verified_entry_point()); + assert(is_call_to_compiled(), "should be compiled after set to compiled"); + } else { + // Patch call site to C2I adapter if code is deoptimized or unloaded. + // We also need to patch the static call stub to set the rmethod register + // to the callee_method so the c2i adapter knows how to build the frame + set_to_interpreted(callee_method, callee_method->get_c2i_entry()); + assert(is_call_to_interpreted(), "should be interpreted after set to interpreted"); } - // Call to compiled code - assert(CodeCache::contains(entry), "wrong entry point"); - set_destination_mt_safe(entry); + + log_trace(inlinecache)("DC@" INTPTR_FORMAT ": set to %s: %s: " INTPTR_FORMAT, + p2i(_call->instruction_address()), + to_compiled ? "compiled" : "interpreter", + callee_method->print_value_string(), + p2i(_call->destination())); } -void CompiledStaticCall::set(const StaticCallInfo& info) { - assert(CompiledICLocker::is_safe(instruction_address()), "mt unsafe call"); - // Updating a cache to the wrong entry can cause bugs that are very hard - // to track down - if cache entry gets invalid - we just clean it. In - // this way it is always the same code path that is responsible for - // updating and resolving an inline cache - assert(is_clean(), "do not update a call entry - use clean"); - - if (info._to_interpreter) { - // Call to interpreted code - set_to_interpreted(info.callee(), info.entry()); - } else { - set_to_compiled(info.entry()); - } +bool CompiledDirectCall::is_clean() const { + return destination() == SharedRuntime::get_resolve_static_call_stub() || + destination() == SharedRuntime::get_resolve_opt_virtual_call_stub(); } -// Compute settings for a CompiledStaticCall. Since we might have to set -// the stub when calling to the interpreter, we need to return arguments. -void CompiledStaticCall::compute_entry(const methodHandle& m, bool caller_is_nmethod, StaticCallInfo& info) { - CompiledMethod* m_code = m->code(); - info._callee = m; - if (m_code != nullptr && m_code->is_in_use() && !m_code->is_unloading()) { - info._to_interpreter = false; - info._entry = m_code->verified_entry_point(); - } else { - // Callee is interpreted code. In any case entering the interpreter - // puts a converter-frame on the stack to save arguments. - assert(!m->is_method_handle_intrinsic(), "Compiled code should never call interpreter MH intrinsics"); - info._to_interpreter = true; - info._entry = m()->get_c2i_entry(); - } +bool CompiledDirectCall::is_call_to_interpreted() const { + // It is a call to interpreted, if it calls to a stub. Hence, the destination + // must be in the stub part of the nmethod that contains the call + CompiledMethod* cm = CodeCache::find_compiled(instruction_address()); + return cm->stub_contains(destination()); } -void CompiledStaticCall::compute_entry_for_continuation_entry(const methodHandle& m, StaticCallInfo& info) { - if (ContinuationEntry::is_interpreted_call(instruction_address())) { - info._to_interpreter = true; - info._entry = m()->get_c2i_entry(); - } +bool CompiledDirectCall::is_call_to_compiled() const { + CompiledMethod* caller = CodeCache::find_compiled(instruction_address()); + CodeBlob* dest_cb = CodeCache::find_blob(destination()); + return !caller->stub_contains(destination()) && dest_cb->is_compiled(); } -address CompiledDirectStaticCall::find_stub_for(address instruction) { +address CompiledDirectCall::find_stub_for(address instruction) { // Find reloc. information containing this call-site RelocIterator iter((nmethod*)nullptr, instruction); while (iter.next()) { @@ -673,8 +399,6 @@ address CompiledDirectStaticCall::find_stub_for(address instruction) { // from the CompiledIC implementation case relocInfo::opt_virtual_call_type: return iter.opt_virtual_call_reloc()->static_stub(); - case relocInfo::poll_type: - case relocInfo::poll_return_type: // A safepoint can't overlap a call. default: ShouldNotReachHere(); } @@ -683,36 +407,13 @@ address CompiledDirectStaticCall::find_stub_for(address instruction) { return nullptr; } -address CompiledDirectStaticCall::find_stub() { - return CompiledDirectStaticCall::find_stub_for(instruction_address()); +address CompiledDirectCall::find_stub() { + return find_stub_for(instruction_address()); } -address CompiledDirectStaticCall::resolve_call_stub() const { - return SharedRuntime::get_resolve_static_call_stub(); -} - -//----------------------------------------------------------------------------- -// Non-product mode code #ifndef PRODUCT - -void CompiledIC::verify() { - _call->verify(); - assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted() - || is_optimized() || is_megamorphic(), "sanity check"); -} - -void CompiledIC::print() { - print_compiled_ic(); - tty->cr(); -} - -void CompiledIC::print_compiled_ic() { - tty->print("Inline cache at " INTPTR_FORMAT ", calling %s " INTPTR_FORMAT " cached_value " INTPTR_FORMAT, - p2i(instruction_address()), is_call_to_interpreted() ? "interpreted " : "", p2i(ic_destination()), p2i(is_optimized() ? nullptr : cached_value())); -} - -void CompiledDirectStaticCall::print() { - tty->print("static call at " INTPTR_FORMAT " -> ", p2i(instruction_address())); +void CompiledDirectCall::print() { + tty->print("direct call at " INTPTR_FORMAT " to " INTPTR_FORMAT " -> ", p2i(instruction_address()), p2i(destination())); if (is_clean()) { tty->print("clean"); } else if (is_call_to_compiled()) { @@ -723,9 +424,10 @@ void CompiledDirectStaticCall::print() { tty->cr(); } -void CompiledDirectStaticCall::verify_mt_safe(const methodHandle& callee, address entry, - NativeMovConstReg* method_holder, - NativeJump* jump) { +void CompiledDirectCall::verify_mt_safe(const methodHandle& callee, address entry, + NativeMovConstReg* method_holder, + NativeJump* jump) { + _call->verify(); // A generated lambda form might be deleted from the Lambdaform // cache in MethodTypeForm. If a jit compiled lambdaform method // becomes not entrant and the cache access returns null, the new @@ -743,4 +445,4 @@ void CompiledDirectStaticCall::verify_mt_safe(const methodHandle& callee, addres || old_method->is_old(), // may be race patching deoptimized nmethod due to redefinition. "b) MT-unsafe modification of inline cache"); } -#endif // !PRODUCT +#endif diff --git a/src/hotspot/share/code/compiledIC.hpp b/src/hotspot/share/code/compiledIC.hpp index 17586fc57a05f..321bf280ed40a 100644 --- a/src/hotspot/share/code/compiledIC.hpp +++ b/src/hotspot/share/code/compiledIC.hpp @@ -27,42 +27,19 @@ #include "code/nativeInst.hpp" #include "interpreter/linkResolver.hpp" -#include "oops/compiledICHolder.hpp" #include "runtime/safepointVerifiers.hpp" //----------------------------------------------------------------------------- // The CompiledIC represents a compiled inline cache. // -// In order to make patching of the inline cache MT-safe, we only allow the following -// transitions (when not at a safepoint): -// -// -// [1] --<-- Clean -->--- [1] -// / (null) \ -// / \ /-<-\ -// / [2] \ / \ -// Interpreted ---------> Monomorphic | [3] -// (CompiledICHolder*) (Klass*) | -// \ / \ / -// [4] \ / [4] \->-/ -// \->- Megamorphic -<-/ -// (CompiledICHolder*) -// -// The text in parentheses () refers to the value of the inline cache receiver (mov instruction) -// -// The numbers in square brackets refer to the kind of transition: -// [1]: Initial fixup. Receiver it found from debug information -// [2]: Compilation of a method -// [3]: Recompilation of a method (note: only entry is changed. The Klass* must stay the same) -// [4]: Inline cache miss. We go directly to megamorphic call. -// -// The class automatically inserts transition stubs (using the InlineCacheBuffer) when an MT-unsafe -// transition is made to a stub. +// It's safe to transition from any state to any state. Typically an inline cache starts +// in the clean state, meaning it will resolve the call when called. Then it typically +// transitions to monomorphic, assuming the first dynamic receiver will be the only one +// observed. If that speculation fails, we transition to megamorphic. // class CompiledIC; class CompiledICProtectionBehaviour; class CompiledMethod; -class ICStub; class CompiledICLocker: public StackObj { CompiledMethod* _method; @@ -77,237 +54,105 @@ class CompiledICLocker: public StackObj { static bool is_safe(address code); }; -class CompiledICInfo : public StackObj { - private: - address _entry; // entry point for call - void* _cached_value; // Value of cached_value (either in stub or inline cache) - bool _is_icholder; // Is the cached value a CompiledICHolder* - bool _is_optimized; // it is an optimized virtual call (i.e., can be statically bound) - bool _to_interpreter; // Call it to interpreter - bool _release_icholder; +// A CompiledICData is a helper object for the inline cache implementation. +// It comprises: +// (1) The first receiver klass and its selected method +// (2) Itable call metadata + +class CompiledICData : public CHeapObj { + friend class VMStructs; + friend class JVMCIVMStructs; + + Method* volatile _speculated_method; + uintptr_t volatile _speculated_klass; + Klass* _itable_defc_klass; + Klass* _itable_refc_klass; + bool _is_initialized; + + bool is_speculated_klass_unloaded() const; + public: - address entry() const { return _entry; } - Metadata* cached_metadata() const { assert(!_is_icholder, ""); return (Metadata*)_cached_value; } - CompiledICHolder* claim_cached_icholder() { - assert(_is_icholder, ""); - assert(_cached_value != nullptr, "must be non-null"); - _release_icholder = false; - CompiledICHolder* icholder = (CompiledICHolder*)_cached_value; - icholder->claim(); - return icholder; - } - bool is_optimized() const { return _is_optimized; } - bool to_interpreter() const { return _to_interpreter; } - - void set_compiled_entry(address entry, Klass* klass, bool is_optimized) { - _entry = entry; - _cached_value = (void*)klass; - _to_interpreter = false; - _is_icholder = false; - _is_optimized = is_optimized; - _release_icholder = false; - } + // Constructor + CompiledICData(); - void set_interpreter_entry(address entry, Method* method) { - _entry = entry; - _cached_value = (void*)method; - _to_interpreter = true; - _is_icholder = false; - _is_optimized = true; - _release_icholder = false; - } + // accessors + Klass* speculated_klass() const; + Method* speculated_method() const { return _speculated_method; } + Klass* itable_defc_klass() const { return _itable_defc_klass; } + Klass* itable_refc_klass() const { return _itable_refc_klass; } - void set_icholder_entry(address entry, CompiledICHolder* icholder) { - _entry = entry; - _cached_value = (void*)icholder; - _to_interpreter = true; - _is_icholder = true; - _is_optimized = false; - _release_icholder = true; - } + static ByteSize speculated_method_offset() { return byte_offset_of(CompiledICData, _speculated_method); } + static ByteSize speculated_klass_offset() { return byte_offset_of(CompiledICData, _speculated_klass); } - CompiledICInfo(): _entry(nullptr), _cached_value(nullptr), _is_icholder(false), - _is_optimized(false), _to_interpreter(false), _release_icholder(false) { - } - ~CompiledICInfo() { - // In rare cases the info is computed but not used, so release any - // CompiledICHolder* that was created - if (_release_icholder) { - assert(_is_icholder, "must be"); - CompiledICHolder* icholder = (CompiledICHolder*)_cached_value; - icholder->claim(); - delete icholder; - } - } -}; + static ByteSize itable_defc_klass_offset() { return byte_offset_of(CompiledICData, _itable_defc_klass); } + static ByteSize itable_refc_klass_offset() { return byte_offset_of(CompiledICData, _itable_refc_klass); } -class NativeCallWrapper: public ResourceObj { -public: - virtual address destination() const = 0; - virtual address instruction_address() const = 0; - virtual address next_instruction_address() const = 0; - virtual address return_address() const = 0; - virtual address get_resolve_call_stub(bool is_optimized) const = 0; - virtual void set_destination_mt_safe(address dest) = 0; - virtual void set_to_interpreted(const methodHandle& method, CompiledICInfo& info) = 0; - virtual void verify() const = 0; - virtual void verify_resolve_call(address dest) const = 0; - - virtual bool is_call_to_interpreted(address dest) const = 0; - virtual bool is_safe_for_patching() const = 0; - - virtual NativeInstruction* get_load_instruction(virtual_call_Relocation* r) const = 0; - - virtual void *get_data(NativeInstruction* instruction) const = 0; - virtual void set_data(NativeInstruction* instruction, intptr_t data) = 0; + void initialize(CallInfo* call_info, Klass* receiver_klass); + + bool is_initialized() const { return _is_initialized; } + + // GC Support + void clean_metadata(); + void metadata_do(MetadataClosure* cl); }; class CompiledIC: public ResourceObj { - friend class InlineCacheBuffer; - friend class ICStub; - - private: - NativeCallWrapper* _call; - NativeInstruction* _value; // patchable value cell for this IC - bool _is_optimized; // an optimized virtual call (i.e., no compiled IC) +private: CompiledMethod* _method; + CompiledICData* _data; + NativeCall* _call; - CompiledIC(CompiledMethod* cm, NativeCall* ic_call); CompiledIC(RelocIterator* iter); - void initialize_from_iter(RelocIterator* iter); + // CompiledICData wrappers + void ensure_initialized(CallInfo* call_info, Klass* receiver_klass); + bool is_speculated_klass(Klass* receiver_klass); - static bool is_icholder_entry(address entry); + // Inline cache states + void set_to_monomorphic(); + void set_to_megamorphic(CallInfo* call_info); - // low-level inline-cache manipulation. Cannot be accessed directly, since it might not be MT-safe - // to change an inline-cache. These changes the underlying inline-cache directly. They *newer* make - // changes to a transition stub. - void internal_set_ic_destination(address entry_point, bool is_icstub, void* cache, bool is_icholder); - void set_ic_destination(ICStub* stub); - void set_ic_destination(address entry_point) { - assert(_is_optimized, "use set_ic_destination_and_value instead"); - internal_set_ic_destination(entry_point, false, nullptr, false); - } - // This only for use by ICStubs where the type of the value isn't known - void set_ic_destination_and_value(address entry_point, void* value) { - internal_set_ic_destination(entry_point, false, value, is_icholder_entry(entry_point)); - } - void set_ic_destination_and_value(address entry_point, Metadata* value) { - internal_set_ic_destination(entry_point, false, value, false); - } - void set_ic_destination_and_value(address entry_point, CompiledICHolder* value) { - internal_set_ic_destination(entry_point, false, value, true); - } - - // Reads the location of the transition stub. This will fail with an assertion, if no transition stub is - // associated with the inline cache. - address stub_address() const; - bool is_in_transition_state() const; // Use InlineCacheBuffer - - public: +public: // conversion (machine PC to CompiledIC*) friend CompiledIC* CompiledIC_before(CompiledMethod* nm, address return_addr); friend CompiledIC* CompiledIC_at(CompiledMethod* nm, address call_site); friend CompiledIC* CompiledIC_at(Relocation* call_site); friend CompiledIC* CompiledIC_at(RelocIterator* reloc_iter); - static bool is_icholder_call_site(virtual_call_Relocation* call_site, const CompiledMethod* cm); - - // Return the cached_metadata/destination associated with this inline cache. If the cache currently points - // to a transition stub, it will read the values from the transition stub. - void* cached_value() const; - CompiledICHolder* cached_icholder() const { - assert(is_icholder_call(), "must be"); - return (CompiledICHolder*) cached_value(); - } - Metadata* cached_metadata() const { - assert(!is_icholder_call(), "must be"); - return (Metadata*) cached_value(); - } - - void* get_data() const { - return _call->get_data(_value); - } - - void set_data(intptr_t data) { - _call->set_data(_value, data); - } - - address ic_destination() const; - - bool is_optimized() const { return _is_optimized; } + CompiledICData* data() const; // State - bool is_clean() const; + bool is_clean() const; + bool is_monomorphic() const; bool is_megamorphic() const; - bool is_call_to_compiled() const; - bool is_call_to_interpreted() const; - - bool is_icholder_call() const; - address end_of_call() const { return _call->return_address(); } + address end_of_call() const { return _call->return_address(); } - // MT-safe patching of inline caches. Note: Only safe to call is_xxx when holding the CompiledIC_ock + // MT-safe patching of inline caches. Note: Only safe to call is_xxx when holding the CompiledICLocker // so you are guaranteed that no patching takes place. The same goes for verify. - // - // Note: We do not provide any direct access to the stub code, to prevent parts of the code - // to manipulate the inline cache in MT-unsafe ways. - // - // They all takes a TRAP argument, since they can cause a GC if the inline-cache buffer is full. - // - bool set_to_clean(bool in_use = true); - bool set_to_monomorphic(CompiledICInfo& info); - void clear_ic_stub(); - - // Returns true if successful and false otherwise. The call can fail if memory - // allocation in the code cache fails, or ic stub refill is required. - bool set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, bool& needs_ic_stub_refill, TRAPS); - - static void compute_monomorphic_entry(const methodHandle& method, Klass* receiver_klass, - bool is_optimized, bool static_bound, bool caller_is_nmethod, - CompiledICInfo& info, TRAPS); + void set_to_clean(); + void update(CallInfo* call_info, Klass* receiver_klass); + + // GC support + void clean_metadata(); + void metadata_do(MetadataClosure* cl); // Location address instruction_address() const { return _call->instruction_address(); } + address destination() const { return _call->destination(); } // Misc void print() PRODUCT_RETURN; - void print_compiled_ic() PRODUCT_RETURN; void verify() PRODUCT_RETURN; }; -inline CompiledIC* CompiledIC_before(CompiledMethod* nm, address return_addr) { - CompiledIC* c_ic = new CompiledIC(nm, nativeCall_before(return_addr)); - c_ic->verify(); - return c_ic; -} - -inline CompiledIC* CompiledIC_at(CompiledMethod* nm, address call_site) { - CompiledIC* c_ic = new CompiledIC(nm, nativeCall_at(call_site)); - c_ic->verify(); - return c_ic; -} - -inline CompiledIC* CompiledIC_at(Relocation* call_site) { - assert(call_site->type() == relocInfo::virtual_call_type || - call_site->type() == relocInfo::opt_virtual_call_type, "wrong reloc. info"); - CompiledIC* c_ic = new CompiledIC(call_site->code(), nativeCall_at(call_site->addr())); - c_ic->verify(); - return c_ic; -} - -inline CompiledIC* CompiledIC_at(RelocIterator* reloc_iter) { - assert(reloc_iter->type() == relocInfo::virtual_call_type || - reloc_iter->type() == relocInfo::opt_virtual_call_type, "wrong reloc. info"); - CompiledIC* c_ic = new CompiledIC(reloc_iter); - c_ic->verify(); - return c_ic; -} +CompiledIC* CompiledIC_before(CompiledMethod* nm, address return_addr); +CompiledIC* CompiledIC_at(CompiledMethod* nm, address call_site); +CompiledIC* CompiledIC_at(Relocation* call_site); +CompiledIC* CompiledIC_at(RelocIterator* reloc_iter); //----------------------------------------------------------------------------- -// The CompiledStaticCall represents a call to a static method in the compiled -// -// Transition diagram of a static call site is somewhat simpler than for an inlined cache: +// The CompiledDirectCall represents a call to a method in the compiled code // // // -----<----- Clean ----->----- @@ -321,63 +166,7 @@ inline CompiledIC* CompiledIC_at(RelocIterator* reloc_iter) { // // -class StaticCallInfo { - private: - address _entry; // Entrypoint - methodHandle _callee; // Callee (used when calling interpreter) - bool _to_interpreter; // call to interpreted method (otherwise compiled) - - friend class CompiledStaticCall; - friend class CompiledDirectStaticCall; - friend class CompiledPltStaticCall; - public: - address entry() const { return _entry; } - methodHandle callee() const { return _callee; } -}; - -class CompiledStaticCall : public ResourceObj { - public: - // Code - - // Returns null if CodeBuffer::expand fails - static address emit_to_interp_stub(CodeBuffer &cbuf, address mark = nullptr); - static int to_interp_stub_size(); - static int to_trampoline_stub_size(); - static int reloc_to_interp_stub(); - - // Compute entry point given a method - static void compute_entry(const methodHandle& m, bool caller_is_nmethod, StaticCallInfo& info); - void compute_entry_for_continuation_entry(const methodHandle& m, StaticCallInfo& info); - -public: - // Clean static call (will force resolving on next use) - virtual address destination() const = 0; - - // Clean static call (will force resolving on next use) - bool set_to_clean(bool in_use = true); - - // Set state. The entry must be the same, as computed by compute_entry. - // Computation and setting is split up, since the actions are separate during - // a OptoRuntime::resolve_xxx. - void set(const StaticCallInfo& info); - - // State - bool is_clean() const; - bool is_call_to_compiled() const; - virtual bool is_call_to_interpreted() const = 0; - - virtual address instruction_address() const = 0; - virtual address end_of_call() const = 0; -protected: - virtual address resolve_call_stub() const = 0; - virtual void set_destination_mt_safe(address dest) = 0; - virtual void set_to_interpreted(const methodHandle& callee, address entry) = 0; - virtual const char* name() const = 0; - - void set_to_compiled(address entry); -}; - -class CompiledDirectStaticCall : public CompiledStaticCall { +class CompiledDirectCall : public ResourceObj { private: friend class CompiledIC; friend class DirectNativeCallWrapper; @@ -392,22 +181,28 @@ class CompiledDirectStaticCall : public CompiledStaticCall { NativeCall* _call; - CompiledDirectStaticCall(NativeCall* call) : _call(call) {} + CompiledDirectCall(NativeCall* call) : _call(call) {} public: - static inline CompiledDirectStaticCall* before(address return_addr) { - CompiledDirectStaticCall* st = new CompiledDirectStaticCall(nativeCall_before(return_addr)); + // Returns null if CodeBuffer::expand fails + static address emit_to_interp_stub(CodeBuffer &cbuf, address mark = nullptr); + static int to_interp_stub_size(); + static int to_trampoline_stub_size(); + static int reloc_to_interp_stub(); + + static inline CompiledDirectCall* before(address return_addr) { + CompiledDirectCall* st = new CompiledDirectCall(nativeCall_before(return_addr)); st->verify(); return st; } - static inline CompiledDirectStaticCall* at(address native_call) { - CompiledDirectStaticCall* st = new CompiledDirectStaticCall(nativeCall_at(native_call)); + static inline CompiledDirectCall* at(address native_call) { + CompiledDirectCall* st = new CompiledDirectCall(nativeCall_at(native_call)); st->verify(); return st; } - static inline CompiledDirectStaticCall* at(Relocation* call_site) { + static inline CompiledDirectCall* at(Relocation* call_site) { return at(call_site->addr()); } @@ -415,8 +210,15 @@ class CompiledDirectStaticCall : public CompiledStaticCall { address destination() const { return _call->destination(); } address end_of_call() const { return _call->return_address(); } + // Clean static call (will force resolving on next use) + void set_to_clean(); + + void set(const methodHandle& callee_method); + // State - virtual bool is_call_to_interpreted() const; + bool is_clean() const; + bool is_call_to_interpreted() const; + bool is_call_to_compiled() const; // Stub support static address find_stub_for(address instruction); @@ -426,10 +228,6 @@ class CompiledDirectStaticCall : public CompiledStaticCall { // Misc. void print() PRODUCT_RETURN; void verify() PRODUCT_RETURN; - - protected: - virtual address resolve_call_stub() const; - virtual const char* name() const { return "CompiledDirectStaticCall"; } }; #endif // SHARE_CODE_COMPILEDIC_HPP diff --git a/src/hotspot/share/code/compiledMethod.cpp b/src/hotspot/share/code/compiledMethod.cpp index a26d4a98aba9c..6553d6f79344f 100644 --- a/src/hotspot/share/code/compiledMethod.cpp +++ b/src/hotspot/share/code/compiledMethod.cpp @@ -28,7 +28,6 @@ #include "code/exceptionHandlerTable.hpp" #include "code/scopeDesc.hpp" #include "code/codeCache.hpp" -#include "code/icBuffer.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetNMethod.hpp" #include "gc/shared/gcBehaviours.hpp" @@ -36,7 +35,6 @@ #include "logging/log.hpp" #include "logging/logTag.hpp" #include "memory/resourceArea.hpp" -#include "oops/compiledICHolder.inline.hpp" #include "oops/klass.inline.hpp" #include "oops/methodData.hpp" #include "oops/method.inline.hpp" @@ -335,28 +333,6 @@ address CompiledMethod::oops_reloc_begin() const { return low_boundary; } -int CompiledMethod::verify_icholder_relocations() { - ResourceMark rm; - int count = 0; - - RelocIterator iter(this); - while(iter.next()) { - if (iter.type() == relocInfo::virtual_call_type) { - if (CompiledIC::is_icholder_call_site(iter.virtual_call_reloc(), this)) { - CompiledIC *ic = CompiledIC_at(&iter); - if (TraceCompiledIC) { - tty->print("noticed icholder " INTPTR_FORMAT " ", p2i(ic->cached_icholder())); - ic->print(); - } - assert(ic->cached_icholder() != nullptr, "must be non-nullptr"); - count++; - } - } - } - - return count; -} - // Method that knows how to preserve outgoing arguments at call. This method must be // called with a frame corresponding to a Java invoke void CompiledMethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { @@ -431,20 +407,6 @@ void CompiledMethod::clear_inline_caches() { } } -// Clear IC callsites, releasing ICStubs of all compiled ICs -// as well as any associated CompiledICHolders. -void CompiledMethod::clear_ic_callsites() { - assert(CompiledICLocker::is_safe(this), "mt unsafe call"); - ResourceMark rm; - RelocIterator iter(this); - while(iter.next()) { - if (iter.type() == relocInfo::virtual_call_type) { - CompiledIC* ic = CompiledIC_at(&iter); - ic->set_to_clean(false); - } - } -} - #ifdef ASSERT // Check class_loader is alive for this bit of metadata. class CheckClass : public MetadataClosure { @@ -466,70 +428,22 @@ class CheckClass : public MetadataClosure { #endif // ASSERT -bool CompiledMethod::clean_ic_if_metadata_is_dead(CompiledIC *ic) { - if (ic->is_clean()) { - return true; - } - if (ic->is_icholder_call()) { - // The only exception is compiledICHolder metadata which may - // yet be marked below. (We check this further below). - CompiledICHolder* cichk_metdata = ic->cached_icholder(); - - if (cichk_metdata->is_loader_alive()) { - return true; - } - } else { - Metadata* ic_metdata = ic->cached_metadata(); - if (ic_metdata != nullptr) { - if (ic_metdata->is_klass()) { - if (((Klass*)ic_metdata)->is_loader_alive()) { - return true; - } - } else if (ic_metdata->is_method()) { - Method* method = (Method*)ic_metdata; - assert(!method->is_old(), "old method should have been cleaned"); - if (method->method_holder()->is_loader_alive()) { - return true; - } - } else { - ShouldNotReachHere(); - } - } else { - // This inline cache is a megamorphic vtable call. Those ICs never hold - // any Metadata and should therefore never be cleaned by this function. - return true; - } - } - - return ic->set_to_clean(); +static void clean_ic_if_metadata_is_dead(CompiledIC *ic) { + ic->clean_metadata(); } // Clean references to unloaded nmethods at addr from this one, which is not unloaded. -template -static bool clean_if_nmethod_is_unloaded(CompiledICorStaticCall *ic, address addr, CompiledMethod* from, +template +static void clean_if_nmethod_is_unloaded(CallsiteT* callsite, CompiledMethod* from, bool clean_all) { - CodeBlob *cb = CodeCache::find_blob(addr); - CompiledMethod* nm = (cb != nullptr) ? cb->as_compiled_method_or_null() : nullptr; - if (nm != nullptr) { - // Clean inline caches pointing to bad nmethods - if (clean_all || !nm->is_in_use() || nm->is_unloading() || (nm->method()->code() != nm)) { - if (!ic->set_to_clean(!from->is_unloading())) { - return false; - } - assert(ic->is_clean(), "nmethod " PTR_FORMAT "not clean %s", p2i(from), from->method()->name_and_sig_as_C_string()); - } + CodeBlob* cb = CodeCache::find_blob(callsite->destination()); + if (!cb->is_compiled()) { + return; + } + CompiledMethod* cm = cb->as_compiled_method(); + if (clean_all || !cm->is_in_use() || cm->is_unloading() || cm->method()->code() != cm) { + callsite->set_to_clean(); } - return true; -} - -static bool clean_if_nmethod_is_unloaded(CompiledIC *ic, CompiledMethod* from, - bool clean_all) { - return clean_if_nmethod_is_unloaded(ic, ic->ic_destination(), from, clean_all); -} - -static bool clean_if_nmethod_is_unloaded(CompiledStaticCall *csc, CompiledMethod* from, - bool clean_all) { - return clean_if_nmethod_is_unloaded(csc, csc->destination(), from, clean_all); } // Cleans caches in nmethods that point to either classes that are unloaded @@ -539,7 +453,7 @@ static bool clean_if_nmethod_is_unloaded(CompiledStaticCall *csc, CompiledMethod // nmethods are unloaded. Return postponed=true in the parallel case for // inline caches found that point to nmethods that are not yet visited during // the do_unloading walk. -bool CompiledMethod::unload_nmethod_caches(bool unloading_occurred) { +void CompiledMethod::unload_nmethod_caches(bool unloading_occurred) { ResourceMark rm; // Exception cache only needs to be called if unloading occurred @@ -547,16 +461,13 @@ bool CompiledMethod::unload_nmethod_caches(bool unloading_occurred) { clean_exception_cache(); } - if (!cleanup_inline_caches_impl(unloading_occurred, false)) { - return false; - } + cleanup_inline_caches_impl(unloading_occurred, false); #ifdef ASSERT // Check that the metadata embedded in the nmethod is alive CheckClass check_class; metadata_do(&check_class); #endif - return true; } void CompiledMethod::run_nmethod_entry_barrier() { @@ -578,8 +489,7 @@ void CompiledMethod::run_nmethod_entry_barrier() { void CompiledMethod::cleanup_inline_caches_whitebox() { assert_locked_or_safepoint(CodeCache_lock); CompiledICLocker ic_locker(this); - guarantee(cleanup_inline_caches_impl(false /* unloading_occurred */, true /* clean_all */), - "Inline cache cleaning in a safepoint can't fail"); + cleanup_inline_caches_impl(false /* unloading_occurred */, true /* clean_all */); } address* CompiledMethod::orig_pc_addr(const frame* fr) { @@ -587,7 +497,7 @@ address* CompiledMethod::orig_pc_addr(const frame* fr) { } // Called to clean up after class unloading for live nmethods -bool CompiledMethod::cleanup_inline_caches_impl(bool unloading_occurred, bool clean_all) { +void CompiledMethod::cleanup_inline_caches_impl(bool unloading_occurred, bool clean_all) { assert(CompiledICLocker::is_safe(this), "mt unsafe call"); ResourceMark rm; @@ -602,26 +512,15 @@ bool CompiledMethod::cleanup_inline_caches_impl(bool unloading_occurred, bool cl if (unloading_occurred) { // If class unloading occurred we first clear ICs where the cached metadata // is referring to an unloaded klass or method. - if (!clean_ic_if_metadata_is_dead(CompiledIC_at(&iter))) { - return false; - } + clean_ic_if_metadata_is_dead(CompiledIC_at(&iter)); } - if (!clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), this, clean_all)) { - return false; - } + clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), this, clean_all); break; case relocInfo::opt_virtual_call_type: - if (!clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), this, clean_all)) { - return false; - } - break; - case relocInfo::static_call_type: - if (!clean_if_nmethod_is_unloaded(compiledStaticCall_at(iter.reloc()), this, clean_all)) { - return false; - } + clean_if_nmethod_is_unloaded(CompiledDirectCall::at(iter.reloc()), this, clean_all); break; case relocInfo::static_stub_type: { @@ -672,8 +571,6 @@ bool CompiledMethod::cleanup_inline_caches_impl(bool unloading_occurred, bool cl break; } } - - return true; } address CompiledMethod::continuation_for_implicit_exception(address pc, bool for_div0_check) { diff --git a/src/hotspot/share/code/compiledMethod.hpp b/src/hotspot/share/code/compiledMethod.hpp index afe0905266259..42d68bda55472 100644 --- a/src/hotspot/share/code/compiledMethod.hpp +++ b/src/hotspot/share/code/compiledMethod.hpp @@ -35,7 +35,7 @@ class ExceptionHandlerTable; class ImplicitExceptionTable; class AbstractCompiler; class xmlStream; -class CompiledStaticCall; +class CompiledDirectCall; class NativeCallWrapper; class ScopeDesc; class CompiledIC; @@ -364,7 +364,7 @@ class CompiledMethod : public CodeBlob { // Inline cache support for class unloading and nmethod unloading private: - bool cleanup_inline_caches_impl(bool unloading_occurred, bool clean_all); + void cleanup_inline_caches_impl(bool unloading_occurred, bool clean_all); address continuation_for_implicit_exception(address pc, bool for_div0_check); @@ -373,13 +373,10 @@ class CompiledMethod : public CodeBlob { void cleanup_inline_caches_whitebox(); virtual void clear_inline_caches(); - void clear_ic_callsites(); // Execute nmethod barrier code, as if entering through nmethod call. void run_nmethod_entry_barrier(); - // Verify and count cached icholder relocations. - int verify_icholder_relocations(); void verify_oop_relocations(); bool has_evol_metadata(); @@ -389,14 +386,8 @@ class CompiledMethod : public CodeBlob { // corresponds to the given method as well. virtual bool is_dependent_on_method(Method* dependee) = 0; - virtual NativeCallWrapper* call_wrapper_at(address call) const = 0; - virtual NativeCallWrapper* call_wrapper_before(address return_pc) const = 0; virtual address call_instruction_address(address pc) const = 0; - virtual CompiledStaticCall* compiledStaticCall_at(Relocation* call_site) const = 0; - virtual CompiledStaticCall* compiledStaticCall_at(address addr) const = 0; - virtual CompiledStaticCall* compiledStaticCall_before(address addr) const = 0; - Method* attached_method(address call_pc); Method* attached_method_before_pc(address pc); @@ -406,16 +397,13 @@ class CompiledMethod : public CodeBlob { protected: address oops_reloc_begin() const; - private: - bool static clean_ic_if_metadata_is_dead(CompiledIC *ic); - public: // GC unloading support // Cleans unloaded klasses and unloaded nmethods in inline caches virtual bool is_unloading() = 0; - bool unload_nmethod_caches(bool class_unloading_occurred); + void unload_nmethod_caches(bool class_unloading_occurred); virtual void do_unloading(bool unloading_occurred) = 0; private: diff --git a/src/hotspot/share/code/icBuffer.cpp b/src/hotspot/share/code/icBuffer.cpp deleted file mode 100644 index ec489eff9c882..0000000000000 --- a/src/hotspot/share/code/icBuffer.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/* - * 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 "code/codeCache.hpp" -#include "code/compiledIC.hpp" -#include "code/icBuffer.hpp" -#include "code/nmethod.hpp" -#include "code/scopeDesc.hpp" -#include "gc/shared/collectedHeap.inline.hpp" -#include "interpreter/interpreter.hpp" -#include "interpreter/linkResolver.hpp" -#include "memory/resourceArea.hpp" -#include "oops/method.hpp" -#include "oops/oop.inline.hpp" -#include "runtime/atomic.hpp" -#include "runtime/handles.inline.hpp" -#include "runtime/javaThread.hpp" -#include "runtime/mutexLocker.hpp" -#include "runtime/stubRoutines.hpp" -#include "runtime/vmOperations.hpp" - -DEF_STUB_INTERFACE(ICStub); - -StubQueue* InlineCacheBuffer::_buffer = nullptr; - -CompiledICHolder* volatile InlineCacheBuffer::_pending_released = nullptr; -volatile int InlineCacheBuffer::_pending_count = 0; - -#ifdef ASSERT -ICRefillVerifier::ICRefillVerifier() - : _refill_requested(false), - _refill_remembered(false) -{ - Thread* thread = Thread::current(); - assert(thread->missed_ic_stub_refill_verifier() == nullptr, "nesting not supported"); - thread->set_missed_ic_stub_refill_verifier(this); -} - -ICRefillVerifier::~ICRefillVerifier() { - assert(!_refill_requested || _refill_remembered, - "Forgot to refill IC stubs after failed IC transition"); - Thread::current()->set_missed_ic_stub_refill_verifier(nullptr); -} - -ICRefillVerifierMark::ICRefillVerifierMark(ICRefillVerifier* verifier) { - Thread* thread = Thread::current(); - assert(thread->missed_ic_stub_refill_verifier() == nullptr, "nesting not supported"); - thread->set_missed_ic_stub_refill_verifier(verifier); -} - -ICRefillVerifierMark::~ICRefillVerifierMark() { - Thread::current()->set_missed_ic_stub_refill_verifier(nullptr); -} - -static ICRefillVerifier* current_ic_refill_verifier() { - Thread* current = Thread::current(); - ICRefillVerifier* verifier = current->missed_ic_stub_refill_verifier(); - assert(verifier != nullptr, "need a verifier for safety"); - return verifier; -} -#endif - -void ICStub::finalize() { - if (!is_empty()) { - ResourceMark rm; - CompiledIC *ic = CompiledIC_at(CodeCache::find_compiled(ic_site()), ic_site()); - assert(CodeCache::find_compiled(ic->instruction_address()) != nullptr, "inline cache in non-compiled?"); - - assert(this == ICStub::from_destination_address(ic->stub_address()), "wrong owner of ic buffer"); - ic->set_ic_destination_and_value(destination(), cached_value()); - } -} - - -address ICStub::destination() const { - return InlineCacheBuffer::ic_buffer_entry_point(code_begin()); -} - -void* ICStub::cached_value() const { - return InlineCacheBuffer::ic_buffer_cached_value(code_begin()); -} - - -void ICStub::set_stub(CompiledIC *ic, void* cached_val, address dest_addr) { - // We cannot store a pointer to the 'ic' object, since it is resource allocated. Instead we - // store the location of the inline cache. Then we have enough information recreate the CompiledIC - // object when we need to remove the stub. - _ic_site = ic->instruction_address(); - - // Assemble new stub - InlineCacheBuffer::assemble_ic_buffer_code(code_begin(), cached_val, dest_addr); - assert(destination() == dest_addr, "can recover destination"); - assert(cached_value() == cached_val, "can recover destination"); -} - - -void ICStub::clear() { - if (CompiledIC::is_icholder_entry(destination())) { - InlineCacheBuffer::queue_for_release((CompiledICHolder*)cached_value()); - } - _ic_site = nullptr; -} - - -#ifndef PRODUCT -// anybody calling to this stub will trap - -void ICStub::verify() { -} - -void ICStub::print() { - tty->print_cr("ICStub: site: " INTPTR_FORMAT, p2i(_ic_site)); -} -#endif - -//----------------------------------------------------------------------------------------------- -// Implementation of InlineCacheBuffer - - -void InlineCacheBuffer::initialize() { - if (_buffer != nullptr) return; // already initialized - _buffer = new StubQueue(new ICStubInterface, checked_cast(InlineCacheBufferSize), InlineCacheBuffer_lock, "InlineCacheBuffer"); - assert (_buffer != nullptr, "cannot allocate InlineCacheBuffer"); -} - - -void InlineCacheBuffer::refill_ic_stubs() { -#ifdef ASSERT - ICRefillVerifier* verifier = current_ic_refill_verifier(); - verifier->request_remembered(); -#endif - // we ran out of inline cache buffer space; must enter safepoint. - // We do this by forcing a safepoint - VM_ICBufferFull ibf; - VMThread::execute(&ibf); -} - -bool InlineCacheBuffer::needs_update_inline_caches() { - // Stub removal - if (buffer()->number_of_stubs() > 0) { - return true; - } - - // Release pending CompiledICHolder - if (pending_icholder_count() > 0) { - return true; - } - - return false; -} - -void InlineCacheBuffer::update_inline_caches() { - if (buffer()->number_of_stubs() > 0) { - if (TraceICBuffer) { - tty->print_cr("[updating inline caches with %d stubs]", buffer()->number_of_stubs()); - } - buffer()->remove_all(); - } - release_pending_icholders(); -} - - -bool InlineCacheBuffer::contains(address instruction_address) { - return buffer()->contains(instruction_address); -} - - -bool InlineCacheBuffer::is_empty() { - return buffer()->number_of_stubs() == 0; -} - - -void InlineCacheBuffer_init() { - InlineCacheBuffer::initialize(); -} - -bool InlineCacheBuffer::create_transition_stub(CompiledIC *ic, void* cached_value, address entry) { - assert(!SafepointSynchronize::is_at_safepoint(), "should not be called during a safepoint"); - assert(CompiledICLocker::is_safe(ic->instruction_address()), "mt unsafe call"); - if (TraceICBuffer) { - tty->print_cr(" create transition stub for " INTPTR_FORMAT " destination " INTPTR_FORMAT " cached value " INTPTR_FORMAT, - p2i(ic->instruction_address()), p2i(entry), p2i(cached_value)); - } - - // allocate and initialize new "out-of-line" inline-cache - ICStub* ic_stub = (ICStub*) buffer()->request_committed(ic_stub_code_size()); - if (ic_stub == nullptr) { -#ifdef ASSERT - ICRefillVerifier* verifier = current_ic_refill_verifier(); - verifier->request_refill(); -#endif - return false; - } - -#ifdef ASSERT - { - ICStub* rev_stub = ICStub::from_destination_address(ic_stub->code_begin()); - assert(ic_stub == rev_stub, - "ICStub mapping is reversible: stub=" PTR_FORMAT ", code=" PTR_FORMAT ", rev_stub=" PTR_FORMAT, - p2i(ic_stub), p2i(ic_stub->code_begin()), p2i(rev_stub)); - } -#endif - - // If an transition stub is already associate with the inline cache, then we remove the association. - if (ic->is_in_transition_state()) { - ICStub* old_stub = ICStub::from_destination_address(ic->stub_address()); - old_stub->clear(); - } - - ic_stub->set_stub(ic, cached_value, entry); - - // Update inline cache in nmethod to point to new "out-of-line" allocated inline cache - ic->set_ic_destination(ic_stub); - return true; -} - - -address InlineCacheBuffer::ic_destination_for(CompiledIC *ic) { - ICStub* stub = ICStub::from_destination_address(ic->stub_address()); - return stub->destination(); -} - - -void* InlineCacheBuffer::cached_value_for(CompiledIC *ic) { - ICStub* stub = ICStub::from_destination_address(ic->stub_address()); - return stub->cached_value(); -} - - -// Free CompiledICHolder*s that are no longer in use -void InlineCacheBuffer::release_pending_icholders() { - assert(SafepointSynchronize::is_at_safepoint(), "should only be called during a safepoint"); - CompiledICHolder* holder = Atomic::load(&_pending_released); - _pending_released = nullptr; - int count = 0; - while (holder != nullptr) { - CompiledICHolder* next = holder->next(); - delete holder; - holder = next; - count++; - } - assert(pending_icholder_count() == count, "wrong count"); - Atomic::store(&_pending_count, 0); -} - -// Enqueue this icholder for release during the next safepoint. It's -// not safe to free them until then since they might be visible to -// another thread. -void InlineCacheBuffer::queue_for_release(CompiledICHolder* icholder) { - assert(icholder->next() == nullptr, "multiple enqueue?"); - - CompiledICHolder* old = Atomic::load(&_pending_released); - for (;;) { - icholder->set_next(old); - // The only reader runs at a safepoint serially so there is no need for a more strict atomic. - CompiledICHolder* cur = Atomic::cmpxchg(&_pending_released, old, icholder, memory_order_relaxed); - if (cur == old) { - break; - } - old = cur; - } - Atomic::inc(&_pending_count, memory_order_relaxed); - - if (TraceICBuffer) { - tty->print_cr("enqueueing icholder " INTPTR_FORMAT " to be freed", p2i(icholder)); - } -} - -int InlineCacheBuffer::pending_icholder_count() { - return Atomic::load(&_pending_count); -} diff --git a/src/hotspot/share/code/icBuffer.hpp b/src/hotspot/share/code/icBuffer.hpp deleted file mode 100644 index f67080e6b5852..0000000000000 --- a/src/hotspot/share/code/icBuffer.hpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * 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. - * - */ - -#ifndef SHARE_CODE_ICBUFFER_HPP -#define SHARE_CODE_ICBUFFER_HPP - -#include "asm/codeBuffer.hpp" -#include "code/stubs.hpp" -#include "interpreter/bytecodes.hpp" -#include "memory/allocation.hpp" -#include "runtime/safepointVerifiers.hpp" -#include "utilities/align.hpp" -#include "utilities/debug.hpp" -#include "utilities/macros.hpp" - -class CompiledIC; -class CompiledICHolder; - -// -// For CompiledIC's: -// -// In cases where we do not have MT-safe state transformation, -// we go to a transition state, using ICStubs. At a safepoint, -// the inline caches are transferred from the transitional code: -// -// instruction_address --> 01 set xxx_oop, Ginline_cache_klass -// 23 jump_to Gtemp, yyyy -// 4 nop - -class ICStub: public Stub { - private: - int _size; // total size of the stub incl. code - address _ic_site; // points at call instruction of owning ic-buffer - /* stub code follows here */ - protected: - friend class ICStubInterface; - // This will be called only by ICStubInterface - void initialize(int size) { _size = size; _ic_site = nullptr; } - void finalize(); // called when a method is removed - - // General info - int size() const { return _size; } - - // To be cautious, we want to make sure that each ICStub is in a separate instruction - // cache line. This would allow for piggybacking on instruction cache coherency on - // some architectures to order the updates to ICStub and setting the destination to - // the ICStub. Note that cache line size might be larger than CodeEntryAlignment - // that is normal alignment for CodeBlobs. - static int alignment() { return DEFAULT_CACHE_LINE_SIZE; } - - // Aligning the code section is normally done for performance reasons, which is not - // required for ICStubs, as these stubs are transitional. Setting code alignment - // to CodeEntryAlignment would waste a lot of memory in ICBuffer. Aligning to - // word size should be enough. This also offsets the costs of aligning the entire - // ICStub to cache line (see above), as smaller code alignment would allow ICStub - // to fit a _single_ cache line. - static int code_alignment() { return HeapWordSize; } - - public: - // Creation - void set_stub(CompiledIC *ic, void* cached_value, address dest_addr); - - // Code info - address code_begin() const { return align_up((address)this + sizeof(ICStub), code_alignment()); } - address code_end() const { return (address)this + size(); } - - // Call site info - address ic_site() const { return _ic_site; } - void clear(); - bool is_empty() const { return _ic_site == nullptr; } - - // stub info - address destination() const; // destination of jump instruction - void* cached_value() const; // cached_value for stub - - // Debugging - void verify() PRODUCT_RETURN; - void print() PRODUCT_RETURN; - - // Creation - static inline ICStub* from_destination_address(address destination_address) { - ICStub* stub = (ICStub*) align_down(destination_address - sizeof(ICStub), alignment()); -#ifdef ASSERT - stub->verify(); -#endif - return stub; - } -}; - -#ifdef ASSERT -// The ICRefillVerifier class is a stack allocated RAII object used to -// detect if a failed IC transition that required IC stub refilling has -// been accidentally missed. It is up to the caller to in that case -// refill IC stubs. -class ICRefillVerifier: StackObj { - bool _refill_requested; - bool _refill_remembered; - - public: - ICRefillVerifier(); - ~ICRefillVerifier(); - - void request_refill() { _refill_requested = true; } - void request_remembered() { _refill_remembered = true; } -}; - -// The ICRefillVerifierMark is used to set the thread's current -// ICRefillVerifier to a provided one. This is useful in particular -// when transitioning IC stubs in parallel and refilling from the -// master thread invoking the IC stub transitioning code. -class ICRefillVerifierMark: StackObj { - public: - ICRefillVerifierMark(ICRefillVerifier* verifier); - ~ICRefillVerifierMark(); -}; -#else -class ICRefillVerifier: StackObj { - public: - ICRefillVerifier() {} -}; -class ICRefillVerifierMark: StackObj { - public: - ICRefillVerifierMark(ICRefillVerifier* verifier) {} -}; -#endif - -class InlineCacheBuffer: public AllStatic { - private: - // friends - friend class ICStub; - - static int ic_stub_code_size(); - - static StubQueue* _buffer; - - static CompiledICHolder* volatile _pending_released; - static volatile int _pending_count; - - static StubQueue* buffer() { return _buffer; } - - // Machine-dependent implementation of ICBuffer - static void assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point); - static address ic_buffer_entry_point (address code_begin); - static void* ic_buffer_cached_value (address code_begin); - - public: - - // Initialization; must be called before first usage - static void initialize(); - - // Access - static bool contains(address instruction_address); - - // removes the ICStubs after backpatching - static bool needs_update_inline_caches(); - static void update_inline_caches(); - static void refill_ic_stubs(); - - // for debugging - static bool is_empty(); - - static void release_pending_icholders(); - static void queue_for_release(CompiledICHolder* icholder); - static int pending_icholder_count(); - - // New interface - static bool create_transition_stub(CompiledIC *ic, void* cached_value, address entry); - static address ic_destination_for(CompiledIC *ic); - static void* cached_value_for(CompiledIC *ic); -}; - -#endif // SHARE_CODE_ICBUFFER_HPP diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index cc2dcf21deebf..2755df3251396 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -640,6 +640,7 @@ nmethod::nmethod( ByteSize basic_lock_sp_offset, OopMapSet* oop_maps ) : CompiledMethod(method, "native nmethod", type, nmethod_size, sizeof(nmethod), code_buffer, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps, false, true), + _compiled_ic_data(nullptr), _is_unlinked(false), _native_receiver_sp_offset(basic_lock_owner_sp_offset), _native_basic_lock_sp_offset(basic_lock_sp_offset), @@ -697,12 +698,12 @@ nmethod::nmethod( clear_unloading_state(); + finalize_relocations(); + Universe::heap()->register_nmethod(this); debug_only(Universe::heap()->verify_nmethod(this)); CodeCache::commit(this); - - finalize_relocations(); } if (PrintNativeNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) { @@ -784,6 +785,7 @@ nmethod::nmethod( #endif ) : CompiledMethod(method, "nmethod", type, nmethod_size, sizeof(nmethod), code_buffer, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps, false, true), + _compiled_ic_data(nullptr), _is_unlinked(false), _native_receiver_sp_offset(in_ByteSize(-1)), _native_basic_lock_sp_offset(in_ByteSize(-1)), @@ -887,13 +889,13 @@ nmethod::nmethod( } #endif + finalize_relocations(); + Universe::heap()->register_nmethod(this); debug_only(Universe::heap()->verify_nmethod(this)); CodeCache::commit(this); - finalize_relocations(); - // Copy contents of ExceptionHandlerTable to nmethod handler_table->copy_to(this); nul_chk_table->copy_to(this); @@ -1145,16 +1147,33 @@ static void install_post_call_nop_displacement(nmethod* nm, address pc) { void nmethod::finalize_relocations() { NoSafepointVerifier nsv; + GrowableArray virtual_call_data; + // Make sure that post call nops fill in nmethod offsets eagerly so // we don't have to race with deoptimization RelocIterator iter(this); while (iter.next()) { - if (iter.type() == relocInfo::post_call_nop_type) { + if (iter.type() == relocInfo::virtual_call_type) { + virtual_call_Relocation* r = iter.virtual_call_reloc(); + NativeMovConstReg* value = nativeMovConstReg_at(r->cached_value()); + virtual_call_data.append(value); + } else if (iter.type() == relocInfo::post_call_nop_type) { post_call_nop_Relocation* const reloc = iter.post_call_nop_reloc(); address pc = reloc->addr(); install_post_call_nop_displacement(this, pc); } } + + if (virtual_call_data.length() > 0) { + // We allocate a block of CompiledICData per nmethod so the GC can purge this faster. + _compiled_ic_data = new CompiledICData[virtual_call_data.length()]; + CompiledICData* next_data = _compiled_ic_data; + + for (NativeMovConstReg* value : virtual_call_data) { + value->set_data((intptr_t)next_data); + next_data++; + } + } } void nmethod::make_deoptimized() { @@ -1180,8 +1199,7 @@ void nmethod::make_deoptimized() { while (iter.next()) { switch (iter.type()) { - case relocInfo::virtual_call_type: - case relocInfo::opt_virtual_call_type: { + case relocInfo::virtual_call_type: { CompiledIC *ic = CompiledIC_at(&iter); address pc = ic->end_of_call(); NativePostCallNop* nop = nativePostCallNop_at(pc); @@ -1191,8 +1209,9 @@ void nmethod::make_deoptimized() { assert(NativeDeoptInstruction::is_deopt_at(pc), "check"); break; } - case relocInfo::static_call_type: { - CompiledStaticCall *csc = compiledStaticCall_at(iter.reloc()); + case relocInfo::static_call_type: + case relocInfo::opt_virtual_call_type: { + CompiledDirectCall *csc = CompiledDirectCall::at(iter.reloc()); address pc = csc->end_of_call(); NativePostCallNop* nop = nativePostCallNop_at(pc); //tty->print_cr(" - static pc %p", pc); @@ -1219,29 +1238,29 @@ void nmethod::verify_clean_inline_caches() { RelocIterator iter(this, oops_reloc_begin()); while(iter.next()) { switch(iter.type()) { - case relocInfo::virtual_call_type: - case relocInfo::opt_virtual_call_type: { + case relocInfo::virtual_call_type: { CompiledIC *ic = CompiledIC_at(&iter); - CodeBlob *cb = CodeCache::find_blob(ic->ic_destination()); + CodeBlob *cb = CodeCache::find_blob(ic->destination()); assert(cb != nullptr, "destination not in CodeBlob?"); nmethod* nm = cb->as_nmethod_or_null(); - if( nm != nullptr ) { + if (nm != nullptr) { // Verify that inline caches pointing to bad nmethods are clean - if (!nm->is_in_use() || (nm->method()->code() != nm)) { + if (!nm->is_in_use() || nm->is_unloading()) { assert(ic->is_clean(), "IC should be clean"); } } break; } - case relocInfo::static_call_type: { - CompiledStaticCall *csc = compiledStaticCall_at(iter.reloc()); - CodeBlob *cb = CodeCache::find_blob(csc->destination()); + case relocInfo::static_call_type: + case relocInfo::opt_virtual_call_type: { + CompiledDirectCall *cdc = CompiledDirectCall::at(iter.reloc()); + CodeBlob *cb = CodeCache::find_blob(cdc->destination()); assert(cb != nullptr, "destination not in CodeBlob?"); nmethod* nm = cb->as_nmethod_or_null(); - if( nm != nullptr ) { + if (nm != nullptr) { // Verify that inline caches pointing to bad nmethods are clean - if (!nm->is_in_use() || (nm->method()->code() != nm)) { - assert(csc->is_clean(), "IC should be clean"); + if (!nm->is_in_use() || nm->is_unloading() || nm->method()->code() != nm) { + assert(cdc->is_clean(), "IC should be clean"); } } break; @@ -1405,9 +1424,7 @@ bool nmethod::make_not_entrant() { // For concurrent GCs, there must be a handshake between unlink and flush void nmethod::unlink() { if (_is_unlinked) { - // Already unlinked. It can be invoked twice because concurrent code cache - // unloading might need to restart when inline cache cleaning fails due to - // running out of ICStubs, which can only be refilled at safepoints + // Already unlinked. return; } @@ -1418,7 +1435,6 @@ void nmethod::unlink() { // the Method, because it is only concurrently unlinked by // the entry barrier, which acquires the per nmethod lock. unlink_from_method(); - clear_ic_callsites(); if (is_osr_method()) { invalidate_osr_method(); @@ -1463,10 +1479,11 @@ void nmethod::purge(bool free_code_cache_data, bool unregister_nmethod) { ec = next; } + delete[] _compiled_ic_data; + if (unregister_nmethod) { Universe::heap()->unregister_nmethod(this); } - CodeCache::unregister_old_nmethod(this); CodeBlob::purge(free_code_cache_data, unregister_nmethod); @@ -1604,16 +1621,7 @@ void nmethod::metadata_do(MetadataClosure* f) { // Check compiledIC holders associated with this nmethod ResourceMark rm; CompiledIC *ic = CompiledIC_at(&iter); - if (ic->is_icholder_call()) { - CompiledICHolder* cichk = ic->cached_icholder(); - f->do_metadata(cichk->holder_metadata()); - f->do_metadata(cichk->holder_klass()); - } else { - Metadata* ic_oop = ic->cached_metadata(); - if (ic_oop != nullptr) { - f->do_metadata(ic_oop); - } - } + ic->metadata_do(f); } } } @@ -1750,8 +1758,7 @@ void nmethod::do_unloading(bool unloading_occurred) { if (is_unloading()) { unlink(); } else { - guarantee(unload_nmethod_caches(unloading_occurred), - "Should not need transition stubs"); + unload_nmethod_caches(unloading_occurred); BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); if (bs_nm != nullptr) { bs_nm->disarm(this); @@ -2284,15 +2291,23 @@ void nmethod::verify() { } -void nmethod::verify_interrupt_point(address call_site) { +void nmethod::verify_interrupt_point(address call_site, bool is_inline_cache) { // Verify IC only when nmethod installation is finished. if (!is_not_installed()) { if (CompiledICLocker::is_safe(this)) { - CompiledIC_at(this, call_site); + if (is_inline_cache) { + CompiledIC_at(this, call_site); + } else { + CompiledDirectCall::at(call_site); + } } else { CompiledICLocker ml_verify(this); - CompiledIC_at(this, call_site); + if (is_inline_cache) { + CompiledIC_at(this, call_site); + } else { + CompiledDirectCall::at(call_site); + } } } @@ -2316,15 +2331,15 @@ void nmethod::verify_scopes() { address stub = nullptr; switch (iter.type()) { case relocInfo::virtual_call_type: - verify_interrupt_point(iter.addr()); + verify_interrupt_point(iter.addr(), true /* is_inline_cache */); break; case relocInfo::opt_virtual_call_type: stub = iter.opt_virtual_call_reloc()->static_stub(); - verify_interrupt_point(iter.addr()); + verify_interrupt_point(iter.addr(), false /* is_inline_cache */); break; case relocInfo::static_call_type: stub = iter.static_call_reloc()->static_stub(); - //verify_interrupt_point(iter.addr()); + verify_interrupt_point(iter.addr(), false /* is_inline_cache */); break; case relocInfo::runtime_call_type: case relocInfo::runtime_call_w_cp_type: { @@ -3239,75 +3254,6 @@ void nmethod::print_code_comment_on(outputStream* st, int column, address begin, #endif -class DirectNativeCallWrapper: public NativeCallWrapper { -private: - NativeCall* _call; - -public: - DirectNativeCallWrapper(NativeCall* call) : _call(call) {} - - virtual address destination() const { return _call->destination(); } - virtual address instruction_address() const { return _call->instruction_address(); } - virtual address next_instruction_address() const { return _call->next_instruction_address(); } - virtual address return_address() const { return _call->return_address(); } - - virtual address get_resolve_call_stub(bool is_optimized) const { - if (is_optimized) { - return SharedRuntime::get_resolve_opt_virtual_call_stub(); - } - return SharedRuntime::get_resolve_virtual_call_stub(); - } - - virtual void set_destination_mt_safe(address dest) { - _call->set_destination_mt_safe(dest); - } - - virtual void set_to_interpreted(const methodHandle& method, CompiledICInfo& info) { - CompiledDirectStaticCall* csc = CompiledDirectStaticCall::at(instruction_address()); - { - csc->set_to_interpreted(method, info.entry()); - } - } - - virtual void verify() const { - // make sure code pattern is actually a call imm32 instruction - _call->verify(); - _call->verify_alignment(); - } - - virtual void verify_resolve_call(address dest) const { - CodeBlob* db = CodeCache::find_blob(dest); - assert(db != nullptr && !db->is_adapter_blob(), "must use stub!"); - } - - virtual bool is_call_to_interpreted(address dest) const { - CodeBlob* cb = CodeCache::find_blob(_call->instruction_address()); - return cb->contains(dest); - } - - virtual bool is_safe_for_patching() const { return false; } - - virtual NativeInstruction* get_load_instruction(virtual_call_Relocation* r) const { - return nativeMovConstReg_at(r->cached_value()); - } - - virtual void *get_data(NativeInstruction* instruction) const { - return (void*)((NativeMovConstReg*) instruction)->data(); - } - - virtual void set_data(NativeInstruction* instruction, intptr_t data) { - ((NativeMovConstReg*) instruction)->set_data(data); - } -}; - -NativeCallWrapper* nmethod::call_wrapper_at(address call) const { - return new DirectNativeCallWrapper((NativeCall*) call); -} - -NativeCallWrapper* nmethod::call_wrapper_before(address return_pc) const { - return new DirectNativeCallWrapper(nativeCall_before(return_pc)); -} - address nmethod::call_instruction_address(address pc) const { if (NativeCall::is_call_before(pc)) { NativeCall *ncall = nativeCall_before(pc); @@ -3316,18 +3262,6 @@ address nmethod::call_instruction_address(address pc) const { return nullptr; } -CompiledStaticCall* nmethod::compiledStaticCall_at(Relocation* call_site) const { - return CompiledDirectStaticCall::at(call_site); -} - -CompiledStaticCall* nmethod::compiledStaticCall_at(address call_site) const { - return CompiledDirectStaticCall::at(call_site); -} - -CompiledStaticCall* nmethod::compiledStaticCall_before(address return_addr) const { - return CompiledDirectStaticCall::before(return_addr); -} - #if defined(SUPPORT_DATA_STRUCTS) void nmethod::print_value_on(outputStream* st) const { st->print("nmethod"); @@ -3341,15 +3275,15 @@ void nmethod::print_calls(outputStream* st) { RelocIterator iter(this); while (iter.next()) { switch (iter.type()) { - case relocInfo::virtual_call_type: - case relocInfo::opt_virtual_call_type: { + case relocInfo::virtual_call_type: { CompiledICLocker ml_verify(this); CompiledIC_at(&iter)->print(); break; } case relocInfo::static_call_type: - st->print_cr("Static call at " INTPTR_FORMAT, p2i(iter.reloc()->addr())); - CompiledDirectStaticCall::at(iter.reloc())->print(); + case relocInfo::opt_virtual_call_type: + st->print_cr("Direct call at " INTPTR_FORMAT, p2i(iter.reloc()->addr())); + CompiledDirectCall::at(iter.reloc())->print(); break; default: break; diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 13cd2f799a76b..2993db21305ee 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -27,6 +27,7 @@ #include "code/compiledMethod.hpp" +class CompiledICData; class CompileTask; class DepChange; class DirectiveSet; @@ -196,6 +197,7 @@ class nmethod : public CompiledMethod { address _verified_entry_point; // entry point without class check address _osr_entry_point; // entry point for on stack replacement + CompiledICData* _compiled_ic_data; bool _is_unlinked; // Shared fields for all nmethod's @@ -604,7 +606,7 @@ class nmethod : public CompiledMethod { // verify operations void verify(); void verify_scopes(); - void verify_interrupt_point(address interrupt_point); + void verify_interrupt_point(address interrupt_point, bool is_inline_cache); // Disassemble this nmethod with additional debug information, e.g. information about blocks. void decode2(outputStream* st) const; @@ -699,14 +701,8 @@ class nmethod : public CompiledMethod { virtual void metadata_do(MetadataClosure* f); - NativeCallWrapper* call_wrapper_at(address call) const; - NativeCallWrapper* call_wrapper_before(address return_pc) const; address call_instruction_address(address pc) const; - virtual CompiledStaticCall* compiledStaticCall_at(Relocation* call_site) const; - virtual CompiledStaticCall* compiledStaticCall_at(address addr) const; - virtual CompiledStaticCall* compiledStaticCall_before(address addr) const; - virtual void make_deoptimized(); void finalize_relocations(); }; diff --git a/src/hotspot/share/code/relocInfo.cpp b/src/hotspot/share/code/relocInfo.cpp index bfb3db72d7265..ef90875767503 100644 --- a/src/hotspot/share/code/relocInfo.cpp +++ b/src/hotspot/share/code/relocInfo.cpp @@ -641,12 +641,10 @@ Method* virtual_call_Relocation::method_value() { return (Method*)m; } -bool virtual_call_Relocation::clear_inline_cache() { - // No stubs for ICs - // Clean IC +void virtual_call_Relocation::clear_inline_cache() { ResourceMark rm; CompiledIC* icache = CompiledIC_at(this); - return icache->set_to_clean(); + icache->set_to_clean(); } @@ -669,18 +667,10 @@ Method* opt_virtual_call_Relocation::method_value() { return (Method*)m; } -template -static bool set_to_clean_no_ic_refill(CompiledICorStaticCall* ic) { - guarantee(ic->set_to_clean(), "Should not need transition stubs"); - return true; -} - -bool opt_virtual_call_Relocation::clear_inline_cache() { - // No stubs for ICs - // Clean IC +void opt_virtual_call_Relocation::clear_inline_cache() { ResourceMark rm; - CompiledIC* icache = CompiledIC_at(this); - return set_to_clean_no_ic_refill(icache); + CompiledDirectCall* callsite = CompiledDirectCall::at(this); + callsite->set_to_clean(); } address opt_virtual_call_Relocation::static_stub() { @@ -717,10 +707,10 @@ void static_call_Relocation::unpack_data() { _method_index = unpack_1_int(); } -bool static_call_Relocation::clear_inline_cache() { - // Safe call site info - CompiledStaticCall* handler = this->code()->compiledStaticCall_at(this); - return set_to_clean_no_ic_refill(handler); +void static_call_Relocation::clear_inline_cache() { + ResourceMark rm; + CompiledDirectCall* callsite = CompiledDirectCall::at(this); + callsite->set_to_clean(); } @@ -759,11 +749,10 @@ address trampoline_stub_Relocation::get_trampoline_for(address call, nmethod* co return nullptr; } -bool static_stub_Relocation::clear_inline_cache() { +void static_stub_Relocation::clear_inline_cache() { // Call stub is only used when calling the interpreted code. // It does not really need to be cleared, except that we want to clean out the methodoop. - CompiledDirectStaticCall::set_stub_to_clean(this); - return true; + CompiledDirectCall::set_stub_to_clean(this); } diff --git a/src/hotspot/share/code/relocInfo.hpp b/src/hotspot/share/code/relocInfo.hpp index 77e24708bb143..5f67f94bdadc5 100644 --- a/src/hotspot/share/code/relocInfo.hpp +++ b/src/hotspot/share/code/relocInfo.hpp @@ -862,7 +862,7 @@ class Relocation { // all relocations are able to reassert their values virtual void set_value(address x); - virtual bool clear_inline_cache() { return true; } + virtual void clear_inline_cache() {} // This method assumes that all virtual/static (inline) caches are cleared (since for static_call_type and // ic_call_type is not always position dependent (depending on the state of the cache)). However, this is @@ -1141,7 +1141,7 @@ class virtual_call_Relocation : public CallRelocation { void pack_data_to(CodeSection* dest) override; void unpack_data() override; - bool clear_inline_cache() override; + void clear_inline_cache() override; }; @@ -1170,7 +1170,7 @@ class opt_virtual_call_Relocation : public CallRelocation { void pack_data_to(CodeSection* dest) override; void unpack_data() override; - bool clear_inline_cache() override; + void clear_inline_cache() override; // find the matching static_stub address static_stub(); @@ -1202,7 +1202,7 @@ class static_call_Relocation : public CallRelocation { void pack_data_to(CodeSection* dest) override; void unpack_data() override; - bool clear_inline_cache() override; + void clear_inline_cache() override; // find the matching static_stub address static_stub(); @@ -1227,7 +1227,7 @@ class static_stub_Relocation : public Relocation { static_stub_Relocation() : Relocation(relocInfo::static_stub_type) { } public: - bool clear_inline_cache() override; + void clear_inline_cache() override; address static_call() { return _static_call; } diff --git a/src/hotspot/share/code/vtableStubs.cpp b/src/hotspot/share/code/vtableStubs.cpp index eed3dc8e7876a..5a54426d6a420 100644 --- a/src/hotspot/share/code/vtableStubs.cpp +++ b/src/hotspot/share/code/vtableStubs.cpp @@ -283,13 +283,6 @@ VtableStub* VtableStubs::entry_point(address pc) { return (s == stub) ? s : nullptr; } -bool VtableStubs::is_icholder_entry(address pc) { - assert(contains(pc), "must contain all vtable blobs"); - VtableStub* stub = (VtableStub*)(pc - VtableStub::entry_offset()); - // itable stubs use CompiledICHolder. - return stub->is_itable_stub(); -} - bool VtableStubs::contains(address pc) { // simple solution for now - we may want to use // a faster way if this function is called often diff --git a/src/hotspot/share/code/vtableStubs.hpp b/src/hotspot/share/code/vtableStubs.hpp index 7076e50f3e3d8..3993e1e72d5cf 100644 --- a/src/hotspot/share/code/vtableStubs.hpp +++ b/src/hotspot/share/code/vtableStubs.hpp @@ -107,7 +107,6 @@ class VtableStubs : AllStatic { static address find_itable_stub(int itable_index) { return find_stub(false, itable_index); } static VtableStub* entry_point(address pc); // vtable stub entry point for a pc - static bool is_icholder_entry(address pc); // is the blob containing pc (which must be a vtable blob) an icholder? static bool contains(address pc); // is pc within any stub? static VtableStub* stub_containing(address pc); // stub containing pc or nullptr static void initialize(); diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp index 1ade28278aedd..3a25112891484 100644 --- a/src/hotspot/share/compiler/compileBroker.cpp +++ b/src/hotspot/share/compiler/compileBroker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -582,7 +582,7 @@ CompilerCounters::CompilerCounters() { // c2 uses explicit CompilerPhaseType idToPhase mapping in opto/phasetype.hpp, // so if c2 is used, it should be always registered first. // This function is called during vm initialization. -void register_jfr_phasetype_serializer(CompilerType compiler_type) { +static void register_jfr_phasetype_serializer(CompilerType compiler_type) { ResourceMark rm; static bool first_registration = true; if (compiler_type == compiler_jvmci) { diff --git a/src/hotspot/share/compiler/compilerOracle.cpp b/src/hotspot/share/compiler/compilerOracle.cpp index 089fc5a4d995e..a8eee10fac539 100644 --- a/src/hotspot/share/compiler/compilerOracle.cpp +++ b/src/hotspot/share/compiler/compilerOracle.cpp @@ -48,7 +48,7 @@ static const char* optiontype_names[] = { #undef enum_of_types }; -const char* optiontype2name(enum OptionType type) { +static const char* optiontype2name(enum OptionType type) { return optiontype_names[static_cast(type)]; } @@ -58,7 +58,7 @@ static enum OptionType option_types[] = { #undef enum_of_options }; -enum OptionType option2type(enum CompileCommand option) { +static enum OptionType option2type(enum CompileCommand option) { return option_types[static_cast(option)]; } @@ -68,7 +68,7 @@ static const char* option_names[] = { #undef enum_of_options }; -const char* option2name(enum CompileCommand option) { +static const char* option2name(enum CompileCommand option) { return option_names[static_cast(option)]; } @@ -108,7 +108,7 @@ static bool print_final_memstat_report = false; // A filter for quick lookup if an option is set static bool option_filter[static_cast(CompileCommand::Unknown) + 1] = { 0 }; -void command_set_in_filter(enum CompileCommand option) { +static void command_set_in_filter(enum CompileCommand option) { assert(option != CompileCommand::Unknown, "sanity"); assert(option2type(option) != OptionType::Unknown, "sanity"); @@ -120,7 +120,7 @@ void command_set_in_filter(enum CompileCommand option) { option_filter[static_cast(option)] = true; } -bool has_command(enum CompileCommand option) { +static bool has_command(enum CompileCommand option) { return option_filter[static_cast(option)]; } @@ -547,7 +547,7 @@ enum OptionType CompilerOracle::parse_option_type(const char* type_str) { return OptionType::Unknown; } -void print_tip() { // CMH Update info +static void print_tip() { // CMH Update info tty->cr(); tty->print_cr("Usage: '-XX:CompileCommand=

- * Access of bytes at an index may be aligned or misaligned for {@code T}, - * with respect to the underlying memory address, {@code A} say, associated - * with the array and index. - * If access is misaligned then access for anything other than the - * {@code get} and {@code set} access modes will result in an - * {@code IllegalStateException}. In such cases atomic access is only - * guaranteed with respect to the largest power of two that divides the GCD - * of {@code A} and the size (in bytes) of {@code T}. - * If access is aligned then following access modes are supported and are - * guaranteed to support atomic access: - *

- *

- * Misaligned access, and therefore atomicity guarantees, may be determined - * for {@code byte[]} arrays without operating on a specific array. Given - * an {@code index}, {@code T} and its corresponding boxed type, - * {@code T_BOX}, misalignment may be determined as follows: - *

{@code
-     * int sizeOfT = T_BOX.BYTES;  // size in bytes of T
-     * int misalignedAtZeroIndex = ByteBuffer.wrap(new byte[0]).
-     *     alignmentOffset(0, sizeOfT);
-     * int misalignedAtIndex = (misalignedAtZeroIndex + index) % sizeOfT;
-     * boolean isMisaligned = misalignedAtIndex != 0;
-     * }
- *

- * If the variable type is {@code float} or {@code double} then atomic - * update access modes compare values using their bitwise representation - * (see {@link Float#floatToRawIntBits} and - * {@link Double#doubleToRawLongBits}, respectively). + * Only plain {@linkplain VarHandle.AccessMode#GET get} and {@linkplain VarHandle.AccessMode#SET set} + * access modes are supported by the returned var handle. For all other access modes, an + * {@link UnsupportedOperationException} will be thrown. + * + * @apiNote if access modes other than plain access are required, clients should + * consider using off-heap memory through + * {@linkplain java.nio.ByteBuffer#allocateDirect(int) direct byte buffers} or + * off-heap {@linkplain java.lang.foreign.MemorySegment memory segments}, + * or memory segments backed by a + * {@linkplain java.lang.foreign.MemorySegment#ofArray(long[]) {@code long[]}}, + * for which stronger alignment guarantees can be made. + * * @param viewArrayClass the view array class, with a component type of * type {@code T} * @param byteOrder the endianness of the view array elements, as @@ -4600,7 +4570,13 @@ public static VarHandle byteArrayViewVarHandle(Class viewArrayClass, * or greater than the {@code ByteBuffer} limit minus the size (in bytes) of * {@code T}. *

- * Access of bytes at an index may be aligned or misaligned for {@code T}, + * For heap byte buffers, access is always unaligned. As a result, only the plain + * {@linkplain VarHandle.AccessMode#GET get} + * and {@linkplain VarHandle.AccessMode#SET set} access modes are supported by the + * returned var handle. For all other access modes, an {@link IllegalStateException} + * will be thrown. + *

+ * For direct buffers only, access of bytes at an index may be aligned or misaligned for {@code T}, * with respect to the underlying memory address, {@code A} say, associated * with the {@code ByteBuffer} and index. * If access is misaligned then access for anything other than the diff --git a/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template b/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template index 08495f2e58d42..995cb38e3ca1e 100644 --- a/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template +++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template @@ -49,7 +49,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); static final int ALIGN = $BoxType$.BYTES - 1; - + static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess(); #if[floatingPoint] @@ -115,14 +115,6 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { return Preconditions.checkIndex(index, ba.length - ALIGN, Preconditions.AIOOBE_FORMATTER); } - @ForceInline - static long address(byte[] ba, int index) { - long address = ((long) index) + Unsafe.ARRAY_BYTE_BASE_OFFSET; - if ((address & ALIGN) != 0) - throw newIllegalStateExceptionForMisalignedAccess(index); - return address; - } - @ForceInline static $type$ get(VarHandle ob, Object oba, int index) { ArrayHandle handle = (ArrayHandle)ob; @@ -160,419 +152,6 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { #end[floatingPoint] } - @ForceInline - static $type$ getVolatile(VarHandle ob, Object oba, int index) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - return convEndian(handle.be, - UNSAFE.get$RawType$Volatile( - ba, - address(ba, index(ba, index)))); - } - - @ForceInline - static void setVolatile(VarHandle ob, Object oba, int index, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - UNSAFE.put$RawType$Volatile( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, value)); - } - - @ForceInline - static $type$ getAcquire(VarHandle ob, Object oba, int index) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - return convEndian(handle.be, - UNSAFE.get$RawType$Acquire( - ba, - address(ba, index(ba, index)))); - } - - @ForceInline - static void setRelease(VarHandle ob, Object oba, int index, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - UNSAFE.put$RawType$Release( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, value)); - } - - @ForceInline - static $type$ getOpaque(VarHandle ob, Object oba, int index) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - return convEndian(handle.be, - UNSAFE.get$RawType$Opaque( - ba, - address(ba, index(ba, index)))); - } - - @ForceInline - static void setOpaque(VarHandle ob, Object oba, int index, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - UNSAFE.put$RawType$Opaque( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, value)); - } -#if[CAS] - - @ForceInline - static boolean compareAndSet(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; -#if[Object] - return UNSAFE.compareAndSetReference( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, expected), convEndian(handle.be, value)); -#else[Object] - return UNSAFE.compareAndSet$RawType$( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, expected), convEndian(handle.be, value)); -#end[Object] - } - - @ForceInline - static $type$ compareAndExchange(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - return convEndian(handle.be, - UNSAFE.compareAndExchange$RawType$( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, expected), convEndian(handle.be, value))); - } - - @ForceInline - static $type$ compareAndExchangeAcquire(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - return convEndian(handle.be, - UNSAFE.compareAndExchange$RawType$Acquire( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, expected), convEndian(handle.be, value))); - } - - @ForceInline - static $type$ compareAndExchangeRelease(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - return convEndian(handle.be, - UNSAFE.compareAndExchange$RawType$Release( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, expected), convEndian(handle.be, value))); - } - - @ForceInline - static boolean weakCompareAndSetPlain(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - return UNSAFE.weakCompareAndSet$RawType$Plain( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, expected), convEndian(handle.be, value)); - } - - @ForceInline - static boolean weakCompareAndSet(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - return UNSAFE.weakCompareAndSet$RawType$( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, expected), convEndian(handle.be, value)); - } - - @ForceInline - static boolean weakCompareAndSetAcquire(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - return UNSAFE.weakCompareAndSet$RawType$Acquire( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, expected), convEndian(handle.be, value)); - } - - @ForceInline - static boolean weakCompareAndSetRelease(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - return UNSAFE.weakCompareAndSet$RawType$Release( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, expected), convEndian(handle.be, value)); - } - - @ForceInline - static $type$ getAndSet(VarHandle ob, Object oba, int index, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; -#if[Object] - return convEndian(handle.be, - UNSAFE.getAndSetReference( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, value))); -#else[Object] - return convEndian(handle.be, - UNSAFE.getAndSet$RawType$( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, value))); -#end[Object] - } - - @ForceInline - static $type$ getAndSetAcquire(VarHandle ob, Object oba, int index, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - return convEndian(handle.be, - UNSAFE.getAndSet$RawType$Acquire( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, value))); - } - - @ForceInline - static $type$ getAndSetRelease(VarHandle ob, Object oba, int index, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - return convEndian(handle.be, - UNSAFE.getAndSet$RawType$Release( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, value))); - } -#end[CAS] -#if[AtomicAdd] - - @ForceInline - static $type$ getAndAdd(VarHandle ob, Object oba, int index, $type$ delta) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - if (handle.be == BE) { - return UNSAFE.getAndAdd$RawType$( - ba, - address(ba, index(ba, index)), - delta); - } else { - return getAndAddConvEndianWithCAS(ba, index, delta); - } - } - - @ForceInline - static $type$ getAndAddAcquire(VarHandle ob, Object oba, int index, $type$ delta) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - if (handle.be == BE) { - return UNSAFE.getAndAdd$RawType$Acquire( - ba, - address(ba, index(ba, index)), - delta); - } else { - return getAndAddConvEndianWithCAS(ba, index, delta); - } - } - - @ForceInline - static $type$ getAndAddRelease(VarHandle ob, Object oba, int index, $type$ delta) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - if (handle.be == BE) { - return UNSAFE.getAndAdd$RawType$Release( - ba, - address(ba, index(ba, index)), - delta); - } else { - return getAndAddConvEndianWithCAS(ba, index, delta); - } - } - - @ForceInline - static $type$ getAndAddConvEndianWithCAS(byte[] ba, int index, $type$ delta) { - $type$ nativeExpectedValue, expectedValue; - long offset = address(ba, index(ba, index)); - do { - nativeExpectedValue = UNSAFE.get$RawType$Volatile(ba, offset); - expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue); - } while (!UNSAFE.weakCompareAndSet$RawType$(ba, offset, - nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue + delta))); - return expectedValue; - } -#end[AtomicAdd] -#if[Bitwise] - - @ForceInline - static $type$ getAndBitwiseOr(VarHandle ob, Object oba, int index, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - if (handle.be == BE) { - return UNSAFE.getAndBitwiseOr$RawType$( - ba, - address(ba, index(ba, index)), - value); - } else { - return getAndBitwiseOrConvEndianWithCAS(ba, index, value); - } - } - - @ForceInline - static $type$ getAndBitwiseOrRelease(VarHandle ob, Object oba, int index, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - if (handle.be == BE) { - return UNSAFE.getAndBitwiseOr$RawType$Release( - ba, - address(ba, index(ba, index)), - value); - } else { - return getAndBitwiseOrConvEndianWithCAS(ba, index, value); - } - } - - @ForceInline - static $type$ getAndBitwiseOrAcquire(VarHandle ob, Object oba, int index, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - if (handle.be == BE) { - return UNSAFE.getAndBitwiseOr$RawType$Acquire( - ba, - address(ba, index(ba, index)), - value); - } else { - return getAndBitwiseOrConvEndianWithCAS(ba, index, value); - } - } - - @ForceInline - static $type$ getAndBitwiseOrConvEndianWithCAS(byte[] ba, int index, $type$ value) { - $type$ nativeExpectedValue, expectedValue; - long offset = address(ba, index(ba, index)); - do { - nativeExpectedValue = UNSAFE.get$RawType$Volatile(ba, offset); - expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue); - } while (!UNSAFE.weakCompareAndSet$RawType$(ba, offset, - nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue | value))); - return expectedValue; - } - - @ForceInline - static $type$ getAndBitwiseAnd(VarHandle ob, Object oba, int index, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - if (handle.be == BE) { - return UNSAFE.getAndBitwiseAnd$RawType$( - ba, - address(ba, index(ba, index)), - value); - } else { - return getAndBitwiseAndConvEndianWithCAS(ba, index, value); - } - } - - @ForceInline - static $type$ getAndBitwiseAndRelease(VarHandle ob, Object oba, int index, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - if (handle.be == BE) { - return UNSAFE.getAndBitwiseAnd$RawType$Release( - ba, - address(ba, index(ba, index)), - value); - } else { - return getAndBitwiseAndConvEndianWithCAS(ba, index, value); - } - } - - @ForceInline - static $type$ getAndBitwiseAndAcquire(VarHandle ob, Object oba, int index, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - if (handle.be == BE) { - return UNSAFE.getAndBitwiseAnd$RawType$Acquire( - ba, - address(ba, index(ba, index)), - value); - } else { - return getAndBitwiseAndConvEndianWithCAS(ba, index, value); - } - } - - @ForceInline - static $type$ getAndBitwiseAndConvEndianWithCAS(byte[] ba, int index, $type$ value) { - $type$ nativeExpectedValue, expectedValue; - long offset = address(ba, index(ba, index)); - do { - nativeExpectedValue = UNSAFE.get$RawType$Volatile(ba, offset); - expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue); - } while (!UNSAFE.weakCompareAndSet$RawType$(ba, offset, - nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue & value))); - return expectedValue; - } - - @ForceInline - static $type$ getAndBitwiseXor(VarHandle ob, Object oba, int index, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - if (handle.be == BE) { - return UNSAFE.getAndBitwiseXor$RawType$( - ba, - address(ba, index(ba, index)), - value); - } else { - return getAndBitwiseXorConvEndianWithCAS(ba, index, value); - } - } - - @ForceInline - static $type$ getAndBitwiseXorRelease(VarHandle ob, Object oba, int index, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - if (handle.be == BE) { - return UNSAFE.getAndBitwiseXor$RawType$Release( - ba, - address(ba, index(ba, index)), - value); - } else { - return getAndBitwiseXorConvEndianWithCAS(ba, index, value); - } - } - - @ForceInline - static $type$ getAndBitwiseXorAcquire(VarHandle ob, Object oba, int index, $type$ value) { - ArrayHandle handle = (ArrayHandle)ob; - byte[] ba = (byte[]) oba; - if (handle.be == BE) { - return UNSAFE.getAndBitwiseXor$RawType$Acquire( - ba, - address(ba, index(ba, index)), - value); - } else { - return getAndBitwiseXorConvEndianWithCAS(ba, index, value); - } - } - - @ForceInline - static $type$ getAndBitwiseXorConvEndianWithCAS(byte[] ba, int index, $type$ value) { - $type$ nativeExpectedValue, expectedValue; - long offset = address(ba, index(ba, index)); - do { - nativeExpectedValue = UNSAFE.get$RawType$Volatile(ba, offset); - expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue); - } while (!UNSAFE.weakCompareAndSet$RawType$(ba, offset, - nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue ^ value))); - return expectedValue; - } -#end[Bitwise] - static final VarForm FORM = new VarForm(ArrayHandle.class, byte[].class, $type$.class, int.class); } @@ -634,6 +213,14 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { return address; } + @ForceInline + static Object checkNullHeapBase(Object hb) { + if (hb != null) { + throw new IllegalStateException("Atomic access not supported for heap buffer"); + } + return hb; + } + @ForceInline static $type$ get(VarHandle ob, Object obb, int index) { ByteBufferHandle handle = (ByteBufferHandle)ob; @@ -677,7 +264,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); return convEndian(handle.be, SCOPED_MEMORY_ACCESS.get$RawType$Volatile(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, index(bb, index)))); } @@ -686,7 +273,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBufferHandle handle = (ByteBufferHandle)ob; ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); SCOPED_MEMORY_ACCESS.put$RawType$Volatile(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), convEndian(handle.be, value)); } @@ -697,7 +284,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); return convEndian(handle.be, SCOPED_MEMORY_ACCESS.get$RawType$Acquire(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, index(bb, index)))); } @@ -706,7 +293,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBufferHandle handle = (ByteBufferHandle)ob; ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); SCOPED_MEMORY_ACCESS.put$RawType$Release(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), convEndian(handle.be, value)); } @@ -717,7 +304,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); return convEndian(handle.be, SCOPED_MEMORY_ACCESS.get$RawType$Opaque(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, index(bb, index)))); } @@ -726,7 +313,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBufferHandle handle = (ByteBufferHandle)ob; ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); SCOPED_MEMORY_ACCESS.put$RawType$Opaque(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), convEndian(handle.be, value)); } @@ -736,17 +323,10 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { static boolean compareAndSet(VarHandle ob, Object obb, int index, $type$ expected, $type$ value) { ByteBufferHandle handle = (ByteBufferHandle)ob; ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); -#if[Object] - return SCOPED_MEMORY_ACCESS.compareAndSetReference(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), - address(bb, indexRO(bb, index)), - convEndian(handle.be, expected), convEndian(handle.be, value)); -#else[Object] return SCOPED_MEMORY_ACCESS.compareAndSet$RawType$(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), convEndian(handle.be, expected), convEndian(handle.be, value)); -#end[Object] } @ForceInline @@ -755,7 +335,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); return convEndian(handle.be, SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), convEndian(handle.be, expected), convEndian(handle.be, value))); } @@ -766,7 +346,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); return convEndian(handle.be, SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$Acquire(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), convEndian(handle.be, expected), convEndian(handle.be, value))); } @@ -777,7 +357,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); return convEndian(handle.be, SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$Release(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), convEndian(handle.be, expected), convEndian(handle.be, value))); } @@ -787,7 +367,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBufferHandle handle = (ByteBufferHandle)ob; ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Plain(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), convEndian(handle.be, expected), convEndian(handle.be, value)); } @@ -797,7 +377,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBufferHandle handle = (ByteBufferHandle)ob; ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), convEndian(handle.be, expected), convEndian(handle.be, value)); } @@ -807,7 +387,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBufferHandle handle = (ByteBufferHandle)ob; ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Acquire(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), convEndian(handle.be, expected), convEndian(handle.be, value)); } @@ -817,7 +397,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBufferHandle handle = (ByteBufferHandle)ob; ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Release(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), convEndian(handle.be, expected), convEndian(handle.be, value)); } @@ -826,19 +406,11 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { static $type$ getAndSet(VarHandle ob, Object obb, int index, $type$ value) { ByteBufferHandle handle = (ByteBufferHandle)ob; ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); -#if[Object] - return convEndian(handle.be, - SCOPED_MEMORY_ACCESS.getAndSetReference(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), - address(bb, indexRO(bb, index)), - convEndian(handle.be, value))); -#else[Object] return convEndian(handle.be, SCOPED_MEMORY_ACCESS.getAndSet$RawType$(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), convEndian(handle.be, value))); -#end[Object] } @ForceInline @@ -847,7 +419,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); return convEndian(handle.be, SCOPED_MEMORY_ACCESS.getAndSet$RawType$Acquire(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), convEndian(handle.be, value))); } @@ -858,7 +430,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); return convEndian(handle.be, SCOPED_MEMORY_ACCESS.getAndSet$RawType$Release(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), convEndian(handle.be, value))); } @@ -871,7 +443,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), delta); } else { @@ -885,7 +457,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$Acquire(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), delta); } else { @@ -899,7 +471,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$Release(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), delta); } else { @@ -910,7 +482,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { @ForceInline static $type$ getAndAddConvEndianWithCAS(ByteBuffer bb, int index, $type$ delta) { $type$ nativeExpectedValue, expectedValue; - Object base = UNSAFE.getReference(bb, BYTE_BUFFER_HB); + Object base = checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)); long offset = address(bb, indexRO(bb, index)); do { nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(session(bb), base, offset); @@ -928,7 +500,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), value); } else { @@ -942,7 +514,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$Release(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), value); } else { @@ -956,7 +528,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$Acquire(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), value); } else { @@ -967,7 +539,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { @ForceInline static $type$ getAndBitwiseOrConvEndianWithCAS(ByteBuffer bb, int index, $type$ value) { $type$ nativeExpectedValue, expectedValue; - Object base = UNSAFE.getReference(bb, BYTE_BUFFER_HB); + Object base = checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)); long offset = address(bb, indexRO(bb, index)); do { nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(session(bb), base, offset); @@ -983,7 +555,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), value); } else { @@ -997,7 +569,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$Release(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), value); } else { @@ -1011,7 +583,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$Acquire(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), value); } else { @@ -1022,7 +594,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { @ForceInline static $type$ getAndBitwiseAndConvEndianWithCAS(ByteBuffer bb, int index, $type$ value) { $type$ nativeExpectedValue, expectedValue; - Object base = UNSAFE.getReference(bb, BYTE_BUFFER_HB); + Object base = checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)); long offset = address(bb, indexRO(bb, index)); do { nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(session(bb), base, offset); @@ -1039,7 +611,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), value); } else { @@ -1053,7 +625,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$Release(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), value); } else { @@ -1067,7 +639,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb); if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$Acquire(session(bb), - UNSAFE.getReference(bb, BYTE_BUFFER_HB), + checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)), address(bb, indexRO(bb, index)), value); } else { @@ -1078,7 +650,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { @ForceInline static $type$ getAndBitwiseXorConvEndianWithCAS(ByteBuffer bb, int index, $type$ value) { $type$ nativeExpectedValue, expectedValue; - Object base = UNSAFE.getReference(bb, BYTE_BUFFER_HB); + Object base = checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)); long offset = address(bb, indexRO(bb, index)); do { nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(session(bb), base, offset); diff --git a/src/java.base/share/classes/java/nio/MappedByteBuffer.java b/src/java.base/share/classes/java/nio/MappedByteBuffer.java index 8b51d602f28aa..9740046322db0 100644 --- a/src/java.base/share/classes/java/nio/MappedByteBuffer.java +++ b/src/java.base/share/classes/java/nio/MappedByteBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -422,6 +422,7 @@ public final MappedByteBuffer rewind() { /** * {@inheritDoc} + * @throws ReadOnlyBufferException {@inheritDoc} */ @Override public abstract MappedByteBuffer compact(); diff --git a/src/java.base/share/classes/java/nio/X-Buffer.java.template b/src/java.base/share/classes/java/nio/X-Buffer.java.template index 2146c86a577e2..1b378a2ef4a91 100644 --- a/src/java.base/share/classes/java/nio/X-Buffer.java.template +++ b/src/java.base/share/classes/java/nio/X-Buffer.java.template @@ -1557,7 +1557,7 @@ public abstract sealed class $Type$Buffer super.position(newPosition); return this; } - + /** * {@inheritDoc} * @since 9 @@ -1571,13 +1571,13 @@ public abstract sealed class $Type$Buffer super.limit(newLimit); return this; } - + /** * {@inheritDoc} * @since 9 */ @Override - public + public #if[!byte] final #end[!byte] @@ -1591,7 +1591,7 @@ public abstract sealed class $Type$Buffer * @since 9 */ @Override - public + public #if[!byte] final #end[!byte] @@ -1605,7 +1605,7 @@ public abstract sealed class $Type$Buffer * @since 9 */ @Override - public + public #if[!byte] final #end[!byte] @@ -1619,7 +1619,7 @@ public abstract sealed class $Type$Buffer * @since 9 */ @Override - public + public #if[!byte] final #end[!byte] @@ -1633,7 +1633,7 @@ public abstract sealed class $Type$Buffer * @since 9 */ @Override - public + public #if[!byte] final #end[!byte] @@ -2208,15 +2208,11 @@ public abstract sealed class $Type$Buffer * alignmentOffset(index + (unitSize - value), unitSize) == 0 * } * must hold. - * + * * @apiNote * This method may be utilized to determine if unit size bytes from an * index can be accessed atomically, if supported by the native platform. * - * @implNote - * This implementation throws {@code UnsupportedOperationException} for - * non-direct buffers when the given unit size is greater then {@code 8}. - * * @param index * The index to query for alignment offset, must be non-negative, no * upper bounds check is performed @@ -2231,13 +2227,7 @@ public abstract sealed class $Type$Buffer * {@code 2} * * @throws UnsupportedOperationException - * If the native platform does not guarantee stable alignment offset - * values for the given unit size when managing the memory regions - * of buffers of the same kind as this buffer (direct or - * non-direct). For example, if garbage collection would result - * in the moving of a memory region covered by a non-direct buffer - * from one location to another and both locations have different - * alignment characteristics. + * If the buffer is non-direct, and {@code unitSize > 1} * * @see #alignedSlice(int) * @since 9 @@ -2247,7 +2237,7 @@ public abstract sealed class $Type$Buffer throw new IllegalArgumentException("Index less than zero: " + index); if (unitSize < 1 || (unitSize & (unitSize - 1)) != 0) throw new IllegalArgumentException("Unit size not a power of two: " + unitSize); - if (unitSize > 8 && !isDirect()) + if (unitSize > 1 && !isDirect()) throw new UnsupportedOperationException("Unit size unsupported for non-direct buffers: " + unitSize); return (int) ((address + index) & (unitSize - 1)); @@ -2287,10 +2277,6 @@ public abstract sealed class $Type$Buffer * from index, that is a multiple of the unit size, may be accessed * atomically, if supported by the native platform. * - * @implNote - * This implementation throws {@code UnsupportedOperationException} for - * non-direct buffers when the given unit size is greater then {@code 8}. - * * @param unitSize * The unit size in bytes, must be a power of {@code 2} * @@ -2300,13 +2286,7 @@ public abstract sealed class $Type$Buffer * If the unit size not a power of {@code 2} * * @throws UnsupportedOperationException - * If the native platform does not guarantee stable aligned slices - * for the given unit size when managing the memory regions - * of buffers of the same kind as this buffer (direct or - * non-direct). For example, if garbage collection would result - * in the moving of a memory region covered by a non-direct buffer - * from one location to another and both locations have different - * alignment characteristics. + * If the buffer is non-direct, and {@code unitSize > 1} * * @see #alignmentOffset(int, int) * @see #slice() diff --git a/src/java.base/share/classes/java/util/zip/ZipInputStream.java b/src/java.base/share/classes/java/util/zip/ZipInputStream.java index 216a914f023da..89fe159d5754c 100644 --- a/src/java.base/share/classes/java/util/zip/ZipInputStream.java +++ b/src/java.base/share/classes/java/util/zip/ZipInputStream.java @@ -92,6 +92,9 @@ public class ZipInputStream extends InflaterInputStream implements ZipConstants private ZipCoder zc; + // Flag to indicate readEnd should expect 64 bit Data Descriptor size fields + private boolean expect64BitDataDescriptor; + /** * Check to make sure that this stream has not been closed */ @@ -521,6 +524,13 @@ private ZipEntry readLOC() throws IOException { } e.method = get16(tmpbuf, LOCHOW); e.xdostime = get32(tmpbuf, LOCTIM); + + // Expect 32-bit Data Descriptor size fields by default + expect64BitDataDescriptor = false; + + long csize = get32(tmpbuf, LOCSIZ); + long size = get32(tmpbuf, LOCLEN); + if ((flag & 8) == 8) { /* "Data Descriptor" present */ if (e.method != DEFLATED) { @@ -529,8 +539,8 @@ private ZipEntry readLOC() throws IOException { } } else { e.crc = get32(tmpbuf, LOCCRC); - e.csize = get32(tmpbuf, LOCSIZ); - e.size = get32(tmpbuf, LOCLEN); + e.csize = csize; + e.size = size; } len = get16(tmpbuf, LOCEXT); if (len > 0) { @@ -538,6 +548,8 @@ private ZipEntry readLOC() throws IOException { readFully(extra, 0, len); e.setExtra0(extra, e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL, true); + // Determine if readEnd should expect 64-bit size fields in the Data Descriptor + expect64BitDataDescriptor = expect64BitDataDescriptor(extra, flag, csize, size); } return e; } @@ -577,7 +589,8 @@ private void readEnd(ZipEntry e) throws IOException { if ((flag & 8) == 8) { /* "Data Descriptor" present */ if (inf.getBytesWritten() > ZIP64_MAGICVAL || - inf.getBytesRead() > ZIP64_MAGICVAL) { + inf.getBytesRead() > ZIP64_MAGICVAL || + expect64BitDataDescriptor) { // ZIP64 format readFully(tmpbuf, 0, ZIP64_EXTHDR); long sig = get32(tmpbuf, 0); @@ -625,6 +638,49 @@ private void readEnd(ZipEntry e) throws IOException { } } + /** + * Determine whether the {@link #readEnd(ZipEntry)} method should interpret the + * 'compressed size' and 'uncompressed size' fields of the Data Descriptor record + * as 64-bit numbers instead of the regular 32-bit numbers. + * + * Returns true if the LOC has the 'streaming mode' flag set, at least one of the + * 'compressed size' and 'uncompressed size' are set to the Zip64 magic value + * 0xFFFFFFFF, and the LOC's extra field contains a Zip64 Extended Information Field. + * + * @param extra the LOC extra field to look for a Zip64 field in + * @param flag the value of the 'general purpose bit flag' field in the LOC + * @param csize the value of the 'compressed size' field in the LOC + * @param size the value of the 'uncompressed size' field in the LOC + */ + private boolean expect64BitDataDescriptor(byte[] extra, int flag, long csize, long size) { + // The LOC's 'general purpose bit flag' 3 must indicate use of a Data Descriptor + if ((flag & 8) == 0) { + return false; + } + + // At least one LOC size field must be marked for Zip64 + if (csize != ZIP64_MAGICVAL && size != ZIP64_MAGICVAL) { + return false; + } + + // Look for a Zip64 field + int headerSize = 2 * Short.BYTES; // id + size + if (extra != null) { + for (int i = 0; i + headerSize < extra.length;) { + int id = get16(extra, i); + int dsize = get16(extra, i + Short.BYTES); + if (i + headerSize + dsize > extra.length) { + return false; // Invalid size + } + if (id == ZIP64_EXTID) { + return true; + } + i += headerSize + dsize; + } + } + return false; + } + /* * Reads bytes, blocking until all bytes are read. */ diff --git a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java index 2c14fa9687edd..636230d8f38b1 100644 --- a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -857,20 +857,18 @@ public long transferTo(long position, long count, WritableByteChannel target) if (position > sz) return 0; - // Now position <= sz so remaining >= 0 and - // remaining == 0 if and only if sz == 0 - long remaining = sz - position; - - // Adjust count only if remaining > 0, i.e., - // sz > position which means sz > 0 - if (remaining > 0 && remaining < count) - count = remaining; - // System calls supporting fast transfers might not work on files // which advertise zero size such as those in Linux /proc if (sz > 0) { - // Attempt a direct transfer, if the kernel supports it, limiting - // the number of bytes according to which platform + // Now sz > 0 and position <= sz so remaining >= 0 and + // remaining == 0 if and only if sz == position + long remaining = sz - position; + + if (remaining >= 0 && remaining < count) + count = remaining; + + // Attempt a direct transfer, if the kernel supports it, + // limiting the number of bytes according to which platform int icount = (int) Math.min(count, nd.maxDirectTransferSize()); long n; if ((n = transferToDirect(position, icount, target)) >= 0) diff --git a/src/java.base/unix/classes/sun/net/www/content-types.properties b/src/java.base/unix/classes/sun/net/www/content-types.properties index 0dbece5902fc5..e056c3ccebef5 100644 --- a/src/java.base/unix/classes/sun/net/www/content-types.properties +++ b/src/java.base/unix/classes/sun/net/www/content-types.properties @@ -26,376 +26,376 @@ temp.file.template: /tmp/%s # The "real" types. # application/octet-stream: \ - description=Generic Binary Stream;\ - file_extensions=.saveme,.dump,.hqx,.arc,.o,.a,.bin,.exe,.z + description=Generic Binary Stream;\ + file_extensions=.saveme,.dump,.hqx,.arc,.o,.a,.bin,.exe,.z application/oda: \ - description=ODA Document;\ - file_extensions=.oda + description=ODA Document;\ + file_extensions=.oda application/pdf: \ - description=Adobe PDF Format;\ - file_extensions=.pdf + description=Adobe PDF Format;\ + file_extensions=.pdf application/postscript: \ - description=Postscript File;\ - file_extensions=.eps,.ai,.ps;\ - icon=ps;\ - action=application;\ - application=imagetool %s + description=Postscript File;\ + file_extensions=.eps,.ai,.ps;\ + icon=ps;\ + action=application;\ + application=imagetool %s application/x-dvi: \ - description=TeX DVI File;\ - file_extensions=.dvi;\ - action=application;\ - application=xdvi %s + description=TeX DVI File;\ + file_extensions=.dvi;\ + action=application;\ + application=xdvi %s application/x-hdf: \ - description=Hierarchical Data Format;\ - file_extensions=.hdf;\ - action=save + description=Hierarchical Data Format;\ + file_extensions=.hdf;\ + action=save application/x-latex: \ - description=LaTeX Source;\ - file_extensions=.latex + description=LaTeX Source;\ + file_extensions=.latex application/x-netcdf: \ - description=Unidata netCDF Data Format;\ - file_extensions=.nc,.cdf;\ - action=save + description=Unidata netCDF Data Format;\ + file_extensions=.nc,.cdf;\ + action=save application/x-tex: \ - description=TeX Source;\ - file_extensions=.tex + description=TeX Source;\ + file_extensions=.tex application/x-texinfo: \ - description=Gnu Texinfo;\ - file_extensions=.texinfo,.texi + description=Gnu Texinfo;\ + file_extensions=.texinfo,.texi application/x-troff: \ - description=Troff Source;\ - file_extensions=.t,.tr,.roff;\ - action=application;\ - application=xterm -title troff -e sh -c \"nroff %s | col | more -w\" + description=Troff Source;\ + file_extensions=.t,.tr,.roff;\ + action=application;\ + application=xterm -title troff -e sh -c \"nroff %s | col | more -w\" application/x-troff-man: \ - description=Troff Manpage Source;\ - file_extensions=.man;\ - action=application;\ - application=xterm -title troff -e sh -c \"nroff -man %s | col | more -w\" + description=Troff Manpage Source;\ + file_extensions=.man;\ + action=application;\ + application=xterm -title troff -e sh -c \"nroff -man %s | col | more -w\" application/x-troff-me: \ - description=Troff ME Macros;\ - file_extensions=.me;\ - action=application;\ - application=xterm -title troff -e sh -c \"nroff -me %s | col | more -w\" + description=Troff ME Macros;\ + file_extensions=.me;\ + action=application;\ + application=xterm -title troff -e sh -c \"nroff -me %s | col | more -w\" application/x-troff-ms: \ - description=Troff MS Macros;\ - file_extensions=.ms;\ - action=application;\ - application=xterm -title troff -e sh -c \"nroff -ms %s | col | more -w\" + description=Troff MS Macros;\ + file_extensions=.ms;\ + action=application;\ + application=xterm -title troff -e sh -c \"nroff -ms %s | col | more -w\" application/x-wais-source: \ - description=Wais Source;\ - file_extensions=.src,.wsrc + description=Wais Source;\ + file_extensions=.src,.wsrc application/zip: \ - description=Zip File;\ - file_extensions=.zip;\ - icon=zip;\ - action=save + description=Zip File;\ + file_extensions=.zip;\ + icon=zip;\ + action=save application/x-bcpio: \ - description=Old Binary CPIO Archive;\ - file_extensions=.bcpio; action=save + description=Old Binary CPIO Archive;\ + file_extensions=.bcpio; action=save application/x-cpio: \ - description=Unix CPIO Archive;\ - file_extensions=.cpio; action=save + description=Unix CPIO Archive;\ + file_extensions=.cpio; action=save application/x-gtar: \ - description=Gnu Tar Archive;\ - file_extensions=.gtar;\ - icon=tar;\ - action=save + description=Gnu Tar Archive;\ + file_extensions=.gtar;\ + icon=tar;\ + action=save application/x-shar: \ - description=Shell Archive;\ - file_extensions=.sh,.shar;\ - action=save + description=Shell Archive;\ + file_extensions=.sh,.shar;\ + action=save application/x-sv4cpio: \ - description=SVR4 CPIO Archive;\ - file_extensions=.sv4cpio; action=save + description=SVR4 CPIO Archive;\ + file_extensions=.sv4cpio; action=save application/x-sv4crc: \ - description=SVR4 CPIO with CRC;\ - file_extensions=.sv4crc; action=save + description=SVR4 CPIO with CRC;\ + file_extensions=.sv4crc; action=save application/x-tar: \ - description=Tar Archive;\ - file_extensions=.tar;\ - icon=tar;\ - action=save + description=Tar Archive;\ + file_extensions=.tar;\ + icon=tar;\ + action=save application/x-ustar: \ - description=US Tar Archive;\ - file_extensions=.ustar;\ - action=save + description=US Tar Archive;\ + file_extensions=.ustar;\ + action=save audio/aac: \ - description=Advanced Audio Coding Audio;\ - file_extensions=.aac + description=Advanced Audio Coding Audio;\ + file_extensions=.aac audio/basic: \ - description=Basic Audio;\ - file_extensions=.snd,.au;\ - icon=audio;\ - action=application;\ - application=audiotool %s + description=Basic Audio;\ + file_extensions=.snd,.au;\ + icon=audio;\ + action=application;\ + application=audiotool %s audio/flac: \ - description=Free Lossless Audio Codec Audio;\ - file_extensions=.flac + description=Free Lossless Audio Codec Audio;\ + file_extensions=.flac audio/mp4: \ - description=MPEG-4 Audio;\ - file_extensions=.m4a + description=MPEG-4 Audio;\ + file_extensions=.m4a audio/mpeg: \ - description=MPEG Audio;\ - file_extensions=.mp2,.mp3 + description=MPEG Audio;\ + file_extensions=.mp2,.mp3 audio/ogg: \ - description=Ogg Audio;\ - file_extensions=.oga,.ogg,.opus,.spx + description=Ogg Audio;\ + file_extensions=.oga,.ogg,.opus,.spx audio/x-aiff: \ - description=Audio Interchange Format File;\ - file_extensions=.aifc,.aif,.aiff;\ - icon=aiff + description=Audio Interchange Format File;\ + file_extensions=.aifc,.aif,.aiff;\ + icon=aiff audio/x-wav: \ - description=Wav Audio;\ - file_extensions=.wav;\ - icon=wav + description=Wav Audio;\ + file_extensions=.wav;\ + icon=wav image/gif: \ - description=GIF Image;\ - file_extensions=.gif;\ - icon=gif;\ - action=browser + description=GIF Image;\ + file_extensions=.gif;\ + icon=gif;\ + action=browser image/ief: \ - description=Image Exchange Format;\ - file_extensions=.ief + description=Image Exchange Format;\ + file_extensions=.ief image/jpeg: \ - description=JPEG Image;\ - file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\ - icon=jpeg;\ - action=browser;\ - application=imagetool %s + description=JPEG Image;\ + file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\ + icon=jpeg;\ + action=browser;\ + application=imagetool %s image/svg+xml: \ - description=Scalable Vector Graphics;\ - file_extensions=.svg,.svgz + description=Scalable Vector Graphics;\ + file_extensions=.svg,.svgz image/tiff: \ - description=TIFF Image;\ - file_extensions=.tif,.tiff;\ - icon=tiff + description=TIFF Image;\ + file_extensions=.tif,.tiff;\ + icon=tiff image/vnd.fpx: \ - description=FlashPix Image;\ - file_extensions=.fpx,.fpix + description=FlashPix Image;\ + file_extensions=.fpx,.fpix image/x-cmu-rast: \ - description=CMU Raster Image;\ - file_extensions=.ras + description=CMU Raster Image;\ + file_extensions=.ras image/x-portable-anymap: \ - description=PBM Anymap Format;\ - file_extensions=.pnm + description=PBM Anymap Format;\ + file_extensions=.pnm image/x-portable-bitmap: \ - description=PBM Bitmap Format;\ - file_extensions=.pbm + description=PBM Bitmap Format;\ + file_extensions=.pbm image/x-portable-graymap: \ - description=PBM Graymap Format;\ - file_extensions=.pgm + description=PBM Graymap Format;\ + file_extensions=.pgm image/x-portable-pixmap: \ - description=PBM Pixmap Format;\ - file_extensions=.ppm + description=PBM Pixmap Format;\ + file_extensions=.ppm image/x-rgb: \ - description=RGB Image;\ - file_extensions=.rgb + description=RGB Image;\ + file_extensions=.rgb image/x-xbitmap: \ - description=X Bitmap Image;\ - file_extensions=.xbm,.xpm + description=X Bitmap Image;\ + file_extensions=.xbm,.xpm image/x-xwindowdump: \ - description=X Window Dump Image;\ - file_extensions=.xwd + description=X Window Dump Image;\ + file_extensions=.xwd image/png: \ - description=PNG Image;\ - file_extensions=.png;\ - icon=png;\ - action=browser + description=PNG Image;\ + file_extensions=.png;\ + icon=png;\ + action=browser image/bmp: \ - description=Bitmap Image;\ - file_extensions=.bmp; + description=Bitmap Image;\ + file_extensions=.bmp; image/webp: \ - description=WEBP image;\ - file_extensions=.webp; + description=WEBP image;\ + file_extensions=.webp; text/css: \ - description=CSS File;\ - file_extensions=.css; + description=CSS File;\ + file_extensions=.css; text/html: \ - description=HTML Document;\ - file_extensions=.htm,.html;\ - icon=html + description=HTML Document;\ + file_extensions=.htm,.html;\ + icon=html text/javascript: \ - description=JavaScript File;\ - file_extensions=.js; + description=JavaScript File;\ + file_extensions=.js; text/plain: \ - description=Plain Text;\ - file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el,.php,.adoc,.py;\ - icon=text;\ - action=browser + description=Plain Text;\ + file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el,.php,.adoc,.py;\ + icon=text;\ + action=browser text/tab-separated-values: \ - description=Tab Separated Values Text;\ - file_extensions=.tsv + description=Tab Separated Values Text;\ + file_extensions=.tsv text/x-setext: \ - description=Structure Enhanced Text;\ - file_extensions=.etx + description=Structure Enhanced Text;\ + file_extensions=.etx text/csv: \ - description=CSV File;\ - file_extensions=.csv; + description=CSV File;\ + file_extensions=.csv; text/markdown: \ - description=Markdown File;\ - file_extensions=.md,.markdown + description=Markdown File;\ + file_extensions=.md,.markdown video/mp4: \ - description=MPEG-4 Video;\ - file_extensions=.m4v,.mp4 + description=MPEG-4 Video;\ + file_extensions=.m4v,.mp4 video/mpeg: \ - description=MPEG Video Clip;\ - file_extensions=.mpg,.mpe,.mpeg;\ - icon=mpeg;\ - action=application;\ - application=mpeg_play %s + description=MPEG Video Clip;\ + file_extensions=.mpg,.mpe,.mpeg;\ + icon=mpeg;\ + action=application;\ + application=mpeg_play %s video/ogg: \ - description=Ogg Video;\ - file_extensions=.ogv + description=Ogg Video;\ + file_extensions=.ogv video/quicktime: \ - description=QuickTime Video Clip;\ - file_extensions=.mov,.qt + description=QuickTime Video Clip;\ + file_extensions=.mov,.qt video/webm: \ - description=WebM Video;\ - file_extensions=.webm + description=WebM Video;\ + file_extensions=.webm application/x-troff-msvideo: \ - description=AVI Video;\ - file_extensions=.avi;\ - icon=avi + description=AVI Video;\ + file_extensions=.avi;\ + icon=avi video/x-sgi-movie: \ - description=SGI Movie;\ - file_extensions=.movie,.mv + description=SGI Movie;\ + file_extensions=.movie,.mv message/rfc822: \ - description=Internet Email Message;\ - file_extensions=.mime + description=Internet Email Message;\ + file_extensions=.mime application/xml: \ - description=XML document;\ - file_extensions=.xml + description=XML document;\ + file_extensions=.xml application/rtf: \ - description=WordPad Document;\ - file_extensions=.rtf; + description=WordPad Document;\ + file_extensions=.rtf; application/gzip: \ - description=GZip File;\ - file_extensions=.gz; + description=GZip File;\ + file_extensions=.gz; application/vnd.oasis.opendocument.presentation: \ - description=OpenDocument presentation document;\ - file_extensions=.odp; + description=OpenDocument presentation document;\ + file_extensions=.odp; application/vnd.oasis.opendocument.spreadsheet: \ - description=OpenDocument spreadsheet document;\ - file_extensions=.ods; + description=OpenDocument spreadsheet document;\ + file_extensions=.ods; application/vnd.oasis.opendocument.text: \ - description=OpenDocument text document;\ - file_extensions=.odt; + description=OpenDocument text document;\ + file_extensions=.odt; application/vnd.ms-excel: \ - description=Microsoft Excel File;\ - file_extensions=.xls; + description=Microsoft Excel File;\ + file_extensions=.xls; application/vnd.openxmlformats-officedocument.spreadsheetml.sheet: \ - description=XLSX File;\ - file_extensions=.xlsx; + description=XLSX File;\ + file_extensions=.xlsx; application/vnd.openxmlformats-officedocument.presentationml.presentation: \ - description=PPTX File;\ - file_extensions=.pptx; + description=PPTX File;\ + file_extensions=.pptx; application/vnd.ms-powerpoint: \ - description=Microsoft PowerPoint File;\ - file_extensions=.ppt; + description=Microsoft PowerPoint File;\ + file_extensions=.ppt; application/x-7z-compressed: \ - description=7-Zip File;\ - file_extensions=.7z; + description=7-Zip File;\ + file_extensions=.7z; application/msword: \ - description=Microsoft Word File;\ - file_extensions=.doc; + description=Microsoft Word File;\ + file_extensions=.doc; application/vnd.openxmlformats-officedocument.wordprocessingml.document: \ - description=DOCX File;\ - file_extensions=.docx; + description=DOCX File;\ + file_extensions=.docx; application/vnd.rar: \ - description=RAR File;\ - file_extensions=.rar; + description=RAR File;\ + file_extensions=.rar; application/json: \ - description=JSON File;\ - file_extensions=.json; + description=JSON File;\ + file_extensions=.json; application/bz2: \ - description=BZ2 File;\ - file_extensions=.bz2; + description=BZ2 File;\ + file_extensions=.bz2; application/java-archive: \ - description=JAR File;\ - file_extensions=.jar; + description=JAR File;\ + file_extensions=.jar; application/wasm: \ - description=WebAssembly File;\ - file_extensions=.wasm; + description=WebAssembly File;\ + file_extensions=.wasm; diff --git a/src/java.base/windows/classes/sun/net/www/content-types.properties b/src/java.base/windows/classes/sun/net/www/content-types.properties index dcd2e5843c04f..24ce247783377 100644 --- a/src/java.base/windows/classes/sun/net/www/content-types.properties +++ b/src/java.base/windows/classes/sun/net/www/content-types.properties @@ -26,369 +26,369 @@ temp.file.template: c:\\temp\\%s # The "real" types. # application/octet-stream: \ - description=Generic Binary Stream;\ - file_extensions=.saveme,.dump,.hqx,.arc,.obj,.lib,.bin,.exe + description=Generic Binary Stream;\ + file_extensions=.saveme,.dump,.hqx,.arc,.obj,.lib,.bin,.exe application/oda: \ - description=ODA Document;\ - file_extensions=.oda + description=ODA Document;\ + file_extensions=.oda application/pdf: \ - description=Adobe PDF Format;\ - file_extensions=.pdf + description=Adobe PDF Format;\ + file_extensions=.pdf application/postscript: \ - description=Postscript File;\ - file_extensions=.eps,.ai,.ps;\ - icon=ps + description=Postscript File;\ + file_extensions=.eps,.ai,.ps;\ + icon=ps application/rtf: \ - description=WordPad Document;\ - file_extensions=.rtf;\ - action=application;\ - application=wordpad.exe %s + description=WordPad Document;\ + file_extensions=.rtf;\ + action=application;\ + application=wordpad.exe %s application/gzip: \ - description=GZip File;\ - file_extensions=.gz; + description=GZip File;\ + file_extensions=.gz; application/x-dvi: \ - description=TeX DVI File;\ - file_extensions=.dvi + description=TeX DVI File;\ + file_extensions=.dvi application/x-hdf: \ - description=Hierarchical Data Format;\ - file_extensions=.hdf;\ - action=save + description=Hierarchical Data Format;\ + file_extensions=.hdf;\ + action=save application/x-latex: \ - description=LaTeX Source;\ - file_extensions=.latex + description=LaTeX Source;\ + file_extensions=.latex application/x-netcdf: \ - description=Unidata netCDF Data Format;\ - file_extensions=.nc,.cdf;\ - action=save + description=Unidata netCDF Data Format;\ + file_extensions=.nc,.cdf;\ + action=save application/x-tex: \ - description=TeX Source;\ - file_extensions=.tex + description=TeX Source;\ + file_extensions=.tex application/x-texinfo: \ - description=Gnu Texinfo;\ - file_extensions=.texinfo,.texi + description=Gnu Texinfo;\ + file_extensions=.texinfo,.texi application/x-troff: \ - description=Troff Source;\ - file_extensions=.t,.tr,.roff + description=Troff Source;\ + file_extensions=.t,.tr,.roff application/x-troff-man: \ - description=Troff Manpage Source;\ - file_extensions=.man + description=Troff Manpage Source;\ + file_extensions=.man application/x-troff-me: \ - description=Troff ME Macros;\ - file_extensions=.me + description=Troff ME Macros;\ + file_extensions=.me application/x-troff-ms: \ - description=Troff MS Macros;\ - file_extensions=.ms + description=Troff MS Macros;\ + file_extensions=.ms application/x-wais-source: \ - description=Wais Source;\ - file_extensions=.src,.wsrc + description=Wais Source;\ + file_extensions=.src,.wsrc application/zip: \ - description=Zip File;\ - file_extensions=.zip;\ - icon=zip;\ - action=save + description=Zip File;\ + file_extensions=.zip;\ + icon=zip;\ + action=save application/x-bcpio: \ - description=Old Binary CPIO Archive;\ - file_extensions=.bcpio;\ - action=save + description=Old Binary CPIO Archive;\ + file_extensions=.bcpio;\ + action=save application/x-cpio: \ - description=Unix CPIO Archive;\ - file_extensions=.cpio;\ - action=save + description=Unix CPIO Archive;\ + file_extensions=.cpio;\ + action=save application/x-gtar: \ - description=Gnu Tar Archive;\ - file_extensions=.gtar;\ - icon=tar;\ - action=save + description=Gnu Tar Archive;\ + file_extensions=.gtar;\ + icon=tar;\ + action=save application/x-shar: \ - description=Shell Archive;\ - file_extensions=.sh,.shar;\ - action=save + description=Shell Archive;\ + file_extensions=.sh,.shar;\ + action=save application/x-sv4cpio: \ - description=SVR4 CPIO Archive;\ - file_extensions=.sv4cpio;\ - action=save + description=SVR4 CPIO Archive;\ + file_extensions=.sv4cpio;\ + action=save application/x-sv4crc: \ - description=SVR4 CPIO with CRC;\ - file_extensions=.sv4crc;\ - action=save + description=SVR4 CPIO with CRC;\ + file_extensions=.sv4crc;\ + action=save application/x-tar: \ - description=Tar Archive;\ - file_extensions=.tar;\ - icon=tar;\ - action=save + description=Tar Archive;\ + file_extensions=.tar;\ + icon=tar;\ + action=save application/x-ustar: \ - description=US Tar Archive;\ - file_extensions=.ustar;\ - action=save + description=US Tar Archive;\ + file_extensions=.ustar;\ + action=save audio/aac: \ - description=Advanced Audio Coding Audio;\ - file_extensions=.aac + description=Advanced Audio Coding Audio;\ + file_extensions=.aac audio/basic: \ - description=Basic Audio;\ - file_extensions=.snd,.au;\ - icon=audio + description=Basic Audio;\ + file_extensions=.snd,.au;\ + icon=audio audio/flac: \ - description=Free Lossless Audio Codec Audio;\ - file_extensions=.flac + description=Free Lossless Audio Codec Audio;\ + file_extensions=.flac audio/mp4: \ - description=MPEG-4 Audio;\ - file_extensions=.m4a + description=MPEG-4 Audio;\ + file_extensions=.m4a audio/mpeg: \ - description=MPEG Audio;\ - file_extensions=.mp2,.mp3 + description=MPEG Audio;\ + file_extensions=.mp2,.mp3 audio/ogg: \ - description=Ogg Audio;\ - file_extensions=.oga,.ogg,.opus,.spx + description=Ogg Audio;\ + file_extensions=.oga,.ogg,.opus,.spx audio/x-aiff: \ - description=Audio Interchange Format File;\ - file_extensions=.aifc,.aif,.aiff;\ - icon=aiff + description=Audio Interchange Format File;\ + file_extensions=.aifc,.aif,.aiff;\ + icon=aiff audio/x-wav: \ - description=Wav Audio;\ - file_extensions=.wav;\ - icon=wav;\ - action=application;\ - application=mplayer.exe %s + description=Wav Audio;\ + file_extensions=.wav;\ + icon=wav;\ + action=application;\ + application=mplayer.exe %s image/gif: \ - description=GIF Image;\ - file_extensions=.gif;\ - icon=gif;\ - action=browser + description=GIF Image;\ + file_extensions=.gif;\ + icon=gif;\ + action=browser image/ief: \ - description=Image Exchange Format;\ - file_extensions=.ief + description=Image Exchange Format;\ + file_extensions=.ief image/jpeg: \ - description=JPEG Image;\ - file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\ - icon=jpeg;\ - action=browser + description=JPEG Image;\ + file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\ + icon=jpeg;\ + action=browser image/svg+xml: \ - description=Scalable Vector Graphics;\ - file_extensions=.svg,.svgz + description=Scalable Vector Graphics;\ + file_extensions=.svg,.svgz image/tiff: \ - description=TIFF Image;\ - file_extensions=.tif,.tiff;\ - icon=tiff + description=TIFF Image;\ + file_extensions=.tif,.tiff;\ + icon=tiff image/vnd.fpx: \ - description=FlashPix Image;\ - file_extensions=.fpx,.fpix + description=FlashPix Image;\ + file_extensions=.fpx,.fpix image/x-cmu-rast: \ - description=CMU Raster Image;\ - file_extensions=.ras + description=CMU Raster Image;\ + file_extensions=.ras image/x-portable-anymap: \ - description=PBM Anymap Image;\ - file_extensions=.pnm + description=PBM Anymap Image;\ + file_extensions=.pnm image/x-portable-bitmap: \ - description=PBM Bitmap Image;\ - file_extensions=.pbm + description=PBM Bitmap Image;\ + file_extensions=.pbm image/x-portable-graymap: \ - description=PBM Graymap Image;\ - file_extensions=.pgm + description=PBM Graymap Image;\ + file_extensions=.pgm image/x-portable-pixmap: \ - description=PBM Pixmap Image;\ - file_extensions=.ppm + description=PBM Pixmap Image;\ + file_extensions=.ppm image/x-rgb: \ - description=RGB Image;\ - file_extensions=.rgb + description=RGB Image;\ + file_extensions=.rgb image/x-xbitmap: \ - description=X Bitmap Image;\ - file_extensions=.xbm,.xpm + description=X Bitmap Image;\ + file_extensions=.xbm,.xpm image/x-xwindowdump: \ - description=X Window Dump Image;\ - file_extensions=.xwd + description=X Window Dump Image;\ + file_extensions=.xwd image/png: \ - description=PNG Image;\ - file_extensions=.png;\ - icon=png;\ - action=browser + description=PNG Image;\ + file_extensions=.png;\ + icon=png;\ + action=browser image/bmp: \ - description=Bitmap Image;\ - file_extensions=.bmp; + description=Bitmap Image;\ + file_extensions=.bmp; image/webp: \ - description=WEBP image;\ - file_extensions=.webp; + description=WEBP image;\ + file_extensions=.webp; text/css: \ - description=CSS File;\ - file_extensions=.css; + description=CSS File;\ + file_extensions=.css; text/html: \ - description=HTML Document;\ - file_extensions=.htm,.html;\ - icon=html + description=HTML Document;\ + file_extensions=.htm,.html;\ + icon=html text/javascript: \ description=JavaScript File;\ file_extensions=.js; text/plain: \ - description=Plain Text;\ - file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el,.php,.adoc,.py;\ - icon=text;\ - action=browser + description=Plain Text;\ + file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el,.php,.adoc,.py;\ + icon=text;\ + action=browser text/tab-separated-values: \ - description=Tab Separated Values Text;\ - file_extensions=.tsv + description=Tab Separated Values Text;\ + file_extensions=.tsv text/x-setext: \ - description=Structure Enhanced Text;\ - file_extensions=.etx + description=Structure Enhanced Text;\ + file_extensions=.etx text/csv: \ - description=CSV File;\ - file_extensions=.csv; + description=CSV File;\ + file_extensions=.csv; text/markdown: \ - description=Markdown File;\ - file_extensions=.md,.markdown + description=Markdown File;\ + file_extensions=.md,.markdown video/mp4: \ - description=MPEG-4 Video;\ - file_extensions=.m4v,.mp4 + description=MPEG-4 Video;\ + file_extensions=.m4v,.mp4 video/mpeg: \ - description=MPEG Video Clip;\ - file_extensions=.mpg,.mpe,.mpeg;\ - icon=mpeg + description=MPEG Video Clip;\ + file_extensions=.mpg,.mpe,.mpeg;\ + icon=mpeg video/ogg: \ - description=Ogg Video;\ - file_extensions=.ogv + description=Ogg Video;\ + file_extensions=.ogv video/quicktime: \ - description=QuickTime Video Clip;\ - file_extensions=.mov,.qt + description=QuickTime Video Clip;\ + file_extensions=.mov,.qt video/webm: \ - description=WebM Video;\ - file_extensions=.webm + description=WebM Video;\ + file_extensions=.webm application/x-troff-msvideo: \ - description=AVI Video;\ - file_extensions=.avi;\ - icon=avi;\ - action=application;\ - application=mplayer.exe %s + description=AVI Video;\ + file_extensions=.avi;\ + icon=avi;\ + action=application;\ + application=mplayer.exe %s video/x-sgi-movie: \ - description=SGI Movie;\ - file_extensions=.movie,.mv + description=SGI Movie;\ + file_extensions=.movie,.mv message/rfc822: \ - description=Internet Email Message;\ - file_extensions=.mime + description=Internet Email Message;\ + file_extensions=.mime application/xml: \ - description=XML document;\ - file_extensions=.xml + description=XML document;\ + file_extensions=.xml application/vnd.oasis.opendocument.presentation: \ - description=OpenDocument presentation document;\ - file_extensions=.odp; + description=OpenDocument presentation document;\ + file_extensions=.odp; application/vnd.oasis.opendocument.spreadsheet: \ - description=OpenDocument spreadsheet document;\ - file_extensions=.ods; + description=OpenDocument spreadsheet document;\ + file_extensions=.ods; application/vnd.oasis.opendocument.text: \ - description=OpenDocument text document;\ - file_extensions=.odt; + description=OpenDocument text document;\ + file_extensions=.odt; application/vnd.ms-excel: \ - description=Microsoft Excel File;\ - file_extensions=.xls; + description=Microsoft Excel File;\ + file_extensions=.xls; application/vnd.openxmlformats-officedocument.spreadsheetml.sheet: \ - description=XLSX File;\ - file_extensions=.xlsx; + description=XLSX File;\ + file_extensions=.xlsx; application/vnd.openxmlformats-officedocument.presentationml.presentation: \ - description=PPTX File;\ - file_extensions=.pptx; + description=PPTX File;\ + file_extensions=.pptx; application/vnd.ms-powerpoint: \ - description=Microsoft PowerPoint File;\ - file_extensions=.ppt; + description=Microsoft PowerPoint File;\ + file_extensions=.ppt; application/x-7z-compressed: \ - description=7-Zip File;\ - file_extensions=.7z; + description=7-Zip File;\ + file_extensions=.7z; application/msword: \ - description=Microsoft Word File;\ - file_extensions=.doc; + description=Microsoft Word File;\ + file_extensions=.doc; application/vnd.openxmlformats-officedocument.wordprocessingml.document: \ - description=DOCX File;\ - file_extensions=.docx; + description=DOCX File;\ + file_extensions=.docx; application/vnd.rar: \ - description=RAR File;\ - file_extensions=.rar; + description=RAR File;\ + file_extensions=.rar; application/json: \ - description=JSON File;\ - file_extensions=.json; + description=JSON File;\ + file_extensions=.json; application/bz2: \ - description=BZ2 File;\ - file_extensions=.bz2; + description=BZ2 File;\ + file_extensions=.bz2; application/java-archive: \ - description=JAR File;\ - file_extensions=.jar; + description=JAR File;\ + file_extensions=.jar; application/wasm: \ - description=WebAssembly File;\ - file_extensions=.wasm; + description=WebAssembly File;\ + file_extensions=.wasm; diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/iio-plugin.properties b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/iio-plugin.properties index 5b9e47b921530..214d9d69b652a 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/iio-plugin.properties +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/iio-plugin.properties @@ -8,7 +8,7 @@ # Common properties ImageUtil0=The supplied Raster does not represent a binary data set. ImageUtil1=The provided sample model is null. -ImageUtil2=The provided image cannot be encoded using: +ImageUtil2=The provided image cannot be encoded using: GetNumImages0=Input has not been set. GetNumImages1=seekForwardOnly and allowSearch cannot both be true. diff --git a/src/java.scripting/share/classes/com/sun/tools/script/shell/messages.properties b/src/java.scripting/share/classes/com/sun/tools/script/shell/messages.properties index 2e17668b26019..096842465b65e 100644 --- a/src/java.scripting/share/classes/com/sun/tools/script/shell/messages.properties +++ b/src/java.scripting/share/classes/com/sun/tools/script/shell/messages.properties @@ -24,22 +24,22 @@ # string.script.error=\ - script error: {0} + script error: {0} file.script.error=\ - script error in file {0} : {1} + script error in file {0} : {1} file.not.found=\ - script file {0} is not found + script file {0} is not found engine.not.found=\ - script engine for language {0} can not be found + script engine for language {0} can not be found engine.info=\ - Language {0} {1} implementation "{2}" {3} + Language {0} {1} implementation "{2}" {3} encoding.unsupported=\ - encoding {0} is not supported + encoding {0} is not supported main.usage=\ Usage: {0} [options] [arguments...]\n\ diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle.properties index 83738d94afdf2..9f30c93e1beaa 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle.properties @@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = getInt Failed on value ( {0} ) in column {1} cachedrowsetimpl.longfail = getLong Failed on value ( {0} ) in column {1} cachedrowsetimpl.floatfail = getFloat failed on value ( {0} ) in column {1} cachedrowsetimpl.doublefail = getDouble failed on value ( {0} ) in column {1} -cachedrowsetimpl.dtypemismt = Data Type Mismatch +cachedrowsetimpl.dtypemismt = Data Type Mismatch cachedrowsetimpl.datefail = getDate Failed on value ( {0} ) in column {1} no conversion available cachedrowsetimpl.timefail = getTime failed on value ( {0} ) in column {1} no conversion available cachedrowsetimpl.posupdate = Positioned updates not supported @@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = Use column name as argument to unsetMatchColumn cachedrowsetimpl.unsetmatch2 = Use column ID as argument to unsetMatchColumn cachedrowsetimpl.numrows = Number of rows is less than zero or less than fetch size cachedrowsetimpl.startpos = Start position cannot be negative -cachedrowsetimpl.nextpage = Populate data before calling +cachedrowsetimpl.nextpage = Populate data before calling cachedrowsetimpl.pagesize = Page size cannot be less than zero cachedrowsetimpl.pagesize1 = Page size cannot be greater than maxRows cachedrowsetimpl.fwdonly = ResultSet is forward only @@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = Invalid writer webrowsetimpl.invalidrd = Invalid reader #FilteredRowSetImpl exceptions -filteredrowsetimpl.relative = relative : Invalid cursor operation +filteredrowsetimpl.relative = relative : Invalid cursor operation filteredrowsetimpl.absolute = absolute : Invalid cursor operation filteredrowsetimpl.notallowed = This value is not allowed through the filter @@ -123,15 +123,15 @@ crsreader.caldetected = Detected a Calendar #CachedRowSetWriter exceptions crswriter.connect = Unable to get connection crswriter.tname = writeData cannot determine table name -crswriter.params1 = Value of params1 : {0} -crswriter.params2 = Value of params2 : {0} -crswriter.conflictsno = conflicts while synchronizing +crswriter.params1 = Value of params1 : {0} +crswriter.params2 = Value of params2 : {0} +crswriter.conflictsno = conflicts while synchronizing #InsertRow exceptions insertrow.novalue = No value has been inserted #SyncResolverImpl exceptions -syncrsimpl.indexval = Index value out of range +syncrsimpl.indexval = Index value out of range syncrsimpl.noconflict = This column not in conflict syncrsimpl.syncnotpos = Synchronization is not possible syncrsimpl.valtores = Value to be resolved can either be in the database or in cachedrowset diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties index 333a5c9e4faaf..1cccbe3774916 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties @@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = getInt bei Wert ( {0} ) in Spalte {1} nicht erfolgrei cachedrowsetimpl.longfail = getLong bei Wert ( {0} ) in Spalte {1} nicht erfolgreich cachedrowsetimpl.floatfail = getFloat bei Wert ( {0} ) in Spalte {1} nicht erfolgreich cachedrowsetimpl.doublefail = getDouble bei Wert ( {0} ) in Spalte {1} nicht erfolgreich -cachedrowsetimpl.dtypemismt = Keine Datentypübereinstimmung +cachedrowsetimpl.dtypemismt = Keine Datentypübereinstimmung cachedrowsetimpl.datefail = getDate bei Wert ( {0} ) in Spalte {1} nicht erfolgreich. Keine Konvertierung möglich cachedrowsetimpl.timefail = getTime bei Wert ( {0} ) in Spalte {1} nicht erfolgreich. Keine Konvertierung möglich cachedrowsetimpl.posupdate = Positionierte Updates werden nicht unterstützt @@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = Spaltenname als Argument für unsetMatchColumn ve cachedrowsetimpl.unsetmatch2 = Spalten-ID als Argument für unsetMatchColumn verwenden cachedrowsetimpl.numrows = Zeilenanzahl ist kleiner als null oder kleiner als Abrufgröße cachedrowsetimpl.startpos = Startposition darf keinen Negativwert aufweisen -cachedrowsetimpl.nextpage = Daten müssen vor dem Aufruf ausgefüllt werden +cachedrowsetimpl.nextpage = Daten müssen vor dem Aufruf ausgefüllt werden cachedrowsetimpl.pagesize = Seitengröße darf nicht kleiner als null sein cachedrowsetimpl.pagesize1 = Seitengröße darf nicht größer als maxRows sein cachedrowsetimpl.fwdonly = ResultSet kann nur vorwärts gerichtet sein @@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = Ungültiger Writer webrowsetimpl.invalidrd = Ungültiger Reader #FilteredRowSetImpl exceptions -filteredrowsetimpl.relative = relative: Ungültiger Cursorvorgang +filteredrowsetimpl.relative = relative: Ungültiger Cursorvorgang filteredrowsetimpl.absolute = absolute: Ungültiger Cursorvorgang filteredrowsetimpl.notallowed = Kein zulässiger Wert im Filter @@ -123,15 +123,15 @@ crsreader.caldetected = Kalender festgestellt #CachedRowSetWriter exceptions crswriter.connect = Verbindung kann nicht hergestellt werden crswriter.tname = writeData kann Tabellennamen nicht bestimmen -crswriter.params1 = Wert für params1: {0} -crswriter.params2 = Wert für params2: {0} -crswriter.conflictsno = Konflikte beim Synchronisieren +crswriter.params1 = Wert für params1: {0} +crswriter.params2 = Wert für params2: {0} +crswriter.conflictsno = Konflikte beim Synchronisieren #InsertRow exceptions insertrow.novalue = Es wurde kein Wert eingefügt #SyncResolverImpl exceptions -syncrsimpl.indexval = Indexwert liegt außerhalb des Bereichs +syncrsimpl.indexval = Indexwert liegt außerhalb des Bereichs syncrsimpl.noconflict = Kein Konflikt bei dieser Spalte syncrsimpl.syncnotpos = Keine Synchronisierung möglich syncrsimpl.valtores = Aufzulösender Wert kann sich entweder in der Datenbank oder in cachedrowset befinden diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_es.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_es.properties index f60fdc07675a3..3793ed8528870 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_es.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_es.properties @@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = Fallo de getInt en valor ( {0} ) de columna {1} cachedrowsetimpl.longfail = Fallo de getLong en valor ( {0} ) de columna {1} cachedrowsetimpl.floatfail = Fallo de getFloat en valor ( {0} ) de columna {1} cachedrowsetimpl.doublefail = Fallo de getDouble en valor ( {0} ) de columna {1} -cachedrowsetimpl.dtypemismt = Discordancia entre Tipos de Datos +cachedrowsetimpl.dtypemismt = Discordancia entre Tipos de Datos cachedrowsetimpl.datefail = Fallo de getDate en valor ( {0} ) de columna {1}. No es posible convertir cachedrowsetimpl.timefail = Fallo de getTime en valor ( {0} ) de columna {1}. No es posible convertir cachedrowsetimpl.posupdate = Actualizaciones posicionadas no soportadas @@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = Use el nombre de columna como argumento en unsetM cachedrowsetimpl.unsetmatch2 = Use el identificador de columna como argumento en unsetMatchColumn cachedrowsetimpl.numrows = El número de filas es menor que cero o menor que el tamaño recuperado cachedrowsetimpl.startpos = La posición de inicio no puede ser negativa -cachedrowsetimpl.nextpage = Rellene los datos antes de realizar la llamada +cachedrowsetimpl.nextpage = Rellene los datos antes de realizar la llamada cachedrowsetimpl.pagesize = El tamaño de página no puede ser menor que cero cachedrowsetimpl.pagesize1 = El tamaño de página no puede ser mayor que maxRows cachedrowsetimpl.fwdonly = ResultSet sólo se reenvía @@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = Escritor no válido webrowsetimpl.invalidrd = Lector no válido #FilteredRowSetImpl exceptions -filteredrowsetimpl.relative = relative: Operación de cursor no válida +filteredrowsetimpl.relative = relative: Operación de cursor no válida filteredrowsetimpl.absolute = absolute: Operación de cursor no válida filteredrowsetimpl.notallowed = El filtro no admite este valor @@ -123,15 +123,15 @@ crsreader.caldetected = Calendario Detectado #CachedRowSetWriter exceptions crswriter.connect = No se ha podido obtener una conexión crswriter.tname = writeData no puede determinar el nombre de tabla -crswriter.params1 = Valor de params1: {0} -crswriter.params2 = Valor de params2: {0} -crswriter.conflictsno = conflictos en la sincronización +crswriter.params1 = Valor de params1: {0} +crswriter.params2 = Valor de params2: {0} +crswriter.conflictsno = conflictos en la sincronización #InsertRow exceptions insertrow.novalue = No se ha insertado ningún valor #SyncResolverImpl exceptions -syncrsimpl.indexval = El valor de índice está fuera de rango +syncrsimpl.indexval = El valor de índice está fuera de rango syncrsimpl.noconflict = Esta columna no está en conflicto syncrsimpl.syncnotpos = No se puede sincronizar syncrsimpl.valtores = El valor que se debe resolver puede estar en la base de datos o en cachedrowset diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_fr.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_fr.properties index 358ab13f1ebc8..48dc5e0d12dd5 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_fr.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_fr.properties @@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = Echec de getInt pour la valeur ({0}) de la colonne {1 cachedrowsetimpl.longfail = Echec de getLong pour la valeur ({0}) de la colonne {1} cachedrowsetimpl.floatfail = Echec de getFloat pour la valeur ({0}) de la colonne {1} cachedrowsetimpl.doublefail = Echec de getDouble pour la valeur ({0}) de la colonne {1} -cachedrowsetimpl.dtypemismt = Le type de données ne correspond pas +cachedrowsetimpl.dtypemismt = Le type de données ne correspond pas cachedrowsetimpl.datefail = Echec de getDate pour la valeur ({0}) de la colonne {1} - Aucune conversion possible cachedrowsetimpl.timefail = Echec de getTime pour la valeur ({0}) de la colonne {1} - Aucune conversion possible cachedrowsetimpl.posupdate = Mises à jour choisies non prises en charge @@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = Utiliser le nom de colonne comme argument pour un cachedrowsetimpl.unsetmatch2 = Utiliser l'ID de colonne comme argument pour unsetMatchColumn cachedrowsetimpl.numrows = Le nombre de lignes est inférieur à zéro ou à la taille d'extraction cachedrowsetimpl.startpos = La position de départ ne peut pas être négative -cachedrowsetimpl.nextpage = Entrer les données avant l'appel +cachedrowsetimpl.nextpage = Entrer les données avant l'appel cachedrowsetimpl.pagesize = La taille de la page ne peut pas être négative cachedrowsetimpl.pagesize1 = La taille de la page ne peut pas être supérieure à maxRows cachedrowsetimpl.fwdonly = ResultSet va en avant seulement @@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = Processus d'écriture non valide webrowsetimpl.invalidrd = Processus de lecture non valide #FilteredRowSetImpl exceptions -filteredrowsetimpl.relative = relative : opération de curseur non valide +filteredrowsetimpl.relative = relative : opération de curseur non valide filteredrowsetimpl.absolute = absolute : opération de curseur non valide filteredrowsetimpl.notallowed = Cette valeur n'est pas autorisée via le filtre @@ -123,15 +123,15 @@ crsreader.caldetected = Un calendrier a été détecté #CachedRowSetWriter exceptions crswriter.connect = Impossible d'obtenir la connexion crswriter.tname = writeData ne peut pas déterminer le nom de la table -crswriter.params1 = Valeur de params1 : {0} -crswriter.params2 = Valeur de params2 : {0} -crswriter.conflictsno = conflits lors de la synchronisation +crswriter.params1 = Valeur de params1 : {0} +crswriter.params2 = Valeur de params2 : {0} +crswriter.conflictsno = conflits lors de la synchronisation #InsertRow exceptions insertrow.novalue = Aucune valeur n'a été insérée #SyncResolverImpl exceptions -syncrsimpl.indexval = Valeur d'index hors plage +syncrsimpl.indexval = Valeur d'index hors plage syncrsimpl.noconflict = Cette colonne n'est pas en conflit syncrsimpl.syncnotpos = La synchronisation est impossible syncrsimpl.valtores = La valeur à résoudre peut être soit dans la base de données, soit dans CachedrowSet diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_it.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_it.properties index 8858052319997..7ab025d8c823b 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_it.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_it.properties @@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = getInt non riuscito per il valore ( {0} ) nella colon cachedrowsetimpl.longfail = getLong non riuscito per il valore ( {0} ) nella colonna {1} cachedrowsetimpl.floatfail = getFloat non riuscito per il valore ( {0} ) nella colonna {1} cachedrowsetimpl.doublefail = getDouble non riuscito per il valore ( {0} ) nella colonna {1} -cachedrowsetimpl.dtypemismt = Mancata corrispondenza tipo di dati +cachedrowsetimpl.dtypemismt = Mancata corrispondenza tipo di dati cachedrowsetimpl.datefail = getDate non riuscito per il valore ( {0} ) nella colonna {1}. Nessuna conversione disponibile. cachedrowsetimpl.timefail = getTime non riuscito per il valore ( {0} ) nella colonna {1}. Nessuna conversione disponibile. cachedrowsetimpl.posupdate = Aggiornamenti posizionati non supportati @@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = Utilizzare il nome di colonna come argomento per cachedrowsetimpl.unsetmatch2 = Utilizzare l'ID di colonna come argomento per unsetMatchColumn cachedrowsetimpl.numrows = Il numero di righe è inferiore a zero o alla dimensione di recupero cachedrowsetimpl.startpos = La posizione iniziale non può essere negativa -cachedrowsetimpl.nextpage = Inserire i dati prima di chiamare +cachedrowsetimpl.nextpage = Inserire i dati prima di chiamare cachedrowsetimpl.pagesize = La dimensione della pagina non può essere inferiore a zero cachedrowsetimpl.pagesize1 = La dimensione della pagina non può essere superiore a maxRows cachedrowsetimpl.fwdonly = ResultSet è a solo inoltro @@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = Processo di scrittura non valido webrowsetimpl.invalidrd = Processo di lettura non valido #FilteredRowSetImpl exceptions -filteredrowsetimpl.relative = relative: operazione cursore non valida +filteredrowsetimpl.relative = relative: operazione cursore non valida filteredrowsetimpl.absolute = absolute: operazione cursore non valida filteredrowsetimpl.notallowed = Questo valore non è consentito nel filtro @@ -123,15 +123,15 @@ crsreader.caldetected = È stato rilevato un calendario #CachedRowSetWriter exceptions crswriter.connect = Impossibile stabilire una connessione crswriter.tname = writeData non riesce a determinare il nome di tabella -crswriter.params1 = Valore dei parametri 1: {0} -crswriter.params2 = Valore dei parametri 2: {0} -crswriter.conflictsno = Conflitti durante la sincronizzazione +crswriter.params1 = Valore dei parametri 1: {0} +crswriter.params2 = Valore dei parametri 2: {0} +crswriter.conflictsno = Conflitti durante la sincronizzazione #InsertRow exceptions insertrow.novalue = Non è stato inserito alcun valore #SyncResolverImpl exceptions -syncrsimpl.indexval = Valore indice non compreso nell'intervallo +syncrsimpl.indexval = Valore indice non compreso nell'intervallo syncrsimpl.noconflict = Questa colonna non è in conflitto syncrsimpl.syncnotpos = Impossibile eseguire la sincronizzazione syncrsimpl.valtores = Il valore da risolvere può essere nel database o in cachedrowset diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties index e5aebb2904e93..e2f906f74cded 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties @@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = 列{1}の値({0})でgetIntが失敗しました cachedrowsetimpl.longfail = 列{1}の値({0})でgetLongが失敗しました cachedrowsetimpl.floatfail = 列{1}の値({0})でgetFloatが失敗しました cachedrowsetimpl.doublefail = 列{1}の値({0})でgetDoubleが失敗しました -cachedrowsetimpl.dtypemismt = データ型の不一致 +cachedrowsetimpl.dtypemismt = データ型の不一致 cachedrowsetimpl.datefail = 列{1}の値({0})でgetDateが失敗。変換できません cachedrowsetimpl.timefail = 列{1}の値({0})でgetTimeが失敗。変換できません cachedrowsetimpl.posupdate = 位置決めされた更新がサポートされません @@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = unsetMatchColumnへの引数として列名を使 cachedrowsetimpl.unsetmatch2 = unsetMatchColumnへの引数として列IDを使用してください cachedrowsetimpl.numrows = 行数がゼロまたはフェッチ・サイズより小さいです cachedrowsetimpl.startpos = 開始位置を負にすることはできません -cachedrowsetimpl.nextpage = 呼出し前にデータを移入します +cachedrowsetimpl.nextpage = 呼出し前にデータを移入します cachedrowsetimpl.pagesize = ページ・サイズをゼロより小さくすることはできません cachedrowsetimpl.pagesize1 = ページ・サイズをmaxRowsより大きくすることができません cachedrowsetimpl.fwdonly = ResultSetは順方向のみです @@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = 無効なライター webrowsetimpl.invalidrd = 無効なリーダー #FilteredRowSetImpl exceptions -filteredrowsetimpl.relative = relative: 無効なカーソル操作 +filteredrowsetimpl.relative = relative: 無効なカーソル操作 filteredrowsetimpl.absolute = absolute: 無効なカーソル操作 filteredrowsetimpl.notallowed = この値はフィルタで許容されません @@ -123,15 +123,15 @@ crsreader.caldetected = カレンダを検出しました #CachedRowSetWriter exceptions crswriter.connect = 接続を取得できません crswriter.tname = writeDataが表名を判別できません -crswriter.params1 = params1の値: {0} -crswriter.params2 = params2の値: {0} -crswriter.conflictsno = 同期中に競合が発生します +crswriter.params1 = params1の値: {0} +crswriter.params2 = params2の値: {0} +crswriter.conflictsno = 同期中に競合が発生します #InsertRow exceptions insertrow.novalue = 値は挿入されていません #SyncResolverImpl exceptions -syncrsimpl.indexval = 範囲外の索引値 +syncrsimpl.indexval = 範囲外の索引値 syncrsimpl.noconflict = この列は競合していません syncrsimpl.syncnotpos = 同期できません syncrsimpl.valtores = 解決される値はデータベースまたはcachedrowsetにある可能性があります diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ko.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ko.properties index f52cbead25242..9f01b1051aa97 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ko.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ko.properties @@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = {1} 열의 값({0})에서 getInt를 실패했습니 cachedrowsetimpl.longfail = {1} 열의 값({0})에서 getLong을 실패했습니다. cachedrowsetimpl.floatfail = {1} 열의 값({0})에서 getFloat를 실패했습니다. cachedrowsetimpl.doublefail = {1} 열의 값({0})에서 getDouble을 실패했습니다. -cachedrowsetimpl.dtypemismt = 데이터 유형이 일치하지 않습니다. +cachedrowsetimpl.dtypemismt = 데이터 유형이 일치하지 않습니다. cachedrowsetimpl.datefail = {1} 열의 값({0})에서 getDate를 실패했습니다. 변환할 수 없습니다. cachedrowsetimpl.timefail = {1} 열의 값({0})에서 getTime을 실패했습니다. 변환할 수 없습니다. cachedrowsetimpl.posupdate = 위치가 지정된 업데이트가 지원되지 않습니다. @@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = 열 이름을 unsetMatchColumn의 인수로 사 cachedrowsetimpl.unsetmatch2 = 열 ID를 unsetMatchColumn의 인수로 사용하십시오. cachedrowsetimpl.numrows = 행 수가 0보다 작거나 인출 크기보다 작습니다. cachedrowsetimpl.startpos = 시작 위치는 음수일 수 없습니다. -cachedrowsetimpl.nextpage = 호출하기 전에 데이터를 채우십시오. +cachedrowsetimpl.nextpage = 호출하기 전에 데이터를 채우십시오. cachedrowsetimpl.pagesize = 페이지 크기는 0보다 작을 수 없습니다. cachedrowsetimpl.pagesize1 = 페이지 크기는 maxRows보다 클 수 없습니다. cachedrowsetimpl.fwdonly = ResultSet는 전달 전용입니다. @@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = 기록 장치가 부적합합니다. webrowsetimpl.invalidrd = 읽기 프로그램이 부적합합니다. #FilteredRowSetImpl exceptions -filteredrowsetimpl.relative = 상대: 커서 작업이 부적합합니다. +filteredrowsetimpl.relative = 상대: 커서 작업이 부적합합니다. filteredrowsetimpl.absolute = 절대: 커서 작업이 부적합합니다. filteredrowsetimpl.notallowed = 이 값은 필터를 통과할 수 없습니다. @@ -123,15 +123,15 @@ crsreader.caldetected = 달력을 감지함 #CachedRowSetWriter exceptions crswriter.connect = 접속할 수 없습니다. crswriter.tname = writeData에서 테이블 이름을 확인할 수 없습니다. -crswriter.params1 = params1의 값: {0} -crswriter.params2 = params2의 값: {0} -crswriter.conflictsno = 동기화하는 중 충돌함 +crswriter.params1 = params1의 값: {0} +crswriter.params2 = params2의 값: {0} +crswriter.conflictsno = 동기화하는 중 충돌함 #InsertRow exceptions insertrow.novalue = 값이 삽입되지 않았습니다. #SyncResolverImpl exceptions -syncrsimpl.indexval = 인덱스 값이 범위를 벗어났습니다. +syncrsimpl.indexval = 인덱스 값이 범위를 벗어났습니다. syncrsimpl.noconflict = 이 열은 충돌하지 않습니다. syncrsimpl.syncnotpos = 동기화할 수 없습니다. syncrsimpl.valtores = 분석할 값이 데이터베이스 또는 cachedrowset에 있을 수 있습니다. diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_pt_BR.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_pt_BR.properties index fb24edc87cd8a..4f0d136918152 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_pt_BR.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_pt_BR.properties @@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = Falha em getInt no valor ( {0} ) na coluna {1} cachedrowsetimpl.longfail = Falha em getLong no valor ( {0} ) na coluna {1} cachedrowsetimpl.floatfail = Falha em getFloat no valor ( {0} ) na coluna {1} cachedrowsetimpl.doublefail = Falha em getDouble no valor ( {0} ) na coluna {1} -cachedrowsetimpl.dtypemismt = Tipo de Dados Incompatível +cachedrowsetimpl.dtypemismt = Tipo de Dados Incompatível cachedrowsetimpl.datefail = Falha em getDate no valor ( {0} ) na coluna {1} sem conversão disponível cachedrowsetimpl.timefail = Falha em getTime no valor ( {0} ) na coluna {1} sem conversão disponível cachedrowsetimpl.posupdate = Atualizações posicionadas não suportadas @@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = Usar o nome da coluna como argumento para unsetMa cachedrowsetimpl.unsetmatch2 = Usar o ID da coluna como argumento para unsetMatchColumn cachedrowsetimpl.numrows = O número de linhas é menor do que zero ou menor do que o tamanho obtido cachedrowsetimpl.startpos = A posição de início não pode ser negativa -cachedrowsetimpl.nextpage = Preencher dados antes de chamar +cachedrowsetimpl.nextpage = Preencher dados antes de chamar cachedrowsetimpl.pagesize = O tamanho da página não pode ser menor do que zero cachedrowsetimpl.pagesize1 = O tamanho da página não pode ser maior do que maxRows cachedrowsetimpl.fwdonly = ResultSet é somente para frente @@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = Gravador inválido webrowsetimpl.invalidrd = Leitor inválido #FilteredRowSetImpl exceptions -filteredrowsetimpl.relative = relative : Operação inválida do cursor +filteredrowsetimpl.relative = relative : Operação inválida do cursor filteredrowsetimpl.absolute = absolute : Operação inválida do cursor filteredrowsetimpl.notallowed = Este valor não é permitido no filtro @@ -123,15 +123,15 @@ crsreader.caldetected = Calendário Detectado #CachedRowSetWriter exceptions crswriter.connect = Não é possível obter a conexão crswriter.tname = writeData não pode determinar o nome da tabela -crswriter.params1 = Valor de params1 : {0} -crswriter.params2 = Valor de params2 : {0} -crswriter.conflictsno = conflitos durante a sincronização +crswriter.params1 = Valor de params1 : {0} +crswriter.params2 = Valor de params2 : {0} +crswriter.conflictsno = conflitos durante a sincronização #InsertRow exceptions insertrow.novalue = Nenhum valor foi inserido #SyncResolverImpl exceptions -syncrsimpl.indexval = Valor de índice fora da faixa +syncrsimpl.indexval = Valor de índice fora da faixa syncrsimpl.noconflict = Está coluna não está em conflito syncrsimpl.syncnotpos = A sincronização não é possível syncrsimpl.valtores = O valor a ser decidido pode estar no banco de dados ou no conjunto de linhas armazenado no cache diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_sv.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_sv.properties index 8529c9169b4d4..3bc14d48f9fa5 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_sv.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_sv.properties @@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = getInt utfördes inte för värdet ({0}) i kolumnen { cachedrowsetimpl.longfail = getLong utfördes inte för värdet ({0}) i kolumnen {1} cachedrowsetimpl.floatfail = getFloat utfördes inte för värdet ({0}) i kolumnen {1} cachedrowsetimpl.doublefail = getDouble utfördes inte för värdet ({0}) i kolumnen {1} -cachedrowsetimpl.dtypemismt = Felmatchad datatyp +cachedrowsetimpl.dtypemismt = Felmatchad datatyp cachedrowsetimpl.datefail = getDate utfördes inte för värdet ({0}) i kolumnen {1}, ingen konvertering tillgänglig cachedrowsetimpl.timefail = getTime utfördes inte för värdet ({0}) i kolumnen {1}, ingen konvertering tillgänglig cachedrowsetimpl.posupdate = Det finns inte stöd för positionerad uppdatering @@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = Använd kolumnnamn som argument för unsetMatchCo cachedrowsetimpl.unsetmatch2 = Använd kolumn-id som argument för unsetMatchColumn cachedrowsetimpl.numrows = Antalet rader understiger noll eller är mindre än hämtningsstorleken cachedrowsetimpl.startpos = Startpositionen får inte vara negativ -cachedrowsetimpl.nextpage = Fyll i data innan anrop +cachedrowsetimpl.nextpage = Fyll i data innan anrop cachedrowsetimpl.pagesize = Sidstorleken får inte understiga noll cachedrowsetimpl.pagesize1 = Sidstorleken får inte överstiga maxRows cachedrowsetimpl.fwdonly = ResultSet kan endast gå framåt @@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = Ogiltig skrivfunktion webrowsetimpl.invalidrd = Ogiltig läsare #FilteredRowSetImpl exceptions -filteredrowsetimpl.relative = relative: Ogiltig marköråtgärd +filteredrowsetimpl.relative = relative: Ogiltig marköråtgärd filteredrowsetimpl.absolute = absolute: Ogiltig marköråtgärd filteredrowsetimpl.notallowed = Detta värde kommer att filtreras bort @@ -123,15 +123,15 @@ crsreader.caldetected = En kalender har identifierats #CachedRowSetWriter exceptions crswriter.connect = Kan inte upprätta anslutning crswriter.tname = writeData kan inte fastställa tabellnamnet -crswriter.params1 = Parametervärde1: {0} -crswriter.params2 = Parametervärde2: {0} -crswriter.conflictsno = orsakar konflikt vid synkronisering +crswriter.params1 = Parametervärde1: {0} +crswriter.params2 = Parametervärde2: {0} +crswriter.conflictsno = orsakar konflikt vid synkronisering #InsertRow exceptions insertrow.novalue = Inget värde har infogats #SyncResolverImpl exceptions -syncrsimpl.indexval = Indexvärdet ligger utanför intervallet +syncrsimpl.indexval = Indexvärdet ligger utanför intervallet syncrsimpl.noconflict = Kolumnen orsakar ingen konflikt syncrsimpl.syncnotpos = Synkronisering är inte möjlig syncrsimpl.valtores = Värdet som ska fastställas kan antingen finnas i databasen eller i cachedrowset diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties index c7469edd5c484..d9b4052f00aa8 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties @@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = 对列 {1} 中的值 ({0}) 执行 getInt 失败 cachedrowsetimpl.longfail = 对列 {1} 中的值 ({0}) 执行 getLong 失败 cachedrowsetimpl.floatfail = 对列 {1} 中的值 ({0}) 执行 getFloat 失败 cachedrowsetimpl.doublefail = 对列 {1} 中的值 ({0}) 执行 getDouble 失败 -cachedrowsetimpl.dtypemismt = 数据类型不匹配 +cachedrowsetimpl.dtypemismt = 数据类型不匹配 cachedrowsetimpl.datefail = 对列 {1} 中的值 ({0}) 执行 getDate 失败, 无可用转换 cachedrowsetimpl.timefail = 对列 {1} 中的值 ({0}) 执行 getTime 失败, 无可用转换 cachedrowsetimpl.posupdate = 不支持定位更新 @@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = 使用列名作为 unsetMatchColumn 的参数 cachedrowsetimpl.unsetmatch2 = 使用列 ID 作为 unsetMatchColumn 的参数 cachedrowsetimpl.numrows = 行数小于零或小于要提取的行数 cachedrowsetimpl.startpos = 起始位置不能为负数 -cachedrowsetimpl.nextpage = 在调用之前先填充数据 +cachedrowsetimpl.nextpage = 在调用之前先填充数据 cachedrowsetimpl.pagesize = 页面大小不能小于零 cachedrowsetimpl.pagesize1 = 页面大小不能大于 maxRows cachedrowsetimpl.fwdonly = ResultSet 的类型为仅向前类型 @@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = 写进程无效 webrowsetimpl.invalidrd = 读进程无效 #FilteredRowSetImpl exceptions -filteredrowsetimpl.relative = relative: 光标操作无效 +filteredrowsetimpl.relative = relative: 光标操作无效 filteredrowsetimpl.absolute = absolute: 光标操作无效 filteredrowsetimpl.notallowed = 不允许此值通过筛选器 @@ -123,15 +123,15 @@ crsreader.caldetected = 检测到日历 #CachedRowSetWriter exceptions crswriter.connect = 无法获取连接 crswriter.tname = writeData 无法确定表名 -crswriter.params1 = params1 的值: {0} -crswriter.params2 = params2 的值: {0} -crswriter.conflictsno = 同步时发生冲突 +crswriter.params1 = params1 的值: {0} +crswriter.params2 = params2 的值: {0} +crswriter.conflictsno = 同步时发生冲突 #InsertRow exceptions insertrow.novalue = 尚未插入任何值 #SyncResolverImpl exceptions -syncrsimpl.indexval = 索引值超出范围 +syncrsimpl.indexval = 索引值超出范围 syncrsimpl.noconflict = 此列不冲突 syncrsimpl.syncnotpos = 不能同步 syncrsimpl.valtores = 要解析的值可以在数据库中, 也可以在 CachedRowSet 中 diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_TW.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_TW.properties index c9a38a280e36d..d1539384bd90d 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_TW.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_TW.properties @@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = 使用欄名作為 unsetMatchColumn 的引數 cachedrowsetimpl.unsetmatch2 = 使用欄 ID 作為 unsetMatchColumn 的引數 cachedrowsetimpl.numrows = 列數小於零或小於擷取大小 cachedrowsetimpl.startpos = 起始位置不能為負數 -cachedrowsetimpl.nextpage = 在呼叫之前植入資料 +cachedrowsetimpl.nextpage = 在呼叫之前植入資料 cachedrowsetimpl.pagesize = 頁面大小不能小於零 cachedrowsetimpl.pagesize1 = 頁面大小不能大於 maxRows cachedrowsetimpl.fwdonly = ResultSet 只能向前進行 @@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = 寫入器無效 webrowsetimpl.invalidrd = 讀取器無效 #FilteredRowSetImpl exceptions -filteredrowsetimpl.relative = relative: 游標作業無效 +filteredrowsetimpl.relative = relative: 游標作業無效 filteredrowsetimpl.absolute = absolute: 游標作業無效 filteredrowsetimpl.notallowed = 不允許此值通過篩選 @@ -123,15 +123,15 @@ crsreader.caldetected = 偵測到行事曆 #CachedRowSetWriter exceptions crswriter.connect = 無法取得連線 crswriter.tname = writeData 不能決定表格名稱 -crswriter.params1 = params1 的值: {0} -crswriter.params2 = params2 的值: {0} -crswriter.conflictsno = 同步化時發生衝突 +crswriter.params1 = params1 的值: {0} +crswriter.params2 = params2 的值: {0} +crswriter.conflictsno = 同步化時發生衝突 #InsertRow exceptions insertrow.novalue = 尚未插入值 #SyncResolverImpl exceptions -syncrsimpl.indexval = 索引值超出範圍 +syncrsimpl.indexval = 索引值超出範圍 syncrsimpl.noconflict = 此欄不衝突 syncrsimpl.syncnotpos = 不可能同步化 syncrsimpl.valtores = 要解析的值可位於資料庫或 cachedrowset 中 diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/xmlsecurity_en.properties b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/xmlsecurity_en.properties index db9c2d544633b..d95071e0bad50 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/xmlsecurity_en.properties +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/xmlsecurity_en.properties @@ -128,7 +128,7 @@ signature.Transform.NullPointerTransform = Null pointer as URI. Programming bug? signature.Transform.UnknownTransform = Unknown transformation. No handler installed for URI {0} signature.Transform.XPathError = Error evaluating XPath expression signature.Transform.node = Current Node: {0} -signature.Transform.nodeAndType = Current Node: {0}, type: {1} +signature.Transform.nodeAndType = Current Node: {0}, type: {1} signature.Util.BignumNonPositive = bigInteger.signum() must be positive signature.Util.NonTextNode = Not a text node signature.Util.TooManyChilds = Too many childs of Type {0} in {1} diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages.properties index 05f67d5b088bf..0472b424c6d29 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages.properties @@ -21,28 +21,28 @@ # The messages are arranged in key and value tuples in a ListResourceBundle. BadMessageKey = The error message corresponding to the message key can not be found. - FormatFailed = An internal error occurred while formatting the following message:\n + FormatFailed = An internal error occurred while formatting the following message:\n # DOM Core # exception codes -DOMSTRING_SIZE_ERR = The specified range of text does not fit into a DOMString. -HIERARCHY_REQUEST_ERR = An attempt was made to insert a node where it is not permitted. +DOMSTRING_SIZE_ERR = The specified range of text does not fit into a DOMString. +HIERARCHY_REQUEST_ERR = An attempt was made to insert a node where it is not permitted. INDEX_SIZE_ERR = The index or size is negative, or greater than the allowed value. INUSE_ATTRIBUTE_ERR = An attempt is made to add an attribute that is already in use elsewhere. -INVALID_ACCESS_ERR = A parameter or an operation is not supported by the underlying object. -INVALID_CHARACTER_ERR = An invalid or illegal XML character is specified. -INVALID_MODIFICATION_ERR = An attempt is made to modify the type of the underlying object. -INVALID_STATE_ERR = An attempt is made to use an object that is not, or is no longer, usable. +INVALID_ACCESS_ERR = A parameter or an operation is not supported by the underlying object. +INVALID_CHARACTER_ERR = An invalid or illegal XML character is specified. +INVALID_MODIFICATION_ERR = An attempt is made to modify the type of the underlying object. +INVALID_STATE_ERR = An attempt is made to use an object that is not, or is no longer, usable. NAMESPACE_ERR = An attempt is made to create or change an object in a way which is incorrect with regard to namespaces. NOT_FOUND_ERR = An attempt is made to reference a node in a context where it does not exist. -NOT_SUPPORTED_ERR = The implementation does not support the requested type of object or operation. +NOT_SUPPORTED_ERR = The implementation does not support the requested type of object or operation. NO_DATA_ALLOWED_ERR = Data is specified for a node which does not support data. NO_MODIFICATION_ALLOWED_ERR = An attempt is made to modify an object where modifications are not allowed. -SYNTAX_ERR = An invalid or illegal string is specified. +SYNTAX_ERR = An invalid or illegal string is specified. VALIDATION_ERR = A call to a method such as insertBefore or removeChild would make the Node invalid with respect to document grammar. WRONG_DOCUMENT_ERR = A node is used in a different document than the one that created it. -TYPE_MISMATCH_ERR = The value type for this parameter name is incompatible with the expected value type. +TYPE_MISMATCH_ERR = The value type for this parameter name is incompatible with the expected value type. #error messages or exceptions FEATURE_NOT_SUPPORTED = The parameter {0} is recognized but the requested value cannot be set. @@ -77,7 +77,7 @@ INVALID_NODE_TYPE_ERR = The container of a boundary-point of a Range is being se #Events -UNSPECIFIED_EVENT_TYPE_ERR = The Event's type was not specified by initializing the event before the method was called. +UNSPECIFIED_EVENT_TYPE_ERR = The Event's type was not specified by initializing the event before the method was called. jaxp-schema-support=Both the setSchema method and the schemaLanguage property is used diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_de.properties index 2c3e7226b30de..3613fca907706 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_de.properties @@ -21,28 +21,28 @@ # The messages are arranged in key and value tuples in a ListResourceBundle. BadMessageKey = Die zum Meldungsschlüssel gehörige Fehlermeldung kann nicht gefunden werden. - FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler aufgetreten:\n + FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler aufgetreten:\n # DOM Core # exception codes -DOMSTRING_SIZE_ERR = Der angegebene Textbereich passt nicht in eine DOMString. -HIERARCHY_REQUEST_ERR = Es wurde versucht, einen Knoten an einer Stelle einzufügen, an der dies nicht zulässig ist. +DOMSTRING_SIZE_ERR = Der angegebene Textbereich passt nicht in eine DOMString. +HIERARCHY_REQUEST_ERR = Es wurde versucht, einen Knoten an einer Stelle einzufügen, an der dies nicht zulässig ist. INDEX_SIZE_ERR = Index oder Größe ist negativ oder größer als der zulässige Wert. INUSE_ATTRIBUTE_ERR = Es wurde versucht, ein Attribut hinzuzufügen, das bereits an einer anderen Stelle verwendet wird. -INVALID_ACCESS_ERR = Ein Parameter oder Vorgang wird nicht vom zugrunde liegenden Objekt unterstützt. -INVALID_CHARACTER_ERR = Ungültiges oder unzulässiges XML-Zeichen angegeben. -INVALID_MODIFICATION_ERR = Es wurde versucht, den Typ des zugrunde liegenden Objekts zu ändern. -INVALID_STATE_ERR = Es wurde versucht, ein Objekt zu ändern, das nicht verwendet werden kann. +INVALID_ACCESS_ERR = Ein Parameter oder Vorgang wird nicht vom zugrunde liegenden Objekt unterstützt. +INVALID_CHARACTER_ERR = Ungültiges oder unzulässiges XML-Zeichen angegeben. +INVALID_MODIFICATION_ERR = Es wurde versucht, den Typ des zugrunde liegenden Objekts zu ändern. +INVALID_STATE_ERR = Es wurde versucht, ein Objekt zu ändern, das nicht verwendet werden kann. NAMESPACE_ERR = Es wurde versucht, ein Objekt auf eine Weise zu erstellen oder zu ändern, die falsch in Bezug auf Namespaces ist. NOT_FOUND_ERR = Es wurde versucht, einen Knoten in einem Kontext zu referenzieren, in dem er nicht vorhanden ist. -NOT_SUPPORTED_ERR = Der angeforderte Typ des Objekts oder Vorgangs wird nicht von der Implementierung unterstützt. +NOT_SUPPORTED_ERR = Der angeforderte Typ des Objekts oder Vorgangs wird nicht von der Implementierung unterstützt. NO_DATA_ALLOWED_ERR = Daten wurden für einen Knoten angegeben, der keine Daten unterstützt. NO_MODIFICATION_ALLOWED_ERR = Es wurde versucht, ein Objekt zu ändern, bei dem Änderungen nicht zulässig sind. -SYNTAX_ERR = Ungültige oder unzulässige Zeichenfolge angegeben. +SYNTAX_ERR = Ungültige oder unzulässige Zeichenfolge angegeben. VALIDATION_ERR = Aufruf einer Methode wie insertBefore oder removeChild würde die Dokumentgrammatik des Knotens ungültig machen. WRONG_DOCUMENT_ERR = Ein Knoten wird in einem anderen Dokument verwendet als dem, von dem er erstellt wurde. -TYPE_MISMATCH_ERR = Der Werttyp für diesen Parameternamen ist nicht mit dem erwarteten Werttyp kompatibel. +TYPE_MISMATCH_ERR = Der Werttyp für diesen Parameternamen ist nicht mit dem erwarteten Werttyp kompatibel. #error messages or exceptions FEATURE_NOT_SUPPORTED = Parameter {0} wird erkannt, aber der angeforderte Wert kann nicht festgelegt werden. @@ -77,7 +77,7 @@ INVALID_NODE_TYPE_ERR = Container eines Grenzwertes eines Bereichs wird entweder #Events -UNSPECIFIED_EVENT_TYPE_ERR = Der Ereignistyp wurde nicht durch Initialisieren des Ereignisses vor dem Aufruf der Methode angegeben. +UNSPECIFIED_EVENT_TYPE_ERR = Der Ereignistyp wurde nicht durch Initialisieren des Ereignisses vor dem Aufruf der Methode angegeben. jaxp-schema-support=setSchema-Methode und schemaLanguage-Eigenschaft werden verwendet diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_es.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_es.properties index deebc5b808b0a..4d190c073c535 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_es.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_es.properties @@ -29,28 +29,28 @@ # The messages are arranged in key and value tuples in a ListResourceBundle. BadMessageKey = No se ha encontrado el mensaje de error correspondiente a la clave de mensaje. - FormatFailed = Se ha producido un error interno al formatear el siguiente mensaje:\n + FormatFailed = Se ha producido un error interno al formatear el siguiente mensaje:\n # DOM Core # exception codes -DOMSTRING_SIZE_ERR = El rango especificado de texto no cabe en una cadena DOM. -HIERARCHY_REQUEST_ERR = Se ha realizado un intento de insertar un nodo donde no está permitido. +DOMSTRING_SIZE_ERR = El rango especificado de texto no cabe en una cadena DOM. +HIERARCHY_REQUEST_ERR = Se ha realizado un intento de insertar un nodo donde no está permitido. INDEX_SIZE_ERR = El índice o tamaño es negativo o superior al valor permitido. INUSE_ATTRIBUTE_ERR = Se ha realizado un intento de agregar un atributo que ya se está utilizando en otro lugar. -INVALID_ACCESS_ERR = El objeto subyacente no soporta un parámetro o una operación. -INVALID_CHARACTER_ERR = Se ha especificado un carácter XML no válido o no permitido. -INVALID_MODIFICATION_ERR = Se ha realizado un intento de modificar el tipo de objeto subyacente. -INVALID_STATE_ERR = Se ha realizado un intento de utilizar un objeto que ya no se puede utilizar. +INVALID_ACCESS_ERR = El objeto subyacente no soporta un parámetro o una operación. +INVALID_CHARACTER_ERR = Se ha especificado un carácter XML no válido o no permitido. +INVALID_MODIFICATION_ERR = Se ha realizado un intento de modificar el tipo de objeto subyacente. +INVALID_STATE_ERR = Se ha realizado un intento de utilizar un objeto que ya no se puede utilizar. NAMESPACE_ERR = Se ha realizado un intento de crear o cambiar un objeto de un modo incorrecto con respecto a los espacios de nombres. NOT_FOUND_ERR = Se ha realizado un intento de hacer referencia a un nodo en un contexto en el que no existe. -NOT_SUPPORTED_ERR = La implantación no soporta el tipo solicitado de objeto u operación. +NOT_SUPPORTED_ERR = La implantación no soporta el tipo solicitado de objeto u operación. NO_DATA_ALLOWED_ERR = Se han especificado datos para un nodo que no soporta datos. NO_MODIFICATION_ALLOWED_ERR = Se ha realizado un intento de modificar un objeto en el que no están permitidas las modificaciones. -SYNTAX_ERR = Se ha especificado una cadena no válida o no permitida. +SYNTAX_ERR = Se ha especificado una cadena no válida o no permitida. VALIDATION_ERR = Una llamada a un método como insertBefore o removeChild invalidaría el nodo con respecto a la gramática del documento. WRONG_DOCUMENT_ERR = Se ha utilizado un nodo en un documento distinto al que lo creó. -TYPE_MISMATCH_ERR = El tipo de valor para este nombre de parámetro no es compatible con el tipo de valor esperado. +TYPE_MISMATCH_ERR = El tipo de valor para este nombre de parámetro no es compatible con el tipo de valor esperado. #error messages or exceptions FEATURE_NOT_SUPPORTED = Se reconoce el parámetro {0} pero no se puede definir el valor solicitado. @@ -85,7 +85,7 @@ INVALID_NODE_TYPE_ERR = El contenedor de un punto de límite de un rango se est #Events -UNSPECIFIED_EVENT_TYPE_ERR = No se ha especificado el tipo de evento mediante la inicialización del evento antes de que se llame al método. +UNSPECIFIED_EVENT_TYPE_ERR = No se ha especificado el tipo de evento mediante la inicialización del evento antes de que se llame al método. jaxp-schema-support=Se utiliza tanto el método setSchema como la propiedad schemaLanguage diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_fr.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_fr.properties index 24e427d88ec7c..deff1f741a023 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_fr.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_fr.properties @@ -29,28 +29,28 @@ # The messages are arranged in key and value tuples in a ListResourceBundle. BadMessageKey = Le message d'erreur correspondant à la clé de message est introuvable. - FormatFailed = Une erreur interne est survenue lors du formatage du message suivant :\n + FormatFailed = Une erreur interne est survenue lors du formatage du message suivant :\n # DOM Core # exception codes -DOMSTRING_SIZE_ERR = La plage de texte indiquée ne tient pas dans un élément DOMString. -HIERARCHY_REQUEST_ERR = Tentative d'insertion d'un noeud à un emplacement non autorisé. +DOMSTRING_SIZE_ERR = La plage de texte indiquée ne tient pas dans un élément DOMString. +HIERARCHY_REQUEST_ERR = Tentative d'insertion d'un noeud à un emplacement non autorisé. INDEX_SIZE_ERR = L'index ou la taille est négatif ou dépasse la valeur autorisée. INUSE_ATTRIBUTE_ERR = Tentative d'ajout d'un attribut déjà utilisé ailleurs. -INVALID_ACCESS_ERR = Un paramètre ou une opération n'est pas pris en charge par l'objet sous-jacent. -INVALID_CHARACTER_ERR = Un caractère XML non valide ou non admis est indiqué. -INVALID_MODIFICATION_ERR = Tentative de modification du type de l'objet sous-jacent. -INVALID_STATE_ERR = Tentative d'utilisation d'un objet qui n'est pas ou plus utilisable. +INVALID_ACCESS_ERR = Un paramètre ou une opération n'est pas pris en charge par l'objet sous-jacent. +INVALID_CHARACTER_ERR = Un caractère XML non valide ou non admis est indiqué. +INVALID_MODIFICATION_ERR = Tentative de modification du type de l'objet sous-jacent. +INVALID_STATE_ERR = Tentative d'utilisation d'un objet qui n'est pas ou plus utilisable. NAMESPACE_ERR = Tentative de création ou de modification d'un objet incorrecte par rapport aux espaces de noms. NOT_FOUND_ERR = Tentative de référencement d'un noeud dans un contexte où il n'existe pas. -NOT_SUPPORTED_ERR = L'implémentation ne prend pas en charge le type d'objet ou d'opération demandé. +NOT_SUPPORTED_ERR = L'implémentation ne prend pas en charge le type d'objet ou d'opération demandé. NO_DATA_ALLOWED_ERR = Des données ont été indiquées pour un noeud ne prenant pas en charge les données. NO_MODIFICATION_ALLOWED_ERR = Tentative de modification d'un objet pour lequel les modifications ne sont pas autorisées. -SYNTAX_ERR = Une chaîne non valide ou non admise est indiquée. +SYNTAX_ERR = Une chaîne non valide ou non admise est indiquée. VALIDATION_ERR = L'appel d'une méthode comme insertBefore ou removeChild risque de rendre le noeud non valide par rapport à la grammaire de document. WRONG_DOCUMENT_ERR = Un noeud est utilisé dans un document différent de celui l'ayant créé. -TYPE_MISMATCH_ERR = Le type de valeur pour ce nom de paramètre n'est pas compatible avec le type de valeur attendu. +TYPE_MISMATCH_ERR = Le type de valeur pour ce nom de paramètre n'est pas compatible avec le type de valeur attendu. #error messages or exceptions FEATURE_NOT_SUPPORTED = Le paramètre {0} est reconnu mais la valeur demandée ne peut pas être définie. @@ -85,7 +85,7 @@ INVALID_NODE_TYPE_ERR = Le conteneur d'un point de limite d'une plage est défin #Events -UNSPECIFIED_EVENT_TYPE_ERR = Le type d'événement n'a pas été indiqué en initialisant l'événement avant l'appel de la méthode. +UNSPECIFIED_EVENT_TYPE_ERR = Le type d'événement n'a pas été indiqué en initialisant l'événement avant l'appel de la méthode. jaxp-schema-support=La méthode setSchema et la propriété schemaLanguage sont utilisées diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_it.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_it.properties index 29afb91340f90..879fcf5a866cf 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_it.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_it.properties @@ -29,28 +29,28 @@ # The messages are arranged in key and value tuples in a ListResourceBundle. BadMessageKey = Impossibile trovare il messaggio di errore corrispondente alla chiave di messaggio. - FormatFailed = Si è verificato un errore interno durante la formattazione del seguente messaggio:\n + FormatFailed = Si è verificato un errore interno durante la formattazione del seguente messaggio:\n # DOM Core # exception codes -DOMSTRING_SIZE_ERR = L'intervallo di testo specificato non si adatta in DOMString. -HIERARCHY_REQUEST_ERR = Si è tentato di inserire un nodo in un punto in cui non è consentito. +DOMSTRING_SIZE_ERR = L'intervallo di testo specificato non si adatta in DOMString. +HIERARCHY_REQUEST_ERR = Si è tentato di inserire un nodo in un punto in cui non è consentito. INDEX_SIZE_ERR = L'indice o la dimensione è negativa o maggiore del valore consentito. INUSE_ATTRIBUTE_ERR = Si è tentato di aggiungere un attributo già in uso altrove. -INVALID_ACCESS_ERR = Un parametro o un'operazione non è supportata dall'oggetto di base. -INVALID_CHARACTER_ERR = È stato specificato un carattere XML non valido. -INVALID_MODIFICATION_ERR = Si è tentato di modificare il tipo dell'oggetto di base. -INVALID_STATE_ERR = Si è tentato di utilizzare un oggetto che non è o non è più utilizzabile. +INVALID_ACCESS_ERR = Un parametro o un'operazione non è supportata dall'oggetto di base. +INVALID_CHARACTER_ERR = È stato specificato un carattere XML non valido. +INVALID_MODIFICATION_ERR = Si è tentato di modificare il tipo dell'oggetto di base. +INVALID_STATE_ERR = Si è tentato di utilizzare un oggetto che non è o non è più utilizzabile. NAMESPACE_ERR = Si è tentato di creare o modificare un oggetto in modo errato per quel che riguarda gli spazi di nomi. NOT_FOUND_ERR = Si è tentato di fare riferimento a un nodo in un contesto in cui non esiste. -NOT_SUPPORTED_ERR = L'implementazione non supporta il tipo richiesto di oggetto o operazione. +NOT_SUPPORTED_ERR = L'implementazione non supporta il tipo richiesto di oggetto o operazione. NO_DATA_ALLOWED_ERR = Sono stati specificati dati per un nodo che non supporta dati. NO_MODIFICATION_ALLOWED_ERR = Si è tentato di modificare un oggetto non modificabile. -SYNTAX_ERR = È stata specificata una stringa non valida. +SYNTAX_ERR = È stata specificata una stringa non valida. VALIDATION_ERR = Se si richiama un metodo come insertBefore o removeChild, il nodo non sarà valido per quel che riguarda la grammatica del documento. WRONG_DOCUMENT_ERR = Un nodo è utilizzato in un documento diverso da quello che lo ha creato. -TYPE_MISMATCH_ERR = Il tipo di valore per questo nome parametro non è compatibile con il tipo di valore previsto. +TYPE_MISMATCH_ERR = Il tipo di valore per questo nome parametro non è compatibile con il tipo di valore previsto. #error messages or exceptions FEATURE_NOT_SUPPORTED = Il parametro {0} è stato riconosciuto, ma non è possibile impostare il valore richiesto. @@ -85,7 +85,7 @@ INVALID_NODE_TYPE_ERR = Il contenitore di un punto limite di un intervallo è st #Events -UNSPECIFIED_EVENT_TYPE_ERR = Il tipo di evento non è stato specificato inizializzando l'evento prima che fosse richiamato il metodo. +UNSPECIFIED_EVENT_TYPE_ERR = Il tipo di evento non è stato specificato inizializzando l'evento prima che fosse richiamato il metodo. jaxp-schema-support=Sono stati utilizzati sia il metodo setSchema che la proprietà schemaLanguage diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ja.properties index b358fc8a32487..a04e36923c3b4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ja.properties @@ -21,28 +21,28 @@ # The messages are arranged in key and value tuples in a ListResourceBundle. BadMessageKey = メッセージ・キーに対応するエラー・メッセージが見つかりません。 - FormatFailed = 次のメッセージの書式設定中に内部エラーが発生しました:\n + FormatFailed = 次のメッセージの書式設定中に内部エラーが発生しました:\n # DOM Core # exception codes -DOMSTRING_SIZE_ERR = 指定したテキスト範囲はDOMStringに収まりません。 -HIERARCHY_REQUEST_ERR = 許可されていない場所でノードを挿入しようとしました。 +DOMSTRING_SIZE_ERR = 指定したテキスト範囲はDOMStringに収まりません。 +HIERARCHY_REQUEST_ERR = 許可されていない場所でノードを挿入しようとしました。 INDEX_SIZE_ERR = 索引またはサイズが負か、許容値より大きくなっています。 INUSE_ATTRIBUTE_ERR = 他の場所ですでに使用されている属性を追加しようとしました。 -INVALID_ACCESS_ERR = 基礎となるオブジェクトでパラメータまたは操作がサポートされていません。 -INVALID_CHARACTER_ERR = 無効または不正なXML文字が指定されています。 -INVALID_MODIFICATION_ERR = 基礎となるオブジェクトのタイプを変更しようとしました。 -INVALID_STATE_ERR = 使用できないか、今後使用できなくなるオブジェクトを使用しようとしました。 +INVALID_ACCESS_ERR = 基礎となるオブジェクトでパラメータまたは操作がサポートされていません。 +INVALID_CHARACTER_ERR = 無効または不正なXML文字が指定されています。 +INVALID_MODIFICATION_ERR = 基礎となるオブジェクトのタイプを変更しようとしました。 +INVALID_STATE_ERR = 使用できないか、今後使用できなくなるオブジェクトを使用しようとしました。 NAMESPACE_ERR = ネームスペースに関して不適切な方法でオブジェクトを作成または変更しようとしました。 NOT_FOUND_ERR = コンテキストに存在しないノードを参照しようとしました。 -NOT_SUPPORTED_ERR = リクエストしたタイプのオブジェクトまたは操作は実装でサポートされていません。 +NOT_SUPPORTED_ERR = リクエストしたタイプのオブジェクトまたは操作は実装でサポートされていません。 NO_DATA_ALLOWED_ERR = データをサポートしていないノードに対してデータが指定されています。 NO_MODIFICATION_ALLOWED_ERR = 変更が許可されていないオブジェクトを変更しようとしました。 -SYNTAX_ERR = 無効または不正な文字列が指定されています。 +SYNTAX_ERR = 無効または不正な文字列が指定されています。 VALIDATION_ERR = insertBefore、removeChildなどのメソッドを呼び出すと、ドキュメントの構文に関してノードが無効になります。 WRONG_DOCUMENT_ERR = ノードが、そのノードを作成したものとは異なるドキュメントで使用されています。 -TYPE_MISMATCH_ERR = このパラメータ名の値タイプは、予想した値タイプと互換性がありません。 +TYPE_MISMATCH_ERR = このパラメータ名の値タイプは、予想した値タイプと互換性がありません。 #error messages or exceptions FEATURE_NOT_SUPPORTED = パラメータ{0}は認識されますが、リクエストした値は設定できません。 @@ -77,7 +77,7 @@ INVALID_NODE_TYPE_ERR = Rangeの境界点のコンテナが、無効なタイプ #Events -UNSPECIFIED_EVENT_TYPE_ERR = メソッドを呼び出す前のイベントの初期化で、イベントのタイプが指定されませんでした。 +UNSPECIFIED_EVENT_TYPE_ERR = メソッドを呼び出す前のイベントの初期化で、イベントのタイプが指定されませんでした。 jaxp-schema-support=setSchemaメソッドおよびschemaLanguageプロパティの両方が使用されています diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ko.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ko.properties index 3d56d383201ef..b702d09928449 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ko.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ko.properties @@ -29,28 +29,28 @@ # The messages are arranged in key and value tuples in a ListResourceBundle. BadMessageKey = 메시지 키에 해당하는 오류 메시지를 찾을 수 없습니다. - FormatFailed = 다음 메시지의 형식을 지정하는 중 내부 오류가 발생했습니다.\n + FormatFailed = 다음 메시지의 형식을 지정하는 중 내부 오류가 발생했습니다.\n # DOM Core # exception codes -DOMSTRING_SIZE_ERR = 텍스트의 지정된 범위가 DOMString에 맞지 않습니다. -HIERARCHY_REQUEST_ERR = 삽입이 허용되지 않는 노드를 삽입하려고 시도했습니다. +DOMSTRING_SIZE_ERR = 텍스트의 지정된 범위가 DOMString에 맞지 않습니다. +HIERARCHY_REQUEST_ERR = 삽입이 허용되지 않는 노드를 삽입하려고 시도했습니다. INDEX_SIZE_ERR = 인덱스 또는 크기가 음수이거나 허용되는 값보다 큽니다. INUSE_ATTRIBUTE_ERR = 다른 위치에서 이미 사용 중인 속성을 추가하려고 시도했습니다. -INVALID_ACCESS_ERR = 기본 객체에서 매개변수 또는 작업을 지원하지 않습니다. -INVALID_CHARACTER_ERR = 부적합하거나 잘못된 XML 문자가 지정되었습니다. -INVALID_MODIFICATION_ERR = 기본 객체의 유형을 수정하려고 시도했습니다. -INVALID_STATE_ERR = 사용할 수 없거나 더 이상 사용이 허가되지 않은 객체를 사용하려고 시도했습니다. +INVALID_ACCESS_ERR = 기본 객체에서 매개변수 또는 작업을 지원하지 않습니다. +INVALID_CHARACTER_ERR = 부적합하거나 잘못된 XML 문자가 지정되었습니다. +INVALID_MODIFICATION_ERR = 기본 객체의 유형을 수정하려고 시도했습니다. +INVALID_STATE_ERR = 사용할 수 없거나 더 이상 사용이 허가되지 않은 객체를 사용하려고 시도했습니다. NAMESPACE_ERR = 네임스페이스에 대해 올바르지 않은 방식으로 객체를 생성하거나 변경하려고 시도했습니다. NOT_FOUND_ERR = 존재하지 않는 컨텍스트의 노드를 참조하려고 시도했습니다. -NOT_SUPPORTED_ERR = 구현에서 요청된 유형의 객체 또는 작업을 지원하지 않습니다. +NOT_SUPPORTED_ERR = 구현에서 요청된 유형의 객체 또는 작업을 지원하지 않습니다. NO_DATA_ALLOWED_ERR = 데이터를 지원하지 않는 노드에 대해 데이터가 지정되었습니다. NO_MODIFICATION_ALLOWED_ERR = 수정이 허용되지 않는 객체를 수정하려고 시도했습니다. -SYNTAX_ERR = 부적합하거나 잘못된 문자열이 지정되었습니다. +SYNTAX_ERR = 부적합하거나 잘못된 문자열이 지정되었습니다. VALIDATION_ERR = insertBefore 또는 removeChild와 같은 메소드를 호출하면 노드가 문서 문법에 대해 부적합해집니다. WRONG_DOCUMENT_ERR = 노드가 생성된 문서가 아닌 다른 문서에서 사용되었습니다. -TYPE_MISMATCH_ERR = 이 매개변수 이름에 대한 값 유형이 필요한 값 유형과 호환되지 않습니다. +TYPE_MISMATCH_ERR = 이 매개변수 이름에 대한 값 유형이 필요한 값 유형과 호환되지 않습니다. #error messages or exceptions FEATURE_NOT_SUPPORTED = {0} 매개변수가 인식되었지만 요청된 값을 설정할 수 없습니다. @@ -85,7 +85,7 @@ INVALID_NODE_TYPE_ERR = 범위의 경계 지점 컨테이너가 부적합한 유 #Events -UNSPECIFIED_EVENT_TYPE_ERR = 메소드가 호출되기 전에 이벤트를 초기화하여 이벤트 유형이 지정되지 않았습니다. +UNSPECIFIED_EVENT_TYPE_ERR = 메소드가 호출되기 전에 이벤트를 초기화하여 이벤트 유형이 지정되지 않았습니다. jaxp-schema-support=setSchema 메소드와 schemaLanguage 속성이 모두 사용되었습니다. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_pt_BR.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_pt_BR.properties index 6ddb17e4e94da..f72410c4cfc66 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_pt_BR.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_pt_BR.properties @@ -29,28 +29,28 @@ # The messages are arranged in key and value tuples in a ListResourceBundle. BadMessageKey = Não foi possível encontrar a mensagem de erro correspondente à chave da mensagem. - FormatFailed = Ocorreu um erro interno ao formatar a mensagem a seguir:\n + FormatFailed = Ocorreu um erro interno ao formatar a mensagem a seguir:\n # DOM Core # exception codes -DOMSTRING_SIZE_ERR = A faixa de texto especificada não se ajusta a DOMString. -HIERARCHY_REQUEST_ERR = Houve uma tentativa de inserir um nó onde não era permitido. +DOMSTRING_SIZE_ERR = A faixa de texto especificada não se ajusta a DOMString. +HIERARCHY_REQUEST_ERR = Houve uma tentativa de inserir um nó onde não era permitido. INDEX_SIZE_ERR = O índice ou o tamanho é negativo ou maior que o valor permitido. INUSE_ATTRIBUTE_ERR = Houve uma tentativa de adicionar um atributo que já está sendo usado em outro lugar. -INVALID_ACCESS_ERR = Um parâmetro ou uma operação não suportado pelo objeto subjacente. -INVALID_CHARACTER_ERR = Um caractere XML inválido ou ilegal foi especificado. -INVALID_MODIFICATION_ERR = Houve uma tentativa de modificar o tipo de objeto subjacente. -INVALID_STATE_ERR = Houve uma tentativa de usar um objeto que não é mais utilizável. +INVALID_ACCESS_ERR = Um parâmetro ou uma operação não suportado pelo objeto subjacente. +INVALID_CHARACTER_ERR = Um caractere XML inválido ou ilegal foi especificado. +INVALID_MODIFICATION_ERR = Houve uma tentativa de modificar o tipo de objeto subjacente. +INVALID_STATE_ERR = Houve uma tentativa de usar um objeto que não é mais utilizável. NAMESPACE_ERR = Houve uma tentativa de criar ou alterar um objeto de uma forma incorreta em relação aos namespaces. NOT_FOUND_ERR = Houve uma tentativa de fazer referência a um nó em um contexto no qual ele não existe. -NOT_SUPPORTED_ERR = A implementação não suporta o tipo solicitado de objeto ou operação. +NOT_SUPPORTED_ERR = A implementação não suporta o tipo solicitado de objeto ou operação. NO_DATA_ALLOWED_ERR = Os dados foram especificados para um nó que não suporta dados. NO_MODIFICATION_ALLOWED_ERR = Foi feita uma tentativa de modificar um objeto no qual não são permitidas modificações. -SYNTAX_ERR = Uma string inválida ou ilegal foi especificada. +SYNTAX_ERR = Uma string inválida ou ilegal foi especificada. VALIDATION_ERR = Uma chamada para um método como insertBefore ou removeChild tornaria o Nó inválido em relação à gramática do documento. WRONG_DOCUMENT_ERR = Um nó é usado em um documento diferente daquele que foi criado. -TYPE_MISMATCH_ERR = O tipo de valor do nome deste parâmetro é incompatível com o tipo de valor esperado. +TYPE_MISMATCH_ERR = O tipo de valor do nome deste parâmetro é incompatível com o tipo de valor esperado. #error messages or exceptions FEATURE_NOT_SUPPORTED = O parâmetro {0} é reconhecido, mas o valor solicitado não pode ser definido. @@ -85,7 +85,7 @@ INVALID_NODE_TYPE_ERR = O container de um ponto-limite de uma Faixa está sendo #Events -UNSPECIFIED_EVENT_TYPE_ERR = O tipo de Evento não foi especificado por meio da inicialização do evento antes do método ser chamado. +UNSPECIFIED_EVENT_TYPE_ERR = O tipo de Evento não foi especificado por meio da inicialização do evento antes do método ser chamado. jaxp-schema-support=O método setSchema e a propriedade schemaLanguage foram usados diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_sv.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_sv.properties index c4e3e4238f732..eb03257c11992 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_sv.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_sv.properties @@ -29,28 +29,28 @@ # The messages are arranged in key and value tuples in a ListResourceBundle. BadMessageKey = Hittar inte felmeddelandet som motsvarar meddelandenyckeln. - FormatFailed = Ett internt fel inträffade vid formatering av följande meddelande:\n + FormatFailed = Ett internt fel inträffade vid formatering av följande meddelande:\n # DOM Core # exception codes -DOMSTRING_SIZE_ERR = Angivet textintervall ryms inte i DOMString. -HIERARCHY_REQUEST_ERR = Ett försök gjordes att infoga nod där det inte är tillåtet. +DOMSTRING_SIZE_ERR = Angivet textintervall ryms inte i DOMString. +HIERARCHY_REQUEST_ERR = Ett försök gjordes att infoga nod där det inte är tillåtet. INDEX_SIZE_ERR = Index eller storlek är negativt tal eller större än tillåtet värde. INUSE_ATTRIBUTE_ERR = Ett försök görs att lägga till ett attribut som redan används på annan plats. -INVALID_ACCESS_ERR = En parameter eller en åtgärd stöds inte av underliggande objekt. -INVALID_CHARACTER_ERR = Ett ogiltigt eller otillåtet XML-tecken har angetts. -INVALID_MODIFICATION_ERR = Ett försök görs att ändra typ av underliggande objekt. -INVALID_STATE_ERR = Ett försök görs att använda ett objekt som inte (längre) är användbar. +INVALID_ACCESS_ERR = En parameter eller en åtgärd stöds inte av underliggande objekt. +INVALID_CHARACTER_ERR = Ett ogiltigt eller otillåtet XML-tecken har angetts. +INVALID_MODIFICATION_ERR = Ett försök görs att ändra typ av underliggande objekt. +INVALID_STATE_ERR = Ett försök görs att använda ett objekt som inte (längre) är användbar. NAMESPACE_ERR = Ett försök görs att skapa eller ändra ett objekt på ett felaktigt sätt avseende namnrymder. NOT_FOUND_ERR = Ett försök görs att skapa referens till en nod i ett sammanhang där den inte finns. -NOT_SUPPORTED_ERR = Implementeringen saknar stöd för begärd typ av objekt eller åtgärd. +NOT_SUPPORTED_ERR = Implementeringen saknar stöd för begärd typ av objekt eller åtgärd. NO_DATA_ALLOWED_ERR = Data anges för en nod som inte stöder data. NO_MODIFICATION_ALLOWED_ERR = Försöker ändra ett objekt där ändringar inte är tillåtna. -SYNTAX_ERR = En ogiltig eller otillåten sträng anges. +SYNTAX_ERR = En ogiltig eller otillåten sträng anges. VALIDATION_ERR = Ett anrop till en metod som insertBefore eller removeChild skulle göra noden ogiltig med aktuell dokumentgrammatik. WRONG_DOCUMENT_ERR = En nod används i ett annat dokument än det som skapade noden. -TYPE_MISMATCH_ERR = Värdetypen för detta parameternamn är inkompatibelt med förväntad värdetyp. +TYPE_MISMATCH_ERR = Värdetypen för detta parameternamn är inkompatibelt med förväntad värdetyp. #error messages or exceptions FEATURE_NOT_SUPPORTED = Parametern {0} kan identifieras, men det begärda värdet kan inte anges. @@ -85,7 +85,7 @@ INVALID_NODE_TYPE_ERR = En container med gränspunktsintervall anges till nod av #Events -UNSPECIFIED_EVENT_TYPE_ERR = Händelsetyp specificerades inte när händelsen initierades före metodanrop. +UNSPECIFIED_EVENT_TYPE_ERR = Händelsetyp specificerades inte när händelsen initierades före metodanrop. jaxp-schema-support=Både setSchema-metoden och schemaLanguage-egenskapen används diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_zh_CN.properties index dac97e7fe406b..dcf11c533e264 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_zh_CN.properties @@ -21,7 +21,7 @@ # The messages are arranged in key and value tuples in a ListResourceBundle. BadMessageKey = 找不到与消息关键字对应的错误消息。 - FormatFailed = 设置以下消息的格式时出现内部错误:\n + FormatFailed = 设置以下消息的格式时出现内部错误:\n # DOM Core diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages.properties index 01ca9e977fe3c..4d475edea5203 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages.properties @@ -26,7 +26,7 @@ FormatFailed = An internal error occurred while formatting the following message # JAXP messages schema-not-supported = The specified schema language is not supported. -jaxp-order-not-supported = Property ''{0}'' must be set before setting property ''{1}''. +jaxp-order-not-supported = Property ''{0}'' must be set before setting property ''{1}''. schema-already-specified = Property ''{0}'' cannot be set when a non-null Schema object has already been specified. # feature messages @@ -48,4 +48,4 @@ incompatible-class = The value specified for property ''{0}'' cannot be casted t start-document-not-called=Property "{0}" should be called after startDocument event is thrown nullparameter=the name parameter for "{0}" is null errorHandlerNotSet=Warning\: validation was turned on but an org.xml.sax.ErrorHandler was not set, which is probably not what is desired. Parser will use a default ErrorHandler to print the first {0} errors. Please call the 'setErrorHandler' method to fix this. -errorHandlerDebugMsg=Error\: URI \= "{0}", Line \= "{1}", \: {2} +errorHandlerDebugMsg=Error\: URI \= "{0}", Line \= "{1}", \: {2} diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_de.properties index 9196318a4182b..877150e9793de 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_de.properties @@ -26,7 +26,7 @@ FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler au # JAXP messages schema-not-supported = Die angegebene Schemasprache wird nicht unterstützt. -jaxp-order-not-supported = Eigenschaft "{0}" muss vor der Eigenschaft "{1}" festgelegt werden. +jaxp-order-not-supported = Eigenschaft "{0}" muss vor der Eigenschaft "{1}" festgelegt werden. schema-already-specified = Eigenschaft "{0}" kann nicht festgelegt werden, wenn bereits ein Schemaobjekt ungleich null angegeben wurde. # feature messages @@ -48,4 +48,4 @@ incompatible-class = Der für Eigenschaft "{0}" angegebene Wert kann nicht in {1 start-document-not-called=Eigenschaft "{0}" sollte aufgerufen werden, nachdem das startDocument-Ereignis ausgelöst wurde nullparameter=Namensparameter für "{0}" ist null errorHandlerNotSet=Warnung: Validierung wurde eingeschaltet, aber es wurde kein org.xml.sax.ErrorHandler festgelegt. Dies ist wahrscheinlich nicht beabsichtigt. Parser druckt die ersten {0} Fehler mit einem Standard-ErrorHandler. Rufen Sie die Methode "setErrorHandler" auf, um dies zu beheben. -errorHandlerDebugMsg=Fehler: URI = "{0}", Zeile = "{1}", : {2} +errorHandlerDebugMsg=Fehler: URI = "{0}", Zeile = "{1}", : {2} diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_es.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_es.properties index fa89d4adeaad1..04612301ad98e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_es.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_es.properties @@ -34,7 +34,7 @@ FormatFailed = Se ha producido un error interno al formatear el siguiente mensaj # JAXP messages schema-not-supported = El idioma del esquema especificado no está soportado. -jaxp-order-not-supported = La propiedad ''{0}'' debe definirse antes de definir la propiedad ''{1}''. +jaxp-order-not-supported = La propiedad ''{0}'' debe definirse antes de definir la propiedad ''{1}''. schema-already-specified = La propiedad ''{0}'' no puede definirse cuando un objeto de esquema no nulo ya se haya especificado. # feature messages @@ -56,4 +56,4 @@ incompatible-class = El valor especificado para la propiedad ''{0}'' no se puede start-document-not-called=La propiedad "{0}" debe llamarse después de que se haya devuelto el evento startDocument nullparameter=el parámetro de nombre para "{0}" es nulo errorHandlerNotSet=Advertencia: se activó la validación pero no se definió un org.xml.sax.ErrorHandler, lo cual probablemente sea un resultado no deseado. El analizador utilizará un ErrorHandler por defecto para imprimir los primeros {0} errores. Llame al método ''setErrorHandler'' para solucionarlo. -errorHandlerDebugMsg=Error: URI = "{0}", Línea = "{1}", : {2} +errorHandlerDebugMsg=Error: URI = "{0}", Línea = "{1}", : {2} diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_fr.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_fr.properties index 1f0e371e45f04..65067a9e85788 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_fr.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_fr.properties @@ -34,7 +34,7 @@ FormatFailed = Une erreur interne est survenue lors du formatage du message suiv # JAXP messages schema-not-supported = La langue de schéma indiquée n'est pas prise en charge. -jaxp-order-not-supported = La propriété ''{0}'' doit être définie avant la propriété ''{1}''. +jaxp-order-not-supported = La propriété ''{0}'' doit être définie avant la propriété ''{1}''. schema-already-specified = La propriété ''{0}'' ne peut pas être définie lorsqu''un objet de schéma non NULL a déjà été indiqué. # feature messages @@ -56,4 +56,4 @@ incompatible-class = La valeur indiquée pour la propriété ''{0}'' ne peut pas start-document-not-called=La propriété "{0}" doit être appelée après qu''un événement startDocument est généré nullparameter=le paramètre de nom pour "{0}" est NULL errorHandlerNotSet=Avertissement : la validation a été activée mais aucun élément org.xml.sax.ErrorHandler n''a été défini, ce qui devrait probablement être le cas. L''analyseur utilisera un gestionnaire d''erreurs par défaut pour imprimer les {0} premières erreurs. Appelez la méthode ''setErrorHandler'' pour résoudre ce problème. -errorHandlerDebugMsg=Erreur : URI = "{0}", ligne = "{1}", : {2} +errorHandlerDebugMsg=Erreur : URI = "{0}", ligne = "{1}", : {2} diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_it.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_it.properties index ea999e0171b10..10dbcb494dda7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_it.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_it.properties @@ -34,7 +34,7 @@ FormatFailed = Si è verificato un errore interno durante la formattazione del s # JAXP messages schema-not-supported = La lingua dello schema specificata non è supportata. -jaxp-order-not-supported = Impostare la proprietà ''{0}'' prima di impostare la proprietà ''{1}''. +jaxp-order-not-supported = Impostare la proprietà ''{0}'' prima di impostare la proprietà ''{1}''. schema-already-specified = Impossibile impostare la proprietà ''{0}'' se è già stato specificato un oggetto di schema non nullo. # feature messages @@ -56,4 +56,4 @@ incompatible-class = Impossibile eseguire la conversione cast del valore specifi start-document-not-called=Richiamare la proprietà "{0}" dopo l''esecuzione dell''evento startDocument nullparameter=il parametro del nome per "{0}" è nullo errorHandlerNotSet=Avvertenza: la convalida è stata attivata, ma org.xml.sax.ErrorHandler non è stato impostato, il che potrebbe essere un errore. Il parser utilizzerà un ErrorHandler predefinito per visualizzare i primi {0} errori. Richiamare il metodo ''setErrorHandler'' per correggere questo problema. -errorHandlerDebugMsg=Errore: URI = "{0}", riga = "{1}", : {2} +errorHandlerDebugMsg=Errore: URI = "{0}", riga = "{1}", : {2} diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ja.properties index ed8af93692c17..27201b883f955 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ja.properties @@ -26,7 +26,7 @@ FormatFailed = 次のメッセージの書式設定中に内部エラーが発 # JAXP messages schema-not-supported = 指定したスキーマ言語はサポートされていません。 -jaxp-order-not-supported = プロパティ''{1}''を設定する前にプロパティ''{0}''を設定する必要があります。 +jaxp-order-not-supported = プロパティ''{1}''を設定する前にプロパティ''{0}''を設定する必要があります。 schema-already-specified = null以外のスキーマ・オブジェクトがすでに指定されている場合、プロパティ''{0}''は設定できません。 # feature messages @@ -48,4 +48,4 @@ incompatible-class = プロパティ''{0}''に指定した値は{1}にキャス start-document-not-called=startDocumentイベントがスローされた後、プロパティ"{0}"を呼び出す必要があります nullparameter="{0}"の名前パラメータがnullです errorHandlerNotSet=警告: 検証はオンになっていますが、org.xml.sax.ErrorHandlerが設定されていません。必要とされているハンドラはこのハンドラではない可能性があります。パーサーでは、デフォルトのErrorHandlerを使用して最初の{0}エラーが出力されます。この問題を修正するには、''setErrorHandler''メソッドを呼び出してください。 -errorHandlerDebugMsg=エラー: URI = "{0}"、行 = "{1}"、: {2} +errorHandlerDebugMsg=エラー: URI = "{0}"、行 = "{1}"、: {2} diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ko.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ko.properties index 5b9e80a351f0d..7f5078f6d26e5 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ko.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ko.properties @@ -34,7 +34,7 @@ FormatFailed = 다음 메시지의 형식을 지정하는 중 내부 오류가 # JAXP messages schema-not-supported = 지정된 스키마 언어는 지원되지 않습니다. -jaxp-order-not-supported = ''{1}'' 속성을 설정하기 전에 ''{0}'' 속성을 설정해야 합니다. +jaxp-order-not-supported = ''{1}'' 속성을 설정하기 전에 ''{0}'' 속성을 설정해야 합니다. schema-already-specified = 널이 아닌 스키마 객체가 이미 지정된 경우 ''{0}'' 속성을 설정할 수 없습니다. # feature messages @@ -56,4 +56,4 @@ incompatible-class = ''{0}'' 속성에 대해 지정된 값의 데이터형을 { start-document-not-called="{0}" 속성은 startDocument 이벤트가 발생된 후 호출해야 합니다. nullparameter="{0}"에 대한 이름 매개변수가 널입니다. errorHandlerNotSet=경고: 검증이 설정되었지만 org.xml.sax.ErrorHandler가 적절히 설정되지 않았습니다. 구문 분석기가 기본 ErrorHandler를 사용하여 처음 {0}개의 오류를 인쇄합니다. 이 오류를 수정하려면 ''setErrorHandler'' 메소드를 호출하십시오. -errorHandlerDebugMsg=오류: URI = "{0}", 행 = "{1}", : {2} +errorHandlerDebugMsg=오류: URI = "{0}", 행 = "{1}", : {2} diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_pt_BR.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_pt_BR.properties index b60b2f5e5530f..7aab380d73980 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_pt_BR.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_pt_BR.properties @@ -34,7 +34,7 @@ FormatFailed = Ocorreu um erro interno ao formatar a mensagem a seguir:\n # JAXP messages schema-not-supported = O idioma do esquema especificado não é suportado. -jaxp-order-not-supported = A propriedade ''{0}'' deve ser definida antes da definição da propriedade ''{1}''. +jaxp-order-not-supported = A propriedade ''{0}'' deve ser definida antes da definição da propriedade ''{1}''. schema-already-specified = A propriedade ''{0}'' não pode ser definida quando um objeto do Esquema não nulo já tiver sido especificado. # feature messages @@ -56,4 +56,4 @@ incompatible-class = O valor especificado para a propriedade ''{0}'' não pode s start-document-not-called=A propriedade "{0}" deve ser chamada após o evento startDocument ser lançado nullparameter=o parâmetro de nome de "{0}" é nulo errorHandlerNotSet=Advertência: A validação foi ativada, mas um org.xml.sax.ErrorHandler não foi definido, provavelmente porque não era necessário. O parser usará um ErrorHandler padrão para imprimir os primeiros {0} erros. Chame o método ''setErrorHandler'' para corrigir o problema. -errorHandlerDebugMsg=Erro: URI = "{0}", Linha = "{1}", : {2} +errorHandlerDebugMsg=Erro: URI = "{0}", Linha = "{1}", : {2} diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_sv.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_sv.properties index cdd56145d37d6..847074319d7e4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_sv.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_sv.properties @@ -34,7 +34,7 @@ FormatFailed = Ett internt fel inträffade vid formatering av följande meddelan # JAXP messages schema-not-supported = Angivet schemaspråk stöds inte. -jaxp-order-not-supported = Egenskapen ''{0}'' måste anges före inställning av egenskapen ''{1}''. +jaxp-order-not-supported = Egenskapen ''{0}'' måste anges före inställning av egenskapen ''{1}''. schema-already-specified = Egenskapen ''{0}'' kan inte anges om ett Schema-objekt som är icke-null redan har angetts. # feature messages @@ -56,4 +56,4 @@ incompatible-class = Värdet angivet för egenskapen ''{0}'' kan inte omvandlas start-document-not-called=Egenskapen "{0}" bör anropas efter startDocument-händelsen utlöses nullparameter=namnparametern för "{0}" är null errorHandlerNotSet=Varning: valideringen startades, men det fanns ingen angiven org.xml.sax.ErrorHandler. Parser använder ErrorHandler av standardtyp vid utskrift av de första {0} felen. Korrigera felet genom anrop av setErrorHandler-metoden. -errorHandlerDebugMsg=Fel: URI = "{0}", Rad = "{1}", : {2} +errorHandlerDebugMsg=Fel: URI = "{0}", Rad = "{1}", : {2} diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_CN.properties index 617839234d5ed..5657e071bd470 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_CN.properties @@ -48,4 +48,4 @@ incompatible-class = 为属性 ''{0}'' 指定的值不能转换为{1}。 start-document-not-called=应在抛出 startDocument 事件后调用属性 "{0}" nullparameter="{0}" 的名称参数为空值 errorHandlerNotSet=警告: 已启用验证, 但未设置 org.xml.sax.ErrorHandler, 这可能不是预期结果。解析器将使用默认 ErrorHandler 来输出前 {0} 个错误。请调用 ''setErrorHandler'' 方法以解决此问题。 -errorHandlerDebugMsg=错误: URI = "{0}", 行 = "{1}", : {2} +errorHandlerDebugMsg=错误: URI = "{0}", 行 = "{1}", : {2} diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_TW.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_TW.properties index e98bda31111de..7c513b7341301 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_TW.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_TW.properties @@ -56,4 +56,4 @@ incompatible-class = 為屬性 ''{0}'' 指定的值不可轉換為 {1}。 start-document-not-called=發生 startDocument 事件之後,應呼叫屬性 "{0}"。 nullparameter="{0}" 的名稱參數為空值 errorHandlerNotSet=警告: 已開啟驗證,但是未設定 org.xml.sax.ErrorHandler,這可能不是所要的狀態。剖析器將使用預設的 ErrorHandler 來列印第一個 {0} 錯誤。請呼叫 ''setErrorHandler'' 方法來修正此問題。 -errorHandlerDebugMsg=錯誤: URI = "{0}",行 = "{1}",: {2} +errorHandlerDebugMsg=錯誤: URI = "{0}",行 = "{1}",: {2} diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages.properties index ae6e486f79d76..9b037ac8d9ff5 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages.properties @@ -17,7 +17,7 @@ # Messages for message reporting BadMessageKey = The error message corresponding to the message key can not be found. -FormatFailed = An internal error occurred while formatting the following message:\n +FormatFailed = An internal error occurred while formatting the following message:\n # Messages for erroneous input NoFallback = An 'include' with href ''{0}''failed, and no 'fallback' element was found. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties index 90ae689b94974..22e552e8b1eca 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties @@ -17,7 +17,7 @@ # Messages for message reporting BadMessageKey = Die zum Meldungsschlüssel gehörige Fehlermeldung kann nicht gefunden werden. -FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler aufgetreten:\n +FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler aufgetreten:\n # Messages for erroneous input NoFallback = "include" mit href "{0}" nicht erfolgreich, und es wurde kein "fallback"-Element gefunden. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_es.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_es.properties index 73267cde35550..0e12106d26b04 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_es.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_es.properties @@ -25,7 +25,7 @@ # Messages for message reporting BadMessageKey = No se ha encontrado el mensaje de error correspondiente a la clave de mensaje. -FormatFailed = Se ha producido un error interno al formatear el siguiente mensaje:\n +FormatFailed = Se ha producido un error interno al formatear el siguiente mensaje:\n # Messages for erroneous input NoFallback = Ha fallado un elemento ''include'' con href ''{0}'' y no se ha encontrado ningún elemento ''fallback''. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_fr.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_fr.properties index 1057584d33bee..556ab78c3e8c9 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_fr.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_fr.properties @@ -25,7 +25,7 @@ # Messages for message reporting BadMessageKey = Le message d'erreur correspondant à la clé de message est introuvable. -FormatFailed = Une erreur interne est survenue lors du formatage du message suivant :\n +FormatFailed = Une erreur interne est survenue lors du formatage du message suivant :\n # Messages for erroneous input NoFallback = Echec d''un élément ''include'' avec l''attribut href ''{0}'' ; aucun élément ''fallback'' n''a été trouvé. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_it.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_it.properties index de42b2936a931..4fbd4e2dbb3ac 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_it.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_it.properties @@ -25,7 +25,7 @@ # Messages for message reporting BadMessageKey = Impossibile trovare il messaggio di errore corrispondente alla chiave di messaggio. -FormatFailed = Si è verificato un errore interno durante la formattazione del seguente messaggio:\n +FormatFailed = Si è verificato un errore interno durante la formattazione del seguente messaggio:\n # Messages for erroneous input NoFallback = Errore dell''elemento ''include'' con href ''{0}''. Non è stato trovato alcune elemento ''fallback''. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties index f9d95d50ec440..3bde121bf5b0b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties @@ -17,7 +17,7 @@ # Messages for message reporting BadMessageKey = メッセージ・キーに対応するエラー・メッセージが見つかりません。 -FormatFailed = 次のメッセージの書式設定中に内部エラーが発生しました:\n +FormatFailed = 次のメッセージの書式設定中に内部エラーが発生しました:\n # Messages for erroneous input NoFallback = href ''{0}''を含む''include''が失敗し、''fallback''要素が見つかりませんでした。 diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ko.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ko.properties index ea4863bd912e5..a9aeadb7891f7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ko.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ko.properties @@ -25,7 +25,7 @@ # Messages for message reporting BadMessageKey = 메시지 키에 해당하는 오류 메시지를 찾을 수 없습니다. -FormatFailed = 다음 메시지의 형식을 지정하는 중 내부 오류가 발생했습니다.\n +FormatFailed = 다음 메시지의 형식을 지정하는 중 내부 오류가 발생했습니다.\n # Messages for erroneous input NoFallback = href ''{0}''을(를) 사용한 ''include''를 실패했으며 ''fallback'' 요소를 찾을 수 없습니다. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_pt_BR.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_pt_BR.properties index dcf3c0ddafb49..d3819a3c64e7d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_pt_BR.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_pt_BR.properties @@ -25,7 +25,7 @@ # Messages for message reporting BadMessageKey = Não foi possível encontrar a mensagem de erro correspondente à chave da mensagem. -FormatFailed = Ocorreu um erro interno ao formatar a mensagem a seguir:\n +FormatFailed = Ocorreu um erro interno ao formatar a mensagem a seguir:\n # Messages for erroneous input NoFallback = Falha em um ''include'' com href ''{0}'' e não foi encontrado elemento ''fallback''. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_sv.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_sv.properties index 6dcef94cca6ff..e51be5c17ab47 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_sv.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_sv.properties @@ -25,7 +25,7 @@ # Messages for message reporting BadMessageKey = Hittar inte felmeddelandet som motsvarar meddelandenyckeln. -FormatFailed = Ett internt fel inträffade vid formatering av följande meddelande:\n +FormatFailed = Ett internt fel inträffade vid formatering av följande meddelande:\n # Messages for erroneous input NoFallback = Ett ''include'' med href ''{0}'' utfördes inte, hittade inget återskapningselement (''fallback''). diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties index 0efe76a5df5de..b8648ce6baef3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties @@ -17,7 +17,7 @@ # Messages for message reporting BadMessageKey = 找不到与消息关键字对应的错误消息。 -FormatFailed = 设置以下消息的格式时出现内部错误:\n +FormatFailed = 设置以下消息的格式时出现内部错误:\n # Messages for erroneous input NoFallback = 带有 href ''{0}'' 的 ''include'' 失败, 并且找不到 ''fallback'' 元素。 diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages.properties index 6e106bd532bfd..78a34631d0b3d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages.properties @@ -24,7 +24,7 @@ # @version BadMessageKey = The error message corresponding to the message key can not be found. - FormatFailed = An internal error occurred while formatting the following message:\n + FormatFailed = An internal error occurred while formatting the following message:\n # Document messages PrematureEOF=Premature end of file. @@ -131,7 +131,7 @@ EncodingDeclRequired = The encoding declaration is required in the text declaration. NoMorePseudoAttributes = No more pseudo attributes are allowed. MorePseudoAttributes = More pseudo attributes are expected. - PseudoAttrNameExpected = A pseudo attribute name is expected. + PseudoAttrNameExpected = A pseudo attribute name is expected. # 4.3.2 Well-Formed Parsed Entities CommentNotInOneEntity = The comment must be entirely contained within the same parsed entity. PINotInOneEntity = The processing instruction must be entirely contained within the same parsed entity. @@ -139,7 +139,7 @@ EncodingDeclInvalid = Invalid encoding name \"{0}\". EncodingByteOrderUnsupported = Given byte order for encoding \"{0}\" is not supported. InvalidByte = Invalid byte {0} of {1}-byte UTF-8 sequence. - ExpectedByte = Expected byte {0} of {1}-byte UTF-8 sequence. + ExpectedByte = Expected byte {0} of {1}-byte UTF-8 sequence. InvalidHighSurrogate = High surrogate bits in UTF-8 sequence must not exceed 0x10 but found 0x{0}. OperationNotSupported = Operation \"{0}\" not supported by {1} reader. InvalidASCII = Byte \"{0}\" is not a member of the (7-bit) ASCII character set. @@ -219,7 +219,7 @@ MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = White space is required before \"NDATA\" in the declaration for the entity \"{0}\". MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = The notation name is required after \"NDATA\" in the declaration for the entity \"{0}\". EntityDeclUnterminated = The declaration for the entity \"{0}\" must end with ''>''. - MSG_DUPLICATE_ENTITY_DEFINITION = Entity \"{0}\" is declared more than once. + MSG_DUPLICATE_ENTITY_DEFINITION = Entity \"{0}\" is declared more than once. # 4.2.2 External Entities ExternalIDRequired = The external entity declaration must begin with either \"SYSTEM\" or \"PUBLIC\". MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = White space is required between \"PUBLIC\" and the public identifier. @@ -275,7 +275,7 @@ RootElementTypeMustMatchDoctypedecl = Document root element \"{1}\", must match DOCTYPE root \"{0}\". UndeclaredElementInContentSpec = The content model of element \"{0}\" refers to the undeclared element \"{1}\". UniqueNotationName = The declaration for the notation \"{0}\" is not unique. A given Name must not be declared in more than one notation declaration. - ENTITYFailedInitializeGrammar = ENTITYDatatype Validator: Failed Need to call initialize method with a valid Grammar reference. + ENTITYFailedInitializeGrammar = ENTITYDatatype Validator: Failed Need to call initialize method with a valid Grammar reference. ENTITYNotUnparsed = ENTITY \"{0}\" is not unparsed. ENTITYNotValid = ENTITY \"{0}\" is not valid. EmptyList = Value of type ENTITIES, IDREFS, and NMTOKENS cannot be empty list. @@ -330,4 +330,3 @@ # Implementation Property DTD JDK_DTD_DENY = JAXP00010008: DOCTYPE is disallowed when the DTD property is set to deny. \ Refer to: property jdk.xml.dtd.support in java.xml/module-summary. - diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties index 7407d4da3e09c..9227a61a60852 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties @@ -24,7 +24,7 @@ # @version BadMessageKey = Die zum Meldungsschlüssel gehörige Fehlermeldung kann nicht gefunden werden. - FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler aufgetreten:\n + FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler aufgetreten:\n # Document messages PrematureEOF=Vorzeitiges Dateiende. @@ -131,7 +131,7 @@ EncodingDeclRequired = Codierungsdeklaration ist in der Textdeklaration erforderlich. NoMorePseudoAttributes = Es sind keine weiteren Pseudoattribute zulässig. MorePseudoAttributes = Es werden weitere Pseudoattribute erwartet. - PseudoAttrNameExpected = Pseudoattributname wird erwartet. + PseudoAttrNameExpected = Pseudoattributname wird erwartet. # 4.3.2 Well-Formed Parsed Entities CommentNotInOneEntity = Kommentar muss vollständig in derselben geparsten Entity enthalten sein. PINotInOneEntity = Verarbeitungsanweisung muss vollständig in derselben geparsten Entity enthalten sein. @@ -139,7 +139,7 @@ EncodingDeclInvalid = Ungültiger Codierungsname "{0}". EncodingByteOrderUnsupported = Angegebene Bytereihenfolge für die Codierung von "{0}" wird nicht unterstützt. InvalidByte = Ungültiges Byte {0} von {1}-Byte-UTF-8-Sequenz. - ExpectedByte = Byte {0} von {1}-Byte-UTF-8-Sequenz erwartet. + ExpectedByte = Byte {0} von {1}-Byte-UTF-8-Sequenz erwartet. InvalidHighSurrogate = High-Surrogate-Bits in UTF-8-Sequenz dürfen 0x10 nicht überschreiten, gefunden wurde aber 0x{0}. OperationNotSupported = Vorgang "{0}" nicht unterstützt von {1}-Reader. InvalidASCII = Byte "{0}" gehört nicht zum (7-Bit) ASCII-Zeichensatz. @@ -219,7 +219,7 @@ MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = Leerstelle vor "NDATA" in der Deklaration für die Entity "{0} erforderlich. MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = Notationsname ist nach "NDATA" in der Deklaration für die Entity "{0} erforderlich. EntityDeclUnterminated = Deklaration für Entity "{0}" muss mit ">" enden. - MSG_DUPLICATE_ENTITY_DEFINITION = Entity "{0}" wurde mehrmals deklariert. + MSG_DUPLICATE_ENTITY_DEFINITION = Entity "{0}" wurde mehrmals deklariert. # 4.2.2 External Entities ExternalIDRequired = Externe Entitydeklaration muss mit "SYSTEM" oder "PUBLIC" beginnen. MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = Leerstelle zwischen "PUBLIC" und der öffentlichen ID erforderlich. @@ -329,4 +329,3 @@ # Implementation Property DTD JDK_DTD_DENY = JAXP00010008: DOCTYPE ist nicht zulässig, wenn die DTD-Eigenschaft auf Ablehnen gesetzt wurde. Weitere Informationen: Eigenschaft jdk.xml.dtd.support in java.xml/module-summary. - diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties index 9639bf0b5647a..f20c7db51646d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties @@ -4,7 +4,7 @@ # @version BadMessageKey = No se ha encontrado el mensaje de error correspondiente a la clave de mensaje. - FormatFailed = Se ha producido un error interno al formatear el siguiente mensaje:\n + FormatFailed = Se ha producido un error interno al formatear el siguiente mensaje:\n # Document messages PrematureEOF=Final de archivo prematuro. @@ -111,7 +111,7 @@ EncodingDeclRequired = La declaración de codificación es necesaria en la declaración de texto. NoMorePseudoAttributes = No se permiten más pseudo atributos. MorePseudoAttributes = Se esperan más pseudo atributos. - PseudoAttrNameExpected = Se espera el nombre de un pseudo atributo. + PseudoAttrNameExpected = Se espera el nombre de un pseudo atributo. # 4.3.2 Well-Formed Parsed Entities CommentNotInOneEntity = El comentario debe incluirse totalmente en la misma entidad analizada. PINotInOneEntity = La instrucción de procesamiento debe incluirse totalmente en la misma entidad analizada. @@ -119,7 +119,7 @@ EncodingDeclInvalid = Nombre de codificación no válido "{0}". EncodingByteOrderUnsupported = El orden de bytes proporcionado para la codificación "{0}" no está soportado. InvalidByte = Byte no válido {0} de la secuencia UTF-8 de {1} bytes - ExpectedByte = Byte esperado {0} de la secuencia UTF-8 de {1} bytes. + ExpectedByte = Byte esperado {0} de la secuencia UTF-8 de {1} bytes. InvalidHighSurrogate = Los bits de sustitución superior en la secuencia UTF-8 no deben exceder 0x10 pero se han encontrado 0x{0}. OperationNotSupported = La operación "{0}" no está soportada por el lector {1}. InvalidASCII = El byte "{0}"no es un miembro del juego de caracteres ASCII (7 bits). @@ -199,7 +199,7 @@ MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = Es necesario un espacio en blanco antes de "NDATA" en la declaración para la entidad "{0}". MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = El nombre de notación es necesario después de "NDATA" en la declaración para la entidad "{0}". EntityDeclUnterminated = La declaración para la entidad "{0}" debe finalizar en ''>''. - MSG_DUPLICATE_ENTITY_DEFINITION = La entidad "{0}" se ha declarado más de una vez. + MSG_DUPLICATE_ENTITY_DEFINITION = La entidad "{0}" se ha declarado más de una vez. # 4.2.2 External Entities ExternalIDRequired = La declaración de entidad externa debe empezar por "SYSTEM" o "PUBLIC". MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = Es necesario un espacio en blanco entre "PUBLIC" y el identificador público. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties index 4300c2f7e4562..a47daba87f00c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties @@ -4,7 +4,7 @@ # @version BadMessageKey = Le message d'erreur correspondant à la clé de message est introuvable. - FormatFailed = Une erreur interne s'est produite pendant la mise en forme du message suivant :\n + FormatFailed = Une erreur interne s'est produite pendant la mise en forme du message suivant :\n # Document messages PrematureEOF=Fin prématurée du fichier. @@ -111,7 +111,7 @@ EncodingDeclRequired = La déclaration d'encodage est obligatoire dans la déclaration textuelle. NoMorePseudoAttributes = Aucun autre pseudo-attribut n'est autorisé. MorePseudoAttributes = D'autres pseudo-attributs sont attendus. - PseudoAttrNameExpected = Un nom de pseudo-attribut est attendu. + PseudoAttrNameExpected = Un nom de pseudo-attribut est attendu. # 4.3.2 Well-Formed Parsed Entities CommentNotInOneEntity = Le commentaire doit être entièrement inclus dans la même entité analysée. PINotInOneEntity = L'instruction de traitement doit être entièrement incluse dans la même entité analysée. @@ -119,7 +119,7 @@ EncodingDeclInvalid = Nom d''encodage "{0}" non valide. EncodingByteOrderUnsupported = L''ordre des octets donné pour encoder "{0}" n''est pas pris en charge. InvalidByte = Octet {0} de la séquence UTF-8 à {1} octets non valide. - ExpectedByte = Octet {0} de la séquence UTF-8 à {1} octets attendu. + ExpectedByte = Octet {0} de la séquence UTF-8 à {1} octets attendu. InvalidHighSurrogate = Les bits de substitution supérieurs (High surrogate) dans la séquence UTF-8 ne doivent pas dépasser 0x10 mais des bits 0x{0} ont été détectés. OperationNotSupported = Opération "{0}" non prise en charge par le lecteur {1}. InvalidASCII = L''octet "{0}" n''appartient pas au jeu de caractères ASCII (7 bits). @@ -199,7 +199,7 @@ MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = Un espace est obligatoire avant "NDATA" dans la déclaration de l''entité "{0}". MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = Le nom de notation est obligatoire après "NDATA" dans la déclaration de l''entité "{0}". EntityDeclUnterminated = La déclaration de l''entité "{0}" doit se terminer par ''>''. - MSG_DUPLICATE_ENTITY_DEFINITION = L''entité "{0}" est déclarée plusieurs fois. + MSG_DUPLICATE_ENTITY_DEFINITION = L''entité "{0}" est déclarée plusieurs fois. # 4.2.2 External Entities ExternalIDRequired = La déclaration d'entité externe doit commencer par "SYSTEM" ou "PUBLIC". MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = Un espace est obligatoire entre "PUBLIC" et l'identificateur public. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties index 0ec786a1bbb15..7af820eb7c097 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties @@ -4,7 +4,7 @@ # @version BadMessageKey = Impossibile trovare il messaggio di errore corrispondente alla chiave di messaggio. - FormatFailed = Si è verificato un errore interno durante la formattazione del seguente messaggio:\n + FormatFailed = Si è verificato un errore interno durante la formattazione del seguente messaggio:\n # Document messages PrematureEOF=Fine del file anticipata. @@ -111,7 +111,7 @@ EncodingDeclRequired = La dichiarazione di codifica è obbligatoria nella dichiarazione di testo. NoMorePseudoAttributes = Non sono consentiti altri attributi pseudo. MorePseudoAttributes = Sono previsti altri attributi pseudo. - PseudoAttrNameExpected = È previsto un nome attributo pseudo. + PseudoAttrNameExpected = È previsto un nome attributo pseudo. # 4.3.2 Well-Formed Parsed Entities CommentNotInOneEntity = Il commento deve essere compreso completamente all'interno della stessa entità analizzata. PINotInOneEntity = L'istruzione di elaborazione deve essere compresa completamente all'interno della stessa entità analizzata. @@ -119,7 +119,7 @@ EncodingDeclInvalid = Nome codifica "{0}" non valido. EncodingByteOrderUnsupported = L''ordine di byte specificato per la codifica "{0}" non è supportato. InvalidByte = Byte non valido {0} della sequenza UTF-8 a {1} byte. - ExpectedByte = È previsto il byte {0} della sequenza UTF-8 a {1} byte. + ExpectedByte = È previsto il byte {0} della sequenza UTF-8 a {1} byte. InvalidHighSurrogate = I bit per surrogato alto nella sequenza UTF-8 non devono superare 0x10, ma è stato trovato 0x{0}. OperationNotSupported = Operazione "{0}" non supportata dal processo di lettura {1}. InvalidASCII = Il byte "{0}" non fa parte del set di caratteri ASCII (a 7 bit). @@ -199,7 +199,7 @@ MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = È richiesto uno spazio prima di "NDATA" nella dichiarazione dell''entità "{0}". MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = Il nome notazione è obbligatorio dopo "NDATA" nella dichiarazione dell''entità "{0}". EntityDeclUnterminated = La dichiarazione per l''entità "{0}" deve terminare con ''>''. - MSG_DUPLICATE_ENTITY_DEFINITION = L''entità "{0}" è stata dichiarata più volte. + MSG_DUPLICATE_ENTITY_DEFINITION = L''entità "{0}" è stata dichiarata più volte. # 4.2.2 External Entities ExternalIDRequired = La dichiarazione di entità esterna deve iniziare con "SYSTEM" o "PUBLIC". MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = È richiesto uno spazio tra "PUBLIC" e l'identificativo pubblico. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties index 7204dfddd3ec0..ef0edf1b18874 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties @@ -24,7 +24,7 @@ # @version BadMessageKey = メッセージ・キーに対応するエラー・メッセージが見つかりません。 - FormatFailed = 次のメッセージの書式設定中に内部エラーが発生しました:\n + FormatFailed = 次のメッセージの書式設定中に内部エラーが発生しました:\n # Document messages PrematureEOF=途中でファイルの末尾に達しました。 @@ -131,7 +131,7 @@ EncodingDeclRequired = テキスト宣言にはエンコーディング宣言が必要です。 NoMorePseudoAttributes = これ以上の疑似属性は指定できません。 MorePseudoAttributes = 疑似属性がさらに必要です。 - PseudoAttrNameExpected = 疑似属性名が必要です。 + PseudoAttrNameExpected = 疑似属性名が必要です。 # 4.3.2 Well-Formed Parsed Entities CommentNotInOneEntity = コメントは、同じ解析済エンティティ内に完全に含まれている必要があります。 PINotInOneEntity = 処理命令は、同じ解析済エンティティ内に完全に含まれている必要があります。 @@ -139,7 +139,7 @@ EncodingDeclInvalid = エンコーディング名"{0}"が無効です。 EncodingByteOrderUnsupported = エンコーディング"{0}"に指定されたバイト順はサポートされていません。 InvalidByte = {1}バイトのUTF-8シーケンスのバイト{0}が無効です。 - ExpectedByte = {1}バイトのUTF-8シーケンスのバイト{0}が必要です。 + ExpectedByte = {1}バイトのUTF-8シーケンスのバイト{0}が必要です。 InvalidHighSurrogate = UTF-8シーケンスの上位サロゲート・ビットの上限は0x10ですが、0x{0}が検出されました。 OperationNotSupported = 操作"{0}"は{1}リーダーでサポートされていません。 InvalidASCII = バイト"{0}"は、(7ビット) ASCII文字セットのメンバーではありません。 @@ -219,7 +219,7 @@ MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = エンティティ"{0}"の宣言では、"NDATA"の前に空白が必要です。 MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = エンティティ"{0}"の宣言では、"NDATA"の後に表記名が必要です。 EntityDeclUnterminated = エンティティ"{0}"の宣言は''>''で終了する必要があります。 - MSG_DUPLICATE_ENTITY_DEFINITION = エンティティ"{0}"が複数回宣言されています。 + MSG_DUPLICATE_ENTITY_DEFINITION = エンティティ"{0}"が複数回宣言されています。 # 4.2.2 External Entities ExternalIDRequired = 外部エンティティ宣言の先頭には"SYSTEM"または"PUBLIC"が必要です。 MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = "PUBLIC"と公開識別子の間には空白が必要です。 @@ -329,4 +329,3 @@ # Implementation Property DTD JDK_DTD_DENY = JAXP00010008: DTDプロパティが拒否に設定されている場合、DOCTYPEは指定できません。参照: java.xml/module-summaryのプロパティjdk.xml.dtd.support。 - diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ko.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ko.properties index 4dbf9a5fb2959..e63654de23c1a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ko.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ko.properties @@ -4,7 +4,7 @@ # @version BadMessageKey = 메시지 키에 해당하는 오류 메시지를 찾을 수 없습니다. - FormatFailed = 다음 메시지의 형식을 지정하는 중 내부 오류가 발생했습니다.\n + FormatFailed = 다음 메시지의 형식을 지정하는 중 내부 오류가 발생했습니다.\n # Document messages PrematureEOF=예기치 않은 파일의 끝입니다. @@ -111,7 +111,7 @@ EncodingDeclRequired = 텍스트 선언에는 인코딩 선언이 필요합니다. NoMorePseudoAttributes = 의사 속성은 더 이상 허용되지 않습니다. MorePseudoAttributes = 의사 속성이 더 필요합니다. - PseudoAttrNameExpected = 의사 속성 이름이 필요합니다. + PseudoAttrNameExpected = 의사 속성 이름이 필요합니다. # 4.3.2 Well-Formed Parsed Entities CommentNotInOneEntity = 주석은 구문이 분석된 동일한 엔티티에 완전히 포함되어야 합니다. PINotInOneEntity = 처리 명령은 구문이 분석된 동일한 엔티티에 완전히 포함되어야 합니다. @@ -119,7 +119,7 @@ EncodingDeclInvalid = "{0}"은(는) 부적합한 인코딩 이름입니다. EncodingByteOrderUnsupported = "{0}" 인코딩에 대해 제공된 바이트 순서는 지원되지 않습니다. InvalidByte = {0}은(는) {1}바이트 UTF-8 시퀀스에 대해 부적합한 바이트입니다. - ExpectedByte = {1}바이트 UTF-8 시퀀스에 필요한 바이트는 {0}입니다. + ExpectedByte = {1}바이트 UTF-8 시퀀스에 필요한 바이트는 {0}입니다. InvalidHighSurrogate = UTF-8 시퀀스의 높은 대리 비트는 0x10을 초과하지 않아야 하지만 0x{0}이(가) 발견되었습니다. OperationNotSupported = {1} 읽기 프로그램은 "{0}" 작업을 지원하지 않습니다. InvalidASCII = 바이트 "{0}"은(는) (7비트) ASCII 문자 집합에 속하지 않습니다. @@ -199,7 +199,7 @@ MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = "{0}" 엔티티에 대한 선언에서는 "NDATA" 앞에 공백이 필요합니다. MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = "{0}" 엔티티에 대한 선언에서는 "NDATA" 다음에 표기법 이름이 필요합니다. EntityDeclUnterminated = "{0}" 엔티티에 대한 선언은 ''>''로 끝나야 합니다. - MSG_DUPLICATE_ENTITY_DEFINITION = "{0}" 엔티티가 두 번 이상 선언되었습니다. + MSG_DUPLICATE_ENTITY_DEFINITION = "{0}" 엔티티가 두 번 이상 선언되었습니다. # 4.2.2 External Entities ExternalIDRequired = 외부 엔티티 선언은 "SYSTEM" 또는 "PUBLIC"으로 시작해야 합니다. MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = "PUBLIC"과 공용 식별자 사이에는 공백이 필요합니다. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_pt_BR.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_pt_BR.properties index 4dbf741007fba..4be5baae0d097 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_pt_BR.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_pt_BR.properties @@ -4,7 +4,7 @@ # @version BadMessageKey = Não foi possível encontrar a mensagem de erro correspondente à chave da mensagem. - FormatFailed = Ocorreu um erro interno ao formatar a mensagem a seguir:\n + FormatFailed = Ocorreu um erro interno ao formatar a mensagem a seguir:\n # Document messages PrematureEOF=Fim prematuro do arquivo. @@ -111,7 +111,7 @@ EncodingDeclRequired = A declaração de codificação é necessária na declaração de texto. NoMorePseudoAttributes = Não são mais permitidos pseudo-atributos. MorePseudoAttributes = São esperados mais pseudo-atributos. - PseudoAttrNameExpected = É esperado um nome de um pseudo-atributo. + PseudoAttrNameExpected = É esperado um nome de um pseudo-atributo. # 4.3.2 Well-Formed Parsed Entities CommentNotInOneEntity = O comentário deve estar totalmente contido na mesma entidade submetida a parsing. PINotInOneEntity = A instrução de processamento deve estar totalmente contida na mesma entidade submetida a parsing. @@ -119,7 +119,7 @@ EncodingDeclInvalid = Nome da codificação inválida "{0}". EncodingByteOrderUnsupported = A ordem de bytes fornecida para codificação "{0}" não é suportada. InvalidByte = Byte inválido {0} da sequência UTF-8 do byte {1}. - ExpectedByte = Esperava {0} byte da sequência UTF-8 do byte {1}. + ExpectedByte = Esperava {0} byte da sequência UTF-8 do byte {1}. InvalidHighSurrogate = Os bits substitutos altos na sequência da UTF-8 não devem exceder 0x10 mas foi encontrado 0x{0}. OperationNotSupported = A operação "{0}" não é suportada pelo leitor {1}. InvalidASCII = O byte "{0}" não é membro do conjunto de caracteres ASCII (7 bits). @@ -199,7 +199,7 @@ MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = O espaço em branco é necessário antes de "NDATA" na declaração da entidade "{0}". MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = O nome da notação é necessário após "NDATA" na declaração da entidade "{0}". EntityDeclUnterminated = A declaração da entidade "{0}" deve terminar com ''>''. - MSG_DUPLICATE_ENTITY_DEFINITION = A entidade "{0}" foi declarada mais de uma vez. + MSG_DUPLICATE_ENTITY_DEFINITION = A entidade "{0}" foi declarada mais de uma vez. # 4.2.2 External Entities ExternalIDRequired = A declaração da entidade externa deve começar com "SYSTEM" ou "PUBLIC". MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = O espaço em branco é necessário entre "PUBLIC" e o identificador público. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_sv.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_sv.properties index b94d0f982a35a..b27963ef058e8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_sv.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_sv.properties @@ -4,7 +4,7 @@ # @version BadMessageKey = Hittar inte felmeddelandet som motsvarar meddelandenyckeln. - FormatFailed = Ett internt fel inträffade vid formatering av följande meddelande:\n + FormatFailed = Ett internt fel inträffade vid formatering av följande meddelande:\n # Document messages PrematureEOF=Filen har avslutats för tidigt. @@ -111,7 +111,7 @@ EncodingDeclRequired = Koddeklaration krävs i textdeklarationen. NoMorePseudoAttributes = Inga fler pseudoattribut är tillåtna. MorePseudoAttributes = Ytterligare pseudoattribut förväntas. - PseudoAttrNameExpected = Ett pseudoattributnamn förväntas. + PseudoAttrNameExpected = Ett pseudoattributnamn förväntas. # 4.3.2 Well-Formed Parsed Entities CommentNotInOneEntity = Kommentaren måste finnas med inom samma tolkade enhet. PINotInOneEntity = Bearbetningsinstruktionen måste finnas med inom samma tolkade enhet. @@ -119,7 +119,7 @@ EncodingDeclInvalid = Ogiltigt kodnamn, "{0}". EncodingByteOrderUnsupported = Angiven byteordningsföljd i kodning "{0}" stöds inte. InvalidByte = Ogiltig byte {0} i UTF-8-sekvensen för {1}-byte. - ExpectedByte = Förväntad byte {0} i UTF-8-sekvensen för {1}-byte. + ExpectedByte = Förväntad byte {0} i UTF-8-sekvensen för {1}-byte. InvalidHighSurrogate = Höga surrogatbitar i UTF-8-sekvens får inte överskrida 0x10, men 0x{0} hittades. OperationNotSupported = Åtgärden "{0}" stöds inte i läsaren {1}. InvalidASCII = Byte "{0}" ingår inte i ASCII-teckenuppsättningen (7 bitar). @@ -199,7 +199,7 @@ MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = Tomt utrymme krävs före "NDATA" i deklarationen för enheten "{0}". MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = Notationsnamnet måste anges efter "NDATA" i deklarationen för enheten "{0}". EntityDeclUnterminated = Deklarationen för enheten "{0}" måste avslutas med ''>''. - MSG_DUPLICATE_ENTITY_DEFINITION = Enheten "{0}" har deklarerats mer än en gång. + MSG_DUPLICATE_ENTITY_DEFINITION = Enheten "{0}" har deklarerats mer än en gång. # 4.2.2 External Entities ExternalIDRequired = Den externa enhetsdeklarationen måste inledas med antingen "SYSTEM" eller "PUBLIC". MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = Tomt utrymme krävs mellan "PUBLIC" och den allmänna identifieraren. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties index de68714fa2e19..0b937ce7623d9 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties @@ -24,7 +24,7 @@ # @version BadMessageKey = 找不到与消息关键字对应的错误消息。 - FormatFailed = 设置以下消息的格式时出现内部错误:\n + FormatFailed = 设置以下消息的格式时出现内部错误:\n # Document messages PrematureEOF=文件提前结束。 @@ -219,7 +219,7 @@ MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = 在实体 "{0}" 的声明中的 "NDATA" 前面需要有空格。 MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = 在实体 "{0}" 的声明中的 "NDATA" 后面需要有记号名称。 EntityDeclUnterminated = 实体 "{0}" 的声明必须以 ''>'' 结尾。 - MSG_DUPLICATE_ENTITY_DEFINITION = 实体 "{0}" 声明了多次。 + MSG_DUPLICATE_ENTITY_DEFINITION = 实体 "{0}" 声明了多次。 # 4.2.2 External Entities ExternalIDRequired = 外部实体声明必须以 "SYSTEM" 或 "PUBLIC" 开头。 MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = 在 "PUBLIC" 和公共标识符之间需要有空格。 @@ -329,4 +329,3 @@ # Implementation Property DTD JDK_DTD_DENY = JAXP00010008:当 DTD 属性设置为拒绝时,不允许使用 DOCTYPE。请参阅:java.xml/module-summary 中的属性 jdk.xml.dtd.support。 - diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_TW.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_TW.properties index 44671abcfd848..976fde3085c67 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_TW.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_TW.properties @@ -199,7 +199,7 @@ MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = 在實體 "{0}" 的宣告中,"NDATA" 之前需要空格。 MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = 在實體 "{0}" 的宣告中,"NDATA" 之後需要表示法名稱。 EntityDeclUnterminated = 實體 "{0}" 的宣告結尾必須為 ''>''。 - MSG_DUPLICATE_ENTITY_DEFINITION = 實體 "{0}" 宣告超過一次以上。 + MSG_DUPLICATE_ENTITY_DEFINITION = 實體 "{0}" 宣告超過一次以上。 # 4.2.2 External Entities ExternalIDRequired = 外部實體宣告的開頭必須為 "SYSTEM" 或 "PUBLIC"。 MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = "PUBLIC" 與公用 ID 之間需要空格。 diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties index 47d8b7e9f535e..f6402e8f65e49 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties @@ -107,7 +107,7 @@ #schema valid (3.X.3) - schema_reference.access = schema_reference: Failed to read schema document ''{0}'', because ''{1}'' access is not allowed due to restriction set by the accessExternalSchema property. + schema_reference.access = schema_reference: Failed to read schema document ''{0}'', because ''{1}'' access is not allowed due to restriction set by the accessExternalSchema property. schema_reference.4 = schema_reference.4: Failed to read schema document ''{0}'', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not . src-annotation = src-annotation: elements can only contain and elements, but ''{0}'' was found. src-attribute.1 = src-attribute.1: The properties ''default'' and ''fixed'' cannot both be present in attribute declaration ''{0}''. Use only one of them. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties index 9ed8feb5ef027..1144488773e72 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties @@ -107,7 +107,7 @@ #schema valid (3.X.3) - schema_reference.access = schema_reference: Schemadokument ''{0}'' konnte nicht gelesen werden, weil der ''{1}''-Zugriff wegen der von der Eigenschaft accessExternalSchema festgelegten Einschränkung nicht zulässig ist. + schema_reference.access = schema_reference: Schemadokument ''{0}'' konnte nicht gelesen werden, weil der ''{1}''-Zugriff wegen der von der Eigenschaft accessExternalSchema festgelegten Einschränkung nicht zulässig ist. schema_reference.4 = schema_reference.4: Schemadokument ''{0}'' konnte nicht gelesen werden, da 1) das Dokument nicht gefunden werden konnte; 2) das Dokument nicht gelesen werden konnte; 3) das Root-Element des Dokuments nicht ist. src-annotation = src-annotation: -Elemente können nur - und -Elemente enthalten, aber es wurde ''{0}'' gefunden. src-attribute.1 = src-attribute.1: Die Eigenschaften ''default'' und ''fixed'' können nicht beide in der Attributdeklaration ''{0}'' vorhanden sein. Verwenden Sie nur eine dieser Eigenschaften. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_es.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_es.properties index fd3310a044288..9b5e412696b3e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_es.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_es.properties @@ -115,7 +115,7 @@ #schema valid (3.X.3) - schema_reference.access = schema_reference: fallo al leer el documento de esquema ''{0}'' porque no se permite el acceso ''{1}'' debido a una restricción definida por la propiedad accessExternalSchema. + schema_reference.access = schema_reference: fallo al leer el documento de esquema ''{0}'' porque no se permite el acceso ''{1}'' debido a una restricción definida por la propiedad accessExternalSchema. schema_reference.4 = schema_reference.4: Fallo al leer el documento de esquema ''{0}'', porque 1) no se ha encontrado el documento; 2) no se ha podido leer el documento; 3) el elemento raíz del documento no es . src-annotation = src-annotation: Los elementos de sólo pueden contener elementos de y , pero se ha encontrado ''{0}''. src-attribute.1 = src-attribute.1: Las propiedades ''default'' y ''fixed'' no pueden estar presentes de forma simultánea en la declaración de atributo ''{0}''. Utilice sólo una de ellas. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_fr.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_fr.properties index 7d320d2f18736..a955e5d11f3e8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_fr.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_fr.properties @@ -115,7 +115,7 @@ #schema valid (3.X.3) - schema_reference.access = schema_reference : échec de la lecture du document de schéma ''{0}'', car l''accès ''{1}'' n''est pas autorisé en raison d''une restriction définie par la propriété accessExternalSchema. + schema_reference.access = schema_reference : échec de la lecture du document de schéma ''{0}'', car l''accès ''{1}'' n''est pas autorisé en raison d''une restriction définie par la propriété accessExternalSchema. schema_reference.4 = schema_reference.4 : Echec de la lecture du document de schéma ''{0}'' pour les raisons suivantes : 1) Le document est introuvable ; 2) Le document n''a pas pu être lu ; 3) L''élément racine du document n''est pas . src-annotation = src-annotation : Les éléments ne peuvent contenir que des éléments et , mais ''{0}'' a été trouvé. src-attribute.1 = src-attribute.1 : Les propriétés ''default'' et ''fixed'' ne peuvent pas figurer simultanément dans la déclaration d''attribut ''{0}''. Utilisez uniquement l''une d''entre elles. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_it.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_it.properties index 7b640448b2c5c..04578cdc31439 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_it.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_it.properties @@ -115,7 +115,7 @@ #schema valid (3.X.3) - schema_reference.access = schema_reference: lettura del documento di schema ''{0}'' non riuscita. Accesso ''{1}'' non consentito a causa della limitazione definita dalla proprietà accessExternalSchema. + schema_reference.access = schema_reference: lettura del documento di schema ''{0}'' non riuscita. Accesso ''{1}'' non consentito a causa della limitazione definita dalla proprietà accessExternalSchema. schema_reference.4 = schema_reference.4: lettura del documento di schema "{0}" non riuscita perché 1) non è stato possibile trovare il documento; 2) non è stato possibile leggere il documento; 3) l''elemento radice del documento non è . src-annotation = src-annotation: possono essere contenuti soltanto elementi e , ma è stato trovato ''{0}''. src-attribute.1 = src-attribute.1: le proprietà ''default'' e ''fixed'' non possono essere entrambi presenti nella dichiarazione di attributo ''{0}''. Utilizzarne solo una. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ko.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ko.properties index 043edbf28670b..91949ed6c9c46 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ko.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ko.properties @@ -115,7 +115,7 @@ #schema valid (3.X.3) - schema_reference.access = schema_reference: accessExternalSchema 속성으로 설정된 제한으로 인해 ''{1}'' 액세스가 허용되지 않으므로 스키마 문서 ''{0}'' 읽기를 실패했습니다. + schema_reference.access = schema_reference: accessExternalSchema 속성으로 설정된 제한으로 인해 ''{1}'' 액세스가 허용되지 않으므로 스키마 문서 ''{0}'' 읽기를 실패했습니다. schema_reference.4 = schema_reference.4: 스키마 문서 ''{0}'' 읽기를 실패했습니다. 원인: 1) 문서를 찾을 수 없습니다. 2) 문서를 읽을 수 없습니다. 3) 문서의 루트 요소가 가 아닙니다. src-annotation = src-annotation: 요소에는 요소만 포함될 수 있지만 ''{0}''이(가) 발견되었습니다. src-attribute.1 = src-attribute.1: ''default'' 및 ''fixed'' 속성은 속성 선언 ''{0}''에 함께 존재할 수 없습니다. 하나만 사용하십시오. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_pt_BR.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_pt_BR.properties index 8874db17b19de..563091b4bd021 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_pt_BR.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_pt_BR.properties @@ -115,7 +115,7 @@ #schema valid (3.X.3) - schema_reference.access = schema_reference: falha ao ler o documento de esquema ''{0}'' porque o acesso a ''{1}'' não é permitido em decorrência de uma restrição definida pela propriedade accessExternalSchema. + schema_reference.access = schema_reference: falha ao ler o documento de esquema ''{0}'' porque o acesso a ''{1}'' não é permitido em decorrência de uma restrição definida pela propriedade accessExternalSchema. schema_reference.4 = schema_reference.4: Falha ao ler o documento do esquema ''{0}'' porque 1) não foi possível encontrar o documento; 2) não foi possível ler o documento; 3) o elemento-raiz do documento não é . src-annotation = src-annotation: os elementos de podem conter somente os elementos e , mas foi encontrado ''{0}''. src-attribute.1 = src-attribute.1: As propriedades ''padrão'' e ''fixed'' não podem estar presentes na declaração do atributo ''{0}''. Use somente uma delas. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_sv.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_sv.properties index ca6d235f8df9e..6cfcddc13920b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_sv.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_sv.properties @@ -115,7 +115,7 @@ #schema valid (3.X.3) - schema_reference.access = schema_reference: Kunde inte läsa schemadokumentet ''{0}'' eftersom ''{1}''-åtkomst inte tillåts på grund av begränsning som anges av egenskapen accessExternalSchema. + schema_reference.access = schema_reference: Kunde inte läsa schemadokumentet ''{0}'' eftersom ''{1}''-åtkomst inte tillåts på grund av begränsning som anges av egenskapen accessExternalSchema. schema_reference.4 = schema_reference.4: Läsning av schemadokument ''{0}'' utfördes inte på grund av 1) det går inte att hitta dokumentet; 2) det går inte att läsa dokumentet; 3) dokumentets rotelement är inte . src-annotation = src-annotation: element för får endast innehålla element för och , men ''{0}'' hittades. src-attribute.1 = src-attribute.1: Båda egenskaperna ''default'' och ''fixed'' kan inte samtidigt ingå i attributdeklarationen ''{0}''. Använd en av dem. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages.properties index ccc25233dacc3..bd71b3488485e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages.properties @@ -21,14 +21,14 @@ # Messages for message reporting BadMessageKey = The error message corresponding to the message key can not be found. -FormatFailed = An internal error occurred while formatting the following message:\n +FormatFailed = An internal error occurred while formatting the following message:\n # XPointer Framework Error Messages XPointerProcessingError = XPointerProcessingError: An error occurred while processing the XPointer expression. InvalidXPointerToken = InvalidXPointerToken: The XPointer expression contains the invalid token ''{0}'' InvalidXPointerExpression = InvalidXPointerExpression: The XPointer expression ''{0}'' is invalid. -MultipleShortHandPointers = MultipleShortHandPointers: The XPointer expression ''{0}'' is invalid. It has more than one ShortHand Pointer. -SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: The XPointer expression ''{0}'' is invalid. The SchemeData was not followed by a '')'' character. +MultipleShortHandPointers = MultipleShortHandPointers: The XPointer expression ''{0}'' is invalid. It has more than one ShortHand Pointer. +SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: The XPointer expression ''{0}'' is invalid. The SchemeData was not followed by a '')'' character. SchemeUnsupported = SchemeUnsupported: The XPointer scheme ''{0}'' is not supported. InvalidShortHandPointer = InvalidShortHandPointer: The NCName of the ShortHand Pointer ''{0}'' is invalid. UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: The XPointer expression ''{0}'' is invalid. The number of open parenthesis ''{1}'' is not equal to the number of close parenthesis ''{2}''. @@ -39,4 +39,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken: The element() scheme XPoi InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: The Element Scheme XPointer expression ''{0}'' is invalid. XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: An error occurred while processing the XPointer element() Scheme expression. InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: The element() Scheme contains a ShortHand Pointer ''{0}'' with an invalid NCName. -InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: The element() Scheme contains an invalid child sequence character ''{0}''. +InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: The element() Scheme contains an invalid child sequence character ''{0}''. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_de.properties index ca3bf6fac5ac8..fcd8b9e5a0ca0 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_de.properties @@ -21,14 +21,14 @@ # Messages for message reporting BadMessageKey = Die zum Meldungsschlüssel gehörige Fehlermeldung kann nicht gefunden werden. -FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler aufgetreten:\n +FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler aufgetreten:\n # XPointer Framework Error Messages XPointerProcessingError = XPointerProcessingError: Beim Verarbeiten des XPointer-Ausdrucks ist ein Fehler aufgetreten. InvalidXPointerToken = InvalidXPointerToken: XPointer-Ausdruck enthält das ungültige Token "{0}" InvalidXPointerExpression = InvalidXPointerExpression: XPointer-Ausdruck "{0}" ist ungültig. MultipleShortHandPointers = MultipleShortHandPointers: XPointer-Ausdruck "{0}" ist ungültig. Mehrere ShortHand-Zeiger vorhanden. -SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: XPointer-Ausdruck "{0}" ist ungültig. Auf SchemeData folgte kein ")"-Zeichen. +SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: XPointer-Ausdruck "{0}" ist ungültig. Auf SchemeData folgte kein ")"-Zeichen. SchemeUnsupported = SchemeUnsupported: XPointer-Schema "{0}" wird nicht unterstützt. InvalidShortHandPointer = InvalidShortHandPointer: NCName von ShortHand-Zeiger "{0}" ist ungültig. UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: XPointer-Ausdruck "{0}" ist ungültig. Die Anzahl der öffnenden Klammern "{1}" entspricht nicht der Anzahl der schließenden Klammern "{2}". @@ -39,4 +39,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken: element()-Schema-XPointer InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: Elementschema-XPointer-Ausdruck "{0}" ist ungültig. XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: Beim Verarbeiten des XPointer-element()-Schemaausdrucks ist ein Fehler aufgetreten. InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: element()-Schema enthält einen ShortHand-Zeiger "{0}" mit einem ungültigen NCName. -InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: element()-Schema enthält ein untergeordnetes Sequenzzeichen "{0}". +InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: element()-Schema enthält ein untergeordnetes Sequenzzeichen "{0}". diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_es.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_es.properties index d90c9a7d5b7be..6f9ae6734cc41 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_es.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_es.properties @@ -29,14 +29,14 @@ # Messages for message reporting BadMessageKey = No se ha encontrado el mensaje de error que corresponde a la clave de mensaje. -FormatFailed = Se ha producido un error interno al formatear el siguiente mensaje:\n +FormatFailed = Se ha producido un error interno al formatear el siguiente mensaje:\n # XPointer Framework Error Messages XPointerProcessingError = XPointerProcessingError: Se ha producido un error al procesar la expresión XPointer. InvalidXPointerToken = InvalidXPointerToken: La expresión XPointer contiene el token no válido ''{0}'' InvalidXPointerExpression = InvalidXPointerExpression: La expresión XPointer ''{0}'' no es válida. -MultipleShortHandPointers = MultipleShortHandPointers: La expresión XPointer ''{0}'' no es válida. Tiene más de un puntero abreviado. -SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: La expresión XPointer ''{0}'' no es válida. SchemeData no viene seguido de un carácter '')''. +MultipleShortHandPointers = MultipleShortHandPointers: La expresión XPointer ''{0}'' no es válida. Tiene más de un puntero abreviado. +SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: La expresión XPointer ''{0}'' no es válida. SchemeData no viene seguido de un carácter '')''. SchemeUnsupported = SchemeUnsupported: El esquema XPointer ''{0}'' no está soportado. InvalidShortHandPointer = InvalidShortHandPointer: El valor de NCName del puntero abreviado ''{0}'' no es válido. UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: La expresión XPointer ''{0}'' no es válida. El número de paréntesis de apertura ''{1}'' no es igual al número de paréntesis de cierre ''{2}''. @@ -47,4 +47,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken: La expresión XPointer de InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: La expresión XPointer del esquema de elemento ''{0}'' no es válida. XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: Se ha producido un error al procesar la expresión de esquema XPointer element(). InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: El esquema element() contiene un puntero abreviado ''{0}'' con un valor de NCName no válido. -InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: El esquema element() contiene un carácter de secuencia secundaria no válido ''{0}''. +InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: El esquema element() contiene un carácter de secuencia secundaria no válido ''{0}''. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_fr.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_fr.properties index 65c0d2040d26e..256a737cf7d39 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_fr.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_fr.properties @@ -29,14 +29,14 @@ # Messages for message reporting BadMessageKey = Le message d'erreur correspondant à la clé de message est introuvable. -FormatFailed = Une erreur interne est survenue lors de la mise en forme du message suivant :\n +FormatFailed = Une erreur interne est survenue lors de la mise en forme du message suivant :\n # XPointer Framework Error Messages XPointerProcessingError = XPointerProcessingError : une erreur est survenue lors du traitement de l'expression XPointer. InvalidXPointerToken = InvalidXPointerToken : l''expression XPointer contient le jeton non valide ''{0}'' InvalidXPointerExpression = InvalidXPointerExpression : l''expression XPointer ''{0}'' n''est pas valide. -MultipleShortHandPointers = MultipleShortHandPointers : l''expression XPointer ''{0}'' n''est pas valide. Elle contient plusieurs pointeurs ShortHand. -SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis : l''expression XPointer ''{0}'' n''est pas valide. L''élément SchemeData n''est pas suivi d''un caractère '')''. +MultipleShortHandPointers = MultipleShortHandPointers : l''expression XPointer ''{0}'' n''est pas valide. Elle contient plusieurs pointeurs ShortHand. +SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis : l''expression XPointer ''{0}'' n''est pas valide. L''élément SchemeData n''est pas suivi d''un caractère '')''. SchemeUnsupported = SchemeUnsupported : le processus XPointer ''{0}'' n''est pas pris en charge. InvalidShortHandPointer = InvalidShortHandPointer : le NCName du pointeur ShortHand ''{0}'' n''est pas valide. UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression : l''expression XPointer ''{0}'' n''est pas valide. Le nombre de parenthèses ouvrantes ''{1}'' est différent du nombre de parenthèses fermantes ''{2}''. @@ -47,4 +47,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken : l''expression XPointer d InvalidElementSchemeXPointer = InvalidElementSchemeXPointer : l''expression XPointer de processus d''élément ''{0}'' n''est pas valide. XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError : une erreur est survenue lors du traitement de l'expression de processus element() XPointer. InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData : le processus element() contient un pointeur ShortHand ''{0}'' avec un NCName non valide. -InvalidChildSequenceCharacter = InvalidChildSequenceCharacter : le processus element() contient un caractère de séquence enfant non valide ''{0}''. +InvalidChildSequenceCharacter = InvalidChildSequenceCharacter : le processus element() contient un caractère de séquence enfant non valide ''{0}''. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_it.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_it.properties index d5822b7e7dc7f..553046c372587 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_it.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_it.properties @@ -29,14 +29,14 @@ # Messages for message reporting BadMessageKey = Impossibile trovare il messaggio di errore corrispondente alla chiave di messaggio. -FormatFailed = Si è verificato un errore interno durante la formattazione del seguente messaggio:\n +FormatFailed = Si è verificato un errore interno durante la formattazione del seguente messaggio:\n # XPointer Framework Error Messages XPointerProcessingError = XPointerProcessingError: si è verificato un errore durante l'elaborazione dell'espressione XPointer. InvalidXPointerToken = InvalidXPointerToken: l''espressione XPointer contiene il token non valido ''{0}''. InvalidXPointerExpression = InvalidXPointerExpression: l''espressione XPointer ''{0}'' non è valida. -MultipleShortHandPointers = MultipleShortHandPointers: l''espressione XPointer ''{0}'' non è valida. Contiene più puntatori ShortHand. -SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: l''espressione XPointer ''{0}'' non è valida. SchemeData non è seguito da un carattere '')''. +MultipleShortHandPointers = MultipleShortHandPointers: l''espressione XPointer ''{0}'' non è valida. Contiene più puntatori ShortHand. +SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: l''espressione XPointer ''{0}'' non è valida. SchemeData non è seguito da un carattere '')''. SchemeUnsupported = SchemeUnsupported: lo schema XPointer ''{0}'' non è supportato. InvalidShortHandPointer = InvalidShortHandPointer: NCName del puntatore ShortHand ''{0}'' non valido. UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: l''espressione XPointer ''{0}'' non è valida. Il numero di parentesi aperte ''{1}'' non corrisponde al numero di parentesi chiuse ''{2}''. @@ -47,4 +47,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken: l''espressione XPointer d InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: l''espressione XPointer ''{0}'' dello schema di elemento non è valida. XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: si è verificato un errore durante l'elaborazione dell'espressione di schema element() XPointer. InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: lo schema element() contiene un puntatore ShortHand ''{0}'' con NCName non valido. -InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: lo schema element() contiene un carattere di sequenza secondaria ''{0}'' non valido. +InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: lo schema element() contiene un carattere di sequenza secondaria ''{0}'' non valido. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ja.properties index 0038baa4d6cc3..d56c65126ce3c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ja.properties @@ -21,14 +21,14 @@ # Messages for message reporting BadMessageKey = メッセージ・キーに対応するエラー・メッセージが見つかりません。 -FormatFailed = 次のメッセージの書式設定中に内部エラーが発生しました:\n +FormatFailed = 次のメッセージの書式設定中に内部エラーが発生しました:\n # XPointer Framework Error Messages XPointerProcessingError = XPointerProcessingError: XPointer式の処理中にエラーが発生しました。 InvalidXPointerToken = InvalidXPointerToken: XPointer式に無効なトークン''{0}''が含まれています InvalidXPointerExpression = InvalidXPointerExpression: XPointer式''{0}''が無効です。 -MultipleShortHandPointers = MultipleShortHandPointers: XPointer式''{0}''が無効です。複数のShortHandポインタが含まれています。 -SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: XPointer式''{0}''が無効です。SchemeDataの後に'')''文字がありません。 +MultipleShortHandPointers = MultipleShortHandPointers: XPointer式''{0}''が無効です。複数のShortHandポインタが含まれています。 +SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: XPointer式''{0}''が無効です。SchemeDataの後に'')''文字がありません。 SchemeUnsupported = SchemeUnsupported: XPointerスキーム''{0}''はサポートされていません。 InvalidShortHandPointer = InvalidShortHandPointer: ShortHandポインタ''{0}''のNCNameが無効です。 UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: XPointer式''{0}''が無効です。左丸カッコ''{1}''の数が右丸カッコ''{2}''の数と一致しません。 @@ -39,4 +39,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken: element() Scheme XPointer InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: Element Scheme XPointer式''{0}''が無効です。 XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: XPointer element() Scheme式の処理中にエラーが発生しました。 InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: element() Schemeに無効なNCNameを持つShortHandポインタ''{0}''が含まれています。 -InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: element() Schemeに無効な子シーケンス文字''{0}''が含まれています。 +InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: element() Schemeに無効な子シーケンス文字''{0}''が含まれています。 diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ko.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ko.properties index 2e920adf16541..3580222cffa3f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ko.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ko.properties @@ -29,14 +29,14 @@ # Messages for message reporting BadMessageKey = 메시지 키에 해당하는 오류 메시지를 찾을 수 없습니다. -FormatFailed = 다음 메시지의 형식을 지정하는 중 내부 오류가 발생했습니다.\n +FormatFailed = 다음 메시지의 형식을 지정하는 중 내부 오류가 발생했습니다.\n # XPointer Framework Error Messages XPointerProcessingError = XPointerProcessingError: XPointer 표현식을 처리하는 중 오류가 발생했습니다. InvalidXPointerToken = InvalidXPointerToken: XPointer 표현식에 부적합한 토큰 ''{0}''이(가) 포함되어 있습니다. InvalidXPointerExpression = InvalidXPointerExpression: XPointer 표현식 ''{0}''이(가) 부적합합니다. -MultipleShortHandPointers = MultipleShortHandPointers: XPointer 표현식 ''{0}''이(가) 부적합합니다. ShortHand Pointer가 두 개 이상 포함되어 있습니다. -SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: XPointer 표현식 ''{0}''이(가) 부적합합니다. SchemeData 뒤에 '')'' 문자가 없습니다. +MultipleShortHandPointers = MultipleShortHandPointers: XPointer 표현식 ''{0}''이(가) 부적합합니다. ShortHand Pointer가 두 개 이상 포함되어 있습니다. +SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: XPointer 표현식 ''{0}''이(가) 부적합합니다. SchemeData 뒤에 '')'' 문자가 없습니다. SchemeUnsupported = SchemeUnsupported: XPointer 체계 ''{0}''은(는) 지원되지 않습니다. InvalidShortHandPointer = InvalidShortHandPointer: ShortHand Pointer ''{0}''의 NCName이 부적합합니다. UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: XPointer 표현식 ''{0}''이(가) 부적합합니다. 여는 괄호의 개수 ''{1}''과(와) 닫는 괄호의 개수 ''{2}''이(가) 일치하지 않습니다. @@ -47,4 +47,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken: element() 체계 XPointer InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: 요소 체계 XPointer 표현식 ''{0}''이(가) 부적합합니다. XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: XPointer element() 체계 표현식을 처리하는 중 오류가 발생했습니다. InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: element() 체계에 NCName이 부적합한 ShortHand Pointer ''{0}''이(가) 포함되어 있습니다. -InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: element() 체계에 부적합한 하위 시퀀스 문자 ''{0}''이(가) 포함되어 있습니다. +InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: element() 체계에 부적합한 하위 시퀀스 문자 ''{0}''이(가) 포함되어 있습니다. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_pt_BR.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_pt_BR.properties index 2d5522e7989ee..4ee319e06e992 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_pt_BR.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_pt_BR.properties @@ -29,14 +29,14 @@ # Messages for message reporting BadMessageKey = Não foi possível encontrar a mensagem de erro correspondente à chave da mensagem. -FormatFailed = Ocorreu um erro interno ao formatar a mensagem a seguir:\n +FormatFailed = Ocorreu um erro interno ao formatar a mensagem a seguir:\n # XPointer Framework Error Messages XPointerProcessingError = XPointerProcessingError: Ocorreu um erro ao processar a expressão XPointer. InvalidXPointerToken = InvalidXPointerToken: A expressão XPointer contém o token inválido ''{0}'' InvalidXPointerExpression = InvalidXPointerExpression: A expressão XPointer ''{0}'' é inválida. -MultipleShortHandPointers = MultipleShortHandPointers: A expressão XPointer ''{0}'' é inválida. Tem mais de um Ponteiro ShortHand. -SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: A expressão XPointer ''{0}'' é inválida. O SchemeData não foi seguida por um caractere '')". +MultipleShortHandPointers = MultipleShortHandPointers: A expressão XPointer ''{0}'' é inválida. Tem mais de um Ponteiro ShortHand. +SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: A expressão XPointer ''{0}'' é inválida. O SchemeData não foi seguida por um caractere '')". SchemeUnsupported = SchemeUnsupported: O esquema XPointer ''{0}'' não é suportado. InvalidShortHandPointer = InvalidShortHandPointer: O NCName do Ponteiro do ShortHand ''{0}'' é inválido. UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: A expressão XPointer ''{0}'' é inválida. O número de parênteses de abertura ''{1}'' não é igual ao número de parênteses de fechamento ''{2}''. @@ -47,4 +47,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken: A expressão XPointer do InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: A expressão XPointer do Esquema do Elemento ''{0}'' é inválida. XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: Ocorreu um erro ao processoar a expressão do Esquema do element() do XPointer. InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: O Esquema do element() contém um Ponteiro de ShortHand ''{0}'' com um NCName inválido. -InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: O Esquema de element() contém um caractere de sequência filho inválido ''{0}''. +InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: O Esquema de element() contém um caractere de sequência filho inválido ''{0}''. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_sv.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_sv.properties index 2247d08110558..f00c5353de8cd 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_sv.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_sv.properties @@ -29,14 +29,14 @@ # Messages for message reporting BadMessageKey = Hittar inte felmeddelandet som motsvarar meddelandenyckeln. -FormatFailed = Ett internt fel inträffade vid formatering av följande meddelande:\n +FormatFailed = Ett internt fel inträffade vid formatering av följande meddelande:\n # XPointer Framework Error Messages XPointerProcessingError = XPointerProcessingError: Ett fel inträffade vid bearbetning av XPointer-uttrycket. InvalidXPointerToken = InvalidXPointerToken: XPointer-uttrycket innehåller ogiltigt tecken, ''{0}'' InvalidXPointerExpression = InvalidXPointerExpression: XPointer-uttrycket ''{0}'' är ogiltigt. -MultipleShortHandPointers = MultipleShortHandPointers: XPointer-uttrycket ''{0}'' är ogiltigt. Det innehåller fler än en ShortHand Pointer. -SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: XPointer-uttrycket ''{0}'' är ogiltigt. SchemeData efterföljdes inte av ett '')''-tecken. +MultipleShortHandPointers = MultipleShortHandPointers: XPointer-uttrycket ''{0}'' är ogiltigt. Det innehåller fler än en ShortHand Pointer. +SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: XPointer-uttrycket ''{0}'' är ogiltigt. SchemeData efterföljdes inte av ett '')''-tecken. SchemeUnsupported = SchemeUnsupported: XPointer-schemat ''{0}'' stöds inte. InvalidShortHandPointer = InvalidShortHandPointer: NCName i ShortHand-pekaren ''{0}'' är ogiltigt. UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: XPointer-uttrycket ''{0}'' är ogiltigt. Antalet vänsterparenteser ''{1}'' är inte samma som antalet högerparenteser ''{2}''. @@ -47,4 +47,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken: XPointer-uttrycket i elem InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: XPointer-uttrycket ''{0}'' i elementschemat är ogiltigt. XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: Ett fel inträffade vid bearbetning av schemauttrycket i XPointer element(). InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: element()-schemat innehåller ShortHand-pekaren ''{0}'' med ogiltigt NCName. -InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: element()-schemat innehåller ett ogiltigt tecken ''{0}'' i underordnad sekvens. +InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: element()-schemat innehåller ett ogiltigt tecken ''{0}'' i underordnad sekvens. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_zh_CN.properties index 140c91a4673b4..f9c7a1ab9337f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_zh_CN.properties @@ -21,7 +21,7 @@ # Messages for message reporting BadMessageKey = 找不到与消息关键字对应的错误消息。 -FormatFailed = 设置以下消息的格式时出现内部错误:\n +FormatFailed = 设置以下消息的格式时出现内部错误:\n # XPointer Framework Error Messages XPointerProcessingError = XPointerProcessingError: 处理 XPointer 表达式时出错。 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 9de7a6292db67..83bcf999da5d2 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1297,24 +1297,12 @@ public void analyzeTree(Env env, JCTree tree, TreeMaker make) { private boolean isBpCovered(Type componentType, PatternDescription newNested) { if (newNested instanceof BindingPattern bp) { - var seltype = types.erasure(componentType); + Type seltype = types.erasure(componentType); + Type pattype = types.erasure(bp.type); - if (seltype.isPrimitive()) { - if (types.isSameType(bp.type, types.boxedClass(seltype).type)) { - return true; - } - - // if the target is unconditionally exact to the pattern, target is covered - if (types.isUnconditionallyExact(seltype, bp.type)) { - return true; - } - } else if (seltype.isReference() && bp.type.isPrimitive() && types.isCastable(seltype, bp.type)) { - return true; - } else { - if (types.isSubtype(seltype, types.erasure(bp.type))) { - return true; - } - } + return seltype.isPrimitive() ? + types.isUnconditionallyExact(seltype, pattype) : + (bp.type.isPrimitive() && types.isUnconditionallyExact(types.unboxedType(seltype), bp.type)) || types.isSubtype(seltype, pattype); } return false; } diff --git a/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver.properties b/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver.properties index 0d5242018d35c..2da648dcb259f 100644 --- a/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver.properties +++ b/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver.properties @@ -24,14 +24,14 @@ # NotSerializable=\ - Class {0} is not Serializable. + Class {0} is not Serializable. ClassNotFound=\ - Class {0} not found. + Class {0} not found. error.parsing.classpath=\ - Error parsing classpath {0}. + Error parsing classpath {0}. error.missing.classpath=\ - Missing argument for -classpath option + Missing argument for -classpath option invalid.flag=\ - Invalid flag {0}. + Invalid flag {0}. usage=\ - use: serialver [-classpath classpath] [classname...] + use: serialver [-classpath classpath] [classname...] diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/CompiledICHolder.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/CompiledICHolder.java deleted file mode 100644 index 1d1a9278abddf..0000000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/CompiledICHolder.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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 sun.jvm.hotspot.oops; - -import java.io.*; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class CompiledICHolder extends VMObject { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("CompiledICHolder"); - holderMetadata = new MetadataField(type.getAddressField("_holder_metadata"), 0); - holderKlass = new MetadataField(type.getAddressField("_holder_klass"), 0); - headerSize = type.getSize(); - } - - public CompiledICHolder(Address addr) { - super(addr); - } - - public boolean isCompiledICHolder() { return true; } - - private static long headerSize; - - // Fields - private static MetadataField holderMetadata; - private static MetadataField holderKlass; - - // Accessors for declared fields - public Metadata getHolderMetadata() { return holderMetadata.getValue(this); } - public Klass getHolderKlass() { return (Klass) holderKlass.getValue(this); } - - public void printValueOn(PrintStream tty) { - tty.print("CompiledICHolder"); - } - } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java index 56c684b5e546c..d6a91a7a9c04b 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java @@ -240,8 +240,8 @@ public enum Option { "name (a stub) or fully qualified name (an nmethod) contains this option's value as a substring."), ForceTranslateFailure(String.class, null, "Forces HotSpotJVMCIRuntime.translate to throw an exception in the context " + "of the peer runtime. The value is a filter that can restrict the forced failure to matching translated " + - "objects. See HotSpotJVMCIRuntime.postTranslation for more details. This option exists soley to test " + - "correct handling of translation failure."), + "objects. See HotSpotJVMCIRuntime.postTranslation for more details. This option exists solely to test " + + "correct handling of translation failures."), PrintConfig(Boolean.class, false, "Prints VM configuration available via JVMCI."), AuditHandles(Boolean.class, false, "Record stack trace along with scoped foreign object reference wrappers " + "to debug issue with a wrapper being used after its scope has closed."), diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties index d0cb53b8a0dc0..463068c517c23 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties @@ -46,8 +46,8 @@ error.bad.cflag=\ error.bad.uflag=\ 'u' flag requires manifest, 'e' flag or input files to be specified! error.bad.eflag=\ - 'e' flag and manifest with the 'Main-Class' attribute cannot be specified \n\ - together! + 'e' flag and manifest with the 'Main-Class' attribute cannot be specified \n\ + together! error.bad.dflag=\ '-d, --describe-module' option requires no input file(s) to be specified error.bad.reason=\ diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java index e0b126dfacf59..ddc8710e517bc 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java @@ -34,7 +34,6 @@ import java.util.TreeSet; import javax.lang.model.element.Element; -import javax.lang.model.element.ModuleElement; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic; @@ -43,7 +42,6 @@ import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.TagName; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; -import jdk.javadoc.internal.doclets.formats.html.markup.Text; import jdk.javadoc.internal.doclets.formats.html.Navigation.PageMode; import jdk.javadoc.internal.doclets.toolkit.DocletException; import jdk.javadoc.internal.doclets.toolkit.util.ClassTree; @@ -422,15 +420,14 @@ protected HtmlTree getClassUseHeader() { protected Navigation getNavBar(PageMode pageMode, Element element) { List subnavLinks = new ArrayList<>(); if (configuration.showModules) { - ModuleElement mdle = utils.elementUtils.getModuleOf(typeElement); - subnavLinks.add(getModuleLink(mdle, Text.of(mdle.getQualifiedName()))); + subnavLinks.add(getBreadcrumbLink(utils.elementUtils.getModuleOf(typeElement), false)); + } + // We may generate a class-use page for an otherwise undocumented page in the condition below. + boolean isUndocumented = options.noDeprecated() && utils.isDeprecated(typeElement); + subnavLinks.add(getBreadcrumbLink(utils.containingPackage(typeElement), isUndocumented)); + if (!isUndocumented) { + subnavLinks.add(getBreadcrumbLink(typeElement, true)); } - PackageElement pkg = utils.containingPackage(typeElement); - subnavLinks.add(getPackageLink(pkg, getLocalizedPackageName(pkg))); - subnavLinks.add(getLink( - new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.PLAIN, typeElement) - .style(HtmlStyle.currentSelection) - .skipPreview(true))); return super.getNavBar(pageMode, element).setSubNavLinks(subnavLinks); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java index f74921464bbd7..b550b35e4d329 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java @@ -35,7 +35,6 @@ import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.ModuleElement; import javax.lang.model.element.Name; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; @@ -454,14 +453,10 @@ protected Content getClassContentHeader() { protected Navigation getNavBar(PageMode pageMode, Element element) { List subnavLinks = new ArrayList<>(); if (configuration.showModules) { - ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(typeElement); - subnavLinks.add(getModuleLink(mdle, Text.of(mdle.getQualifiedName()))); + subnavLinks.add(getBreadcrumbLink(utils.elementUtils.getModuleOf(typeElement), false)); } - PackageElement pkg = utils.containingPackage(typeElement); - subnavLinks.add(getPackageLink(pkg, getLocalizedPackageName(pkg))); - subnavLinks.add(getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.PLAIN, typeElement) - .style(HtmlStyle.currentSelection) - .skipPreview(true))); + subnavLinks.add(getBreadcrumbLink(utils.containingPackage(typeElement), false)); + subnavLinks.add(getBreadcrumbLink(typeElement, true)); return super.getNavBar(pageMode, element).setSubNavLinks(subnavLinks); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandler.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandler.java index 93fd296280b07..47b2b6b41fe6f 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandler.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandler.java @@ -30,9 +30,7 @@ import com.sun.source.doctree.StartElementTree; import com.sun.source.util.DocTreeFactory; import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents; -import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; -import jdk.javadoc.internal.doclets.formats.html.markup.Text; import jdk.javadoc.internal.doclets.toolkit.DocFileElement; import jdk.javadoc.internal.doclets.toolkit.DocletException; import jdk.javadoc.internal.doclets.toolkit.util.DocFile; @@ -220,14 +218,10 @@ protected Navigation getNavBar(PageMode pageMode, Element element) { List subnavLinks = new ArrayList<>(); var pkg = dfElement.getPackageElement(); if (configuration.showModules) { - var mdle = utils.elementUtils.getModuleOf(element); - subnavLinks.add(links.createLink(pathToRoot.resolve(docPaths.moduleSummary(mdle)), - Text.of(mdle.getQualifiedName()), - pkg.isUnnamed() ? HtmlStyle.currentSelection : null, "")); + subnavLinks.add(getBreadcrumbLink(utils.elementUtils.getModuleOf(element), pkg.isUnnamed())); } if (!pkg.isUnnamed()) { - subnavLinks.add(links.createLink(pathString(pkg, DocPaths.PACKAGE_SUMMARY), - getLocalizedPackageName(pkg), HtmlStyle.currentSelection, "")); + subnavLinks.add(getBreadcrumbLink(pkg, true)); } return super.getNavBar(pageMode, element).setSubNavLinks(subnavLinks); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java index 73ce7bb784fdb..4eb05aeb695f6 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java @@ -31,7 +31,6 @@ import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; @@ -84,13 +83,11 @@ import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.Head; -import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlId; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.markup.Links; -import jdk.javadoc.internal.doclets.formats.html.markup.ListBuilder; import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml; import jdk.javadoc.internal.doclets.formats.html.markup.Script; import jdk.javadoc.internal.doclets.formats.html.markup.TagName; @@ -634,6 +631,29 @@ protected DocPath pathString(PackageElement packageElement, DocPath name) { return pathToRoot.resolve(docPaths.forPackage(packageElement).resolve(name)); } + /** + * {@return a content element containing a breadcrumb navigtation link for {@code elem}} + * Only module, package and type elements can appear in breadcrumb navigation. + * + * @param elem the element + * @param selected whether to use the style for current page element + */ + protected Content getBreadcrumbLink(Element elem, boolean selected) { + HtmlTree link = switch (elem) { + case ModuleElement mdle -> links.createLink(pathToRoot.resolve(docPaths.moduleSummary(mdle)), + Text.of(mdle.getQualifiedName())); + case PackageElement pkg -> links.createLink(pathString(pkg, DocPaths.PACKAGE_SUMMARY), + getLocalizedPackageName(pkg)); + case TypeElement type -> links.createLink(pathString(type, docPaths.forName(type)), + utils.getSimpleName(type)); + default -> throw new IllegalArgumentException(Objects.toString(elem)); + }; + if (selected) { + link.setStyle(HtmlStyle.currentSelection); + } + return link; + } + /** * {@return the link to the given package} * diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriter.java index bf362e478ff62..24718c089bcb6 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriter.java @@ -277,10 +277,7 @@ protected Content getModuleHeader(String heading) { @Override protected Navigation getNavBar(PageMode pageMode, Element element) { return super.getNavBar(pageMode, element) - .setSubNavLinks(List.of( - links.createLink(pathToRoot.resolve(docPaths.moduleSummary(mdle)), - Text.of(mdle.getQualifiedName()), - HtmlStyle.currentSelection, ""))); + .setSubNavLinks(List.of(getBreadcrumbLink(mdle, true))); } protected Content getContentHeader() { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java index 75009ad20663d..e8705923d945d 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java @@ -220,11 +220,9 @@ private HtmlTree getBody() { protected Navigation getNavBar(PageMode pageMode, Element element) { List subnavLinks = new ArrayList<>(); if (configuration.showModules) { - var mdle = utils.elementUtils.getModuleOf(packageElement); - subnavLinks.add(getModuleLink(mdle, Text.of(mdle.getQualifiedName()))); + subnavLinks.add(getBreadcrumbLink(utils.elementUtils.getModuleOf(packageElement), false)); } - subnavLinks.add(links.createLink(pathString(packageElement, DocPaths.PACKAGE_SUMMARY), - getLocalizedPackageName(packageElement), HtmlStyle.currentSelection, "")); + subnavLinks.add(getBreadcrumbLink(packageElement, true)); return super.getNavBar(pageMode, element).setSubNavLinks(subnavLinks); } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriter.java index f9d3164a1d538..2983eeaaf58ed 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriter.java @@ -272,12 +272,9 @@ private List findRelatedPackages() { protected Navigation getNavBar(PageMode pageMode, Element element) { List subnavLinks = new ArrayList<>(); if (configuration.showModules) { - ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(packageElement); - subnavLinks.add(links.createLink(pathToRoot.resolve(docPaths.moduleSummary(mdle)), - Text.of(mdle.getQualifiedName()))); + subnavLinks.add(getBreadcrumbLink(utils.elementUtils.getModuleOf(packageElement), false)); } - subnavLinks.add(links.createLink(pathString(packageElement, DocPaths.PACKAGE_SUMMARY), - getLocalizedPackageName(packageElement), HtmlStyle.currentSelection, "")); + subnavLinks.add(getBreadcrumbLink(packageElement, true)); return super.getNavBar(pageMode, element).setSubNavLinks(subnavLinks); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template index 9ec4b1c56704b..e08ff5db68c5e 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template @@ -363,7 +363,7 @@ document.addEventListener("DOMContentLoaded", function(e) { scrollTimeout = setTimeout(() => { scrollTimeout = null; handleScroll(); - }, 50); + }, 100); } function handleScroll() { if (!sidebar || !sidebar.offsetParent || sidebar.classList.contains("hide-sidebar")) { @@ -445,7 +445,7 @@ document.addEventListener("DOMContentLoaded", function(e) { // Resize handler function handleResize(e) { if (expanded) { - if (windowWidth != window.innerWidth) { + if (windowWidth !== window.innerWidth) { collapse(); } else { expand(); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveRecordingEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveRecordingEvent.java index 985b5c61fb579..352a8b6a07397 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveRecordingEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveRecordingEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,6 @@ @Name(Type.EVENT_NAME_PREFIX + "ActiveRecording") @Label("Flight Recording") @Category("Flight Recorder") -@StackTrace(false) @RemoveFields({"duration", "eventThread", "stackTrace"}) public final class ActiveRecordingEvent extends AbstractJDKEvent { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveSettingEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveSettingEvent.java index d751580fa3aa1..3658b06eb14a8 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveSettingEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveSettingEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,6 @@ @Name(Type.EVENT_NAME_PREFIX + "ActiveSetting") @Label("Recording Setting") @Category("Flight Recorder") -@StackTrace(false) @RemoveFields({"duration", "eventThread", "stackTrace"}) public final class ActiveSettingEvent extends AbstractJDKEvent { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionStatisticsEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionStatisticsEvent.java index a5d3f485fad20..cdaa6372f68c7 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionStatisticsEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionStatisticsEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,6 @@ @Category({ "Java Application", "Statistics" }) @Description("Number of objects derived from java.lang.Throwable that have been created") @MirrorEvent(className = "jdk.internal.event.ExceptionStatisticsEvent") -@StackTrace(false) public final class ExceptionStatisticsEvent extends AbstractPeriodicEvent { @Label("Exceptions Created") diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/StackFilter.java b/src/jdk.jfr/share/classes/jdk/jfr/events/StackFilter.java index f0c6a45bf836f..da9cac8a3945c 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/events/StackFilter.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/StackFilter.java @@ -1,3 +1,28 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 jdk.jfr.events; import java.lang.annotation.ElementType; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java index 8ec3a10993da0..3b6859304b86d 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java @@ -77,8 +77,7 @@ Object get(long id) { if (id != 0) { String msg = "Missing object ID " + id + " in pool " + getName() + ". All IDs should reference an object"; Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, msg); - // Disable assertion until JDK-8323883 is fixed - // assert false : msg; + assert false : msg; } return null; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/test/DeprecatedMethods.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/test/DeprecatedMethods.java index 1d2973b4266da..7e425b3bdb5a9 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/test/DeprecatedMethods.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/test/DeprecatedMethods.java @@ -4,7 +4,9 @@ * * 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. + * 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 diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/test/DeprecatedThing.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/test/DeprecatedThing.java index dbc869c1c6ccc..6d607557caf30 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/test/DeprecatedThing.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/test/DeprecatedThing.java @@ -4,7 +4,9 @@ * * 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. + * 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 diff --git a/src/jdk.jfr/share/conf/jfr/default.jfc b/src/jdk.jfr/share/conf/jfr/default.jfc index cd6d45bf285b7..1ea936ae20d5d 100644 --- a/src/jdk.jfr/share/conf/jfr/default.jfc +++ b/src/jdk.jfr/share/conf/jfr/default.jfc @@ -833,6 +833,7 @@ true + true 0 ms diff --git a/src/jdk.jfr/share/conf/jfr/profile.jfc b/src/jdk.jfr/share/conf/jfr/profile.jfc index dc9c5c326f26a..0b018d33058ce 100644 --- a/src/jdk.jfr/share/conf/jfr/profile.jfc +++ b/src/jdk.jfr/share/conf/jfr/profile.jfc @@ -833,6 +833,7 @@ true + true 0 ms diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties index 196d8e9b41637..e09eadbb3d0ff 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties @@ -62,7 +62,7 @@ main.opt.launcher=\ \ --launcher =[/]\n\ \ Add a launcher command of the given\n\ \ name for the module and the main class\n\ -\ if specified +\ if specified main.opt.bind-services=\ \ --bind-services Link in service provider modules and\n\ diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties index a48a494895ea4..833b56ee5f381 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties @@ -41,7 +41,7 @@ main.opt.limit-modules=\ --limit-modules [,...] Begrenzt den Ber main.opt.output=\ --output Ort des Ausgabepfads -main.opt.launcher=\ --launcher =[/]\n Fügt einen Launcher-Befehl mit dem angegebenen\n Namen für das Modul und die Hauptklasse hinzu,\n falls angegeben +main.opt.launcher=\ --launcher =[/]\n Fügt einen Launcher-Befehl mit dem angegebenen\n Namen für das Modul und die Hauptklasse hinzu,\n falls angegeben main.opt.bind-services=\ --bind-services Bindet Serviceprovidermodule und ihre\n Abhängigkeiten ein diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties index df378866f9125..e54e62bafed9e 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties @@ -41,7 +41,7 @@ main.opt.limit-modules=\ --limit-modules [,...] 参照可能な main.opt.output=\ --output 出力パスの場所 -main.opt.launcher=\ --launcher =[/]\n モジュールおよびメイン・クラス(指定した場合)に\n 指定された名前の起動ツール・コマンドを\n 追加します +main.opt.launcher=\ --launcher =[/]\n モジュールおよびメイン・クラス(指定した場合)に\n 指定された名前の起動ツール・コマンドを\n 追加します main.opt.bind-services=\ --bind-services サービス・プロバイダ・モジュールとその依存性\n 内でリンクします diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties index fae2369fedcdc..9c44e826b9358 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties @@ -41,7 +41,7 @@ main.opt.limit-modules=\ --limit-modules <模块>[,<模块>...] 限制可 main.opt.output=\ --output <路径> 输出路径的位置 -main.opt.launcher=\ --launcher <名称>=<模块>[/<主类>]\n 为模块和主类添加给定\n 名称的启动程序命令\n (如果指定) +main.opt.launcher=\ --launcher <名称>=<模块>[/<主类>]\n 为模块和主类添加给定\n 名称的启动程序命令\n (如果指定) main.opt.bind-services=\ --bind-services 链接服务提供方模块及其\n 被依赖对象 diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_de.properties b/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_de.properties index afe1e7e168f55..ef06daa85776d 100644 --- a/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_de.properties +++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_de.properties @@ -186,12 +186,12 @@ arg=Aragonisch arm=Armenisch arn=Mapudungun art=Kunstsprache -asm=Assamesisch +asm=Assamesisch ast=Asturisch ath=Athapaskisch aus=Australisch ava=Avarisch -ave=Avestisch +ave=Avestisch aze=Aserbaidschanisch bai=Bamileke-Sprache bak=Baschkirisch @@ -235,7 +235,7 @@ cpe=Kreolisch-Englische Sprache cpf=Kreolisch-Französische Sprache cpp=Kreolisch-Portugiesische Sprache crh=Krimtatarisch -crp=Kreolische Sprache +crp=Kreolische Sprache csb=Kaschubisch cus=Kuschitisch cze=Tschechisch @@ -253,7 +253,7 @@ eng=Englisch enm=Mittelenglisch est=Estnisch fan=Pangwe -fao=Färöisch +fao=Färöisch fij=Fidschi fin=Finnisch fiu=Finnougrisch @@ -433,7 +433,7 @@ snd=Zinti-Sprache sog=Sogdisch som=Somalisch son=Songhai-Sprache -sot=Süd-Sotho +sot=Süd-Sotho spa=Spanisch srd=Sardisch srn=Srananisch diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sv.properties b/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sv.properties index cc201fdbe3fb8..da7fddb29253a 100644 --- a/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sv.properties +++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sv.properties @@ -789,7 +789,7 @@ AE=Förenade Arabemiraten AG=Antigua och Barbuda AL=Albanien AM=Armenien -AN=Nederländska Antillerna +AN=Nederländska Antillerna AQ=Antarktis AS=Amerikanska Samoa AT=Österrike diff --git a/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent_ja.properties b/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent_ja.properties index e61dfd6ec37bd..c63e5bd73857a 100644 --- a/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent_ja.properties +++ b/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent_ja.properties @@ -24,7 +24,7 @@ # agent.err.error = エラー -agent.err.exception = エージェントが例外をスローしました +agent.err.exception = エージェントが例外をスローしました agent.err.warning = 警告 agent.err.configfile.notfound = 構成ファイルが見つかりません diff --git a/test/hotspot/gtest/classfile/test_symbolTable.cpp b/test/hotspot/gtest/classfile/test_symbolTable.cpp index 10f9560530ee8..73cf27220d496 100644 --- a/test/hotspot/gtest/classfile/test_symbolTable.cpp +++ b/test/hotspot/gtest/classfile/test_symbolTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ // Helper to avoid interference from the cleanup delay queue by draining it // immediately after creation. -TempNewSymbol stable_temp_symbol(Symbol* sym) { +static TempNewSymbol stable_temp_symbol(Symbol* sym) { TempNewSymbol t = sym; TempSymbolCleanupDelayer::drain_queue(); return t; diff --git a/test/hotspot/gtest/oops/test_oop.cpp b/test/hotspot/gtest/oops/test_oop.cpp index 16dd319fa0d17..b50ee5a56aad7 100644 --- a/test/hotspot/gtest/oops/test_oop.cpp +++ b/test/hotspot/gtest/oops/test_oop.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ static unsigned char memory[32]; -oop fake_object() { +static oop fake_object() { return cast_to_oop(memory); } diff --git a/test/hotspot/gtest/os/linux/test_cgroupSubsystem_linux.cpp b/test/hotspot/gtest/os/linux/test_cgroupSubsystem_linux.cpp index cfac19185a39e..3b8e6929730c3 100644 --- a/test/hotspot/gtest/os/linux/test_cgroupSubsystem_linux.cpp +++ b/test/hotspot/gtest/os/linux/test_cgroupSubsystem_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,12 +34,12 @@ // Utilities -bool file_exists(const char* filename) { +static bool file_exists(const char* filename) { struct stat st; return os::stat(filename, &st) == 0; } -char* temp_file(const char* prefix) { +static char* temp_file(const char* prefix) { const testing::TestInfo* test_info = ::testing::UnitTest::GetInstance()->current_test_info(); stringStream path; path.print_raw(os::get_temp_directory()); @@ -49,7 +49,7 @@ char* temp_file(const char* prefix) { return path.as_string(true); } -void delete_file(const char* filename) { +static void delete_file(const char* filename) { if (!file_exists(filename)) { return; } @@ -66,7 +66,7 @@ class TestController : public CgroupController { }; }; -void fill_file(const char* path, const char* content) { +static void fill_file(const char* path, const char* content) { delete_file(path); FILE* fp = os::fopen(path, "w"); if (fp == nullptr) { diff --git a/test/hotspot/gtest/runtime/test_lockStack.cpp b/test/hotspot/gtest/runtime/test_lockStack.cpp new file mode 100644 index 0000000000000..43e8959ed260d --- /dev/null +++ b/test/hotspot/gtest/runtime/test_lockStack.cpp @@ -0,0 +1,427 @@ +/* + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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/interfaceSupport.inline.hpp" +#include "runtime/lockStack.inline.hpp" +#include "runtime/os.hpp" +#include "unittest.hpp" +#include "utilities/globalDefinitions.hpp" + +class LockStackTest : public ::testing::Test { +public: + static void push_raw(LockStack& ls, oop obj) { + ls._base[ls.to_index(ls._top)] = obj; + ls._top += oopSize; + } + + static void pop_raw(LockStack& ls) { + ls._top -= oopSize; +#ifdef ASSERT + ls._base[ls.to_index(ls._top)] = nullptr; +#endif + } + + static oop at(LockStack& ls, int index) { + return ls._base[index]; + } + + static size_t size(LockStack& ls) { + return ls.to_index(ls._top); + } +}; + +#define recursive_enter(ls, obj) \ + do { \ + bool ret = ls.try_recursive_enter(obj); \ + EXPECT_TRUE(ret); \ + } while (false) + +#define recursive_exit(ls, obj) \ + do { \ + bool ret = ls.try_recursive_exit(obj); \ + EXPECT_TRUE(ret); \ + } while (false) + +TEST_VM_F(LockStackTest, is_recursive) { + if (LockingMode != LM_LIGHTWEIGHT || !VM_Version::supports_recursive_lightweight_locking()) { + return; + } + + JavaThread* THREAD = JavaThread::current(); + // the thread should be in vm to use locks + ThreadInVMfromNative ThreadInVMfromNative(THREAD); + + LockStack& ls = THREAD->lock_stack(); + + EXPECT_TRUE(ls.is_empty()); + + oop obj0 = Universe::int_mirror(); + oop obj1 = Universe::float_mirror(); + + push_raw(ls, obj0); + + // 0 + EXPECT_FALSE(ls.is_recursive(obj0)); + + push_raw(ls, obj1); + + // 0, 1 + EXPECT_FALSE(ls.is_recursive(obj0)); + EXPECT_FALSE(ls.is_recursive(obj1)); + + push_raw(ls, obj1); + + // 0, 1, 1 + EXPECT_FALSE(ls.is_recursive(obj0)); + EXPECT_TRUE(ls.is_recursive(obj1)); + + pop_raw(ls); + pop_raw(ls); + push_raw(ls, obj0); + + // 0, 0 + EXPECT_TRUE(ls.is_recursive(obj0)); + + push_raw(ls, obj0); + + // 0, 0, 0 + EXPECT_TRUE(ls.is_recursive(obj0)); + + pop_raw(ls); + push_raw(ls, obj1); + + // 0, 0, 1 + EXPECT_TRUE(ls.is_recursive(obj0)); + EXPECT_FALSE(ls.is_recursive(obj1)); + + push_raw(ls, obj1); + + // 0, 0, 1, 1 + EXPECT_TRUE(ls.is_recursive(obj0)); + EXPECT_TRUE(ls.is_recursive(obj1)); + + // Clear stack + pop_raw(ls); + pop_raw(ls); + pop_raw(ls); + pop_raw(ls); + + EXPECT_TRUE(ls.is_empty()); +} + +TEST_VM_F(LockStackTest, try_recursive_enter) { + if (LockingMode != LM_LIGHTWEIGHT || !VM_Version::supports_recursive_lightweight_locking()) { + return; + } + + JavaThread* THREAD = JavaThread::current(); + // the thread should be in vm to use locks + ThreadInVMfromNative ThreadInVMfromNative(THREAD); + + LockStack& ls = THREAD->lock_stack(); + + EXPECT_TRUE(ls.is_empty()); + + oop obj0 = Universe::int_mirror(); + oop obj1 = Universe::float_mirror(); + + ls.push(obj0); + + // 0 + EXPECT_FALSE(ls.is_recursive(obj0)); + + ls.push(obj1); + + // 0, 1 + EXPECT_FALSE(ls.is_recursive(obj0)); + EXPECT_FALSE(ls.is_recursive(obj1)); + + recursive_enter(ls, obj1); + + // 0, 1, 1 + EXPECT_FALSE(ls.is_recursive(obj0)); + EXPECT_TRUE(ls.is_recursive(obj1)); + + recursive_exit(ls, obj1); + pop_raw(ls); + recursive_enter(ls, obj0); + + // 0, 0 + EXPECT_TRUE(ls.is_recursive(obj0)); + + recursive_enter(ls, obj0); + + // 0, 0, 0 + EXPECT_TRUE(ls.is_recursive(obj0)); + + recursive_exit(ls, obj0); + push_raw(ls, obj1); + + // 0, 0, 1 + EXPECT_TRUE(ls.is_recursive(obj0)); + EXPECT_FALSE(ls.is_recursive(obj1)); + + recursive_enter(ls, obj1); + + // 0, 0, 1, 1 + EXPECT_TRUE(ls.is_recursive(obj0)); + EXPECT_TRUE(ls.is_recursive(obj1)); + + // Clear stack + pop_raw(ls); + pop_raw(ls); + pop_raw(ls); + pop_raw(ls); + + EXPECT_TRUE(ls.is_empty()); +} + +TEST_VM_F(LockStackTest, contains) { + if (LockingMode != LM_LIGHTWEIGHT) { + return; + } + + const bool test_recursive = VM_Version::supports_recursive_lightweight_locking(); + + JavaThread* THREAD = JavaThread::current(); + // the thread should be in vm to use locks + ThreadInVMfromNative ThreadInVMfromNative(THREAD); + + LockStack& ls = THREAD->lock_stack(); + + EXPECT_TRUE(ls.is_empty()); + + oop obj0 = Universe::int_mirror(); + oop obj1 = Universe::float_mirror(); + + EXPECT_FALSE(ls.contains(obj0)); + + ls.push(obj0); + + // 0 + EXPECT_TRUE(ls.contains(obj0)); + EXPECT_FALSE(ls.contains(obj1)); + + if (test_recursive) { + push_raw(ls, obj0); + + // 0, 0 + EXPECT_TRUE(ls.contains(obj0)); + EXPECT_FALSE(ls.contains(obj1)); + } + + push_raw(ls, obj1); + + // 0, 0, 1 + EXPECT_TRUE(ls.contains(obj0)); + EXPECT_TRUE(ls.contains(obj1)); + + if (test_recursive) { + push_raw(ls, obj1); + + // 0, 0, 1, 1 + EXPECT_TRUE(ls.contains(obj0)); + EXPECT_TRUE(ls.contains(obj1)); + } + + pop_raw(ls); + if (test_recursive) { + pop_raw(ls); + pop_raw(ls); + } + push_raw(ls, obj1); + + // 0, 1 + EXPECT_TRUE(ls.contains(obj0)); + EXPECT_TRUE(ls.contains(obj1)); + + // Clear stack + pop_raw(ls); + pop_raw(ls); + + EXPECT_TRUE(ls.is_empty()); +} + +TEST_VM_F(LockStackTest, remove) { + if (LockingMode != LM_LIGHTWEIGHT) { + return; + } + + const bool test_recursive = VM_Version::supports_recursive_lightweight_locking(); + + JavaThread* THREAD = JavaThread::current(); + // the thread should be in vm to use locks + ThreadInVMfromNative ThreadInVMfromNative(THREAD); + + LockStack& ls = THREAD->lock_stack(); + + EXPECT_TRUE(ls.is_empty()); + + oop obj0 = Universe::int_mirror(); + oop obj1 = Universe::float_mirror(); + oop obj2 = Universe::short_mirror(); + oop obj3 = Universe::long_mirror(); + + push_raw(ls, obj0); + + // 0 + { + size_t removed = ls.remove(obj0); + EXPECT_EQ(removed, 1u); + EXPECT_FALSE(ls.contains(obj0)); + } + + if (test_recursive) { + push_raw(ls, obj0); + push_raw(ls, obj0); + + // 0, 0 + { + size_t removed = ls.remove(obj0); + EXPECT_EQ(removed, 2u); + EXPECT_FALSE(ls.contains(obj0)); + } + } + + push_raw(ls, obj0); + push_raw(ls, obj1); + + // 0, 1 + { + size_t removed = ls.remove(obj0); + EXPECT_EQ(removed, 1u); + EXPECT_FALSE(ls.contains(obj0)); + EXPECT_TRUE(ls.contains(obj1)); + + ls.remove(obj1); + EXPECT_TRUE(ls.is_empty()); + } + + push_raw(ls, obj0); + push_raw(ls, obj1); + + // 0, 1 + { + size_t removed = ls.remove(obj1); + EXPECT_EQ(removed, 1u); + EXPECT_FALSE(ls.contains(obj1)); + EXPECT_TRUE(ls.contains(obj0)); + + ls.remove(obj0); + EXPECT_TRUE(ls.is_empty()); + } + + if (test_recursive) { + push_raw(ls, obj0); + push_raw(ls, obj0); + push_raw(ls, obj1); + + // 0, 0, 1 + { + size_t removed = ls.remove(obj0); + EXPECT_EQ(removed, 2u); + EXPECT_FALSE(ls.contains(obj0)); + EXPECT_TRUE(ls.contains(obj1)); + + ls.remove(obj1); + EXPECT_TRUE(ls.is_empty()); + } + + push_raw(ls, obj0); + push_raw(ls, obj1); + push_raw(ls, obj1); + + // 0, 1, 1 + { + size_t removed = ls.remove(obj1); + EXPECT_EQ(removed, 2u); + EXPECT_FALSE(ls.contains(obj1)); + EXPECT_TRUE(ls.contains(obj0)); + + ls.remove(obj0); + EXPECT_TRUE(ls.is_empty()); + } + + push_raw(ls, obj0); + push_raw(ls, obj1); + push_raw(ls, obj1); + push_raw(ls, obj2); + push_raw(ls, obj2); + push_raw(ls, obj2); + push_raw(ls, obj2); + push_raw(ls, obj3); + + // 0, 1, 1, 2, 2, 2, 2, 3 + { + EXPECT_EQ(size(ls), 8u); + + size_t removed = ls.remove(obj1); + EXPECT_EQ(removed, 2u); + + EXPECT_TRUE(ls.contains(obj0)); + EXPECT_FALSE(ls.contains(obj1)); + EXPECT_TRUE(ls.contains(obj2)); + EXPECT_TRUE(ls.contains(obj3)); + + EXPECT_EQ(at(ls, 0), obj0); + EXPECT_EQ(at(ls, 1), obj2); + EXPECT_EQ(at(ls, 2), obj2); + EXPECT_EQ(at(ls, 3), obj2); + EXPECT_EQ(at(ls, 4), obj2); + EXPECT_EQ(at(ls, 5), obj3); + EXPECT_EQ(size(ls), 6u); + + removed = ls.remove(obj2); + EXPECT_EQ(removed, 4u); + + EXPECT_TRUE(ls.contains(obj0)); + EXPECT_FALSE(ls.contains(obj1)); + EXPECT_FALSE(ls.contains(obj2)); + EXPECT_TRUE(ls.contains(obj3)); + + EXPECT_EQ(at(ls, 0), obj0); + EXPECT_EQ(at(ls, 1), obj3); + EXPECT_EQ(size(ls), 2u); + + removed = ls.remove(obj0); + EXPECT_EQ(removed, 1u); + + EXPECT_FALSE(ls.contains(obj0)); + EXPECT_FALSE(ls.contains(obj1)); + EXPECT_FALSE(ls.contains(obj2)); + EXPECT_TRUE(ls.contains(obj3)); + + EXPECT_EQ(at(ls, 0), obj3); + EXPECT_EQ(size(ls), 1u); + + removed = ls.remove(obj3); + EXPECT_EQ(removed, 1u); + + EXPECT_TRUE(ls.is_empty()); + EXPECT_EQ(size(ls), 0u); + } + } + + EXPECT_TRUE(ls.is_empty()); +} diff --git a/test/hotspot/gtest/runtime/test_safefetch.cpp b/test/hotspot/gtest/runtime/test_safefetch.cpp index 3e217cc63daba..721944b05d9a7 100644 --- a/test/hotspot/gtest/runtime/test_safefetch.cpp +++ b/test/hotspot/gtest/runtime/test_safefetch.cpp @@ -47,7 +47,7 @@ static intptr_t* const good_addressN = dataN + 1; static int* const good_address32 = data32 + 1; -void test_safefetchN_positive() { +static void test_safefetchN_positive() { intptr_t a = SafeFetchN(good_addressN, 1); ASSERT_EQ(patternN, a); } diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index 7c48edcb10520..22ce64b980135 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -142,6 +142,7 @@ serviceability_ttf_virtual = \ tier1_common = \ sanity/BasicVMTest.java \ gtest/GTestWrapper.java \ + gtest/LockStackGtests.java \ gtest/MetaspaceGtests.java \ gtest/LargePageGtests.java \ gtest/NMTGtests.java \ diff --git a/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndMemoryLoop.java b/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndMemoryLoop.java new file mode 100644 index 0000000000000..765dcee7c5b3c --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndMemoryLoop.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8322854 + * @summary Check that the RAM optimization works when there is a memory loop. + * @library /test/lib / + * @requires vm.compiler2.enabled + * @run main/othervm -XX:CompileCommand=compileonly,*TestReduceAllocationAndMemoryLoop*::test* + * -XX:-TieredCompilation -Xbatch + * compiler.c2.TestReduceAllocationAndMemoryLoop + */ + +package compiler.c2; + +public class TestReduceAllocationAndMemoryLoop { + public static void main(String[] args) throws Exception { + // Warmup + for (int i = 0; i < 50_000; ++i) { + test(false, 10); + } + + // Trigger deoptimization + MyClass obj = test(false, 11); + if (obj.val != 42) { + throw new RuntimeException("Test failed, val = " + obj.val); + } + } + + static class MyClass { + final int val; + + public MyClass(int val) { + this.val = val; + } + } + + public static MyClass test(boolean alwaysFalse, int limit) { + for (int i = 0; ; ++i) { + MyClass obj = new MyClass(42); + if (alwaysFalse || i > 10) { + return obj; + } + if (i == limit) { + return null; + } + } + } +} diff --git a/test/hotspot/jtreg/gtest/LockStackGtests.java b/test/hotspot/jtreg/gtest/LockStackGtests.java new file mode 100644 index 0000000000000..e426b2c56f3b3 --- /dev/null +++ b/test/hotspot/jtreg/gtest/LockStackGtests.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* @test + * @summary Run LockStack gtests with LockingMode=2 + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.xml + * @requires vm.flagless + * @run main/native GTestWrapper --gtest_filter=LockStackTest* -XX:LockingMode=2 + */ diff --git a/test/hotspot/jtreg/runtime/lockStack/TestLockStackCapacity.java b/test/hotspot/jtreg/runtime/lockStack/TestLockStackCapacity.java new file mode 100644 index 0000000000000..01ba1f4f12c65 --- /dev/null +++ b/test/hotspot/jtreg/runtime/lockStack/TestLockStackCapacity.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test TestLockStackCapacity + * @summary Tests the interaction between recursive lightweight locking and + * when the lock stack capacity is exceeded. + * @requires vm.flagless + * @library /testlibrary /test/lib + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xint -XX:LockingMode=2 TestLockStackCapacity + */ + +import jdk.test.lib.Asserts; +import jdk.test.whitebox.WhiteBox; +import jtreg.SkippedException; + +public class TestLockStackCapacity { + static final WhiteBox WB = WhiteBox.getWhiteBox(); + static final int LockingMode = WB.getIntVMFlag("LockingMode").intValue(); + static final int LM_LIGHTWEIGHT = 2; + + static class SynchronizedObject { + static final SynchronizedObject OUTER = new SynchronizedObject(); + static final SynchronizedObject INNER = new SynchronizedObject(); + static final int LockStackCapacity = WB.getLockStackCapacity(); + + synchronized void runInner(int depth) { + assertNotInflated(); + if (depth == 1) { + return; + } else { + runInner(depth - 1); + } + assertNotInflated(); + } + + synchronized void runOuter(int depth, SynchronizedObject inner) { + assertNotInflated(); + if (depth == 1) { + inner.runInner(LockStackCapacity); + } else { + runOuter(depth - 1, inner); + } + assertInflated(); + } + + public static void runTest() { + // Test Requires a capacity of at least 2. + Asserts.assertGTE(LockStackCapacity, 2); + + // Just checking + OUTER.assertNotInflated(); + INNER.assertNotInflated(); + + synchronized(OUTER) { + OUTER.assertNotInflated(); + INNER.assertNotInflated(); + OUTER.runOuter(LockStackCapacity - 1, INNER); + + OUTER.assertInflated(); + INNER.assertNotInflated(); + } + } + + void assertNotInflated() { + Asserts.assertFalse(WB.isMonitorInflated(this)); + } + + void assertInflated() { + Asserts.assertTrue(WB.isMonitorInflated(this)); + } + } + + public static void main(String... args) throws Exception { + if (LockingMode != LM_LIGHTWEIGHT) { + throw new SkippedException("Test only valid for LM_LIGHTWEIGHT"); + } + + if (!WB.supportsRecursiveLightweightLocking()) { + throw new SkippedException("Test only valid if LM_LIGHTWEIGHT supports recursion"); + } + + SynchronizedObject.runTest(); + } +} diff --git a/test/hotspot/jtreg/runtime/logging/SafepointCleanupTest.java b/test/hotspot/jtreg/runtime/logging/SafepointCleanupTest.java index d4ec877f19bb6..0586bf29989d9 100644 --- a/test/hotspot/jtreg/runtime/logging/SafepointCleanupTest.java +++ b/test/hotspot/jtreg/runtime/logging/SafepointCleanupTest.java @@ -40,7 +40,6 @@ static void analyzeOutputOn(ProcessBuilder pb) throws Exception { OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("[safepoint,cleanup]"); output.shouldContain("safepoint cleanup tasks"); - output.shouldContain("updating inline caches"); output.shouldHaveExitValue(0); } diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/config/files/catalog2.properties b/test/jaxp/javax/xml/jaxp/unittest/common/config/files/catalog2.properties index 06c25c3ba816c..c4a6e6bd10e53 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/common/config/files/catalog2.properties +++ b/test/jaxp/javax/xml/jaxp/unittest/common/config/files/catalog2.properties @@ -1,13 +1,13 @@ ################################################################################ # XML Library (java.xml) Configuration File # -# This file is in java.util.Properties format and typically located in the conf +# This file is in java.util.Properties format and typically located in the conf # directory of the Java installation. It may contain key/value pairs for specifying # the implementation class of a factory and/or properties that have corresponding -# system properties. +# system properties. # -# This file can be replaced by specifying a filename with the java.xml.config.file -# system property. For example java -Djava.xml.config.file=myfile +# This file can be replaced by specifying a filename with the java.xml.config.file +# system property. For example java -Djava.xml.config.file=myfile ################################################################################ # ---- Config File: for testing the CATALOG property ---- diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/config/files/customJaxp.properties b/test/jaxp/javax/xml/jaxp/unittest/common/config/files/customJaxp.properties index 610e0d08d1285..42a86e342ad2f 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/common/config/files/customJaxp.properties +++ b/test/jaxp/javax/xml/jaxp/unittest/common/config/files/customJaxp.properties @@ -1,13 +1,13 @@ ################################################################################ # XML Library (java.xml) Configuration File # -# This file is in java.util.Properties format and typically located in the conf +# This file is in java.util.Properties format and typically located in the conf # directory of the Java installation. It may contain key/value pairs for specifying # the implementation class of a factory and/or properties that have corresponding -# system properties. +# system properties. # -# This file can be replaced by specifying a filename with the jdk.xml.config.file -# system property. For example java -Djava.xml.config.file=myfile +# This file can be replaced by specifying a filename with the jdk.xml.config.file +# system property. For example java -Djava.xml.config.file=myfile ################################################################################ # ---- Custom Configuration File ---- diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/config/files/jaxpImpls.properties b/test/jaxp/javax/xml/jaxp/unittest/common/config/files/jaxpImpls.properties index 787543f185e6f..e937d612d69e3 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/common/config/files/jaxpImpls.properties +++ b/test/jaxp/javax/xml/jaxp/unittest/common/config/files/jaxpImpls.properties @@ -1,17 +1,17 @@ ################################################################################ # XML Library (java.xml) Configuration File # -# This file is in java.util.Properties format and typically located in the conf +# This file is in java.util.Properties format and typically located in the conf # directory of the Java installation. It may contain key/value pairs for specifying # the implementation class of a factory and/or properties that have corresponding -# system properties. +# system properties. # -# This file can be replaced by specifying a filename with the jdk.xml.config.file +# This file can be replaced by specifying a filename with the jdk.xml.config.file # system property. For example java -Djava.xml.config.file=myfile ################################################################################ # ---- Configuration for test ---- -# +# # Factory implementation class javax.xml.parsers.DocumentBuilderFactory=common.config.DOMImplTest javax.xml.parsers.SAXParserFactory=common.config.SAXImplTest diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java index 9d74f2da26e09..f88bb052f5e90 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java @@ -159,8 +159,11 @@ void fill(byte[] values) { } static class VarHandleSource extends Source { - VarHandleSource(VarHandle vh, MemoryMode... modes) { + final boolean supportsAtomicAccess; + + VarHandleSource(VarHandle vh, boolean supportsAtomicAccess, MemoryMode... modes) { super(vh, modes); + this.supportsAtomicAccess = supportsAtomicAccess; } boolean matches(ByteArrayViewSource bav) { diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java index ea2aca9b5435d..b18655fcb0353 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java @@ -72,12 +72,12 @@ public List setupVarHandleSources(boolean same) { arrayType = int[].class; } VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(arrayType, bo), + MethodHandles.byteArrayViewVarHandle(arrayType, bo), false, endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(arrayType, bo), + MethodHandles.byteBufferViewVarHandle(arrayType, bo), true, endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -114,38 +114,48 @@ public void testIsAccessModeSupported(VarHandleSource vhs) { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); - - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); - - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); - - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); + if (vhs.supportsAtomicAccess) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); + } else { + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); + } + + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); + + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); + + + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); } @Test(dataProvider = "typesProvider") @@ -180,9 +190,6 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleSourceAccessTestCase( "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h), false)); - cases.add(new VarHandleSourceAccessTestCase( - "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h), - false)); } else { ByteBufferSource bbs = (ByteBufferSource) bav; @@ -207,9 +214,11 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleSourceAccessTestCase( "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h), false)); - cases.add(new VarHandleSourceAccessTestCase( - "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h), - false)); + if (bbs.s.isDirect()) { + cases.add(new VarHandleSourceAccessTestCase( + "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h), + false)); + } } } } @@ -243,33 +252,6 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) { checkNPE(() -> { vh.set(array, ci, VALUE_1); }); - - checkNPE(() -> { - char x = (char) vh.getVolatile(array, ci); - }); - - checkNPE(() -> { - char x = (char) vh.getAcquire(array, ci); - }); - - checkNPE(() -> { - char x = (char) vh.getOpaque(array, ci); - }); - - checkNPE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - - checkNPE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkNPE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); - - - } static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) { @@ -423,7 +405,7 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { }); } - if (readOnly) { + if (readOnly && array.isDirect()) { checkROBE(() -> { vh.setVolatile(array, ci, VALUE_1); }); @@ -435,6 +417,11 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { checkROBE(() -> { vh.setOpaque(array, ci, VALUE_1); }); + + + } + + if (array.isDirect()) { checkUOE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); @@ -478,7 +465,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { checkUOE(() -> { char o = (char) vh.getAndSetRelease(array, ci, VALUE_1); }); - checkUOE(() -> { char o = (char) vh.getAndAdd(array, ci, VALUE_1); }); @@ -490,7 +476,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { checkUOE(() -> { char o = (char) vh.getAndAddRelease(array, ci, VALUE_1); }); - checkUOE(() -> { char o = (char) vh.getAndBitwiseOr(array, ci, VALUE_1); }); @@ -526,8 +511,18 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { checkUOE(() -> { char o = (char) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); }); - } - else { + } else { + checkISE(() -> { + vh.setVolatile(array, ci, VALUE_1); + }); + + checkISE(() -> { + vh.setRelease(array, ci, VALUE_1); + }); + + checkISE(() -> { + vh.setOpaque(array, ci, VALUE_1); + }); checkUOE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); @@ -636,33 +631,6 @@ static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) t checkAIOOBE(() -> { vh.set(array, ci, VALUE_1); }); - - checkAIOOBE(() -> { - char x = (char) vh.getVolatile(array, ci); - }); - - checkAIOOBE(() -> { - char x = (char) vh.getAcquire(array, ci); - }); - - checkAIOOBE(() -> { - char x = (char) vh.getOpaque(array, ci); - }); - - checkAIOOBE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - - checkAIOOBE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkAIOOBE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); - - - } } @@ -686,74 +654,35 @@ static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) }); } - checkIOOBE(() -> { - char x = (char) vh.getVolatile(array, ci); - }); - - checkIOOBE(() -> { - char x = (char) vh.getAcquire(array, ci); - }); - - checkIOOBE(() -> { - char x = (char) vh.getOpaque(array, ci); - }); - - if (!readOnly) { - checkIOOBE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - + if (array.isDirect()) { checkIOOBE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); - - - - } - } - } - - static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable { - VarHandle vh = vhs.s; - byte[] array = bs.s; - - int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE); - - int length = array.length - SIZE + 1; - for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; - final int ci = i; - - if (!iAligned) { - checkISE(() -> { char x = (char) vh.getVolatile(array, ci); }); - checkISE(() -> { + checkIOOBE(() -> { char x = (char) vh.getAcquire(array, ci); }); - checkISE(() -> { + checkIOOBE(() -> { char x = (char) vh.getOpaque(array, ci); }); - checkISE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); + if (!readOnly) { + checkIOOBE(() -> { + vh.setVolatile(array, ci, VALUE_1); + }); - checkISE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + vh.setRelease(array, ci, VALUE_1); + }); + + checkIOOBE(() -> { + vh.setOpaque(array, ci, VALUE_1); + }); - checkISE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); + } } } } @@ -795,9 +724,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) checkISE(() -> { vh.setOpaque(array, ci, VALUE_1); }); - - - } } } @@ -807,45 +733,15 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; byte[] array = bs.s; - int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE); - bs.fill((byte) 0xff); int length = array.length - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; - // Plain { vh.set(array, i, VALUE_1); char x = (char) vh.get(array, i); assertEquals(x, VALUE_1, "get char value"); } - - - if (iAligned) { - // Volatile - { - vh.setVolatile(array, i, VALUE_2); - char x = (char) vh.getVolatile(array, i); - assertEquals(x, VALUE_2, "setVolatile char value"); - } - - // Lazy - { - vh.setRelease(array, i, VALUE_1); - char x = (char) vh.getAcquire(array, i); - assertEquals(x, VALUE_1, "setRelease char value"); - } - - // Opaque - { - vh.setOpaque(array, i, VALUE_2); - char x = (char) vh.getOpaque(array, i); - assertEquals(x, VALUE_2, "setOpaque char value"); - } - - - } } } @@ -854,12 +750,10 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; ByteBuffer array = bs.s; - int misalignmentAtZero = array.alignmentOffset(0, SIZE); - bs.fill((byte) 0xff); int length = array.limit() - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; + boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false; // Plain { @@ -899,15 +793,13 @@ static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; ByteBuffer array = bs.s; - int misalignmentAtZero = array.alignmentOffset(0, SIZE); - ByteBuffer bb = ByteBuffer.allocate(SIZE); bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); bs.fill(bb.putChar(0, VALUE_2).array()); int length = array.limit() - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; + boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false; char v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? rotateLeft(VALUE_2, (i % SIZE) << 3) diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java index 9dcaf2193236b..808c3ec04cb73 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java @@ -72,12 +72,12 @@ public List setupVarHandleSources(boolean same) { arrayType = int[].class; } VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(arrayType, bo), + MethodHandles.byteArrayViewVarHandle(arrayType, bo), false, endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(arrayType, bo), + MethodHandles.byteBufferViewVarHandle(arrayType, bo), true, endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -114,38 +114,62 @@ public void testIsAccessModeSupported(VarHandleSource vhs) { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); - - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); - - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); - - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); + if (vhs.supportsAtomicAccess) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); + } else { + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); + } + + if (vhs.supportsAtomicAccess) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); + } else { + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); + } + + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); + + + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); } @Test(dataProvider = "typesProvider") @@ -180,9 +204,6 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleSourceAccessTestCase( "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h), false)); - cases.add(new VarHandleSourceAccessTestCase( - "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h), - false)); } else { ByteBufferSource bbs = (ByteBufferSource) bav; @@ -207,9 +228,11 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleSourceAccessTestCase( "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h), false)); - cases.add(new VarHandleSourceAccessTestCase( - "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h), - false)); + if (bbs.s.isDirect()) { + cases.add(new VarHandleSourceAccessTestCase( + "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h), + false)); + } } } } @@ -243,6 +266,20 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) { checkNPE(() -> { vh.set(array, ci, VALUE_1); }); + } + + static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) { + VarHandle vh = vhs.s; + ByteBuffer array = null; + int ci = 1; + + checkNPE(() -> { + double x = (double) vh.get(array, ci); + }); + + checkNPE(() -> { + vh.set(array, ci, VALUE_1); + }); checkNPE(() -> { double x = (double) vh.getVolatile(array, ci); @@ -315,96 +352,55 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) { } - static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) { + static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; - ByteBuffer array = null; + byte[] array = bs.s; int ci = 1; - checkNPE(() -> { - double x = (double) vh.get(array, ci); - }); - - checkNPE(() -> { - vh.set(array, ci, VALUE_1); - }); - - checkNPE(() -> { - double x = (double) vh.getVolatile(array, ci); - }); - - checkNPE(() -> { - double x = (double) vh.getAcquire(array, ci); - }); - - checkNPE(() -> { - double x = (double) vh.getOpaque(array, ci); - }); - - checkNPE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - - checkNPE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkNPE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); - - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { double o = (double) vh.getAndSet(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { double o = (double) vh.getAndSetRelease(array, ci, VALUE_1); }); - - } - - static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) { - VarHandle vh = vhs.s; - byte[] array = bs.s; - int ci = 1; - - checkUOE(() -> { double o = (double) vh.getAndAdd(array, ci, VALUE_1); }); @@ -466,7 +462,7 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { }); } - if (readOnly) { + if (readOnly && array.isDirect()) { checkROBE(() -> { vh.setVolatile(array, ci, VALUE_1); }); @@ -478,7 +474,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { checkROBE(() -> { vh.setOpaque(array, ci, VALUE_1); }); - checkROBE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); @@ -524,6 +519,9 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { }); + } + + if (array.isDirect()) { checkUOE(() -> { double o = (double) vh.getAndAdd(array, ci, VALUE_1); }); @@ -535,7 +533,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { checkUOE(() -> { double o = (double) vh.getAndAddRelease(array, ci, VALUE_1); }); - checkUOE(() -> { double o = (double) vh.getAndBitwiseOr(array, ci, VALUE_1); }); @@ -571,8 +568,61 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { checkUOE(() -> { double o = (double) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); }); - } - else { + } else { + checkISE(() -> { + vh.setVolatile(array, ci, VALUE_1); + }); + + checkISE(() -> { + vh.setRelease(array, ci, VALUE_1); + }); + + checkISE(() -> { + vh.setOpaque(array, ci, VALUE_1); + }); + checkISE(() -> { + boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); + }); + + checkISE(() -> { + double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); + }); + + checkISE(() -> { + double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); + }); + + checkISE(() -> { + double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); + }); + + checkISE(() -> { + boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); + }); + + checkISE(() -> { + boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); + }); + + checkISE(() -> { + boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); + }); + + checkISE(() -> { + boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); + }); + + checkISE(() -> { + double o = (double) vh.getAndSet(array, ci, VALUE_1); + }); + + checkISE(() -> { + double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1); + }); + + checkISE(() -> { + double o = (double) vh.getAndSetRelease(array, ci, VALUE_1); + }); checkUOE(() -> { double o = (double) vh.getAndAdd(array, ci, VALUE_1); }); @@ -638,77 +688,6 @@ static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) t checkAIOOBE(() -> { vh.set(array, ci, VALUE_1); }); - - checkAIOOBE(() -> { - double x = (double) vh.getVolatile(array, ci); - }); - - checkAIOOBE(() -> { - double x = (double) vh.getAcquire(array, ci); - }); - - checkAIOOBE(() -> { - double x = (double) vh.getOpaque(array, ci); - }); - - checkAIOOBE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - - checkAIOOBE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkAIOOBE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); - - checkAIOOBE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); - }); - - checkAIOOBE(() -> { - double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); - }); - - checkAIOOBE(() -> { - double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); - }); - - checkAIOOBE(() -> { - double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); - }); - - checkAIOOBE(() -> { - boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); - }); - - checkAIOOBE(() -> { - boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); - }); - - checkAIOOBE(() -> { - boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); - }); - - checkAIOOBE(() -> { - boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); - }); - - checkAIOOBE(() -> { - double o = (double) vh.getAndSet(array, ci, VALUE_1); - }); - - checkAIOOBE(() -> { - double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1); - }); - - checkAIOOBE(() -> { - double o = (double) vh.getAndSetRelease(array, ci, VALUE_1); - }); - - - } } @@ -732,161 +711,78 @@ static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) }); } - checkIOOBE(() -> { - double x = (double) vh.getVolatile(array, ci); - }); - - checkIOOBE(() -> { - double x = (double) vh.getAcquire(array, ci); - }); - - checkIOOBE(() -> { - double x = (double) vh.getOpaque(array, ci); - }); - - if (!readOnly) { - checkIOOBE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - + if (array.isDirect()) { checkIOOBE(() -> { - vh.setRelease(array, ci, VALUE_1); + double x = (double) vh.getVolatile(array, ci); }); checkIOOBE(() -> { - vh.setOpaque(array, ci, VALUE_1); + double x = (double) vh.getAcquire(array, ci); }); checkIOOBE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); + double x = (double) vh.getOpaque(array, ci); }); - checkIOOBE(() -> { - double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); - }); + if (!readOnly) { + checkIOOBE(() -> { + vh.setVolatile(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); - }); + checkIOOBE(() -> { + vh.setRelease(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); - }); + checkIOOBE(() -> { + vh.setOpaque(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); + }); - checkIOOBE(() -> { - double o = (double) vh.getAndSet(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - double o = (double) vh.getAndSetRelease(array, ci, VALUE_1); - }); - - - } - } - } - - static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable { - VarHandle vh = vhs.s; - byte[] array = bs.s; - - int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE); - - int length = array.length - SIZE + 1; - for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; - final int ci = i; - - if (!iAligned) { - checkISE(() -> { - double x = (double) vh.getVolatile(array, ci); - }); - - checkISE(() -> { - double x = (double) vh.getAcquire(array, ci); - }); - - checkISE(() -> { - double x = (double) vh.getOpaque(array, ci); - }); - - checkISE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - - checkISE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkISE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); - - checkISE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); - }); - - checkISE(() -> { - double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); - }); - - checkISE(() -> { - double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); + }); - checkISE(() -> { - boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); + }); - checkISE(() -> { - boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); + }); - checkISE(() -> { - double o = (double) vh.getAndSet(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + double o = (double) vh.getAndSet(array, ci, VALUE_1); + }); - checkISE(() -> { - double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1); + }); - checkISE(() -> { - double o = (double) vh.getAndSetRelease(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + double o = (double) vh.getAndSetRelease(array, ci, VALUE_1); + }); + } } } } @@ -928,7 +824,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) checkISE(() -> { vh.setOpaque(array, ci, VALUE_1); }); - checkISE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); @@ -972,8 +867,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) checkISE(() -> { double o = (double) vh.getAndSetRelease(array, ci, VALUE_1); }); - - } } } @@ -983,204 +876,15 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; byte[] array = bs.s; - int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE); - bs.fill((byte) 0xff); int length = array.length - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; - // Plain { vh.set(array, i, VALUE_1); double x = (double) vh.get(array, i); assertEquals(x, VALUE_1, "get double value"); } - - - if (iAligned) { - // Volatile - { - vh.setVolatile(array, i, VALUE_2); - double x = (double) vh.getVolatile(array, i); - assertEquals(x, VALUE_2, "setVolatile double value"); - } - - // Lazy - { - vh.setRelease(array, i, VALUE_1); - double x = (double) vh.getAcquire(array, i); - assertEquals(x, VALUE_1, "setRelease double value"); - } - - // Opaque - { - vh.setOpaque(array, i, VALUE_2); - double x = (double) vh.getOpaque(array, i); - assertEquals(x, VALUE_2, "setOpaque double value"); - } - - vh.set(array, i, VALUE_1); - - // Compare - { - boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "success compareAndSet double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_2, "success compareAndSet double value"); - } - - { - boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3); - assertEquals(r, false, "failing compareAndSet double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_2, "failing compareAndSet double value"); - } - - { - double r = (double) vh.compareAndExchange(array, i, VALUE_2, VALUE_1); - assertEquals(r, VALUE_2, "success compareAndExchange double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_1, "success compareAndExchange double value"); - } - - { - double r = (double) vh.compareAndExchange(array, i, VALUE_2, VALUE_3); - assertEquals(r, VALUE_1, "failing compareAndExchange double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_1, "failing compareAndExchange double value"); - } - - { - double r = (double) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2); - assertEquals(r, VALUE_1, "success compareAndExchangeAcquire double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_2, "success compareAndExchangeAcquire double value"); - } - - { - double r = (double) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3); - assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire double value"); - } - - { - double r = (double) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1); - assertEquals(r, VALUE_2, "success compareAndExchangeRelease double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_1, "success compareAndExchangeRelease double value"); - } - - { - double r = (double) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3); - assertEquals(r, VALUE_1, "failing compareAndExchangeRelease double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_1, "failing compareAndExchangeRelease double value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSetPlain double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_2, "success weakCompareAndSetPlain double value"); - } - - { - boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSetPlain double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain double value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSetAcquire double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire double"); - } - - { - boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSetAcquire double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire double value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSetRelease double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_2, "success weakCompareAndSetRelease double"); - } - - { - boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSetRelease double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease double value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSet double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_1, "success weakCompareAndSet double"); - } - - { - boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSet double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_1, "failing weakCompareAndSet double value"); - } - - // Compare set and get - { - vh.set(array, i, VALUE_1); - - double o = (double) vh.getAndSet(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndSet double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_2, "getAndSet double value"); - } - - { - vh.set(array, i, VALUE_1); - - double o = (double) vh.getAndSetAcquire(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndSetAcquire double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_2, "getAndSetAcquire double value"); - } - - { - vh.set(array, i, VALUE_1); - - double o = (double) vh.getAndSetRelease(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndSetRelease double"); - double x = (double) vh.get(array, i); - assertEquals(x, VALUE_2, "getAndSetRelease double value"); - } - - - } } } @@ -1189,12 +893,10 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; ByteBuffer array = bs.s; - int misalignmentAtZero = array.alignmentOffset(0, SIZE); - bs.fill((byte) 0xff); int length = array.limit() - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; + boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false; // Plain { @@ -1393,15 +1095,13 @@ static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; ByteBuffer array = bs.s; - int misalignmentAtZero = array.alignmentOffset(0, SIZE); - ByteBuffer bb = ByteBuffer.allocate(SIZE); bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); bs.fill(bb.putDouble(0, VALUE_2).array()); int length = array.limit() - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; + boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false; double v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? rotateLeft(VALUE_2, (i % SIZE) << 3) diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java index e1c8413142ca1..5c3854b6068db 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java @@ -72,12 +72,12 @@ public List setupVarHandleSources(boolean same) { arrayType = int[].class; } VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(arrayType, bo), + MethodHandles.byteArrayViewVarHandle(arrayType, bo), false, endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(arrayType, bo), + MethodHandles.byteBufferViewVarHandle(arrayType, bo), true, endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -114,38 +114,62 @@ public void testIsAccessModeSupported(VarHandleSource vhs) { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); - - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); - - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); - - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); + if (vhs.supportsAtomicAccess) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); + } else { + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); + } + + if (vhs.supportsAtomicAccess) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); + } else { + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); + } + + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); + + + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); } @Test(dataProvider = "typesProvider") @@ -180,9 +204,6 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleSourceAccessTestCase( "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h), false)); - cases.add(new VarHandleSourceAccessTestCase( - "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h), - false)); } else { ByteBufferSource bbs = (ByteBufferSource) bav; @@ -207,9 +228,11 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleSourceAccessTestCase( "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h), false)); - cases.add(new VarHandleSourceAccessTestCase( - "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h), - false)); + if (bbs.s.isDirect()) { + cases.add(new VarHandleSourceAccessTestCase( + "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h), + false)); + } } } } @@ -243,6 +266,20 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) { checkNPE(() -> { vh.set(array, ci, VALUE_1); }); + } + + static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) { + VarHandle vh = vhs.s; + ByteBuffer array = null; + int ci = 1; + + checkNPE(() -> { + float x = (float) vh.get(array, ci); + }); + + checkNPE(() -> { + vh.set(array, ci, VALUE_1); + }); checkNPE(() -> { float x = (float) vh.getVolatile(array, ci); @@ -315,96 +352,55 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) { } - static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) { + static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; - ByteBuffer array = null; + byte[] array = bs.s; int ci = 1; - checkNPE(() -> { - float x = (float) vh.get(array, ci); - }); - - checkNPE(() -> { - vh.set(array, ci, VALUE_1); - }); - - checkNPE(() -> { - float x = (float) vh.getVolatile(array, ci); - }); - - checkNPE(() -> { - float x = (float) vh.getAcquire(array, ci); - }); - - checkNPE(() -> { - float x = (float) vh.getOpaque(array, ci); - }); - - checkNPE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - - checkNPE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkNPE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); - - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { float o = (float) vh.getAndSet(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { float o = (float) vh.getAndSetRelease(array, ci, VALUE_1); }); - - } - - static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) { - VarHandle vh = vhs.s; - byte[] array = bs.s; - int ci = 1; - - checkUOE(() -> { float o = (float) vh.getAndAdd(array, ci, VALUE_1); }); @@ -466,7 +462,7 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { }); } - if (readOnly) { + if (readOnly && array.isDirect()) { checkROBE(() -> { vh.setVolatile(array, ci, VALUE_1); }); @@ -478,7 +474,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { checkROBE(() -> { vh.setOpaque(array, ci, VALUE_1); }); - checkROBE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); @@ -524,6 +519,9 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { }); + } + + if (array.isDirect()) { checkUOE(() -> { float o = (float) vh.getAndAdd(array, ci, VALUE_1); }); @@ -535,7 +533,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { checkUOE(() -> { float o = (float) vh.getAndAddRelease(array, ci, VALUE_1); }); - checkUOE(() -> { float o = (float) vh.getAndBitwiseOr(array, ci, VALUE_1); }); @@ -571,8 +568,61 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { checkUOE(() -> { float o = (float) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); }); - } - else { + } else { + checkISE(() -> { + vh.setVolatile(array, ci, VALUE_1); + }); + + checkISE(() -> { + vh.setRelease(array, ci, VALUE_1); + }); + + checkISE(() -> { + vh.setOpaque(array, ci, VALUE_1); + }); + checkISE(() -> { + boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); + }); + + checkISE(() -> { + float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); + }); + + checkISE(() -> { + float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); + }); + + checkISE(() -> { + float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); + }); + + checkISE(() -> { + boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); + }); + + checkISE(() -> { + boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); + }); + + checkISE(() -> { + boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); + }); + + checkISE(() -> { + boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); + }); + + checkISE(() -> { + float o = (float) vh.getAndSet(array, ci, VALUE_1); + }); + + checkISE(() -> { + float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1); + }); + + checkISE(() -> { + float o = (float) vh.getAndSetRelease(array, ci, VALUE_1); + }); checkUOE(() -> { float o = (float) vh.getAndAdd(array, ci, VALUE_1); }); @@ -638,77 +688,6 @@ static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) t checkAIOOBE(() -> { vh.set(array, ci, VALUE_1); }); - - checkAIOOBE(() -> { - float x = (float) vh.getVolatile(array, ci); - }); - - checkAIOOBE(() -> { - float x = (float) vh.getAcquire(array, ci); - }); - - checkAIOOBE(() -> { - float x = (float) vh.getOpaque(array, ci); - }); - - checkAIOOBE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - - checkAIOOBE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkAIOOBE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); - - checkAIOOBE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); - }); - - checkAIOOBE(() -> { - float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); - }); - - checkAIOOBE(() -> { - float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); - }); - - checkAIOOBE(() -> { - float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); - }); - - checkAIOOBE(() -> { - boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); - }); - - checkAIOOBE(() -> { - boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); - }); - - checkAIOOBE(() -> { - boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); - }); - - checkAIOOBE(() -> { - boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); - }); - - checkAIOOBE(() -> { - float o = (float) vh.getAndSet(array, ci, VALUE_1); - }); - - checkAIOOBE(() -> { - float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1); - }); - - checkAIOOBE(() -> { - float o = (float) vh.getAndSetRelease(array, ci, VALUE_1); - }); - - - } } @@ -732,161 +711,78 @@ static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) }); } - checkIOOBE(() -> { - float x = (float) vh.getVolatile(array, ci); - }); - - checkIOOBE(() -> { - float x = (float) vh.getAcquire(array, ci); - }); - - checkIOOBE(() -> { - float x = (float) vh.getOpaque(array, ci); - }); - - if (!readOnly) { - checkIOOBE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - + if (array.isDirect()) { checkIOOBE(() -> { - vh.setRelease(array, ci, VALUE_1); + float x = (float) vh.getVolatile(array, ci); }); checkIOOBE(() -> { - vh.setOpaque(array, ci, VALUE_1); + float x = (float) vh.getAcquire(array, ci); }); checkIOOBE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); + float x = (float) vh.getOpaque(array, ci); }); - checkIOOBE(() -> { - float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); - }); + if (!readOnly) { + checkIOOBE(() -> { + vh.setVolatile(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); - }); + checkIOOBE(() -> { + vh.setRelease(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); - }); + checkIOOBE(() -> { + vh.setOpaque(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); + }); - checkIOOBE(() -> { - float o = (float) vh.getAndSet(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - float o = (float) vh.getAndSetRelease(array, ci, VALUE_1); - }); - - - } - } - } - - static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable { - VarHandle vh = vhs.s; - byte[] array = bs.s; - - int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE); - - int length = array.length - SIZE + 1; - for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; - final int ci = i; - - if (!iAligned) { - checkISE(() -> { - float x = (float) vh.getVolatile(array, ci); - }); - - checkISE(() -> { - float x = (float) vh.getAcquire(array, ci); - }); - - checkISE(() -> { - float x = (float) vh.getOpaque(array, ci); - }); - - checkISE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - - checkISE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkISE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); - - checkISE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); - }); - - checkISE(() -> { - float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); - }); - - checkISE(() -> { - float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); + }); - checkISE(() -> { - boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); + }); - checkISE(() -> { - boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); + }); - checkISE(() -> { - float o = (float) vh.getAndSet(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + float o = (float) vh.getAndSet(array, ci, VALUE_1); + }); - checkISE(() -> { - float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1); + }); - checkISE(() -> { - float o = (float) vh.getAndSetRelease(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + float o = (float) vh.getAndSetRelease(array, ci, VALUE_1); + }); + } } } } @@ -928,7 +824,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) checkISE(() -> { vh.setOpaque(array, ci, VALUE_1); }); - checkISE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); @@ -972,8 +867,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) checkISE(() -> { float o = (float) vh.getAndSetRelease(array, ci, VALUE_1); }); - - } } } @@ -983,204 +876,15 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; byte[] array = bs.s; - int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE); - bs.fill((byte) 0xff); int length = array.length - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; - // Plain { vh.set(array, i, VALUE_1); float x = (float) vh.get(array, i); assertEquals(x, VALUE_1, "get float value"); } - - - if (iAligned) { - // Volatile - { - vh.setVolatile(array, i, VALUE_2); - float x = (float) vh.getVolatile(array, i); - assertEquals(x, VALUE_2, "setVolatile float value"); - } - - // Lazy - { - vh.setRelease(array, i, VALUE_1); - float x = (float) vh.getAcquire(array, i); - assertEquals(x, VALUE_1, "setRelease float value"); - } - - // Opaque - { - vh.setOpaque(array, i, VALUE_2); - float x = (float) vh.getOpaque(array, i); - assertEquals(x, VALUE_2, "setOpaque float value"); - } - - vh.set(array, i, VALUE_1); - - // Compare - { - boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "success compareAndSet float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_2, "success compareAndSet float value"); - } - - { - boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3); - assertEquals(r, false, "failing compareAndSet float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_2, "failing compareAndSet float value"); - } - - { - float r = (float) vh.compareAndExchange(array, i, VALUE_2, VALUE_1); - assertEquals(r, VALUE_2, "success compareAndExchange float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_1, "success compareAndExchange float value"); - } - - { - float r = (float) vh.compareAndExchange(array, i, VALUE_2, VALUE_3); - assertEquals(r, VALUE_1, "failing compareAndExchange float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_1, "failing compareAndExchange float value"); - } - - { - float r = (float) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2); - assertEquals(r, VALUE_1, "success compareAndExchangeAcquire float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_2, "success compareAndExchangeAcquire float value"); - } - - { - float r = (float) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3); - assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire float value"); - } - - { - float r = (float) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1); - assertEquals(r, VALUE_2, "success compareAndExchangeRelease float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_1, "success compareAndExchangeRelease float value"); - } - - { - float r = (float) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3); - assertEquals(r, VALUE_1, "failing compareAndExchangeRelease float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_1, "failing compareAndExchangeRelease float value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSetPlain float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_2, "success weakCompareAndSetPlain float value"); - } - - { - boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSetPlain float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain float value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSetAcquire float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire float"); - } - - { - boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSetAcquire float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire float value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSetRelease float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_2, "success weakCompareAndSetRelease float"); - } - - { - boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSetRelease float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease float value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSet float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_1, "success weakCompareAndSet float"); - } - - { - boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSet float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_1, "failing weakCompareAndSet float value"); - } - - // Compare set and get - { - vh.set(array, i, VALUE_1); - - float o = (float) vh.getAndSet(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndSet float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_2, "getAndSet float value"); - } - - { - vh.set(array, i, VALUE_1); - - float o = (float) vh.getAndSetAcquire(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndSetAcquire float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_2, "getAndSetAcquire float value"); - } - - { - vh.set(array, i, VALUE_1); - - float o = (float) vh.getAndSetRelease(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndSetRelease float"); - float x = (float) vh.get(array, i); - assertEquals(x, VALUE_2, "getAndSetRelease float value"); - } - - - } } } @@ -1189,12 +893,10 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; ByteBuffer array = bs.s; - int misalignmentAtZero = array.alignmentOffset(0, SIZE); - bs.fill((byte) 0xff); int length = array.limit() - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; + boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false; // Plain { @@ -1393,15 +1095,13 @@ static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; ByteBuffer array = bs.s; - int misalignmentAtZero = array.alignmentOffset(0, SIZE); - ByteBuffer bb = ByteBuffer.allocate(SIZE); bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); bs.fill(bb.putFloat(0, VALUE_2).array()); int length = array.limit() - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; + boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false; float v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? rotateLeft(VALUE_2, (i % SIZE) << 3) diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java index 3f6066c57bb2f..a03a6248a0fd5 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java @@ -72,12 +72,12 @@ public List setupVarHandleSources(boolean same) { arrayType = long[].class; } VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(arrayType, bo), + MethodHandles.byteArrayViewVarHandle(arrayType, bo), false, endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(arrayType, bo), + MethodHandles.byteBufferViewVarHandle(arrayType, bo), true, endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -114,38 +114,80 @@ public void testIsAccessModeSupported(VarHandleSource vhs) { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); - - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); - - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); - - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); + if (vhs.supportsAtomicAccess) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); + } else { + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); + } + + if (vhs.supportsAtomicAccess) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); + } else { + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); + } + + if (vhs.supportsAtomicAccess) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); + } else { + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); + } + + + if (vhs.supportsAtomicAccess) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); + } else { + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); + } } @Test(dataProvider = "typesProvider") @@ -180,9 +222,6 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleSourceAccessTestCase( "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h), false)); - cases.add(new VarHandleSourceAccessTestCase( - "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h), - false)); } else { ByteBufferSource bbs = (ByteBufferSource) bav; @@ -207,9 +246,11 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleSourceAccessTestCase( "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h), false)); - cases.add(new VarHandleSourceAccessTestCase( - "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h), - false)); + if (bbs.s.isDirect()) { + cases.add(new VarHandleSourceAccessTestCase( + "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h), + false)); + } } } } @@ -243,6 +284,20 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) { checkNPE(() -> { vh.set(array, ci, VALUE_1); }); + } + + static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) { + VarHandle vh = vhs.s; + ByteBuffer array = null; + int ci = 1; + + checkNPE(() -> { + int x = (int) vh.get(array, ci); + }); + + checkNPE(() -> { + vh.set(array, ci, VALUE_1); + }); checkNPE(() -> { int x = (int) vh.getVolatile(array, ci); @@ -361,145 +416,104 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) { }); } - static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) { + static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; - ByteBuffer array = null; + byte[] array = bs.s; int ci = 1; - checkNPE(() -> { - int x = (int) vh.get(array, ci); - }); - - checkNPE(() -> { - vh.set(array, ci, VALUE_1); - }); - - checkNPE(() -> { - int x = (int) vh.getVolatile(array, ci); - }); - - checkNPE(() -> { - int x = (int) vh.getAcquire(array, ci); - }); - - checkNPE(() -> { - int x = (int) vh.getOpaque(array, ci); - }); - - checkNPE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - - checkNPE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkNPE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); - - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { int r = (int) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { int o = (int) vh.getAndSet(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { int o = (int) vh.getAndSetAcquire(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { int o = (int) vh.getAndSetRelease(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { int o = (int) vh.getAndAdd(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { int o = (int) vh.getAndAddAcquire(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { int o = (int) vh.getAndAddRelease(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { int o = (int) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { int o = (int) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { int o = (int) vh.getAndBitwiseAnd(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { int o = (int) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { int o = (int) vh.getAndBitwiseAndRelease(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { int o = (int) vh.getAndBitwiseXor(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { int o = (int) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); }); } - static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) { - VarHandle vh = vhs.s; - byte[] array = bs.s; - int ci = 1; - - - - } - static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; ByteBuffer array = bs.s; @@ -512,7 +526,7 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { }); } - if (readOnly) { + if (readOnly && array.isDirect()) { checkROBE(() -> { vh.setVolatile(array, ci, VALUE_1); }); @@ -524,7 +538,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { checkROBE(() -> { vh.setOpaque(array, ci, VALUE_1); }); - checkROBE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); @@ -569,7 +582,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { int o = (int) vh.getAndSetRelease(array, ci, VALUE_1); }); - checkROBE(() -> { int o = (int) vh.getAndAdd(array, ci, VALUE_1); }); @@ -618,143 +630,128 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); }); } - else { - } - } - - - static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable { - VarHandle vh = vhs.s; - byte[] array = bs.s; - - int length = array.length - SIZE + 1; - for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) { - final int ci = i; - - checkAIOOBE(() -> { - int x = (int) vh.get(array, ci); - }); - - checkAIOOBE(() -> { - vh.set(array, ci, VALUE_1); - }); - - checkAIOOBE(() -> { - int x = (int) vh.getVolatile(array, ci); - }); - - checkAIOOBE(() -> { - int x = (int) vh.getAcquire(array, ci); - }); - checkAIOOBE(() -> { - int x = (int) vh.getOpaque(array, ci); - }); - - checkAIOOBE(() -> { + if (array.isDirect()) { + } else { + checkISE(() -> { vh.setVolatile(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { vh.setRelease(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { vh.setOpaque(array, ci, VALUE_1); }); - - checkAIOOBE(() -> { + checkISE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { + checkISE(() -> { int r = (int) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { + checkISE(() -> { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { + checkISE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { + checkISE(() -> { boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { + checkISE(() -> { int o = (int) vh.getAndSet(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { int o = (int) vh.getAndSetAcquire(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { int o = (int) vh.getAndSetRelease(array, ci, VALUE_1); }); - - checkAIOOBE(() -> { + checkISE(() -> { int o = (int) vh.getAndAdd(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { int o = (int) vh.getAndAddAcquire(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { int o = (int) vh.getAndAddRelease(array, ci, VALUE_1); }); - - checkAIOOBE(() -> { + checkISE(() -> { int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { int o = (int) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { int o = (int) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { int o = (int) vh.getAndBitwiseAnd(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { int o = (int) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { int o = (int) vh.getAndBitwiseAndRelease(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { int o = (int) vh.getAndBitwiseXor(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { int o = (int) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); }); + } + } + + + static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable { + VarHandle vh = vhs.s; + byte[] array = bs.s; + + int length = array.length - SIZE + 1; + for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) { + final int ci = i; + + checkAIOOBE(() -> { + int x = (int) vh.get(array, ci); + }); + checkAIOOBE(() -> { + vh.set(array, ci, VALUE_1); + }); } } @@ -778,253 +775,124 @@ static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) }); } - checkIOOBE(() -> { - int x = (int) vh.getVolatile(array, ci); - }); - - checkIOOBE(() -> { - int x = (int) vh.getAcquire(array, ci); - }); - - checkIOOBE(() -> { - int x = (int) vh.getOpaque(array, ci); - }); - - if (!readOnly) { + if (array.isDirect()) { checkIOOBE(() -> { - vh.setVolatile(array, ci, VALUE_1); + int x = (int) vh.getVolatile(array, ci); }); checkIOOBE(() -> { - vh.setRelease(array, ci, VALUE_1); + int x = (int) vh.getAcquire(array, ci); }); checkIOOBE(() -> { - vh.setOpaque(array, ci, VALUE_1); + int x = (int) vh.getOpaque(array, ci); }); - checkIOOBE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); - }); + if (!readOnly) { + checkIOOBE(() -> { + vh.setVolatile(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - int r = (int) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); - }); + checkIOOBE(() -> { + vh.setRelease(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); - }); + checkIOOBE(() -> { + vh.setOpaque(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); - }); + checkIOOBE(() -> { + boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + int r = (int) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - int o = (int) vh.getAndSet(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - int o = (int) vh.getAndSetAcquire(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - int o = (int) vh.getAndSetRelease(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - int o = (int) vh.getAndAdd(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + int o = (int) vh.getAndSet(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - int o = (int) vh.getAndAddAcquire(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + int o = (int) vh.getAndSetAcquire(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - int o = (int) vh.getAndAddRelease(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + int o = (int) vh.getAndSetRelease(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + int o = (int) vh.getAndAdd(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - int o = (int) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + int o = (int) vh.getAndAddAcquire(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - int o = (int) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + int o = (int) vh.getAndAddRelease(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - int o = (int) vh.getAndBitwiseAnd(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - int o = (int) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - int o = (int) vh.getAndBitwiseAndRelease(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - int o = (int) vh.getAndBitwiseXor(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - int o = (int) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); - }); - } - } - } - - static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable { - VarHandle vh = vhs.s; - byte[] array = bs.s; - - int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE); - - int length = array.length - SIZE + 1; - for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; - final int ci = i; - - if (!iAligned) { - checkISE(() -> { - int x = (int) vh.getVolatile(array, ci); - }); - - checkISE(() -> { - int x = (int) vh.getAcquire(array, ci); - }); - - checkISE(() -> { - int x = (int) vh.getOpaque(array, ci); - }); - - checkISE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - - checkISE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkISE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); - - checkISE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - int r = (int) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); - }); - - checkISE(() -> { - int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); - }); - - checkISE(() -> { - int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - int o = (int) vh.getAndSet(array, ci, VALUE_1); - }); - - checkISE(() -> { - int o = (int) vh.getAndSetAcquire(array, ci, VALUE_1); - }); - - checkISE(() -> { - int o = (int) vh.getAndSetRelease(array, ci, VALUE_1); - }); - - checkISE(() -> { - int o = (int) vh.getAndAdd(array, ci, VALUE_1); - }); - - checkISE(() -> { - int o = (int) vh.getAndAddAcquire(array, ci, VALUE_1); - }); - - checkISE(() -> { - int o = (int) vh.getAndAddRelease(array, ci, VALUE_1); - }); - - checkISE(() -> { - int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1); + }); - checkISE(() -> { - int o = (int) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + int o = (int) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); + }); - checkISE(() -> { - int o = (int) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + int o = (int) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); + }); - checkISE(() -> { - int o = (int) vh.getAndBitwiseAnd(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + int o = (int) vh.getAndBitwiseAnd(array, ci, VALUE_1); + }); - checkISE(() -> { - int o = (int) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + int o = (int) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); + }); - checkISE(() -> { - int o = (int) vh.getAndBitwiseAndRelease(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + int o = (int) vh.getAndBitwiseAndRelease(array, ci, VALUE_1); + }); - checkISE(() -> { - int o = (int) vh.getAndBitwiseXor(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + int o = (int) vh.getAndBitwiseXor(array, ci, VALUE_1); + }); - checkISE(() -> { - int o = (int) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + int o = (int) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); + }); - checkISE(() -> { - int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); + }); + } } } } @@ -1066,7 +934,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) checkISE(() -> { vh.setOpaque(array, ci, VALUE_1); }); - checkISE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); @@ -1110,7 +977,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) checkISE(() -> { int o = (int) vh.getAndSetRelease(array, ci, VALUE_1); }); - checkISE(() -> { int o = (int) vh.getAndAdd(array, ci, VALUE_1); }); @@ -1122,7 +988,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) checkISE(() -> { int o = (int) vh.getAndAddRelease(array, ci, VALUE_1); }); - checkISE(() -> { int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1); }); @@ -1167,314 +1032,15 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; byte[] array = bs.s; - int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE); - bs.fill((byte) 0xff); int length = array.length - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; - // Plain { vh.set(array, i, VALUE_1); int x = (int) vh.get(array, i); assertEquals(x, VALUE_1, "get int value"); } - - - if (iAligned) { - // Volatile - { - vh.setVolatile(array, i, VALUE_2); - int x = (int) vh.getVolatile(array, i); - assertEquals(x, VALUE_2, "setVolatile int value"); - } - - // Lazy - { - vh.setRelease(array, i, VALUE_1); - int x = (int) vh.getAcquire(array, i); - assertEquals(x, VALUE_1, "setRelease int value"); - } - - // Opaque - { - vh.setOpaque(array, i, VALUE_2); - int x = (int) vh.getOpaque(array, i); - assertEquals(x, VALUE_2, "setOpaque int value"); - } - - vh.set(array, i, VALUE_1); - - // Compare - { - boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "success compareAndSet int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_2, "success compareAndSet int value"); - } - - { - boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3); - assertEquals(r, false, "failing compareAndSet int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_2, "failing compareAndSet int value"); - } - - { - int r = (int) vh.compareAndExchange(array, i, VALUE_2, VALUE_1); - assertEquals(r, VALUE_2, "success compareAndExchange int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1, "success compareAndExchange int value"); - } - - { - int r = (int) vh.compareAndExchange(array, i, VALUE_2, VALUE_3); - assertEquals(r, VALUE_1, "failing compareAndExchange int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1, "failing compareAndExchange int value"); - } - - { - int r = (int) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2); - assertEquals(r, VALUE_1, "success compareAndExchangeAcquire int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_2, "success compareAndExchangeAcquire int value"); - } - - { - int r = (int) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3); - assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire int value"); - } - - { - int r = (int) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1); - assertEquals(r, VALUE_2, "success compareAndExchangeRelease int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1, "success compareAndExchangeRelease int value"); - } - - { - int r = (int) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3); - assertEquals(r, VALUE_1, "failing compareAndExchangeRelease int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1, "failing compareAndExchangeRelease int value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSetPlain int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_2, "success weakCompareAndSetPlain int value"); - } - - { - boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSetPlain int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain int value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSetAcquire int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire int"); - } - - { - boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSetAcquire int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire int value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSetRelease int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_2, "success weakCompareAndSetRelease int"); - } - - { - boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSetRelease int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease int value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSet int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1, "success weakCompareAndSet int"); - } - - { - boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSet int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1, "failing weakCompareAndSet int value"); - } - - // Compare set and get - { - vh.set(array, i, VALUE_1); - - int o = (int) vh.getAndSet(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndSet int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_2, "getAndSet int value"); - } - - { - vh.set(array, i, VALUE_1); - - int o = (int) vh.getAndSetAcquire(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndSetAcquire int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_2, "getAndSetAcquire int value"); - } - - { - vh.set(array, i, VALUE_1); - - int o = (int) vh.getAndSetRelease(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndSetRelease int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_2, "getAndSetRelease int value"); - } - - // get and add, add and get - { - vh.set(array, i, VALUE_1); - - int o = (int) vh.getAndAdd(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndAdd int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1 + VALUE_2, "getAndAdd int value"); - } - - { - vh.set(array, i, VALUE_1); - - int o = (int) vh.getAndAddAcquire(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndAddAcquire int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1 + VALUE_2, "getAndAddAcquire int value"); - } - - { - vh.set(array, i, VALUE_1); - - int o = (int) vh.getAndAddRelease(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndAddRelease int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1 + VALUE_2, "getAndAddRelease int value"); - } - - // get and bitwise or - { - vh.set(array, i, VALUE_1); - - int o = (int) vh.getAndBitwiseOr(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseOr int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOr int value"); - } - - { - vh.set(array, i, VALUE_1); - - int o = (int) vh.getAndBitwiseOrAcquire(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseOrAcquire int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrAcquire int value"); - } - - { - vh.set(array, i, VALUE_1); - - int o = (int) vh.getAndBitwiseOrRelease(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseOrRelease int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrRelease int value"); - } - - // get and bitwise and - { - vh.set(array, i, VALUE_1); - - int o = (int) vh.getAndBitwiseAnd(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseAnd int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAnd int value"); - } - - { - vh.set(array, i, VALUE_1); - - int o = (int) vh.getAndBitwiseAndAcquire(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseAndAcquire int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndAcquire int value"); - } - - { - vh.set(array, i, VALUE_1); - - int o = (int) vh.getAndBitwiseAndRelease(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseAndRelease int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndRelease int value"); - } - - // get and bitwise xor - { - vh.set(array, i, VALUE_1); - - int o = (int) vh.getAndBitwiseXor(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseXor int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXor int value"); - } - - { - vh.set(array, i, VALUE_1); - - int o = (int) vh.getAndBitwiseXorAcquire(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseXorAcquire int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorAcquire int value"); - } - - { - vh.set(array, i, VALUE_1); - - int o = (int) vh.getAndBitwiseXorRelease(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseXorRelease int"); - int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorRelease int value"); - } - } } } @@ -1483,12 +1049,10 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; ByteBuffer array = bs.s; - int misalignmentAtZero = array.alignmentOffset(0, SIZE); - bs.fill((byte) 0xff); int length = array.limit() - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; + boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false; // Plain { @@ -1797,15 +1361,13 @@ static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; ByteBuffer array = bs.s; - int misalignmentAtZero = array.alignmentOffset(0, SIZE); - ByteBuffer bb = ByteBuffer.allocate(SIZE); bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); bs.fill(bb.putInt(0, VALUE_2).array()); int length = array.limit() - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; + boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false; int v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? rotateLeft(VALUE_2, (i % SIZE) << 3) diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java index d13bb1c03df26..8324a48803505 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java @@ -72,12 +72,12 @@ public List setupVarHandleSources(boolean same) { arrayType = int[].class; } VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(arrayType, bo), + MethodHandles.byteArrayViewVarHandle(arrayType, bo), false, endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(arrayType, bo), + MethodHandles.byteBufferViewVarHandle(arrayType, bo), true, endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -114,38 +114,80 @@ public void testIsAccessModeSupported(VarHandleSource vhs) { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); - - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); - - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); - - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); + if (vhs.supportsAtomicAccess) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); + } else { + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); + } + + if (vhs.supportsAtomicAccess) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); + } else { + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); + } + + if (vhs.supportsAtomicAccess) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); + } else { + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); + } + + + if (vhs.supportsAtomicAccess) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); + } else { + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); + } } @Test(dataProvider = "typesProvider") @@ -180,9 +222,6 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleSourceAccessTestCase( "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h), false)); - cases.add(new VarHandleSourceAccessTestCase( - "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h), - false)); } else { ByteBufferSource bbs = (ByteBufferSource) bav; @@ -207,9 +246,11 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleSourceAccessTestCase( "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h), false)); - cases.add(new VarHandleSourceAccessTestCase( - "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h), - false)); + if (bbs.s.isDirect()) { + cases.add(new VarHandleSourceAccessTestCase( + "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h), + false)); + } } } } @@ -243,6 +284,20 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) { checkNPE(() -> { vh.set(array, ci, VALUE_1); }); + } + + static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) { + VarHandle vh = vhs.s; + ByteBuffer array = null; + int ci = 1; + + checkNPE(() -> { + long x = (long) vh.get(array, ci); + }); + + checkNPE(() -> { + vh.set(array, ci, VALUE_1); + }); checkNPE(() -> { long x = (long) vh.getVolatile(array, ci); @@ -361,145 +416,104 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) { }); } - static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) { + static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; - ByteBuffer array = null; + byte[] array = bs.s; int ci = 1; - checkNPE(() -> { - long x = (long) vh.get(array, ci); - }); - - checkNPE(() -> { - vh.set(array, ci, VALUE_1); - }); - - checkNPE(() -> { - long x = (long) vh.getVolatile(array, ci); - }); - - checkNPE(() -> { - long x = (long) vh.getAcquire(array, ci); - }); - - checkNPE(() -> { - long x = (long) vh.getOpaque(array, ci); - }); - - checkNPE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - - checkNPE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkNPE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); - - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { long r = (long) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); }); - checkNPE(() -> { + checkUOE(() -> { long o = (long) vh.getAndSet(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { long o = (long) vh.getAndSetAcquire(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { long o = (long) vh.getAndSetRelease(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { long o = (long) vh.getAndAdd(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { long o = (long) vh.getAndAddAcquire(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { long o = (long) vh.getAndAddRelease(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { long o = (long) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { long o = (long) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { long o = (long) vh.getAndBitwiseAnd(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { long o = (long) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { long o = (long) vh.getAndBitwiseAndRelease(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { long o = (long) vh.getAndBitwiseXor(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { long o = (long) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); }); - checkNPE(() -> { + checkUOE(() -> { long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); }); } - static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) { - VarHandle vh = vhs.s; - byte[] array = bs.s; - int ci = 1; - - - - } - static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; ByteBuffer array = bs.s; @@ -512,7 +526,7 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { }); } - if (readOnly) { + if (readOnly && array.isDirect()) { checkROBE(() -> { vh.setVolatile(array, ci, VALUE_1); }); @@ -524,7 +538,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { checkROBE(() -> { vh.setOpaque(array, ci, VALUE_1); }); - checkROBE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); @@ -569,7 +582,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { long o = (long) vh.getAndSetRelease(array, ci, VALUE_1); }); - checkROBE(() -> { long o = (long) vh.getAndAdd(array, ci, VALUE_1); }); @@ -618,143 +630,128 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); }); } - else { - } - } - - - static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable { - VarHandle vh = vhs.s; - byte[] array = bs.s; - - int length = array.length - SIZE + 1; - for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) { - final int ci = i; - - checkAIOOBE(() -> { - long x = (long) vh.get(array, ci); - }); - - checkAIOOBE(() -> { - vh.set(array, ci, VALUE_1); - }); - - checkAIOOBE(() -> { - long x = (long) vh.getVolatile(array, ci); - }); - - checkAIOOBE(() -> { - long x = (long) vh.getAcquire(array, ci); - }); - checkAIOOBE(() -> { - long x = (long) vh.getOpaque(array, ci); - }); - - checkAIOOBE(() -> { + if (array.isDirect()) { + } else { + checkISE(() -> { vh.setVolatile(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { vh.setRelease(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { vh.setOpaque(array, ci, VALUE_1); }); - - checkAIOOBE(() -> { + checkISE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { + checkISE(() -> { long r = (long) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { + checkISE(() -> { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { + checkISE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { + checkISE(() -> { boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { + checkISE(() -> { long o = (long) vh.getAndSet(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { long o = (long) vh.getAndSetAcquire(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { long o = (long) vh.getAndSetRelease(array, ci, VALUE_1); }); - - checkAIOOBE(() -> { + checkISE(() -> { long o = (long) vh.getAndAdd(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { long o = (long) vh.getAndAddAcquire(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { long o = (long) vh.getAndAddRelease(array, ci, VALUE_1); }); - - checkAIOOBE(() -> { + checkISE(() -> { long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { long o = (long) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { long o = (long) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { long o = (long) vh.getAndBitwiseAnd(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { long o = (long) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { long o = (long) vh.getAndBitwiseAndRelease(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { long o = (long) vh.getAndBitwiseXor(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { long o = (long) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); }); + } + } + + + static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable { + VarHandle vh = vhs.s; + byte[] array = bs.s; + + int length = array.length - SIZE + 1; + for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) { + final int ci = i; + + checkAIOOBE(() -> { + long x = (long) vh.get(array, ci); + }); + checkAIOOBE(() -> { + vh.set(array, ci, VALUE_1); + }); } } @@ -778,253 +775,124 @@ static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) }); } - checkIOOBE(() -> { - long x = (long) vh.getVolatile(array, ci); - }); - - checkIOOBE(() -> { - long x = (long) vh.getAcquire(array, ci); - }); - - checkIOOBE(() -> { - long x = (long) vh.getOpaque(array, ci); - }); - - if (!readOnly) { + if (array.isDirect()) { checkIOOBE(() -> { - vh.setVolatile(array, ci, VALUE_1); + long x = (long) vh.getVolatile(array, ci); }); checkIOOBE(() -> { - vh.setRelease(array, ci, VALUE_1); + long x = (long) vh.getAcquire(array, ci); }); checkIOOBE(() -> { - vh.setOpaque(array, ci, VALUE_1); + long x = (long) vh.getOpaque(array, ci); }); - checkIOOBE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); - }); + if (!readOnly) { + checkIOOBE(() -> { + vh.setVolatile(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - long r = (long) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); - }); + checkIOOBE(() -> { + vh.setRelease(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); - }); + checkIOOBE(() -> { + vh.setOpaque(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); - }); + checkIOOBE(() -> { + boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + long r = (long) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - long o = (long) vh.getAndSet(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - long o = (long) vh.getAndSetAcquire(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - long o = (long) vh.getAndSetRelease(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - long o = (long) vh.getAndAdd(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + long o = (long) vh.getAndSet(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - long o = (long) vh.getAndAddAcquire(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + long o = (long) vh.getAndSetAcquire(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - long o = (long) vh.getAndAddRelease(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + long o = (long) vh.getAndSetRelease(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + long o = (long) vh.getAndAdd(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - long o = (long) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + long o = (long) vh.getAndAddAcquire(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - long o = (long) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + long o = (long) vh.getAndAddRelease(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - long o = (long) vh.getAndBitwiseAnd(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - long o = (long) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - long o = (long) vh.getAndBitwiseAndRelease(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - long o = (long) vh.getAndBitwiseXor(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - long o = (long) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); - }); - } - } - } - - static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable { - VarHandle vh = vhs.s; - byte[] array = bs.s; - - int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE); - - int length = array.length - SIZE + 1; - for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; - final int ci = i; - - if (!iAligned) { - checkISE(() -> { - long x = (long) vh.getVolatile(array, ci); - }); - - checkISE(() -> { - long x = (long) vh.getAcquire(array, ci); - }); - - checkISE(() -> { - long x = (long) vh.getOpaque(array, ci); - }); - - checkISE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - - checkISE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkISE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); - - checkISE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - long r = (long) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); - }); - - checkISE(() -> { - long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); - }); - - checkISE(() -> { - long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - long o = (long) vh.getAndSet(array, ci, VALUE_1); - }); - - checkISE(() -> { - long o = (long) vh.getAndSetAcquire(array, ci, VALUE_1); - }); - - checkISE(() -> { - long o = (long) vh.getAndSetRelease(array, ci, VALUE_1); - }); - - checkISE(() -> { - long o = (long) vh.getAndAdd(array, ci, VALUE_1); - }); - - checkISE(() -> { - long o = (long) vh.getAndAddAcquire(array, ci, VALUE_1); - }); - - checkISE(() -> { - long o = (long) vh.getAndAddRelease(array, ci, VALUE_1); - }); - - checkISE(() -> { - long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1); + }); - checkISE(() -> { - long o = (long) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + long o = (long) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); + }); - checkISE(() -> { - long o = (long) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + long o = (long) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); + }); - checkISE(() -> { - long o = (long) vh.getAndBitwiseAnd(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + long o = (long) vh.getAndBitwiseAnd(array, ci, VALUE_1); + }); - checkISE(() -> { - long o = (long) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + long o = (long) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); + }); - checkISE(() -> { - long o = (long) vh.getAndBitwiseAndRelease(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + long o = (long) vh.getAndBitwiseAndRelease(array, ci, VALUE_1); + }); - checkISE(() -> { - long o = (long) vh.getAndBitwiseXor(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + long o = (long) vh.getAndBitwiseXor(array, ci, VALUE_1); + }); - checkISE(() -> { - long o = (long) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + long o = (long) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); + }); - checkISE(() -> { - long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); + }); + } } } } @@ -1066,7 +934,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) checkISE(() -> { vh.setOpaque(array, ci, VALUE_1); }); - checkISE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); @@ -1110,7 +977,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) checkISE(() -> { long o = (long) vh.getAndSetRelease(array, ci, VALUE_1); }); - checkISE(() -> { long o = (long) vh.getAndAdd(array, ci, VALUE_1); }); @@ -1122,7 +988,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) checkISE(() -> { long o = (long) vh.getAndAddRelease(array, ci, VALUE_1); }); - checkISE(() -> { long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1); }); @@ -1167,314 +1032,15 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; byte[] array = bs.s; - int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE); - bs.fill((byte) 0xff); int length = array.length - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; - // Plain { vh.set(array, i, VALUE_1); long x = (long) vh.get(array, i); assertEquals(x, VALUE_1, "get long value"); } - - - if (iAligned) { - // Volatile - { - vh.setVolatile(array, i, VALUE_2); - long x = (long) vh.getVolatile(array, i); - assertEquals(x, VALUE_2, "setVolatile long value"); - } - - // Lazy - { - vh.setRelease(array, i, VALUE_1); - long x = (long) vh.getAcquire(array, i); - assertEquals(x, VALUE_1, "setRelease long value"); - } - - // Opaque - { - vh.setOpaque(array, i, VALUE_2); - long x = (long) vh.getOpaque(array, i); - assertEquals(x, VALUE_2, "setOpaque long value"); - } - - vh.set(array, i, VALUE_1); - - // Compare - { - boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "success compareAndSet long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_2, "success compareAndSet long value"); - } - - { - boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3); - assertEquals(r, false, "failing compareAndSet long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_2, "failing compareAndSet long value"); - } - - { - long r = (long) vh.compareAndExchange(array, i, VALUE_2, VALUE_1); - assertEquals(r, VALUE_2, "success compareAndExchange long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1, "success compareAndExchange long value"); - } - - { - long r = (long) vh.compareAndExchange(array, i, VALUE_2, VALUE_3); - assertEquals(r, VALUE_1, "failing compareAndExchange long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1, "failing compareAndExchange long value"); - } - - { - long r = (long) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2); - assertEquals(r, VALUE_1, "success compareAndExchangeAcquire long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_2, "success compareAndExchangeAcquire long value"); - } - - { - long r = (long) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3); - assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire long value"); - } - - { - long r = (long) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1); - assertEquals(r, VALUE_2, "success compareAndExchangeRelease long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1, "success compareAndExchangeRelease long value"); - } - - { - long r = (long) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3); - assertEquals(r, VALUE_1, "failing compareAndExchangeRelease long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1, "failing compareAndExchangeRelease long value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSetPlain long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_2, "success weakCompareAndSetPlain long value"); - } - - { - boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSetPlain long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain long value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSetAcquire long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire long"); - } - - { - boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSetAcquire long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire long value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSetRelease long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_2, "success weakCompareAndSetRelease long"); - } - - { - boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSetRelease long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease long value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSet long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1, "success weakCompareAndSet long"); - } - - { - boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSet long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1, "failing weakCompareAndSet long value"); - } - - // Compare set and get - { - vh.set(array, i, VALUE_1); - - long o = (long) vh.getAndSet(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndSet long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_2, "getAndSet long value"); - } - - { - vh.set(array, i, VALUE_1); - - long o = (long) vh.getAndSetAcquire(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndSetAcquire long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_2, "getAndSetAcquire long value"); - } - - { - vh.set(array, i, VALUE_1); - - long o = (long) vh.getAndSetRelease(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndSetRelease long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_2, "getAndSetRelease long value"); - } - - // get and add, add and get - { - vh.set(array, i, VALUE_1); - - long o = (long) vh.getAndAdd(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndAdd long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1 + VALUE_2, "getAndAdd long value"); - } - - { - vh.set(array, i, VALUE_1); - - long o = (long) vh.getAndAddAcquire(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndAddAcquire long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1 + VALUE_2, "getAndAddAcquire long value"); - } - - { - vh.set(array, i, VALUE_1); - - long o = (long) vh.getAndAddRelease(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndAddRelease long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1 + VALUE_2, "getAndAddRelease long value"); - } - - // get and bitwise or - { - vh.set(array, i, VALUE_1); - - long o = (long) vh.getAndBitwiseOr(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseOr long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOr long value"); - } - - { - vh.set(array, i, VALUE_1); - - long o = (long) vh.getAndBitwiseOrAcquire(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseOrAcquire long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrAcquire long value"); - } - - { - vh.set(array, i, VALUE_1); - - long o = (long) vh.getAndBitwiseOrRelease(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseOrRelease long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrRelease long value"); - } - - // get and bitwise and - { - vh.set(array, i, VALUE_1); - - long o = (long) vh.getAndBitwiseAnd(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseAnd long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAnd long value"); - } - - { - vh.set(array, i, VALUE_1); - - long o = (long) vh.getAndBitwiseAndAcquire(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseAndAcquire long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndAcquire long value"); - } - - { - vh.set(array, i, VALUE_1); - - long o = (long) vh.getAndBitwiseAndRelease(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseAndRelease long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndRelease long value"); - } - - // get and bitwise xor - { - vh.set(array, i, VALUE_1); - - long o = (long) vh.getAndBitwiseXor(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseXor long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXor long value"); - } - - { - vh.set(array, i, VALUE_1); - - long o = (long) vh.getAndBitwiseXorAcquire(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseXorAcquire long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorAcquire long value"); - } - - { - vh.set(array, i, VALUE_1); - - long o = (long) vh.getAndBitwiseXorRelease(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseXorRelease long"); - long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorRelease long value"); - } - } } } @@ -1483,12 +1049,10 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; ByteBuffer array = bs.s; - int misalignmentAtZero = array.alignmentOffset(0, SIZE); - bs.fill((byte) 0xff); int length = array.limit() - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; + boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false; // Plain { @@ -1797,15 +1361,13 @@ static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; ByteBuffer array = bs.s; - int misalignmentAtZero = array.alignmentOffset(0, SIZE); - ByteBuffer bb = ByteBuffer.allocate(SIZE); bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); bs.fill(bb.putLong(0, VALUE_2).array()); int length = array.limit() - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; + boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false; long v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? rotateLeft(VALUE_2, (i % SIZE) << 3) diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java index d25d24cdeabd5..20751c9d76480 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java @@ -72,12 +72,12 @@ public List setupVarHandleSources(boolean same) { arrayType = int[].class; } VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(arrayType, bo), + MethodHandles.byteArrayViewVarHandle(arrayType, bo), false, endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(arrayType, bo), + MethodHandles.byteBufferViewVarHandle(arrayType, bo), true, endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -114,38 +114,48 @@ public void testIsAccessModeSupported(VarHandleSource vhs) { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); - - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); - - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); - - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); + if (vhs.supportsAtomicAccess) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); + } else { + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); + } + + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); + + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); + + + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); } @Test(dataProvider = "typesProvider") @@ -180,9 +190,6 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleSourceAccessTestCase( "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h), false)); - cases.add(new VarHandleSourceAccessTestCase( - "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h), - false)); } else { ByteBufferSource bbs = (ByteBufferSource) bav; @@ -207,9 +214,11 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleSourceAccessTestCase( "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h), false)); - cases.add(new VarHandleSourceAccessTestCase( - "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h), - false)); + if (bbs.s.isDirect()) { + cases.add(new VarHandleSourceAccessTestCase( + "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h), + false)); + } } } } @@ -243,33 +252,6 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) { checkNPE(() -> { vh.set(array, ci, VALUE_1); }); - - checkNPE(() -> { - short x = (short) vh.getVolatile(array, ci); - }); - - checkNPE(() -> { - short x = (short) vh.getAcquire(array, ci); - }); - - checkNPE(() -> { - short x = (short) vh.getOpaque(array, ci); - }); - - checkNPE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - - checkNPE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkNPE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); - - - } static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) { @@ -423,7 +405,7 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { }); } - if (readOnly) { + if (readOnly && array.isDirect()) { checkROBE(() -> { vh.setVolatile(array, ci, VALUE_1); }); @@ -435,6 +417,11 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { checkROBE(() -> { vh.setOpaque(array, ci, VALUE_1); }); + + + } + + if (array.isDirect()) { checkUOE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); @@ -478,7 +465,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { checkUOE(() -> { short o = (short) vh.getAndSetRelease(array, ci, VALUE_1); }); - checkUOE(() -> { short o = (short) vh.getAndAdd(array, ci, VALUE_1); }); @@ -490,7 +476,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { checkUOE(() -> { short o = (short) vh.getAndAddRelease(array, ci, VALUE_1); }); - checkUOE(() -> { short o = (short) vh.getAndBitwiseOr(array, ci, VALUE_1); }); @@ -526,8 +511,18 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { checkUOE(() -> { short o = (short) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); }); - } - else { + } else { + checkISE(() -> { + vh.setVolatile(array, ci, VALUE_1); + }); + + checkISE(() -> { + vh.setRelease(array, ci, VALUE_1); + }); + + checkISE(() -> { + vh.setOpaque(array, ci, VALUE_1); + }); checkUOE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); @@ -636,33 +631,6 @@ static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) t checkAIOOBE(() -> { vh.set(array, ci, VALUE_1); }); - - checkAIOOBE(() -> { - short x = (short) vh.getVolatile(array, ci); - }); - - checkAIOOBE(() -> { - short x = (short) vh.getAcquire(array, ci); - }); - - checkAIOOBE(() -> { - short x = (short) vh.getOpaque(array, ci); - }); - - checkAIOOBE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - - checkAIOOBE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkAIOOBE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); - - - } } @@ -686,74 +654,35 @@ static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) }); } - checkIOOBE(() -> { - short x = (short) vh.getVolatile(array, ci); - }); - - checkIOOBE(() -> { - short x = (short) vh.getAcquire(array, ci); - }); - - checkIOOBE(() -> { - short x = (short) vh.getOpaque(array, ci); - }); - - if (!readOnly) { - checkIOOBE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - + if (array.isDirect()) { checkIOOBE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); - - - - } - } - } - - static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable { - VarHandle vh = vhs.s; - byte[] array = bs.s; - - int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE); - - int length = array.length - SIZE + 1; - for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; - final int ci = i; - - if (!iAligned) { - checkISE(() -> { short x = (short) vh.getVolatile(array, ci); }); - checkISE(() -> { + checkIOOBE(() -> { short x = (short) vh.getAcquire(array, ci); }); - checkISE(() -> { + checkIOOBE(() -> { short x = (short) vh.getOpaque(array, ci); }); - checkISE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); + if (!readOnly) { + checkIOOBE(() -> { + vh.setVolatile(array, ci, VALUE_1); + }); - checkISE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + vh.setRelease(array, ci, VALUE_1); + }); + + checkIOOBE(() -> { + vh.setOpaque(array, ci, VALUE_1); + }); - checkISE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); + } } } } @@ -795,9 +724,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) checkISE(() -> { vh.setOpaque(array, ci, VALUE_1); }); - - - } } } @@ -807,45 +733,15 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; byte[] array = bs.s; - int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE); - bs.fill((byte) 0xff); int length = array.length - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; - // Plain { vh.set(array, i, VALUE_1); short x = (short) vh.get(array, i); assertEquals(x, VALUE_1, "get short value"); } - - - if (iAligned) { - // Volatile - { - vh.setVolatile(array, i, VALUE_2); - short x = (short) vh.getVolatile(array, i); - assertEquals(x, VALUE_2, "setVolatile short value"); - } - - // Lazy - { - vh.setRelease(array, i, VALUE_1); - short x = (short) vh.getAcquire(array, i); - assertEquals(x, VALUE_1, "setRelease short value"); - } - - // Opaque - { - vh.setOpaque(array, i, VALUE_2); - short x = (short) vh.getOpaque(array, i); - assertEquals(x, VALUE_2, "setOpaque short value"); - } - - - } } } @@ -854,12 +750,10 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; ByteBuffer array = bs.s; - int misalignmentAtZero = array.alignmentOffset(0, SIZE); - bs.fill((byte) 0xff); int length = array.limit() - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; + boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false; // Plain { @@ -899,15 +793,13 @@ static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) { VarHandle vh = vhs.s; ByteBuffer array = bs.s; - int misalignmentAtZero = array.alignmentOffset(0, SIZE); - ByteBuffer bb = ByteBuffer.allocate(SIZE); bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); bs.fill(bb.putShort(0, VALUE_2).array()); int length = array.limit() - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; + boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false; short v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? rotateLeft(VALUE_2, (i % SIZE) << 3) diff --git a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template index 84111ac5eb7c3..a79dbb3547eee 100644 --- a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template +++ b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template @@ -76,12 +76,12 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { #end[int] } VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(arrayType, bo), + MethodHandles.byteArrayViewVarHandle(arrayType, bo), false, endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(arrayType, bo), + MethodHandles.byteBufferViewVarHandle(arrayType, bo), true, endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -118,69 +118,91 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); + if (vhs.supportsAtomicAccess) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); + } else { + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); + } #if[CAS] - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); -#else[CAS] - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); + if (vhs.supportsAtomicAccess) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); + } else { +#end[CAS] + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE)); +#if[CAS] + } #end[CAS] #if[AtomicAdd] - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); -#else[AtomicAdd] - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); + if (vhs.supportsAtomicAccess) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); + } else { +#end[AtomicAdd] + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE)); +#if[AtomicAdd] + } #end[AtomicAdd] + #if[Bitwise] - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); -#else[Bitwise] - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); + if (vhs.supportsAtomicAccess) { + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); + } else { +#end[Bitwise] + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE)); +#if[Bitwise] + } #end[Bitwise] } @@ -216,9 +238,6 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { cases.add(new VarHandleSourceAccessTestCase( "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h), false)); - cases.add(new VarHandleSourceAccessTestCase( - "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h), - false)); } else { ByteBufferSource bbs = (ByteBufferSource) bav; @@ -243,9 +262,11 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { cases.add(new VarHandleSourceAccessTestCase( "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h), false)); - cases.add(new VarHandleSourceAccessTestCase( - "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h), - false)); + if (bbs.s.isDirect()) { + cases.add(new VarHandleSourceAccessTestCase( + "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h), + false)); + } } } } @@ -279,128 +300,6 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { checkNPE(() -> { vh.set(array, ci, VALUE_1); }); - - checkNPE(() -> { - $type$ x = ($type$) vh.getVolatile(array, ci); - }); - - checkNPE(() -> { - $type$ x = ($type$) vh.getAcquire(array, ci); - }); - - checkNPE(() -> { - $type$ x = ($type$) vh.getOpaque(array, ci); - }); - - checkNPE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - - checkNPE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkNPE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); - -#if[CAS] - checkNPE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); - }); - - checkNPE(() -> { - $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); - }); - - checkNPE(() -> { - $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); - }); - - checkNPE(() -> { - $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); - }); - - checkNPE(() -> { - boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); - }); - - checkNPE(() -> { - boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); - }); - - checkNPE(() -> { - boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); - }); - - checkNPE(() -> { - boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); - }); - - checkNPE(() -> { - $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1); - }); - - checkNPE(() -> { - $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1); - }); - - checkNPE(() -> { - $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1); - }); -#end[CAS] - -#if[AtomicAdd] - checkNPE(() -> { - $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1); - }); - - checkNPE(() -> { - $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1); - }); - - checkNPE(() -> { - $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1); - }); -#end[AtomicAdd] - -#if[Bitwise] - checkNPE(() -> { - $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1); - }); - - checkNPE(() -> { - $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); - }); - - checkNPE(() -> { - $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); - }); - - checkNPE(() -> { - $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1); - }); - - checkNPE(() -> { - $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); - }); - - checkNPE(() -> { - $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1); - }); - - checkNPE(() -> { - $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1); - }); - - checkNPE(() -> { - $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); - }); - - checkNPE(() -> { - $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); - }); -#end[Bitwise] } static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) { @@ -544,7 +443,6 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { byte[] array = bs.s; int ci = 1; -#if[!CAS] checkUOE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); @@ -588,9 +486,7 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { checkUOE(() -> { $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1); }); -#end[CAS] -#if[!AtomicAdd] checkUOE(() -> { $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1); }); @@ -602,9 +498,7 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { checkUOE(() -> { $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1); }); -#end[AtomicAdd] -#if[!Bitwise] checkUOE(() -> { $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1); }); @@ -640,7 +534,6 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { checkUOE(() -> { $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); }); -#end[Bitwise] } static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { @@ -655,7 +548,7 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { }); } - if (readOnly) { + if (readOnly && array.isDirect()) { checkROBE(() -> { vh.setVolatile(array, ci, VALUE_1); }); @@ -668,7 +561,6 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { vh.setOpaque(array, ci, VALUE_1); }); #if[CAS] - checkROBE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); @@ -712,51 +604,6 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { checkROBE(() -> { $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1); }); - -#else[CAS] - checkUOE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); - }); - - checkUOE(() -> { - $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); - }); - - checkUOE(() -> { - $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); - }); - - checkUOE(() -> { - $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); - }); - - checkUOE(() -> { - boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); - }); - - checkUOE(() -> { - boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); - }); - - checkUOE(() -> { - boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); - }); - - checkUOE(() -> { - boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); - }); - - checkUOE(() -> { - $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1); - }); - - checkUOE(() -> { - $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1); - }); - - checkUOE(() -> { - $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1); - }); #end[CAS] #if[AtomicAdd] @@ -771,18 +618,6 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { checkROBE(() -> { $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1); }); -#else[AtomicAdd] - checkUOE(() -> { - $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1); - }); - - checkUOE(() -> { - $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1); - }); - - checkUOE(() -> { - $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1); - }); #end[AtomicAdd] #if[Bitwise] @@ -821,45 +656,10 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { checkROBE(() -> { $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); }); -#else[Bitwise] - checkUOE(() -> { - $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1); - }); - - checkUOE(() -> { - $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); - }); - - checkUOE(() -> { - $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); - }); - - checkUOE(() -> { - $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1); - }); - - checkUOE(() -> { - $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); - }); - - checkUOE(() -> { - $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1); - }); - - checkUOE(() -> { - $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1); - }); - - checkUOE(() -> { - $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); - }); - - checkUOE(() -> { - $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); - }); #end[Bitwise] } - else { + + if (array.isDirect()) { #if[!CAS] checkUOE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); @@ -955,148 +755,224 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); }); #end[Bitwise] - } - } - + } else { + checkISE(() -> { + vh.setVolatile(array, ci, VALUE_1); + }); - static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable { - VarHandle vh = vhs.s; - byte[] array = bs.s; + checkISE(() -> { + vh.setRelease(array, ci, VALUE_1); + }); - int length = array.length - SIZE + 1; - for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) { - final int ci = i; + checkISE(() -> { + vh.setOpaque(array, ci, VALUE_1); + }); +#if[!CAS] + checkUOE(() -> { + boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); + }); - checkAIOOBE(() -> { - $type$ x = ($type$) vh.get(array, ci); + checkUOE(() -> { + $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); }); - checkAIOOBE(() -> { - vh.set(array, ci, VALUE_1); + checkUOE(() -> { + $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); }); - checkAIOOBE(() -> { - $type$ x = ($type$) vh.getVolatile(array, ci); + checkUOE(() -> { + $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); }); - checkAIOOBE(() -> { - $type$ x = ($type$) vh.getAcquire(array, ci); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { - $type$ x = ($type$) vh.getOpaque(array, ci); + checkUOE(() -> { + boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { - vh.setVolatile(array, ci, VALUE_1); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { - vh.setRelease(array, ci, VALUE_1); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { - vh.setOpaque(array, ci, VALUE_1); + checkUOE(() -> { + $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1); }); -#if[CAS] - checkAIOOBE(() -> { + checkUOE(() -> { + $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1); + }); + + checkUOE(() -> { + $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1); + }); +#else[CAS] + checkISE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { + checkISE(() -> { $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { + checkISE(() -> { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { + checkISE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { + checkISE(() -> { boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); }); - checkAIOOBE(() -> { + checkISE(() -> { $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1); }); #end[CAS] +#if[!AtomicAdd] + checkUOE(() -> { + $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1); + }); -#if[AtomicAdd] - checkAIOOBE(() -> { + checkUOE(() -> { + $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1); + }); + + checkUOE(() -> { + $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1); + }); +#else[AtomicAdd] + checkISE(() -> { $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1); }); #end[AtomicAdd] +#if[!Bitwise] + checkUOE(() -> { + $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1); + }); -#if[Bitwise] - checkAIOOBE(() -> { + checkUOE(() -> { + $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); + }); + + checkUOE(() -> { + $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); + }); + + checkUOE(() -> { + $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1); + }); + + checkUOE(() -> { + $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); + }); + + checkUOE(() -> { + $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1); + }); + + checkUOE(() -> { + $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1); + }); + + checkUOE(() -> { + $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); + }); + + checkUOE(() -> { + $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); + }); +#else[Bitwise] + checkISE(() -> { $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); }); - checkAIOOBE(() -> { + checkISE(() -> { $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); }); #end[Bitwise] + } + } + + + static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable { + VarHandle vh = vhs.s; + byte[] array = bs.s; + + int length = array.length - SIZE + 1; + for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) { + final int ci = i; + + checkAIOOBE(() -> { + $type$ x = ($type$) vh.get(array, ci); + }); + checkAIOOBE(() -> { + vh.set(array, ci, VALUE_1); + }); } } @@ -1120,726 +996,283 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { }); } - checkIOOBE(() -> { - $type$ x = ($type$) vh.getVolatile(array, ci); - }); - - checkIOOBE(() -> { - $type$ x = ($type$) vh.getAcquire(array, ci); - }); - - checkIOOBE(() -> { - $type$ x = ($type$) vh.getOpaque(array, ci); - }); - - if (!readOnly) { + if (array.isDirect()) { checkIOOBE(() -> { - vh.setVolatile(array, ci, VALUE_1); + $type$ x = ($type$) vh.getVolatile(array, ci); }); checkIOOBE(() -> { - vh.setRelease(array, ci, VALUE_1); + $type$ x = ($type$) vh.getAcquire(array, ci); }); checkIOOBE(() -> { - vh.setOpaque(array, ci, VALUE_1); + $type$ x = ($type$) vh.getOpaque(array, ci); }); + if (!readOnly) { + checkIOOBE(() -> { + vh.setVolatile(array, ci, VALUE_1); + }); + + checkIOOBE(() -> { + vh.setRelease(array, ci, VALUE_1); + }); + + checkIOOBE(() -> { + vh.setOpaque(array, ci, VALUE_1); + }); + #if[CAS] - checkIOOBE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); - }); + checkIOOBE(() -> { + $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); + }); - checkIOOBE(() -> { - $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); - }); + checkIOOBE(() -> { + $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); + }); - checkIOOBE(() -> { - $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); - }); + checkIOOBE(() -> { + $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); - }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); + }); - checkIOOBE(() -> { - $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1); + }); #end[CAS] #if[AtomicAdd] - checkIOOBE(() -> { - $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1); + }); #end[AtomicAdd] #if[Bitwise] - checkIOOBE(() -> { - $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1); - }); - - checkIOOBE(() -> { - $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); - }); + checkIOOBE(() -> { + $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); + }); - checkIOOBE(() -> { - $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); - }); -#end[Bitwise] - } - } - } + checkIOOBE(() -> { + $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); + }); - static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable { - VarHandle vh = vhs.s; - byte[] array = bs.s; + checkIOOBE(() -> { + $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1); + }); - int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE); + checkIOOBE(() -> { + $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); + }); - int length = array.length - SIZE + 1; - for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; - final int ci = i; - - if (!iAligned) { - checkISE(() -> { - $type$ x = ($type$) vh.getVolatile(array, ci); - }); - - checkISE(() -> { - $type$ x = ($type$) vh.getAcquire(array, ci); - }); - - checkISE(() -> { - $type$ x = ($type$) vh.getOpaque(array, ci); - }); - - checkISE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - - checkISE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkISE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); -#if[CAS] - - checkISE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); - }); - - checkISE(() -> { - $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); - }); - - checkISE(() -> { - $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1); - }); -#end[CAS] - -#if[AtomicAdd] - checkISE(() -> { - $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1); - }); -#end[AtomicAdd] - -#if[Bitwise] - checkISE(() -> { - $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); - }); -#end[Bitwise] - } - } - } - - static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable { - VarHandle vh = vhs.s; - ByteBuffer array = bs.s; - - boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes); - int misalignmentAtZero = array.alignmentOffset(0, SIZE); - - int length = array.limit() - SIZE + 1; - for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; - final int ci = i; - - if (!iAligned) { - checkISE(() -> { - $type$ x = ($type$) vh.getVolatile(array, ci); - }); - - checkISE(() -> { - $type$ x = ($type$) vh.getAcquire(array, ci); - }); - - checkISE(() -> { - $type$ x = ($type$) vh.getOpaque(array, ci); - }); - - if (!readOnly) { - checkISE(() -> { - vh.setVolatile(array, ci, VALUE_1); - }); - - checkISE(() -> { - vh.setRelease(array, ci, VALUE_1); - }); - - checkISE(() -> { - vh.setOpaque(array, ci, VALUE_1); - }); - -#if[CAS] - checkISE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); - }); - - checkISE(() -> { - $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); - }); - - checkISE(() -> { - $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1); - }); -#end[CAS] - -#if[AtomicAdd] - checkISE(() -> { - $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1); - }); -#end[AtomicAdd] - -#if[Bitwise] - checkISE(() -> { - $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); - }); - - checkISE(() -> { + checkIOOBE(() -> { $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1); }); - checkISE(() -> { - $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); - }); - - checkISE(() -> { - $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); - }); -#end[Bitwise] - } - } - } - } - - static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { - VarHandle vh = vhs.s; - byte[] array = bs.s; - - int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE); - - bs.fill((byte) 0xff); - int length = array.length - SIZE + 1; - for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; - - // Plain - { - vh.set(array, i, VALUE_1); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1, "get $type$ value"); - } - - - if (iAligned) { - // Volatile - { - vh.setVolatile(array, i, VALUE_2); - $type$ x = ($type$) vh.getVolatile(array, i); - assertEquals(x, VALUE_2, "setVolatile $type$ value"); - } - - // Lazy - { - vh.setRelease(array, i, VALUE_1); - $type$ x = ($type$) vh.getAcquire(array, i); - assertEquals(x, VALUE_1, "setRelease $type$ value"); - } - - // Opaque - { - vh.setOpaque(array, i, VALUE_2); - $type$ x = ($type$) vh.getOpaque(array, i); - assertEquals(x, VALUE_2, "setOpaque $type$ value"); - } -#if[CAS] - - vh.set(array, i, VALUE_1); - - // Compare - { - boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "success compareAndSet $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_2, "success compareAndSet $type$ value"); - } - - { - boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3); - assertEquals(r, false, "failing compareAndSet $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_2, "failing compareAndSet $type$ value"); - } - - { - $type$ r = ($type$) vh.compareAndExchange(array, i, VALUE_2, VALUE_1); - assertEquals(r, VALUE_2, "success compareAndExchange $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1, "success compareAndExchange $type$ value"); - } - - { - $type$ r = ($type$) vh.compareAndExchange(array, i, VALUE_2, VALUE_3); - assertEquals(r, VALUE_1, "failing compareAndExchange $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1, "failing compareAndExchange $type$ value"); - } - - { - $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2); - assertEquals(r, VALUE_1, "success compareAndExchangeAcquire $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_2, "success compareAndExchangeAcquire $type$ value"); - } - - { - $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3); - assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire $type$ value"); - } - - { - $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1); - assertEquals(r, VALUE_2, "success compareAndExchangeRelease $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1, "success compareAndExchangeRelease $type$ value"); - } - - { - $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3); - assertEquals(r, VALUE_1, "failing compareAndExchangeRelease $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1, "failing compareAndExchangeRelease $type$ value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSetPlain $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_2, "success weakCompareAndSetPlain $type$ value"); - } - - { - boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSetPlain $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain $type$ value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSetAcquire $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire $type$"); - } - - { - boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSetAcquire $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire $type$ value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSetRelease $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_2, "success weakCompareAndSetRelease $type$"); - } - - { - boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSetRelease $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease $type$ value"); - } - - { - boolean success = false; - for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1); - if (!success) weakDelay(); - } - assertEquals(success, true, "success weakCompareAndSet $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1, "success weakCompareAndSet $type$"); - } - - { - boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3); - assertEquals(success, false, "failing weakCompareAndSet $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1, "failing weakCompareAndSet $type$ value"); - } + checkIOOBE(() -> { + $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1); + }); - // Compare set and get - { - vh.set(array, i, VALUE_1); + checkIOOBE(() -> { + $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); + }); - $type$ o = ($type$) vh.getAndSet(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndSet $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_2, "getAndSet $type$ value"); + checkIOOBE(() -> { + $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); + }); +#end[Bitwise] } + } + } + } - { - vh.set(array, i, VALUE_1); + static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable { + VarHandle vh = vhs.s; + ByteBuffer array = bs.s; - $type$ o = ($type$) vh.getAndSetAcquire(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndSetAcquire $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_2, "getAndSetAcquire $type$ value"); - } + boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes); + int misalignmentAtZero = array.alignmentOffset(0, SIZE); - { - vh.set(array, i, VALUE_1); + int length = array.limit() - SIZE + 1; + for (int i = 0; i < length; i++) { + boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; + final int ci = i; - $type$ o = ($type$) vh.getAndSetRelease(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndSetRelease $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_2, "getAndSetRelease $type$ value"); - } -#end[CAS] + if (!iAligned) { + checkISE(() -> { + $type$ x = ($type$) vh.getVolatile(array, ci); + }); -#if[AtomicAdd] - // get and add, add and get - { - vh.set(array, i, VALUE_1); + checkISE(() -> { + $type$ x = ($type$) vh.getAcquire(array, ci); + }); - $type$ o = ($type$) vh.getAndAdd(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndAdd $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1 + VALUE_2, "getAndAdd $type$ value"); - } + checkISE(() -> { + $type$ x = ($type$) vh.getOpaque(array, ci); + }); - { - vh.set(array, i, VALUE_1); + if (!readOnly) { + checkISE(() -> { + vh.setVolatile(array, ci, VALUE_1); + }); - $type$ o = ($type$) vh.getAndAddAcquire(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndAddAcquire $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1 + VALUE_2, "getAndAddAcquire $type$ value"); - } + checkISE(() -> { + vh.setRelease(array, ci, VALUE_1); + }); - { - vh.set(array, i, VALUE_1); + checkISE(() -> { + vh.setOpaque(array, ci, VALUE_1); + }); +#if[CAS] + checkISE(() -> { + boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); + }); - $type$ o = ($type$) vh.getAndAddRelease(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndAddRelease $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1 + VALUE_2, "getAndAddRelease $type$ value"); - } -#end[AtomicAdd] + checkISE(() -> { + $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1); + }); -#if[Bitwise] - // get and bitwise or - { - vh.set(array, i, VALUE_1); + checkISE(() -> { + $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); + }); - $type$ o = ($type$) vh.getAndBitwiseOr(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseOr $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOr $type$ value"); - } + checkISE(() -> { + $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); + }); - { - vh.set(array, i, VALUE_1); + checkISE(() -> { + boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2); + }); - $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseOrAcquire $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrAcquire $type$ value"); - } + checkISE(() -> { + boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); + }); - { - vh.set(array, i, VALUE_1); + checkISE(() -> { + boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); + }); - $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseOrRelease $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrRelease $type$ value"); - } + checkISE(() -> { + boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); + }); - // get and bitwise and - { - vh.set(array, i, VALUE_1); + checkISE(() -> { + $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1); + }); - $type$ o = ($type$) vh.getAndBitwiseAnd(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseAnd $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAnd $type$ value"); - } + checkISE(() -> { + $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1); + }); - { - vh.set(array, i, VALUE_1); + checkISE(() -> { + $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1); + }); +#end[CAS] +#if[AtomicAdd] + checkISE(() -> { + $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1); + }); - $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseAndAcquire $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndAcquire $type$ value"); - } + checkISE(() -> { + $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1); + }); - { - vh.set(array, i, VALUE_1); + checkISE(() -> { + $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1); + }); +#end[AtomicAdd] +#if[Bitwise] + checkISE(() -> { + $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1); + }); - $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseAndRelease $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndRelease $type$ value"); - } + checkISE(() -> { + $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1); + }); - // get and bitwise xor - { - vh.set(array, i, VALUE_1); + checkISE(() -> { + $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1); + }); - $type$ o = ($type$) vh.getAndBitwiseXor(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseXor $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXor $type$ value"); - } + checkISE(() -> { + $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1); + }); - { - vh.set(array, i, VALUE_1); + checkISE(() -> { + $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1); + }); - $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseXorAcquire $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorAcquire $type$ value"); - } + checkISE(() -> { + $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1); + }); - { - vh.set(array, i, VALUE_1); + checkISE(() -> { + $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1); + }); - $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, i, VALUE_2); - assertEquals(o, VALUE_1, "getAndBitwiseXorRelease $type$"); - $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorRelease $type$ value"); - } + checkISE(() -> { + $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1); + }); + + checkISE(() -> { + $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1); + }); #end[Bitwise] + } + } + } + } + + static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { + VarHandle vh = vhs.s; + byte[] array = bs.s; + + bs.fill((byte) 0xff); + int length = array.length - SIZE + 1; + for (int i = 0; i < length; i++) { + // Plain + { + vh.set(array, i, VALUE_1); + $type$ x = ($type$) vh.get(array, i); + assertEquals(x, VALUE_1, "get $type$ value"); } } } @@ -1849,12 +1282,10 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { VarHandle vh = vhs.s; ByteBuffer array = bs.s; - int misalignmentAtZero = array.alignmentOffset(0, SIZE); - bs.fill((byte) 0xff); int length = array.limit() - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; + boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false; // Plain { @@ -2169,15 +1600,13 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { VarHandle vh = vhs.s; ByteBuffer array = bs.s; - int misalignmentAtZero = array.alignmentOffset(0, SIZE); - ByteBuffer bb = ByteBuffer.allocate(SIZE); bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); bs.fill(bb.put$Type$(0, VALUE_2).array()); int length = array.limit() - SIZE + 1; for (int i = 0; i < length; i++) { - boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; + boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false; $type$ v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? rotateLeft(VALUE_2, (i % SIZE) << 3) diff --git a/test/jdk/java/nio/Buffer/Basic-X.java.template b/test/jdk/java/nio/Buffer/Basic-X.java.template index d26d3e3e6222b..4cd61ea8043cf 100644 --- a/test/jdk/java/nio/Buffer/Basic-X.java.template +++ b/test/jdk/java/nio/Buffer/Basic-X.java.template @@ -384,7 +384,7 @@ public class Basic$Type$ // unit size not a power of two catchIllegalArgument(b, () -> b.alignmentOffset(0, _us)); } else { - if (direct || us <= 8) { + if (direct || us == 1) { b.alignmentOffset(0, us); } else { // unit size > 8 with non-direct buffer @@ -394,12 +394,11 @@ public class Basic$Type$ } } - // Probe for long misalignment at index zero for a newly created buffer - ByteBuffer empty = - direct ? ByteBuffer.allocateDirect(0) : ByteBuffer.allocate(0); - int longMisalignmentAtZero = empty.alignmentOffset(0, 8); - if (direct) { + // Probe for long misalignment at index zero for a newly created buffer + ByteBuffer empty = ByteBuffer.allocateDirect(0); + int longMisalignmentAtZero = empty.alignmentOffset(0, 8); + // Freshly created direct byte buffers should be aligned at index 0 // for ref and primitive values (see Unsafe.allocateMemory) if (longMisalignmentAtZero != 0) { @@ -407,78 +406,67 @@ public class Basic$Type$ + " for ref and primitive values " + longMisalignmentAtZero); } - } else { - // For heap byte buffers misalignment may occur on 32-bit systems - // where Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 == 4 and not 0 - // Note the GC will preserve alignment of the base address of the - // array - if (jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 - != longMisalignmentAtZero) { - fail("Heap byte buffer misaligned at index 0" - + " for ref and primitive values " - + longMisalignmentAtZero); - } - } - // Ensure test buffer is correctly aligned at index 0 - if (b.alignmentOffset(0, 8) != longMisalignmentAtZero) - fail("Test input buffer not correctly aligned at index 0", b); + // Ensure test buffer is correctly aligned at index 0 + if (b.alignmentOffset(0, 8) != longMisalignmentAtZero) + fail("Test input buffer not correctly aligned at index 0", b); - // Test misalignment values - for (int us : new int[]{1, 2, 4, 8}) { - for (int i = 0; i < us * 2; i++) { - int am = b.alignmentOffset(i, us); - int expectedAm = (longMisalignmentAtZero + i) % us; + // Test misalignment values + for (int us : new int[]{1, 2, 4, 8}) { + for (int i = 0; i < us * 2; i++) { + int am = b.alignmentOffset(i, us); + int expectedAm = (longMisalignmentAtZero + i) % us; - if (am != expectedAm) { - String f = "b.alignmentOffset(%d, %d) == %d incorrect, expected %d"; - fail(String.format(f, i, us, am, expectedAm)); + if (am != expectedAm) { + String f = "b.alignmentOffset(%d, %d) == %d incorrect, expected %d"; + fail(String.format(f, i, us, am, expectedAm)); + } } } - } - // Created aligned slice to test against - int ap = 8 - longMisalignmentAtZero; - int al = b.limit() - b.alignmentOffset(b.limit(), 8); - ByteBuffer ab = b.position(ap).limit(al). - slice(); - if (ab.limit() == 0) { - fail("Test input buffer not sufficiently sized to cover" + - " an aligned region for all values", b); - } - if (ab.alignmentOffset(0, 8) != 0) - fail("Aligned test input buffer not correctly aligned at index 0", ab); - - for (int us : new int[]{1, 2, 4, 8}) { - for (int p = 1; p < 16; p++) { - int l = ab.limit() - p; - - ByteBuffer as = ab.slice().position(p).limit(l). - alignedSlice(us); - - ck(as, 0, as.position()); - ck(as, as.capacity(), as.limit()); - if (b.isDirect() != as.isDirect()) - fail("Lost direction", as); - if (b.isReadOnly() != as.isReadOnly()) - fail("Lost read-only", as); - - if (as.alignmentOffset(0, us) != 0) - fail("Buffer not correctly aligned at index 0", as); - - if (as.alignmentOffset(as.limit(), us) != 0) - fail("Buffer not correctly aligned at limit", as); - - int p_mod = ab.alignmentOffset(p, us); - int l_mod = ab.alignmentOffset(l, us); - // Round up position - p = (p_mod > 0) ? p + (us - p_mod) : p; - // Round down limit - l = l - l_mod; - - int ec = l - p; - if (as.limit() != ec) { - fail("Buffer capacity incorrect, expected: " + ec, as); + // Created aligned slice to test against + int ap = 8 - longMisalignmentAtZero; + int al = b.limit() - b.alignmentOffset(b.limit(), 8); + ByteBuffer ab = b.position(ap).limit(al). + slice(); + if (ab.limit() == 0) { + fail("Test input buffer not sufficiently sized to cover" + + " an aligned region for all values", b); + } + if (ab.alignmentOffset(0, 8) != 0) + fail("Aligned test input buffer not correctly aligned at index 0", ab); + + for (int us : new int[]{1, 2, 4, 8}) { + for (int p = 1; p < 16; p++) { + int l = ab.limit() - p; + + ByteBuffer as = ab.slice().position(p).limit(l). + alignedSlice(us); + + ck(as, 0, as.position()); + ck(as, as.capacity(), as.limit()); + if (b.isDirect() != as.isDirect()) + fail("Lost direction", as); + if (b.isReadOnly() != as.isReadOnly()) + fail("Lost read-only", as); + + if (as.alignmentOffset(0, us) != 0) + fail("Buffer not correctly aligned at index 0", as); + + if (as.alignmentOffset(as.limit(), us) != 0) + fail("Buffer not correctly aligned at limit", as); + + int p_mod = ab.alignmentOffset(p, us); + int l_mod = ab.alignmentOffset(l, us); + // Round up position + p = (p_mod > 0) ? p + (us - p_mod) : p; + // Round down limit + l = l - l_mod; + + int ec = l - p; + if (as.limit() != ec) { + fail("Buffer capacity incorrect, expected: " + ec, as); + } } } } diff --git a/test/jdk/java/nio/Buffer/BasicByte.java b/test/jdk/java/nio/Buffer/BasicByte.java index b3db0b0c1053b..05bf8e523bbea 100644 --- a/test/jdk/java/nio/Buffer/BasicByte.java +++ b/test/jdk/java/nio/Buffer/BasicByte.java @@ -384,7 +384,7 @@ private static void testAlign(final ByteBuffer b, boolean direct) { // unit size not a power of two catchIllegalArgument(b, () -> b.alignmentOffset(0, _us)); } else { - if (direct || us <= 8) { + if (direct || us == 1) { b.alignmentOffset(0, us); } else { // unit size > 8 with non-direct buffer @@ -394,12 +394,11 @@ private static void testAlign(final ByteBuffer b, boolean direct) { } } - // Probe for long misalignment at index zero for a newly created buffer - ByteBuffer empty = - direct ? ByteBuffer.allocateDirect(0) : ByteBuffer.allocate(0); - int longMisalignmentAtZero = empty.alignmentOffset(0, 8); - if (direct) { + // Probe for long misalignment at index zero for a newly created buffer + ByteBuffer empty = ByteBuffer.allocateDirect(0); + int longMisalignmentAtZero = empty.alignmentOffset(0, 8); + // Freshly created direct byte buffers should be aligned at index 0 // for ref and primitive values (see Unsafe.allocateMemory) if (longMisalignmentAtZero != 0) { @@ -407,78 +406,67 @@ private static void testAlign(final ByteBuffer b, boolean direct) { + " for ref and primitive values " + longMisalignmentAtZero); } - } else { - // For heap byte buffers misalignment may occur on 32-bit systems - // where Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 == 4 and not 0 - // Note the GC will preserve alignment of the base address of the - // array - if (jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 - != longMisalignmentAtZero) { - fail("Heap byte buffer misaligned at index 0" - + " for ref and primitive values " - + longMisalignmentAtZero); - } - } - // Ensure test buffer is correctly aligned at index 0 - if (b.alignmentOffset(0, 8) != longMisalignmentAtZero) - fail("Test input buffer not correctly aligned at index 0", b); + // Ensure test buffer is correctly aligned at index 0 + if (b.alignmentOffset(0, 8) != longMisalignmentAtZero) + fail("Test input buffer not correctly aligned at index 0", b); - // Test misalignment values - for (int us : new int[]{1, 2, 4, 8}) { - for (int i = 0; i < us * 2; i++) { - int am = b.alignmentOffset(i, us); - int expectedAm = (longMisalignmentAtZero + i) % us; + // Test misalignment values + for (int us : new int[]{1, 2, 4, 8}) { + for (int i = 0; i < us * 2; i++) { + int am = b.alignmentOffset(i, us); + int expectedAm = (longMisalignmentAtZero + i) % us; - if (am != expectedAm) { - String f = "b.alignmentOffset(%d, %d) == %d incorrect, expected %d"; - fail(String.format(f, i, us, am, expectedAm)); + if (am != expectedAm) { + String f = "b.alignmentOffset(%d, %d) == %d incorrect, expected %d"; + fail(String.format(f, i, us, am, expectedAm)); + } } } - } - // Created aligned slice to test against - int ap = 8 - longMisalignmentAtZero; - int al = b.limit() - b.alignmentOffset(b.limit(), 8); - ByteBuffer ab = b.position(ap).limit(al). - slice(); - if (ab.limit() == 0) { - fail("Test input buffer not sufficiently sized to cover" + - " an aligned region for all values", b); - } - if (ab.alignmentOffset(0, 8) != 0) - fail("Aligned test input buffer not correctly aligned at index 0", ab); - - for (int us : new int[]{1, 2, 4, 8}) { - for (int p = 1; p < 16; p++) { - int l = ab.limit() - p; - - ByteBuffer as = ab.slice().position(p).limit(l). - alignedSlice(us); - - ck(as, 0, as.position()); - ck(as, as.capacity(), as.limit()); - if (b.isDirect() != as.isDirect()) - fail("Lost direction", as); - if (b.isReadOnly() != as.isReadOnly()) - fail("Lost read-only", as); - - if (as.alignmentOffset(0, us) != 0) - fail("Buffer not correctly aligned at index 0", as); - - if (as.alignmentOffset(as.limit(), us) != 0) - fail("Buffer not correctly aligned at limit", as); - - int p_mod = ab.alignmentOffset(p, us); - int l_mod = ab.alignmentOffset(l, us); - // Round up position - p = (p_mod > 0) ? p + (us - p_mod) : p; - // Round down limit - l = l - l_mod; - - int ec = l - p; - if (as.limit() != ec) { - fail("Buffer capacity incorrect, expected: " + ec, as); + // Created aligned slice to test against + int ap = 8 - longMisalignmentAtZero; + int al = b.limit() - b.alignmentOffset(b.limit(), 8); + ByteBuffer ab = b.position(ap).limit(al). + slice(); + if (ab.limit() == 0) { + fail("Test input buffer not sufficiently sized to cover" + + " an aligned region for all values", b); + } + if (ab.alignmentOffset(0, 8) != 0) + fail("Aligned test input buffer not correctly aligned at index 0", ab); + + for (int us : new int[]{1, 2, 4, 8}) { + for (int p = 1; p < 16; p++) { + int l = ab.limit() - p; + + ByteBuffer as = ab.slice().position(p).limit(l). + alignedSlice(us); + + ck(as, 0, as.position()); + ck(as, as.capacity(), as.limit()); + if (b.isDirect() != as.isDirect()) + fail("Lost direction", as); + if (b.isReadOnly() != as.isReadOnly()) + fail("Lost read-only", as); + + if (as.alignmentOffset(0, us) != 0) + fail("Buffer not correctly aligned at index 0", as); + + if (as.alignmentOffset(as.limit(), us) != 0) + fail("Buffer not correctly aligned at limit", as); + + int p_mod = ab.alignmentOffset(p, us); + int l_mod = ab.alignmentOffset(l, us); + // Round up position + p = (p_mod > 0) ? p + (us - p_mod) : p; + // Round down limit + l = l - l_mod; + + int ec = l - p; + if (as.limit() != ec) { + fail("Buffer capacity incorrect, expected: " + ec, as); + } } } } diff --git a/test/jdk/java/nio/Buffer/BasicChar.java b/test/jdk/java/nio/Buffer/BasicChar.java index c1358847ad25c..8d6cfd1eecf91 100644 --- a/test/jdk/java/nio/Buffer/BasicChar.java +++ b/test/jdk/java/nio/Buffer/BasicChar.java @@ -527,18 +527,6 @@ private static void checkSlice(CharBuffer b, CharBuffer slice) { - - - - - - - - - - - - diff --git a/test/jdk/java/nio/Buffer/BasicDouble.java b/test/jdk/java/nio/Buffer/BasicDouble.java index d74fe3db0b7aa..4b1cde85a0843 100644 --- a/test/jdk/java/nio/Buffer/BasicDouble.java +++ b/test/jdk/java/nio/Buffer/BasicDouble.java @@ -527,18 +527,6 @@ private static void checkSlice(DoubleBuffer b, DoubleBuffer slice) { - - - - - - - - - - - - diff --git a/test/jdk/java/nio/Buffer/BasicFloat.java b/test/jdk/java/nio/Buffer/BasicFloat.java index e60fb7b203c54..654dfe72fbe6d 100644 --- a/test/jdk/java/nio/Buffer/BasicFloat.java +++ b/test/jdk/java/nio/Buffer/BasicFloat.java @@ -527,18 +527,6 @@ private static void checkSlice(FloatBuffer b, FloatBuffer slice) { - - - - - - - - - - - - diff --git a/test/jdk/java/nio/Buffer/BasicInt.java b/test/jdk/java/nio/Buffer/BasicInt.java index 2d0f591e892aa..4e1b8a237b4d7 100644 --- a/test/jdk/java/nio/Buffer/BasicInt.java +++ b/test/jdk/java/nio/Buffer/BasicInt.java @@ -527,18 +527,6 @@ private static void checkSlice(IntBuffer b, IntBuffer slice) { - - - - - - - - - - - - diff --git a/test/jdk/java/nio/Buffer/BasicLong.java b/test/jdk/java/nio/Buffer/BasicLong.java index 04807c3461bba..02b30e879b6e7 100644 --- a/test/jdk/java/nio/Buffer/BasicLong.java +++ b/test/jdk/java/nio/Buffer/BasicLong.java @@ -527,18 +527,6 @@ private static void checkSlice(LongBuffer b, LongBuffer slice) { - - - - - - - - - - - - diff --git a/test/jdk/java/nio/Buffer/BasicShort.java b/test/jdk/java/nio/Buffer/BasicShort.java index bbf1b7a7fa4ea..22c6dd4b59d8a 100644 --- a/test/jdk/java/nio/Buffer/BasicShort.java +++ b/test/jdk/java/nio/Buffer/BasicShort.java @@ -527,18 +527,6 @@ private static void checkSlice(ShortBuffer b, ShortBuffer slice) { - - - - - - - - - - - - diff --git a/test/jdk/java/nio/channels/FileChannel/Transfer.java b/test/jdk/java/nio/channels/FileChannel/Transfer.java index 453230fff9598..51adba60b06df 100644 --- a/test/jdk/java/nio/channels/FileChannel/Transfer.java +++ b/test/jdk/java/nio/channels/FileChannel/Transfer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* @test - * @bug 4434723 4482726 4559072 4795550 5081340 5103988 6984545 + * @bug 4434723 4482726 4559072 4795550 5081340 5103988 6984545 8325382 * @summary Test FileChannel.transferFrom and transferTo (use -Dseed=X to set PRNG seed) * @library .. * @library /test/lib @@ -48,11 +48,13 @@ import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.channels.spi.SelectorProvider; +import java.nio.file.Files; import java.util.Random; import java.util.concurrent.TimeUnit; import jdk.test.lib.RandomFactory; +import org.testng.Assert; import org.testng.annotations.Test; public class Transfer { @@ -158,6 +160,33 @@ public void testReadableByteChannel() throws Exception { } } + @Test + public void transferToNoThrow() throws IOException { // for bug 8325382 + File source = File.createTempFile("before", "after"); + source.deleteOnExit(); + + CharSequence csq = "Reality is greater than the sum of its parts."; + Files.writeString(source.toPath(), csq); + final long length = csq.length(); + Assert.assertEquals(source.length(), length); + + File target = File.createTempFile("before", "after"); + target.deleteOnExit(); + + try (FileInputStream in = new FileInputStream(source); + FileOutputStream out = new FileOutputStream(target); + FileChannel chSource = in.getChannel(); + FileChannel chTarget = out.getChannel()) { + // The count of bytes requested to transfer must exceed + // FileChannelImpl.MAPPED_TRANSFER_THRESHOLD which is + // currently 16384 + long n = chSource.transferTo(length, 16385, chTarget); + + // At the end of the input so no bytes should be transferred + Assert.assertEquals(n, 0); + } + } + @Test public void xferTest02() throws Exception { // for bug 4482726 byte[] srcData = new byte[5000]; diff --git a/test/jdk/java/nio/channels/unixdomain/SocketOptions.java b/test/jdk/java/nio/channels/unixdomain/SocketOptions.java index f275b519394ba..95188ebcef1e4 100644 --- a/test/jdk/java/nio/channels/unixdomain/SocketOptions.java +++ b/test/jdk/java/nio/channels/unixdomain/SocketOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,7 +72,8 @@ static void testPeerCred() throws Exception { // Check returned user name if (!s1.equals(s2)) { - throw new RuntimeException("wrong username"); + throw new RuntimeException("wrong username, actual " + s1 + + " but expected value from property user.name is " + s2); } // Try setting the option: Read only diff --git a/test/jdk/java/nio/file/Files/ReadWriteString.java b/test/jdk/java/nio/file/Files/ReadWriteString.java index 885cbb771dc26..8b5241fa1cf05 100644 --- a/test/jdk/java/nio/file/Files/ReadWriteString.java +++ b/test/jdk/java/nio/file/Files/ReadWriteString.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,8 +29,13 @@ import java.nio.charset.UnmappableCharacterException; import static java.nio.charset.StandardCharsets.ISO_8859_1; import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_16; import static java.nio.charset.StandardCharsets.UTF_8; +import static java.nio.charset.StandardCharsets.UTF_16; +import static java.nio.charset.StandardCharsets.UTF_16BE; +import static java.nio.charset.StandardCharsets.UTF_16LE; +import static java.nio.charset.StandardCharsets.UTF_32; +import static java.nio.charset.StandardCharsets.UTF_32BE; +import static java.nio.charset.StandardCharsets.UTF_32LE; import java.nio.file.Files; import java.nio.file.OpenOption; import java.nio.file.Path; @@ -40,15 +45,15 @@ import java.util.Arrays; import java.util.Random; import java.util.concurrent.Callable; +import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; -import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /* @test - * @bug 8201276 8205058 8209576 8287541 8288589 + * @bug 8201276 8205058 8209576 8287541 8288589 8325590 * @build ReadWriteString PassThroughFileSystem * @run testng ReadWriteString * @summary Unit test for methods for Files readString and write methods. @@ -61,6 +66,7 @@ public class ReadWriteString { // data for text files final String TEXT_UNICODE = "\u201CHello\u201D"; final String TEXT_ASCII = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n abcdefghijklmnopqrstuvwxyz\n 1234567890\n"; + final static String TEXT_PERSON_CART_WHEELING = "\ud83e\udd38"; private static final String JA_STRING = "\u65e5\u672c\u8a9e\u6587\u5b57\u5217"; private static final Charset WINDOWS_1252 = Charset.forName("windows-1252"); private static final Charset WINDOWS_31J = Charset.forName("windows-31j"); @@ -154,7 +160,16 @@ public Object[][] getReadString() { {testFiles[1], TEXT_ASCII, US_ASCII, US_ASCII}, {testFiles[1], TEXT_ASCII, US_ASCII, UTF_8}, {testFiles[1], TEXT_UNICODE, UTF_8, null}, - {testFiles[1], TEXT_UNICODE, UTF_8, UTF_8} + {testFiles[1], TEXT_UNICODE, UTF_8, UTF_8}, + {testFiles[1], TEXT_ASCII, US_ASCII, ISO_8859_1}, + {testFiles[1], TEXT_PERSON_CART_WHEELING, UTF_16, UTF_16}, + {testFiles[1], TEXT_PERSON_CART_WHEELING, UTF_16BE, UTF_16BE}, + {testFiles[1], TEXT_PERSON_CART_WHEELING, UTF_16LE, UTF_16LE}, + {testFiles[1], TEXT_PERSON_CART_WHEELING, UTF_32, UTF_32}, + {testFiles[1], TEXT_PERSON_CART_WHEELING, UTF_32BE, UTF_32BE}, + {testFiles[1], TEXT_PERSON_CART_WHEELING, UTF_32LE, UTF_32LE}, + {testFiles[1], TEXT_PERSON_CART_WHEELING, WINDOWS_1252, WINDOWS_1252}, + {testFiles[1], TEXT_PERSON_CART_WHEELING, WINDOWS_31J, WINDOWS_31J} }; } @@ -304,6 +319,21 @@ public void testMalformedReadBytes(byte[] data, Charset csRead, Class c) { try { c.call(); diff --git a/test/jdk/java/util/zip/ZipFile/Zip64SizeTest.java b/test/jdk/java/util/zip/ZipFile/Zip64SizeTest.java index a7afa2681a0c3..ca472aa2aa75c 100644 --- a/test/jdk/java/util/zip/ZipFile/Zip64SizeTest.java +++ b/test/jdk/java/util/zip/ZipFile/Zip64SizeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -20,117 +20,174 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; -import java.io.*; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; -import static org.testng.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; + /** * @test - * @bug 8226530 - * @summary ZIP File System tests that leverage DirectoryStream + * @bug 8226530 8303891 + * @summary Verify that ZipFile reads size fields using the Zip64 extra + * field when only the 'uncompressed size' field has the ZIP64 "magic value" 0xFFFFFFFF * @compile Zip64SizeTest.java - * @run testng Zip64SizeTest + * @run junit Zip64SizeTest */ public class Zip64SizeTest { - - private static final int BUFFER_SIZE = 2048; // ZIP file to create - private static final String ZIP_FILE_NAME = "Zip64SizeTest.zip"; - // File that will be created with a size greater than 0xFFFFFFFF - private static final String LARGE_FILE_NAME = "LargeZipEntry.txt"; - // File that will be created with a size less than 0xFFFFFFFF - private static final String SMALL_FILE_NAME = "SmallZipEntry.txt"; - // List of files to be added to the ZIP file - private static final List ZIP_ENTRIES = List.of(LARGE_FILE_NAME, - SMALL_FILE_NAME); - private static final long LARGE_FILE_SIZE = 5L * 1024L * 1024L * 1024L; // 5GB - private static final long SMALL_FILE_SIZE = 0x100000L; // 1024L x 1024L; + private static final Path ZIP_FILE = Path.of("Zip64SizeTest.zip"); + // Contents to write to ZIP entries + private static final byte[] CONTENT = "Hello".getBytes(StandardCharsets.UTF_8); + // This opaque tag will be ignored by ZipEntry.setExtra0 + private static final int UNKNOWN_TAG = 0x9902; + // Tag used when converting the extra field to a real ZIP64 extra field + private static final short ZIP64_TAG = 0x1; + // Marker value to indicate that the actual value is stored in the ZIP64 extra field + private static final int ZIP64_MAGIC_VALUE = 0xFFFFFFFF; /** - * Validate that if the size of a ZIP entry exceeds 0xFFFFFFFF, that the - * correct size is returned from the ZIP64 Extended information. - * @throws IOException + * Validate that if the 'uncompressed size' of a ZIP CEN header is 0xFFFFFFFF, then the + * actual size is retrieved from the corresponding ZIP64 Extended information field. + * + * @throws IOException if an unexpected IOException occurs */ @Test - private static void validateZipEntrySizes() throws IOException { - createFiles(); + public void validateZipEntrySizes() throws IOException { createZipFile(); System.out.println("Validating Zip Entry Sizes"); - try (ZipFile zip = new ZipFile(ZIP_FILE_NAME)) { - ZipEntry ze = zip.getEntry(LARGE_FILE_NAME); + try (ZipFile zip = new ZipFile(ZIP_FILE.toFile())) { + ZipEntry ze = zip.getEntry("first"); System.out.printf("Entry: %s, size= %s%n", ze.getName(), ze.getSize()); - assertTrue(ze.getSize() == LARGE_FILE_SIZE); - ze = zip.getEntry(SMALL_FILE_NAME); + assertEquals(CONTENT.length, ze.getSize()); + ze = zip.getEntry("second"); System.out.printf("Entry: %s, size= %s%n", ze.getName(), ze.getSize()); - assertTrue(ze.getSize() == SMALL_FILE_SIZE); - + assertEquals(CONTENT.length, ze.getSize()); } } /** - * Delete the files created for use by the test - * @throws IOException if an error occurs deleting the files + * Create a ZIP file with a CEN entry where the 'uncompressed size' is stored in + * the ZIP64 field, but the 'compressed size' is in the CEN field. This makes the + * ZIP64 data block 8 bytes long, which triggers the regression described in 8226530. + * + * The CEN entry for the "first" entry will have the following structure: + * (Note the CEN 'Uncompressed Length' being 0xFFFFFFFF and the ZIP64 + * 'Uncompressed Size' being 5) + * + * 0081 CENTRAL HEADER #1 02014B50 + * 0085 Created Zip Spec 14 '2.0' + * 0086 Created OS 00 'MS-DOS' + * [...] Omitted for brevity + * 0091 CRC F7D18982 + * 0095 Compressed Length 00000007 + * 0099 Uncompressed Length FFFFFFFF + * [...] Omitted for brevity + * 00AF Filename 'first' + * 00B4 Extra ID #0001 0001 'ZIP64' + * 00B6 Length 0008 + * 00B8 Uncompressed Size 0000000000000005 + * + * @throws IOException if an error occurs creating the ZIP File */ - private static void deleteFiles() throws IOException { - Files.deleteIfExists(Path.of(ZIP_FILE_NAME)); - Files.deleteIfExists(Path.of(LARGE_FILE_NAME)); - Files.deleteIfExists(Path.of(SMALL_FILE_NAME)); + private static void createZipFile() throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (ZipOutputStream zos = new ZipOutputStream(baos)) { + + // The 'first' entry will store 'uncompressed size' in the Zip64 format + ZipEntry e1 = new ZipEntry("first"); + + // Make an extra field with the correct size for an 8-byte 'uncompressed size' + // Zip64 field. Temporarily use the 'unknown' tag 0x9902 to make + // ZipEntry.setExtra0 skip parsing this as a Zip64. + // See APPNOTE.TXT, 4.6.1 Third Party Mappings + byte[] opaqueExtra = createBlankExtra((short) UNKNOWN_TAG, (short) Long.BYTES); + e1.setExtra(opaqueExtra); + + zos.putNextEntry(e1); + zos.write(CONTENT); + + // A second entry, not in Zip64 format + ZipEntry e2 = new ZipEntry("second"); + zos.putNextEntry(e2); + zos.write(CONTENT); + } + + byte[] zip = baos.toByteArray(); + + // Update the CEN of 'first' to use the Zip64 format + updateCENHeaderToZip64(zip); + Files.write(ZIP_FILE, zip); } /** - * Create the ZIP file adding an entry whose size exceeds 0xFFFFFFFF - * @throws IOException if an error occurs creating the ZIP File + * Update the CEN entry of the "first" entry to use ZIP64 format for the + * 'uncompressed size' field. The updated extra field will have the following + * structure: + * + * 00B4 Extra ID #0001 0001 'ZIP64' + * 00B6 Length 0008 + * 00B8 Uncompressed Size 0000000000000005 + * + * @param zip the ZIP file to update to ZIP64 */ - private static void createZipFile() throws IOException { - try (FileOutputStream fos = new FileOutputStream(ZIP_FILE_NAME); - ZipOutputStream zos = new ZipOutputStream(fos)) { - System.out.printf("Creating Zip file: %s%n", ZIP_FILE_NAME); - for (String srcFile : ZIP_ENTRIES) { - System.out.printf("...Adding Entry: %s%n", srcFile); - File fileToZip = new File(srcFile); - try (FileInputStream fis = new FileInputStream(fileToZip)) { - ZipEntry zipEntry = new ZipEntry(fileToZip.getName()); - zipEntry.setSize(fileToZip.length()); - zos.putNextEntry(zipEntry); - byte[] bytes = new byte[BUFFER_SIZE]; - int length; - while ((length = fis.read(bytes)) >= 0) { - zos.write(bytes, 0, length); - } - } - } - } + private static void updateCENHeaderToZip64(byte[] zip) { + ByteBuffer buffer = ByteBuffer.wrap(zip).order(ByteOrder.LITTLE_ENDIAN); + // Find the offset of the first CEN header + int cenOffset = buffer.getInt(zip.length- ZipFile.ENDHDR + ZipFile.ENDOFF); + // Find the offset of the extra field + int nlen = buffer.getShort(cenOffset + ZipFile.CENNAM); + int extraOffset = cenOffset + ZipFile.CENHDR + nlen; + + // Change the header ID from 'unknown' to ZIP64 + buffer.putShort(extraOffset, ZIP64_TAG); + // Update the 'uncompressed size' ZIP64 value to the actual uncompressed length + int fieldOffset = extraOffset + + Short.BYTES // TAG + + Short.BYTES; // data size + buffer.putLong(fieldOffset, CONTENT.length); + + // Set the 'uncompressed size' field of the CEN to 0xFFFFFFFF + buffer.putInt(cenOffset + ZipFile.CENLEN, ZIP64_MAGIC_VALUE); } /** - * Create the files that will be added to the ZIP file - * @throws IOException if there is a problem creating the files + * Create an extra field with the given tag and data block size, and a + * blank data block. + * @return an extra field with the specified tag and size + * @param tag the header id of the extra field + * @param blockSize the size of the extra field's data block */ - private static void createFiles() throws IOException { - try (RandomAccessFile largeFile = new RandomAccessFile(LARGE_FILE_NAME, "rw"); - RandomAccessFile smallFile = new RandomAccessFile(SMALL_FILE_NAME, "rw")) { - System.out.printf("Creating %s%n", LARGE_FILE_NAME); - largeFile.setLength(LARGE_FILE_SIZE); - System.out.printf("Creating %s%n", SMALL_FILE_NAME); - smallFile.setLength(SMALL_FILE_SIZE); - } + private static byte[] createBlankExtra(short tag, short blockSize) { + int size = Short.BYTES // tag + + Short.BYTES // data block size + + blockSize; // data block; + + byte[] extra = new byte[size]; + ByteBuffer.wrap(extra).order(ByteOrder.LITTLE_ENDIAN) + .putShort(0, tag) + .putShort(Short.BYTES, blockSize); + return extra; } /** * Make sure the needed test files do not exist prior to executing the test * @throws IOException */ - @BeforeMethod + @BeforeEach public void setUp() throws IOException { deleteFiles(); } @@ -139,8 +196,16 @@ public void setUp() throws IOException { * Remove the files created for the test * @throws IOException */ - @AfterMethod + @AfterEach public void tearDown() throws IOException { deleteFiles(); } + + /** + * Delete the files created for use by the test + * @throws IOException if an error occurs deleting the files + */ + private static void deleteFiles() throws IOException { + Files.deleteIfExists(ZIP_FILE); + } } diff --git a/test/jdk/java/util/zip/ZipInputStream/Zip64DataDescriptor.java b/test/jdk/java/util/zip/ZipInputStream/Zip64DataDescriptor.java new file mode 100644 index 0000000000000..3581561008424 --- /dev/null +++ b/test/jdk/java/util/zip/ZipInputStream/Zip64DataDescriptor.java @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8303866 + * @summary ZipInputStream should read 8-byte data descriptors if the LOC has + * a ZIP64 extended information extra field + * @run junit Zip64DataDescriptor + */ + + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; +import java.util.HexFormat; +import java.util.zip.*; + +import static org.junit.jupiter.api.Assertions.*; + +public class Zip64DataDescriptor { + + // A byte array holding a small-sized Zip64 ZIP file, described below + private byte[] zip64File; + + // A byte array holding a ZIP used for testing invalid Zip64 extra fields + private byte[] invalidZip64; + + @BeforeEach + public void setup() throws IOException { + /* + * Structure of the ZIP64 file used below . Note the presence + * of a Zip64 extended information extra field and the + * Data Descriptor having 8-byte values for csize and size. + * + * The file was produced using the zip command on MacOS + * (zip 3.0, by Info-ZIP), in streamming mode (to enable Zip64), + * using the -fd option (to force the use of data descriptors) + * + * The following command was used: + *

echo hello | zip -fd > hello.zip
+ * + * ------ Local File Header ------ + * 000000 signature 0x04034b50 + * 000004 version 45 + * 000006 flags 0x0008 + * 000008 method 8 Deflated + * 000010 time 0xb180 22:12 + * 000012 date 0x565c 2023-02-28 + * 000014 crc 0x00000000 + * 000018 csize -1 + * 000022 size -1 + * 000026 nlen 1 + * 000028 elen 20 + * 000030 name 1 bytes '-' + * 000031 ext id 0x0001 Zip64 extended information extra field + * 000033 ext size 16 + * 000035 z64 size 0 + * 000043 z64 csize 0 + * + * ------ File Data ------ + * 000051 data 8 bytes + * + * ------ Data Desciptor ------ + * 000059 signature 0x08074b50 + * 000063 crc 0x363a3020 + * 000067 csize 8 + * 000075 size 6 + * 000083 ... + */ + + String hex = """ + 504b03042d000800080080b15c5600000000ffffffffffffffff01001400 + 2d0100100000000000000000000000000000000000cb48cdc9c9e7020050 + 4b070820303a3608000000000000000600000000000000504b01021e032d + 000800080080b15c5620303a360800000006000000010000000000000001 + 000000b011000000002d504b050600000000010001002f00000053000000 + 0000"""; + + zip64File = HexFormat.of().parseHex(hex.replaceAll("\n", "")); + + // Create the ZIP file used for testing that invalid Zip64 extra fields are ignored + // This ZIP has the regular 4-bit data descriptor + + byte[] extra = new byte[Long.BYTES + Long.BYTES + Short.BYTES * 2]; // Size of a regular Zip64 extra field + ByteBuffer buffer = ByteBuffer.wrap(extra).order(ByteOrder.LITTLE_ENDIAN); + buffer.putShort(0, (short) 123); // Not processed by ZipEntry.setExtra + buffer.putShort(Short.BYTES, (short) (extra.length - 4)); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (ZipOutputStream zo = new ZipOutputStream(baos)) { + ZipEntry ze = new ZipEntry("-"); + ze.setExtra(extra); + zo.putNextEntry(ze); + zo.write("hello\n".getBytes(StandardCharsets.UTF_8)); + } + + invalidZip64 = baos.toByteArray(); + + // Set Zip64 magic values on compressed and uncompressed size fields + ByteBuffer.wrap(invalidZip64).order(ByteOrder.LITTLE_ENDIAN) + .putInt(ZipFile.LOCSIZ, 0xFFFFFFFF) + .putInt(ZipFile.LOCLEN, 0xFFFFFFFF); + + // Set the Zip64 header ID 0x1 on the extra field in the invalid file + setExtraHeaderId((short) 0x1); + } + + /* + * Verify that small-sized Zip64 entries can be parsed by ZipInputStream + */ + @Test + public void shouldReadZip64Descriptor() throws IOException { + readZipInputStream(zip64File); + } + + /* + * For maximal backward compatibility when reading Zip64 descriptors, invalid + * Zip64 extra data sizes should be ignored + */ + @Test + public void shouldIgnoreInvalidExtraSize() throws IOException { + setExtraSize((short) 42); + readZipInputStream(invalidZip64); + } + + /* + * Files with Zip64 magic values but no Zip64 field should be ignored + * when considering 8 byte data descriptors + */ + @Test + public void shouldIgnoreNoZip64Header() throws IOException { + setExtraSize((short) 123); + readZipInputStream(invalidZip64); + } + + /* + * Theoretically, ZIP files may exist with ZIP64 format, but with 4-byte + * data descriptors. Such files will fail to parse, as demonstrated by this test. + */ + @Test + public void shouldFailParsingZip64With4ByteDataDescriptor() throws IOException { + ZipException ex = assertThrows(ZipException.class, () -> { + readZipInputStream(invalidZip64); + }); + + String msg = String.format("Expected exeption message to contain 'invalid entry size', was %s", + ex.getMessage()); + assertTrue(ex.getMessage().contains("invalid entry size"), msg); + } + + /* + * Validate that an extra data size exceeding the length of the extra field is ignored + */ + @Test + public void shouldIgnoreExcessiveExtraSize() throws IOException { + + setExtraSize(Short.MAX_VALUE); + + + readZipInputStream(invalidZip64); + } + + /* + * Validate that the Data Descriptor is read with 32-bit fields if neither the + * LOC's 'uncompressed size' or 'compressed size' fields have the Zip64 magic value, + * even when there is a Zip64 field in the extra field. + */ + @Test + public void shouldIgnoreNoMagicMarkers() throws IOException { + // Set compressed and uncompressed size fields to zero + ByteBuffer.wrap(invalidZip64).order(ByteOrder.LITTLE_ENDIAN) + .putInt(ZipFile.LOCSIZ, 0) + .putInt(ZipFile.LOCLEN, 0); + + + readZipInputStream(invalidZip64); + } + + /* + * Validate that an extra data size exceeding the length of the extra field is ignored + */ + @Test + public void shouldIgnoreTrucatedZip64Extra() throws IOException { + + truncateZip64(); + + readZipInputStream(invalidZip64); + } + + /** + * Update the Extra field header ID of the invalid file + */ + private void setExtraHeaderId(short id) { + // Set the header ID on the extra field + ByteBuffer buffer = ByteBuffer.wrap(invalidZip64).order(ByteOrder.LITTLE_ENDIAN); + int nlen = buffer.getShort(ZipFile.LOCNAM); + buffer.putShort(ZipFile.LOCHDR + nlen, id); + } + + /** + * Updates the 16-bit 'data size' field of the Zip64 extended information field, + * potentially to an invalid value. + * @param size the value to set in the 'data size' field. + */ + private void setExtraSize(short size) { + ByteBuffer buffer = ByteBuffer.wrap(invalidZip64).order(ByteOrder.LITTLE_ENDIAN); + // Compute the offset to the Zip64 data block size field + short nlen = buffer.getShort(ZipFile.LOCNAM); + int dataSizeOffset = ZipFile.LOCHDR + nlen + Short.BYTES; + buffer.putShort(dataSizeOffset, size); + } + + /** + * Puts a truncated Zip64 field (just the tag) at the end of the LOC extra field. + * The beginning of the extra field is filled with a generic extra field containing + * just zeros. + */ + private void truncateZip64() { + ByteBuffer buffer = ByteBuffer.wrap(invalidZip64).order(ByteOrder.LITTLE_ENDIAN); + // Get the LOC name and extra sizes + short nlen = buffer.getShort(ZipFile.LOCNAM); + short elen = buffer.getShort(ZipFile.LOCEXT); + int cenOffset = ZipFile.LOCHDR + nlen + elen; + + // Zero out the extra field + int estart = ZipFile.LOCHDR + nlen; + buffer.put(estart, new byte[elen]); + // Put a generic extra field in the start + buffer.putShort(estart, (short) 42); + buffer.putShort(estart + Short.BYTES, (short) (elen - 4 - 2)); + // Put a truncated (just the tag) Zip64 field at the end + buffer.putShort(cenOffset - Short.BYTES, (short) 0x0001); + } + + /* + * Consume and verify the ZIP file using ZipInputStream + */ + private void readZipInputStream(byte[] zip) throws IOException { + try (ZipInputStream in = new ZipInputStream(new ByteArrayInputStream(zip))) { + // Read the ZIP entry, this calls readLOC + ZipEntry e = in.getNextEntry(); + + // Sanity check the zip entry + assertNotNull(e, "Missing zip entry"); + assertEquals("-", e.getName()); + + // Read the entry data, this causes readEND to parse the data descriptor + assertEquals("hello\n", new String(in.readAllBytes(), StandardCharsets.UTF_8)); + + // There should only be a single zip entry + assertNull(in.getNextEntry(), "Unexpected additional zip entry"); + } + } +} diff --git a/test/jdk/javax/net/ssl/Stapling/TEST.properties b/test/jdk/javax/net/ssl/Stapling/TEST.properties index f4117a3ced2b7..f5039eb9e0a97 100644 --- a/test/jdk/javax/net/ssl/Stapling/TEST.properties +++ b/test/jdk/javax/net/ssl/Stapling/TEST.properties @@ -2,4 +2,4 @@ modules = \ java.base/sun.security.provider.certpath \ java.base/sun.security.util \ java.base/sun.security.validator \ - java.base/sun.security.x509 + java.base/sun.security.x509 diff --git a/test/jdk/jdk/jfr/event/runtime/TestSafepointEvents.java b/test/jdk/jdk/jfr/event/runtime/TestSafepointEvents.java index 285592bce1699..6b165375383ea 100644 --- a/test/jdk/jdk/jfr/event/runtime/TestSafepointEvents.java +++ b/test/jdk/jdk/jfr/event/runtime/TestSafepointEvents.java @@ -52,8 +52,8 @@ public class TestSafepointEvents { static final String[] EVENT_NAMES = new String[] { EventNames.SafepointBegin, EventNames.SafepointStateSynchronization, + // EventNames.SafepointCleanupTask, EventNames.SafepointCleanup, - EventNames.SafepointCleanupTask, EventNames.SafepointEnd }; diff --git a/test/jdk/performance/client/SwingMark/src/resources/TextAreaTest.properties b/test/jdk/performance/client/SwingMark/src/resources/TextAreaTest.properties index 07df149851b5d..a3a8e39ce5919 100644 --- a/test/jdk/performance/client/SwingMark/src/resources/TextAreaTest.properties +++ b/test/jdk/performance/client/SwingMark/src/resources/TextAreaTest.properties @@ -29,4 +29,4 @@ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Resource bundle for Menu Test -DisplayString=Swing is Fast!!! +DisplayString=Swing is Fast!!! diff --git a/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/filechooser/resources/FileChooserDemo.properties b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/filechooser/resources/FileChooserDemo.properties index c5c4c99bedad0..36eef6c8b3d67 100644 --- a/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/filechooser/resources/FileChooserDemo.properties +++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/filechooser/resources/FileChooserDemo.properties @@ -8,18 +8,18 @@ FileChooserDemo.cancel.text = Cancel FileChooserDemo.filter.blur = blur FileChooserDemo.filter.edge = edge -FileChooserDemo.filter.sharpen = sharpen +FileChooserDemo.filter.sharpen = sharpen FileChooserDemo.filter.darken = darken FileChooserDemo.filter.brighten = brighten FileChooserDemo.filter.lesscontrast = less contrast FileChooserDemo.filter.morecontrast = more contrast FileChooserDemo.filter.gray = gray -FileChooserDemo.applyfilter.tooltip = Apply filter -FileChooserDemo.rotateleft.tooltip = Rotate left -FileChooserDemo.rotateright.tooltip = Rotate right -FileChooserDemo.fliphorizontal.tooltip = Flip horizontal -FileChooserDemo.flipvertical.tooltip = Flip vertical +FileChooserDemo.applyfilter.tooltip = Apply filter +FileChooserDemo.rotateleft.tooltip = Rotate left +FileChooserDemo.rotateright.tooltip = Rotate right +FileChooserDemo.fliphorizontal.tooltip = Flip horizontal +FileChooserDemo.flipvertical.tooltip = Flip vertical FileChooserDemo.preview.type = Type: FileChooserDemo.preview.size = Size: diff --git a/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/resources/TableDemo.properties b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/resources/TableDemo.properties index 1210d3f9c540f..4ce5a8f4cbb04 100644 --- a/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/resources/TableDemo.properties +++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/resources/TableDemo.properties @@ -9,9 +9,9 @@ TableDemo.searchLabel=Search Titles and Recipients TableDemo.winnersLabel=Show Only Winners TableDemo.noDataStatusLabel=No data loaded -TableDemo.loadingStatusLabel=Loading data: -TableDemo.rowCountLabel=Showing -TableDemo.searchCountLabel=Search found +TableDemo.loadingStatusLabel=Loading data:\u0020 +TableDemo.rowCountLabel=Showing\u0020 +TableDemo.searchCountLabel=Search found\u0020 TableDemo.yearColumnTitle=Year TableDemo.categoryColumnTitle=Award Category @@ -19,4 +19,3 @@ TableDemo.movieTitleColumnTitle=Movie Title TableDemo.nomineesColumnTitle=Nominee(s) TableDemo.imdbLinkNotFound=Unable to locate IMDB URL for - diff --git a/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/togglebutton/resources/ToggleButtonDemo.properties b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/togglebutton/resources/ToggleButtonDemo.properties index 241368aacaaa9..61676a284a836 100644 --- a/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/togglebutton/resources/ToggleButtonDemo.properties +++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/togglebutton/resources/ToggleButtonDemo.properties @@ -1,6 +1,6 @@ ### Button Demo ### -ToggleButtonDemo.accessible_description=The ButtonDemo shows examples of using JButton, JRadioButton, JToggleButton, and JCheckBox +ToggleButtonDemo.accessible_description=The ButtonDemo shows examples of using JButton, JRadioButton, JToggleButton, and JCheckBox ToggleButtonDemo.tooltip=JButton, JRadioButton, JToggleButton, JCheckbox demos ToggleButtonDemo.name=Button Demo @@ -18,16 +18,16 @@ ToggleButtonDemo.imagetogglebuttons=Image Toggle Buttons ToggleButtonDemo.textcheckboxes=Text CheckBoxes ToggleButtonDemo.imagecheckboxes=Image CheckBoxes -ToggleButtonDemo.button1=One +ToggleButtonDemo.button1=One ToggleButtonDemo.button2=Two ToggleButtonDemo.button3=Three! -ToggleButtonDemo.radio1=Radio One +ToggleButtonDemo.radio1=Radio One ToggleButtonDemo.radio2=Radio Two ToggleButtonDemo.radio3=Radio Three ToggleButtonDemo.radioX=Three(HTML!) -ToggleButtonDemo.check1=One +ToggleButtonDemo.check1=One ToggleButtonDemo.check2=Two ToggleButtonDemo.check3=Three ToggleButtonDemo.checkX=Three(HTML!) @@ -35,7 +35,7 @@ ToggleButtonDemo.checkX=Three(HTML!)p  >  -
  • C
  • +
  • C
  • """); checkOutput("o/p/C.html", true, @@ -182,7 +182,7 @@ public void exportSameName(Path base) throws Exception {  > 
  • p
  •  >  -
  • C
  • +
  • C
  • """); checkOutput("type-search-index.js", true, diff --git a/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java b/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java index 157bf956c53be..53cd7e204eb85 100644 --- a/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java +++ b/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java @@ -412,7 +412,7 @@ public void testUnnamedPackage(Path base) throws Exception { """); } diff --git a/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java b/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java index f8f9d80e1e431..76d422eb5a97c 100644 --- a/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java +++ b/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8250768 8261976 8277300 8282452 8287597 + * @bug 8250768 8261976 8277300 8282452 8287597 8325325 * @summary test generated docs for items declared using preview * @library ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool @@ -77,7 +77,7 @@ public void testPreviewAPIJavadoc() { checkExit(Exit.OK); checkOutput("preview-list.html", true, - """ + """

    Contents

    """, - """ + """ +
    +
    +
    Packages
    +
    +
    +
    +
    Package
    +
    Preview Feature
    +
    Description
    + +
    Test Feature
    +
    +
    Preview package.
    +
    + """, + """
    Record Classes
    @@ -105,7 +122,7 @@ public void testPreviewAPIJavadoc() {
    """, - """ + """
    Methods
    @@ -121,6 +138,24 @@ public void testPreviewAPIJavadoc() {
    Returns the value of the i record component.
    """); + + // 8325325: Breadcrumb navigation links should not contain PREVIEW link + checkOutput("java.base/preview/package-summary.html", true, + """ + """); + checkOutput("java.base/preview/Core.html", true, + """ + """); } @Test diff --git a/src/hotspot/share/oops/compiledICHolder.inline.hpp b/test/langtools/jdk/javadoc/doclet/testPreview/api/preview/package-info.java similarity index 63% rename from src/hotspot/share/oops/compiledICHolder.inline.hpp rename to test/langtools/jdk/javadoc/doclet/testPreview/api/preview/package-info.java index efbfcec064762..050d5512013da 100644 --- a/src/hotspot/share/oops/compiledICHolder.inline.hpp +++ b/test/langtools/jdk/javadoc/doclet/testPreview/api/preview/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -19,25 +19,13 @@ * 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. - * */ -#ifndef SHARE_OOPS_COMPILEDICHOLDER_INLINE_HPP -#define SHARE_OOPS_COMPILEDICHOLDER_INLINE_HPP - -#include "oops/compiledICHolder.hpp" - -#include "oops/klass.inline.hpp" - -inline bool CompiledICHolder::is_loader_alive() { - Klass* k = _is_metadata_method ? ((Method*)_holder_metadata)->method_holder() : (Klass*)_holder_metadata; - if (!k->is_loader_alive()) { - return false; - } - if (!_holder_klass->is_loader_alive()) { - return false; - } - return true; -} +/** + * Preview package. + */ +@PreviewFeature(feature=Feature.TEST) +package preview; -#endif // SHARE_OOPS_COMPILEDICHOLDER_INLINE_HPP +import jdk.internal.javac.PreviewFeature; +import jdk.internal.javac.PreviewFeature.Feature; diff --git a/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.java b/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.java index 71e6193275ba9..e0e153eb0f5fe 100644 --- a/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.java +++ b/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.java @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 8304487 + * @bug 8304487 8325653 * @summary Compiler Implementation for Primitive types in patterns, instanceof, and switch (Preview) * @enablePreview * @compile/fail/ref=PrimitivePatternsSwitchErrors.out -XDrawDiagnostics -XDshould-stop.at=FLOW PrimitivePatternsSwitchErrors.java @@ -217,4 +217,28 @@ void nullAndPrimitive() { default -> System.out.println("any other integral value"); } } + + public static int nonExhaustive4() { + Number n = Byte.valueOf((byte) 42); + return switch (n) { // Error - not exhaustive + case byte b when b == 42 -> 1; + case byte b -> -1 ; + }; + } + + public static int nonExhaustive5() { + Object n = 42; + return switch (n) { // Error - not exhaustive + case int b when b == 42 -> 1; + case int b -> -1 ; + }; + } + + public static int nonExhaustive6() { + Object n = 42; + return switch (n) { // Error - not exhaustive + case byte b -> -1 ; + case int b -> -2 ; + }; + } } diff --git a/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.out b/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.out index 2026afe58c2de..97b0d67cec733 100644 --- a/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.out +++ b/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.out @@ -32,6 +32,9 @@ PrimitivePatternsSwitchErrors.java:44:16: compiler.err.not.exhaustive PrimitivePatternsSwitchErrors.java:52:16: compiler.err.not.exhaustive PrimitivePatternsSwitchErrors.java:201:16: compiler.err.not.exhaustive PrimitivePatternsSwitchErrors.java:207:9: compiler.err.not.exhaustive.statement +PrimitivePatternsSwitchErrors.java:223:16: compiler.err.not.exhaustive +PrimitivePatternsSwitchErrors.java:231:16: compiler.err.not.exhaustive +PrimitivePatternsSwitchErrors.java:239:16: compiler.err.not.exhaustive - compiler.note.preview.filename: PrimitivePatternsSwitchErrors.java, DEFAULT - compiler.note.preview.recompile -34 errors \ No newline at end of file +37 errors \ No newline at end of file diff --git a/test/lib/jdk/test/whitebox/WhiteBox.java b/test/lib/jdk/test/whitebox/WhiteBox.java index 2d33182331d4f..2402e39974e3d 100644 --- a/test/lib/jdk/test/whitebox/WhiteBox.java +++ b/test/lib/jdk/test/whitebox/WhiteBox.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -119,6 +119,10 @@ public boolean isMonitorInflated(Object obj) { return isMonitorInflated0(obj); } + public native int getLockStackCapacity(); + + public native boolean supportsRecursiveLightweightLocking(); + public native void forceSafepoint(); public native void forceClassLoaderStatsSafepoint(); diff --git a/test/micro/org/openjdk/bench/vm/compiler/FinalFieldInitialize.java b/test/micro/org/openjdk/bench/vm/compiler/FinalFieldInitialize.java deleted file mode 100644 index ee0779faecf2a..0000000000000 --- a/test/micro/org/openjdk/bench/vm/compiler/FinalFieldInitialize.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2024, Alibaba Group Co., Ltd. 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.vm.compiler; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.*; - -import java.util.concurrent.TimeUnit; -import org.openjdk.jmh.infra.Blackhole; - -/* test allocation speed of object with final field */ -@BenchmarkMode(Mode.Throughput) -@OutputTimeUnit(TimeUnit.SECONDS) -@State(Scope.Benchmark) -@Warmup(iterations = 5, time = 3, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 3, time = 3, timeUnit = TimeUnit.SECONDS) -@Fork(value = 3) -public class FinalFieldInitialize { - final static int LEN = 100_000; - Object arr[] = null; - @Setup - public void setup(){ - arr = new Object[LEN]; - } - - @Benchmark - public void testAlloc(Blackhole bh) { - for (int i=0; i holder; + + @Setup(Level.Iteration) + public void generateGarbage() { + holder = GarbageGenerator.generateObjectArrays(); + holder = null; + } + + @Benchmark + public void gc() { + System.gc(); + } +} diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/AllLive.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/AllLive.java new file mode 100644 index 0000000000000..ddd9f56cf6022 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/AllLive.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.vm.gc.systemgc; + +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 java.util.ArrayList; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.SingleShotTime) +@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +public class AllLive { + + /* + * Test the System GC when all allocated objects are live. + * + * The jvmArgs are provided to avoid GCs during object creation. + */ + + static ArrayList holder; + + @Setup(Level.Iteration) + public void generateGarbage() { + holder = GarbageGenerator.generateObjectArrays(); + } + + @Benchmark + public void gc() { + System.gc(); + } +} diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesArray.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesArray.java new file mode 100644 index 0000000000000..a4dcfdaaeb594 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesArray.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.vm.gc.systemgc; + +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 java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.SingleShotTime) +@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +public class DifferentObjectSizesArray { + + /* + * Test the System GC when 2/3 of the objects are live + * and kept reachable through an object array. + * + * The jvmArgs are provided to avoid GCs during object creation. + */ + + static Object[] largeObjArray; + + @Setup(Level.Iteration) + public void generateGarbage() { + largeObjArray = GarbageGenerator.generateAndFillLargeObjArray(false); + // Removing a third of the objects and keeping a good + // distribution of sizes. + for (int i = 0; i < largeObjArray.length; i++) { + if (i%3 == 0) { + largeObjArray[i] = null; + } + } + } + + @Benchmark + public void gc() { + System.gc(); + } +} diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesHashMap.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesHashMap.java new file mode 100644 index 0000000000000..839147251611a --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesHashMap.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.vm.gc.systemgc; + +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 java.util.HashMap; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.SingleShotTime) +@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +public class DifferentObjectSizesHashMap { + + /* + * Test the System GC when 2/3 of the objects are live + * and kept reachable through a HashMap. + * + * The jvmArgs are provided to avoid GCs during object creation. + */ + + static HashMap largeMap; + + @Setup(Level.Iteration) + public void generateGarbage() { + largeMap = GarbageGenerator.generateAndFillHashMap(false); + int numberOfObjects = largeMap.size(); + // Removing a third of the objects and keeping a good + // distribution of sizes. + for (int i = 0; i < numberOfObjects; i++) { + if (i%3 == 0) { + largeMap.remove(i); + } + } + } + + @Benchmark + public void gc() { + System.gc(); + } +} diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesTreeMap.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesTreeMap.java new file mode 100644 index 0000000000000..66aaffff693a2 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesTreeMap.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.vm.gc.systemgc; + +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 java.util.TreeMap; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.SingleShotTime) +@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +public class DifferentObjectSizesTreeMap { + + /* + * Test the System GC when 2/3 of the objects are live + * and kept reachable through a TreeMap. + * + * The jvmArgs are provided to avoid GCs during object creation. + */ + static TreeMap largeMap; + + @Setup(Level.Iteration) + public void generateGarbage() { + largeMap = GarbageGenerator.generateAndFillTreeMap(false); + int numberOfObjects = largeMap.size(); + // Removing a third of the objects and keeping a good + // distribution of sizes. + for (int i = 0; i < numberOfObjects; i++) { + if (i%3 == 0) { + largeMap.remove(i); + } + } + } + + @Benchmark + public void gc() { + System.gc(); + } +} diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/GarbageGenerator.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/GarbageGenerator.java new file mode 100644 index 0000000000000..12f53ec257f67 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/GarbageGenerator.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.vm.gc.systemgc; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.TreeMap; + +public class GarbageGenerator { + static final int K = 1024; + static final int M = K * K; + + /** + * Generates roughly 1GB of objects stored as an arraylist of + * 1024 Object[]. Each Objects[] stores 1024 byte[] of size 1024. + * + * @return ArrayList of 1024 Objects[]. + */ + static ArrayList generateObjectArrays() { + ArrayList tmp = new ArrayList<>(); + for (int i = 0; i < GarbageGenerator.K; i++) { + Object[] x = new Object[GarbageGenerator.K]; + for (int j=0; j < GarbageGenerator.K; j++) { + x[j] = new byte[GarbageGenerator.K]; + } + tmp.add(x); + } + return tmp; + } + + /** + * Allocating an Object[] with elements and filling each slot with + * byte[]. If sameSize is true all byte[] are 1024 large, otherwise + * there are 8 different sizes from K/8 to 16K. + * + * @param sameSize all objects are 1K large. + * @return + */ + public static Object[] generateAndFillLargeObjArray(boolean sameSize) { + // Aiming for ~ 1gb of heap usage. For different sizes + // the average size is ~ 4k. + Object[] tmp = new Object[sameSize ? M : M / 4]; + for (int i = 0; i < tmp.length; i++) { + if (sameSize) { + tmp[i] = new byte[K]; + } else { + int multiplier = 1 << (i % 8); // 1,2,4,8,16,32,64,128 + tmp[i] = new byte[(K / 8) * multiplier ]; + } + } + return tmp; + } + + public static HashMap generateAndFillHashMap(boolean sameSize) { + HashMap tmp = new HashMap<>(); + int numberOfObjects = sameSize ? M : M / 4; + for (int i = 0; i < numberOfObjects; i++) { + if (sameSize) { + tmp.put(i, new byte[K]); + } else { + int multiplier = 1 << (i % 8); // 1,2,4,8,16,32,64,128 + tmp.put(i, new byte[(K / 8) * multiplier]); + } + } + return tmp; + } + + public static TreeMap generateAndFillTreeMap(boolean sameSize) { + TreeMap tmp = new TreeMap<>(); + int numberOfObjects = sameSize ? M : M / 4; + for (int i = 0; i < numberOfObjects; i++) { + if (sameSize) { + tmp.put(i, new byte[K]); + } else { + int multiplier = 1 << (i % 8); // 1,2,4,8,16,32,64,128 + tmp.put(i, new byte[(K / 8) * multiplier]); + } + } + return tmp; + } +} diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadFirstPart.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadFirstPart.java new file mode 100644 index 0000000000000..80cefbfe10f86 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadFirstPart.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.vm.gc.systemgc; + +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 java.util.ArrayList; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.SingleShotTime) +@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +public class HalfDeadFirstPart { + + /* + * Test the System GC when half of the objects are dead. + * In this test the first half of the objects are cleared. + * + * The jvmArgs are provided to avoid GCs during object creation. + */ + + static ArrayList holder; + + @Setup(Level.Iteration) + public void generateGarbage() { + holder = GarbageGenerator.generateObjectArrays(); + // Clearing every other object array in the holder + for (int i = 0; i < holder.size() / 2; i++) { + holder.set(i, null); + } + } + + @Benchmark + public void gc() { + System.gc(); + } +} diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleaved.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleaved.java new file mode 100644 index 0000000000000..bda9ccfa2135b --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleaved.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.vm.gc.systemgc; + +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 java.util.ArrayList; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.SingleShotTime) +@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +public class HalfDeadInterleaved { + + /* + * Test the System GC when half of the objects are dead. + * In this test every other object is cleared. + * + * The jvmArgs are provided to avoid GCs during object creation. + */ + + static ArrayList holder; + + @Setup(Level.Iteration) + public void generateGarbage() { + holder = GarbageGenerator.generateObjectArrays(); + for (Object[] objArray : holder) { + for (int i=0; i < objArray.length; i++) { + if ((i & 1) == 1) { + objArray[i] = null; + } + } + } + } + + @Benchmark + public void gc() { + System.gc(); + } +} diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleavedChunks.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleavedChunks.java new file mode 100644 index 0000000000000..06955381f5ca9 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleavedChunks.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.vm.gc.systemgc; + +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 java.util.ArrayList; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.SingleShotTime) +@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +public class HalfDeadInterleavedChunks { + + /* + * Test the System GC when half of the objects are dead. + * In this test every other array of objects is cleared. + * + * The jvmArgs are provided to avoid GCs during object creation. + */ + + static ArrayList holder; + + @Setup(Level.Iteration) + public void generateGarbage() { + holder = GarbageGenerator.generateObjectArrays(); + // Clearing every other object array in the holder + for (int i = 0; i < holder.size(); i++) { + if ((i & 1) == 1) { + holder.set(i, null); + } + } + } + + @Benchmark + public void gc() { + System.gc(); + } +} diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadSecondPart.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadSecondPart.java new file mode 100644 index 0000000000000..89606f5a07a99 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadSecondPart.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.vm.gc.systemgc; + +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 java.util.ArrayList; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.SingleShotTime) +@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +public class HalfDeadSecondPart { + + /* + * Test the System GC when half of the objects are dead. + * In this test the second half of the objects are cleared. + * + * The jvmArgs are provided to avoid GCs during object creation. + */ + + static ArrayList holder; + + @Setup(Level.Iteration) + public void generateGarbage() { + holder = GarbageGenerator.generateObjectArrays(); + // Clearing every other object array in the holder + for (int i = holder.size() / 2; i < holder.size(); i++) { + holder.set(i, null); + } + } + + @Benchmark + public void gc() { + System.gc(); + } +} diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfHashedHalfDead.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfHashedHalfDead.java new file mode 100644 index 0000000000000..6692e02a13576 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfHashedHalfDead.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.gc.systemgc; + +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 java.util.ArrayList; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.SingleShotTime) +@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +public class HalfHashedHalfDead { + + /* + * Test the System GC when there is a big amount of objects + * with hash codes calculated. + * + * The jvmArgs are provided to avoid GCs during object creation. + */ + + static ArrayList holder; + + @Setup(Level.Iteration) + public void generateGarbage() { + holder = GarbageGenerator.generateObjectArrays(); + // Keeping half the objects and calculating the hash code to + // force some GCs to preserve marks. + for (Object[] objectArray: holder) { + for (int i = 0; i < objectArray.length; i++) { + if (i % 2 == 0) { + objectArray[i].hashCode(); + } else { + objectArray[i] = null; + } + } + } + } + + @Benchmark + public void gc() { + System.gc(); + } +} diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/NoObjects.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/NoObjects.java new file mode 100644 index 0000000000000..a2e35e550611c --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/NoObjects.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.vm.gc.systemgc; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.SingleShotTime) +@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +public class NoObjects { + + /* + * Test the System GC when there are no additionally allocate + * objects. + * + * The heap settings provided are the same as for the other + * test for consistency. + */ + + @Benchmark + public void gc() { + System.gc(); + } + +} diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/OneBigObject.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/OneBigObject.java new file mode 100644 index 0000000000000..5601abdcb709e --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/OneBigObject.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.vm.gc.systemgc; + +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 java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.SingleShotTime) +@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +public class OneBigObject { + + /* + * Test the System GC when there is a single large object. + * + * The heap settings provided are the same as for the other + * test for consistency. + */ + + static Object[] holder; + + @Setup(Level.Iteration) + public void generateGarbage() { + holder = new Object[1024*1024*128]; + } + + @Benchmark + public void gc() { + System.gc(); + } +}